4 * Copyright 1993 David Metcalfe
5 * Copyright 1996 Frans van Dorsselaer
6 * Copyright 2001 Eric Pouech
7 * Copyright 2002 Alexandre Julliard
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28 #include "wine/server.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(caret);
39 static CARET Caret = { 0, 500 };
41 #define TIMERID 0xffff /* system timer id for the caret */
44 /*****************************************************************
47 static void CARET_DisplayCaret( HWND hwnd, const RECT *r )
52 /* do not use DCX_CACHE here, for x,y,width,height are in logical units */
53 if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE /*| DCX_CACHE*/ ))) return;
54 hCompDC = CreateCompatibleDC(hdc);
59 hPrevBmp = SelectObject(hCompDC, Caret.hBmp);
60 BitBlt(hdc, r->left, r->top, r->right-r->left, r->bottom-r->top, hCompDC, 0, 0, SRCINVERT);
61 SelectObject(hCompDC, hPrevBmp);
64 ReleaseDC( hwnd, hdc );
68 /*****************************************************************
71 static void CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT id, DWORD ctime)
78 SERVER_START_REQ( set_caret_info )
80 req->flags = SET_CARET_STATE;
85 req->state = -1; /* toggle current state */
86 if ((ret = !wine_server_call( req )))
88 hwnd = reply->full_handle;
89 r.left = reply->old_rect.left;
90 r.top = reply->old_rect.top;
91 r.right = reply->old_rect.right;
92 r.bottom = reply->old_rect.bottom;
93 old_state = reply->old_state;
94 hidden = reply->old_hide;
99 if (ret && !hidden) CARET_DisplayCaret( hwnd, &r );
103 /*****************************************************************
104 * CreateCaret (USER32.@)
106 BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap, INT width, INT height )
115 TRACE("hwnd=%p\n", hwnd);
117 if (!hwnd) return FALSE;
119 if (bitmap && (bitmap != (HBITMAP)1))
122 if (!GetObjectA( bitmap, sizeof(bmp), &bmp )) return FALSE;
124 height = bmp.bmHeight;
126 hBmp = CreateBitmapIndirect(&bmp);
129 /* copy the bitmap */
130 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, bmp.bmWidthBytes * bmp.bmHeight);
131 GetBitmapBits(bitmap, bmp.bmWidthBytes * bmp.bmHeight, buf);
132 SetBitmapBits(hBmp, bmp.bmWidthBytes * bmp.bmHeight, buf);
133 HeapFree(GetProcessHeap(), 0, buf);
140 if (!width) width = GetSystemMetrics(SM_CXBORDER);
141 if (!height) height = GetSystemMetrics(SM_CYBORDER);
143 /* create the uniform bitmap on the fly */
147 HDC hMemDC = CreateCompatibleDC(hdc);
150 if ((hBmp = CreateCompatibleBitmap(hMemDC, width, height )))
152 HBITMAP hPrevBmp = SelectObject(hMemDC, hBmp);
153 SetRect( &r, 0, 0, width, height );
154 FillRect(hMemDC, &r, (HBRUSH)((bitmap ? COLOR_GRAYTEXT : COLOR_WINDOW) + 1));
155 SelectObject(hMemDC, hPrevBmp);
159 ReleaseDC(hwnd, hdc);
162 if (!hBmp) return FALSE;
164 SERVER_START_REQ( set_caret_window )
168 req->height = height;
169 if ((ret = !wine_server_call_err( req )))
171 prev = reply->previous;
172 r.left = reply->old_rect.left;
173 r.top = reply->old_rect.top;
174 r.right = reply->old_rect.right;
175 r.bottom = reply->old_rect.bottom;
176 old_state = reply->old_state;
177 hidden = reply->old_hide;
181 if (!ret) return FALSE;
183 if (prev && !hidden) /* hide the previous one */
185 /* FIXME: won't work if prev belongs to a different process */
186 KillSystemTimer( prev, TIMERID );
187 if (old_state) CARET_DisplayCaret( prev, &r );
190 if (Caret.hBmp) DeleteObject( Caret.hBmp );
192 Caret.timeout = GetProfileIntA( "windows", "CursorBlinkRate", 500 );
197 /*****************************************************************
198 * DestroyCaret (USER32.@)
200 BOOL WINAPI DestroyCaret(void)
208 SERVER_START_REQ( set_caret_window )
213 if ((ret = !wine_server_call_err( req )))
215 prev = reply->previous;
216 r.left = reply->old_rect.left;
217 r.top = reply->old_rect.top;
218 r.right = reply->old_rect.right;
219 r.bottom = reply->old_rect.bottom;
220 old_state = reply->old_state;
221 hidden = reply->old_hide;
226 if (ret && prev && !hidden)
228 /* FIXME: won't work if prev belongs to a different process */
229 KillSystemTimer( prev, TIMERID );
230 if (old_state) CARET_DisplayCaret( prev, &r );
232 if (Caret.hBmp) DeleteObject( Caret.hBmp );
238 /*****************************************************************
239 * SetCaretPos (USER32.@)
241 BOOL WINAPI SetCaretPos( INT x, INT y )
249 SERVER_START_REQ( set_caret_info )
251 req->flags = SET_CARET_POS|SET_CARET_STATE;
257 if ((ret = !wine_server_call_err( req )))
259 hwnd = reply->full_handle;
260 r.left = reply->old_rect.left;
261 r.top = reply->old_rect.top;
262 r.right = reply->old_rect.right;
263 r.bottom = reply->old_rect.bottom;
264 old_state = reply->old_state;
265 hidden = reply->old_hide;
271 if (old_state) CARET_DisplayCaret( hwnd, &r );
272 r.right += x - r.left;
273 r.bottom += y - r.top;
276 CARET_DisplayCaret( hwnd, &r );
277 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
283 /*****************************************************************
284 * HideCaret (USER32.@)
286 BOOL WINAPI HideCaret( HWND hwnd )
293 SERVER_START_REQ( set_caret_info )
295 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
301 if ((ret = !wine_server_call_err( req )))
303 hwnd = reply->full_handle;
304 r.left = reply->old_rect.left;
305 r.top = reply->old_rect.top;
306 r.right = reply->old_rect.right;
307 r.bottom = reply->old_rect.bottom;
308 old_state = reply->old_state;
309 hidden = reply->old_hide;
316 if (old_state) CARET_DisplayCaret( hwnd, &r );
317 KillSystemTimer( hwnd, TIMERID );
323 /*****************************************************************
324 * ShowCaret (USER32.@)
326 BOOL WINAPI ShowCaret( HWND hwnd )
333 SERVER_START_REQ( set_caret_info )
335 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
341 if ((ret = !wine_server_call_err( req )))
343 hwnd = reply->full_handle;
344 r.left = reply->old_rect.left;
345 r.top = reply->old_rect.top;
346 r.right = reply->old_rect.right;
347 r.bottom = reply->old_rect.bottom;
348 old_state = reply->old_state;
349 hidden = reply->old_hide;
354 if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */
356 CARET_DisplayCaret( hwnd, &r );
357 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
363 /*****************************************************************
364 * GetCaretPos (USER32.@)
366 BOOL WINAPI GetCaretPos( LPPOINT pt )
370 SERVER_START_REQ( set_caret_info )
372 req->flags = 0; /* don't set anything */
378 if ((ret = !wine_server_call_err( req )))
380 pt->x = reply->old_rect.left;
381 pt->y = reply->old_rect.top;
389 /*****************************************************************
390 * SetCaretBlinkTime (USER32.@)
392 BOOL WINAPI SetCaretBlinkTime( UINT msecs )
394 TRACE("msecs=%d\n", msecs);
396 Caret.timeout = msecs;
397 /* if (Caret.hwnd) CARET_SetTimer(); FIXME */
402 /*****************************************************************
403 * GetCaretBlinkTime (USER32.@)
405 UINT WINAPI GetCaretBlinkTime(void)
407 return Caret.timeout;