Release 1.7.42.
[wine.git] / dlls / user32 / caret.c
blob53bb5b44f5e55562f1960c83de04f927f27f1dde
1 /*
2 * Caret functions
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "config.h"
25 #include "wine/port.h"
27 #include <stdarg.h>
29 #include "windef.h"
30 #include "winbase.h"
31 #include "wingdi.h"
32 #include "winuser.h"
33 #include "wine/server.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(caret);
38 typedef struct
40 HBITMAP hBmp;
41 UINT timeout;
42 } CARET;
44 static CARET Caret = { 0, 500 };
46 #define TIMERID 0xffff /* system timer id for the caret */
49 /*****************************************************************
50 * CARET_DisplayCaret
52 static void CARET_DisplayCaret( HWND hwnd, const RECT *r )
54 HDC hdc;
55 HDC hCompDC;
57 /* do not use DCX_CACHE here, for x,y,width,height are in logical units */
58 if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE /*| DCX_CACHE*/ ))) return;
59 hCompDC = CreateCompatibleDC(hdc);
60 if (hCompDC)
62 HBITMAP hPrevBmp;
64 hPrevBmp = SelectObject(hCompDC, Caret.hBmp);
65 BitBlt(hdc, r->left, r->top, r->right-r->left, r->bottom-r->top, hCompDC, 0, 0, SRCINVERT);
66 SelectObject(hCompDC, hPrevBmp);
67 DeleteDC(hCompDC);
69 ReleaseDC( hwnd, hdc );
73 /*****************************************************************
74 * CARET_Callback
76 static void CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT_PTR id, DWORD ctime)
78 BOOL ret;
79 RECT r;
80 int hidden = 0;
82 SERVER_START_REQ( set_caret_info )
84 req->flags = SET_CARET_STATE;
85 req->handle = wine_server_user_handle( hwnd );
86 req->x = 0;
87 req->y = 0;
88 req->hide = 0;
89 req->state = -1; /* toggle current state */
90 if ((ret = !wine_server_call( req )))
92 hwnd = wine_server_ptr_handle( reply->full_handle );
93 r.left = reply->old_rect.left;
94 r.top = reply->old_rect.top;
95 r.right = reply->old_rect.right;
96 r.bottom = reply->old_rect.bottom;
97 hidden = reply->old_hide;
100 SERVER_END_REQ;
102 if (ret && !hidden) CARET_DisplayCaret( hwnd, &r );
106 /*****************************************************************
107 * CreateCaret (USER32.@)
109 BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap, INT width, INT height )
111 BOOL ret;
112 RECT r;
113 int old_state = 0;
114 int hidden = 0;
115 HBITMAP hBmp = 0;
116 HWND prev = 0;
118 TRACE("hwnd=%p\n", hwnd);
120 if (!hwnd) return FALSE;
122 if (bitmap && (bitmap != (HBITMAP)1))
124 BITMAP bmp;
125 if (!GetObjectA( bitmap, sizeof(bmp), &bmp )) return FALSE;
126 width = bmp.bmWidth;
127 height = bmp.bmHeight;
128 bmp.bmBits = NULL;
129 hBmp = CreateBitmapIndirect(&bmp);
130 if (hBmp)
132 /* copy the bitmap */
133 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, bmp.bmWidthBytes * bmp.bmHeight);
134 GetBitmapBits(bitmap, bmp.bmWidthBytes * bmp.bmHeight, buf);
135 SetBitmapBits(hBmp, bmp.bmWidthBytes * bmp.bmHeight, buf);
136 HeapFree(GetProcessHeap(), 0, buf);
139 else
141 HDC hdc;
143 if (!width) width = GetSystemMetrics(SM_CXBORDER);
144 if (!height) height = GetSystemMetrics(SM_CYBORDER);
146 /* create the uniform bitmap on the fly */
147 hdc = GetDC(hwnd);
148 if (hdc)
150 HDC hMemDC = CreateCompatibleDC(hdc);
151 if (hMemDC)
153 if ((hBmp = CreateCompatibleBitmap(hMemDC, width, height )))
155 HBITMAP hPrevBmp = SelectObject(hMemDC, hBmp);
156 SetRect( &r, 0, 0, width, height );
157 FillRect(hMemDC, &r, bitmap ? GetStockObject(GRAY_BRUSH) : GetStockObject(WHITE_BRUSH));
158 SelectObject(hMemDC, hPrevBmp);
160 DeleteDC(hMemDC);
162 ReleaseDC(hwnd, hdc);
165 if (!hBmp) return FALSE;
167 SERVER_START_REQ( set_caret_window )
169 req->handle = wine_server_user_handle( hwnd );
170 req->width = width;
171 req->height = height;
172 if ((ret = !wine_server_call_err( req )))
174 prev = wine_server_ptr_handle( reply->previous );
175 r.left = reply->old_rect.left;
176 r.top = reply->old_rect.top;
177 r.right = reply->old_rect.right;
178 r.bottom = reply->old_rect.bottom;
179 old_state = reply->old_state;
180 hidden = reply->old_hide;
183 SERVER_END_REQ;
184 if (!ret) return FALSE;
186 if (prev && !hidden) /* hide the previous one */
188 /* FIXME: won't work if prev belongs to a different process */
189 KillSystemTimer( prev, TIMERID );
190 if (old_state) CARET_DisplayCaret( prev, &r );
193 if (Caret.hBmp) DeleteObject( Caret.hBmp );
194 Caret.hBmp = hBmp;
195 Caret.timeout = GetProfileIntA( "windows", "CursorBlinkRate", 500 );
196 return TRUE;
200 /*****************************************************************
201 * DestroyCaret (USER32.@)
203 BOOL WINAPI DestroyCaret(void)
205 BOOL ret;
206 HWND prev = 0;
207 RECT r;
208 int old_state = 0;
209 int hidden = 0;
211 SERVER_START_REQ( set_caret_window )
213 req->handle = 0;
214 req->width = 0;
215 req->height = 0;
216 if ((ret = !wine_server_call_err( req )))
218 prev = wine_server_ptr_handle( reply->previous );
219 r.left = reply->old_rect.left;
220 r.top = reply->old_rect.top;
221 r.right = reply->old_rect.right;
222 r.bottom = reply->old_rect.bottom;
223 old_state = reply->old_state;
224 hidden = reply->old_hide;
227 SERVER_END_REQ;
229 if (ret && prev && !hidden)
231 /* FIXME: won't work if prev belongs to a different process */
232 KillSystemTimer( prev, TIMERID );
233 if (old_state) CARET_DisplayCaret( prev, &r );
235 if (Caret.hBmp) DeleteObject( Caret.hBmp );
236 Caret.hBmp = 0;
237 return ret;
241 /*****************************************************************
242 * SetCaretPos (USER32.@)
244 BOOL WINAPI SetCaretPos( INT x, INT y )
246 BOOL ret;
247 HWND hwnd = 0;
248 RECT r;
249 int old_state = 0;
250 int hidden = 0;
252 SERVER_START_REQ( set_caret_info )
254 req->flags = SET_CARET_POS|SET_CARET_STATE;
255 req->handle = 0;
256 req->x = x;
257 req->y = y;
258 req->hide = 0;
259 req->state = 1;
260 if ((ret = !wine_server_call_err( req )))
262 hwnd = wine_server_ptr_handle( reply->full_handle );
263 r.left = reply->old_rect.left;
264 r.top = reply->old_rect.top;
265 r.right = reply->old_rect.right;
266 r.bottom = reply->old_rect.bottom;
267 old_state = reply->old_state;
268 hidden = reply->old_hide;
271 SERVER_END_REQ;
272 if (ret && !hidden && (x != r.left || y != r.top))
274 if (old_state) CARET_DisplayCaret( hwnd, &r );
275 r.right += x - r.left;
276 r.bottom += y - r.top;
277 r.left = x;
278 r.top = y;
279 CARET_DisplayCaret( hwnd, &r );
280 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
282 return ret;
286 /*****************************************************************
287 * HideCaret (USER32.@)
289 BOOL WINAPI HideCaret( HWND hwnd )
291 BOOL ret;
292 RECT r;
293 int old_state = 0;
294 int hidden = 0;
296 SERVER_START_REQ( set_caret_info )
298 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
299 req->handle = wine_server_user_handle( hwnd );
300 req->x = 0;
301 req->y = 0;
302 req->hide = 1;
303 req->state = 0;
304 if ((ret = !wine_server_call_err( req )))
306 hwnd = wine_server_ptr_handle( reply->full_handle );
307 r.left = reply->old_rect.left;
308 r.top = reply->old_rect.top;
309 r.right = reply->old_rect.right;
310 r.bottom = reply->old_rect.bottom;
311 old_state = reply->old_state;
312 hidden = reply->old_hide;
315 SERVER_END_REQ;
317 if (ret && !hidden)
319 if (old_state) CARET_DisplayCaret( hwnd, &r );
320 KillSystemTimer( hwnd, TIMERID );
322 return ret;
326 /*****************************************************************
327 * ShowCaret (USER32.@)
329 BOOL WINAPI ShowCaret( HWND hwnd )
331 BOOL ret;
332 RECT r;
333 int hidden = 0;
335 SERVER_START_REQ( set_caret_info )
337 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
338 req->handle = wine_server_user_handle( hwnd );
339 req->x = 0;
340 req->y = 0;
341 req->hide = -1;
342 req->state = 1;
343 if ((ret = !wine_server_call_err( req )))
345 hwnd = wine_server_ptr_handle( reply->full_handle );
346 r.left = reply->old_rect.left;
347 r.top = reply->old_rect.top;
348 r.right = reply->old_rect.right;
349 r.bottom = reply->old_rect.bottom;
350 hidden = reply->old_hide;
353 SERVER_END_REQ;
355 if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */
357 CARET_DisplayCaret( hwnd, &r );
358 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
360 return ret;
364 /*****************************************************************
365 * GetCaretPos (USER32.@)
367 BOOL WINAPI GetCaretPos( LPPOINT pt )
369 BOOL ret;
371 SERVER_START_REQ( set_caret_info )
373 req->flags = 0; /* don't set anything */
374 req->handle = 0;
375 req->x = 0;
376 req->y = 0;
377 req->hide = 0;
378 req->state = 0;
379 if ((ret = !wine_server_call_err( req )))
381 pt->x = reply->old_rect.left;
382 pt->y = reply->old_rect.top;
385 SERVER_END_REQ;
386 return ret;
390 /*****************************************************************
391 * SetCaretBlinkTime (USER32.@)
393 BOOL WINAPI SetCaretBlinkTime( UINT msecs )
395 TRACE("msecs=%d\n", msecs);
397 Caret.timeout = msecs;
398 /* if (Caret.hwnd) CARET_SetTimer(); FIXME */
399 return TRUE;
403 /*****************************************************************
404 * GetCaretBlinkTime (USER32.@)
406 UINT WINAPI GetCaretBlinkTime(void)
408 return Caret.timeout;