1 /*
2 * Caret functions
3 *
4 * Copyright 1993 David Metcalfe
5 * Copyright 1996 Frans van Dorsselaer
6 * Copyright 2001 Eric Pouech
7 * Copyright 2002 Alexandre Julliard
8 *
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.
13 *
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.
18 *
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
22 */
23
24 #include "config.h"
25 #include "wine/port.h"
26
27 #include <stdarg.h>
28
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"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(caret);
37
38 typedef struct
39 {
40 HBITMAP hBmp;
41 UINT timeout;
42 } CARET;
43
44 static CARET Caret = { 0, 500 };
45
46 #define TIMERID 0xffff /* system timer id for the caret */
47
48
49 /*****************************************************************
50 * CARET_DisplayCaret
51 */
52 static void CARET_DisplayCaret( HWND hwnd, const RECT *r )
53 {
54 HDC hdc;
55 HDC hCompDC;
56
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)
61 {
62 HBITMAP hPrevBmp;
63
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);
68 }
69 ReleaseDC( hwnd, hdc );
70 }
71
72
73 /*****************************************************************
74 * CARET_Callback
75 */
76 static void CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT_PTR id, DWORD ctime)
77 {
78 BOOL ret;
79 RECT r;
80 int hidden = 0;
81
82 SERVER_START_REQ( set_caret_info )
83 {
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 )))
91 {
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;
98 }
99 }
100 SERVER_END_REQ;
101
102 if (ret && !hidden) CARET_DisplayCaret( hwnd, &r );
103 }
104
105
106 /*****************************************************************
107 * CreateCaret (USER32.@)
108 */
109 BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap, INT width, INT height )
110 {
111 BOOL ret;
112 RECT r;
113 int old_state = 0;
114 int hidden = 0;
115 HBITMAP hBmp = 0;
116 HWND prev = 0;
117
118 TRACE("hwnd=%p\n", hwnd);
119
120 if (!hwnd) return FALSE;
121
122 if (bitmap && (bitmap != (HBITMAP)1))
123 {
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)
131 {
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);
137 }
138 }
139 else
140 {
141 HDC hdc;
142
143 if (!width) width = GetSystemMetrics(SM_CXBORDER);
144 if (!height) height = GetSystemMetrics(SM_CYBORDER);
145
146 /* create the uniform bitmap on the fly */
147 hdc = GetDC(hwnd);
148 if (hdc)
149 {
150 HDC hMemDC = CreateCompatibleDC(hdc);
151 if (hMemDC)
152 {
153 if ((hBmp = CreateCompatibleBitmap(hMemDC, width, height )))
154 {
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);
159 }
160 DeleteDC(hMemDC);
161 }
162 ReleaseDC(hwnd, hdc);
163 }
164 }
165 if (!hBmp) return FALSE;
166
167 SERVER_START_REQ( set_caret_window )
168 {
169 req->handle = wine_server_user_handle( hwnd );
170 req->width = width;
171 req->height = height;
172 if ((ret = !wine_server_call_err( req )))
173 {
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;
181 }
182 }
183 SERVER_END_REQ;
184 if (!ret) return FALSE;
185
186 if (prev && !hidden) /* hide the previous one */
187 {
188 /* FIXME: won't work if prev belongs to a different process */
189 KillSystemTimer( prev, TIMERID );
190 if (old_state) CARET_DisplayCaret( prev, &r );
191 }
192
193 if (Caret.hBmp) DeleteObject( Caret.hBmp );
194 Caret.hBmp = hBmp;
195 Caret.timeout = GetProfileIntA( "windows", "CursorBlinkRate", 500 );
196 return TRUE;
197 }
198
199
200 /*****************************************************************
201 * DestroyCaret (USER32.@)
202 */
203 BOOL WINAPI DestroyCaret(void)
204 {
205 BOOL ret;
206 HWND prev = 0;
207 RECT r;
208 int old_state = 0;
209 int hidden = 0;
210
211 SERVER_START_REQ( set_caret_window )
212 {
213 req->handle = 0;
214 req->width = 0;
215 req->height = 0;
216 if ((ret = !wine_server_call_err( req )))
217 {
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;
225 }
226 }
227 SERVER_END_REQ;
228
229 if (ret && prev && !hidden)
230 {
231 /* FIXME: won't work if prev belongs to a different process */
232 KillSystemTimer( prev, TIMERID );
233 if (old_state) CARET_DisplayCaret( prev, &r );
234 }
235 if (Caret.hBmp) DeleteObject( Caret.hBmp );
236 Caret.hBmp = 0;
237 return ret;
238 }
239
240
241 /*****************************************************************
242 * SetCaretPos (USER32.@)
243 */
244 BOOL WINAPI SetCaretPos( INT x, INT y )
245 {
246 BOOL ret;
247 HWND hwnd = 0;
248 RECT r;
249 int old_state = 0;
250 int hidden = 0;
251
252 SERVER_START_REQ( set_caret_info )
253 {
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 )))
261 {
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;
269 }
270 }
271 SERVER_END_REQ;
272 if (ret && !hidden && (x != r.left || y != r.top))
273 {
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 );
281 }
282 return ret;
283 }
284
285
286 /*****************************************************************
287 * HideCaret (USER32.@)
288 */
289 BOOL WINAPI HideCaret( HWND hwnd )
290 {
291 BOOL ret;
292 RECT r;
293 int old_state = 0;
294 int hidden = 0;
295
296 SERVER_START_REQ( set_caret_info )
297 {
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 )))
305 {
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;
313 }
314 }
315 SERVER_END_REQ;
316
317 if (ret && !hidden)
318 {
319 if (old_state) CARET_DisplayCaret( hwnd, &r );
320 KillSystemTimer( hwnd, TIMERID );
321 }
322 return ret;
323 }
324
325
326 /*****************************************************************
327 * ShowCaret (USER32.@)
328 */
329 BOOL WINAPI ShowCaret( HWND hwnd )
330 {
331 BOOL ret;
332 RECT r;
333 int hidden = 0;
334
335 SERVER_START_REQ( set_caret_info )
336 {
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 )))
344 {
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;
351 }
352 }
353 SERVER_END_REQ;
354
355 if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */
356 {
357 CARET_DisplayCaret( hwnd, &r );
358 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
359 }
360 return ret;
361 }
362
363
364 /*****************************************************************
365 * GetCaretPos (USER32.@)
366 */
367 BOOL WINAPI GetCaretPos( LPPOINT pt )
368 {
369 BOOL ret;
370
371 SERVER_START_REQ( set_caret_info )
372 {
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 )))
380 {
381 pt->x = reply->old_rect.left;
382 pt->y = reply->old_rect.top;
383 }
384 }
385 SERVER_END_REQ;
386 return ret;
387 }
388
389
390 /*****************************************************************
391 * SetCaretBlinkTime (USER32.@)
392 */
393 BOOL WINAPI SetCaretBlinkTime( UINT msecs )
394 {
395 TRACE("msecs=%d\n", msecs);
396
397 Caret.timeout = msecs;
398 /* if (Caret.hwnd) CARET_SetTimer(); FIXME */
399 return TRUE;
400 }
401
402
403 /*****************************************************************
404 * GetCaretBlinkTime (USER32.@)
405 */
406 UINT WINAPI GetCaretBlinkTime(void)
407 {
408 return Caret.timeout;
409 }
410
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.