kernel32: Update version to Win 10.
[wine.git] / dlls / user32 / caret.c
blob2da7e02ca1a69e8c74ae8f4855edc17ca1f1b7d3
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 <stdarg.h>
26 #include "windef.h"
27 #include "winbase.h"
28 #include "wingdi.h"
29 #include "winuser.h"
30 #include "wine/server.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(caret);
35 typedef struct
37 HBITMAP hBmp;
38 UINT timeout;
39 } CARET;
41 static CARET Caret = { 0, 500 };
43 #define TIMERID 0xffff /* system timer id for the caret */
46 /*****************************************************************
47 * CARET_DisplayCaret
49 static void CARET_DisplayCaret( HWND hwnd, const RECT *r )
51 HDC hdc;
52 HDC hCompDC;
54 /* do not use DCX_CACHE here, for x,y,width,height are in logical units */
55 if (!(hdc = GetDCEx( hwnd, 0, DCX_USESTYLE /*| DCX_CACHE*/ ))) return;
56 hCompDC = CreateCompatibleDC(hdc);
57 if (hCompDC)
59 HBITMAP hPrevBmp;
61 hPrevBmp = SelectObject(hCompDC, Caret.hBmp);
62 BitBlt(hdc, r->left, r->top, r->right-r->left, r->bottom-r->top, hCompDC, 0, 0, SRCINVERT);
63 SelectObject(hCompDC, hPrevBmp);
64 DeleteDC(hCompDC);
66 ReleaseDC( hwnd, hdc );
70 /*****************************************************************
71 * CARET_Callback
73 static void CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT_PTR id, DWORD ctime)
75 BOOL ret;
76 RECT r;
77 int hidden = 0;
79 SERVER_START_REQ( set_caret_info )
81 req->flags = SET_CARET_STATE;
82 req->handle = wine_server_user_handle( hwnd );
83 req->x = 0;
84 req->y = 0;
85 req->hide = 0;
86 req->state = CARET_STATE_TOGGLE;
87 if ((ret = !wine_server_call( req )))
89 hwnd = wine_server_ptr_handle( reply->full_handle );
90 r.left = reply->old_rect.left;
91 r.top = reply->old_rect.top;
92 r.right = reply->old_rect.right;
93 r.bottom = reply->old_rect.bottom;
94 hidden = reply->old_hide;
97 SERVER_END_REQ;
99 if (ret && !hidden) CARET_DisplayCaret( hwnd, &r );
103 /*****************************************************************
104 * CreateCaret (USER32.@)
106 BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap, INT width, INT height )
108 BOOL ret;
109 RECT r;
110 int old_state = 0;
111 int hidden = 0;
112 HBITMAP hBmp = 0;
113 HWND prev = 0;
115 TRACE("hwnd=%p\n", hwnd);
117 if (!hwnd) return FALSE;
119 if (bitmap && (bitmap != (HBITMAP)1))
121 BITMAP bmp;
122 if (!GetObjectA( bitmap, sizeof(bmp), &bmp )) return FALSE;
123 width = bmp.bmWidth;
124 height = bmp.bmHeight;
125 bmp.bmBits = NULL;
126 hBmp = CreateBitmapIndirect(&bmp);
127 if (hBmp)
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);
136 else
138 HDC hdc;
140 if (!width) width = GetSystemMetrics(SM_CXBORDER);
141 if (!height) height = GetSystemMetrics(SM_CYBORDER);
143 /* create the uniform bitmap on the fly */
144 hdc = GetDC(hwnd);
145 if (hdc)
147 HDC hMemDC = CreateCompatibleDC(hdc);
148 if (hMemDC)
150 if ((hBmp = CreateCompatibleBitmap(hMemDC, width, height )))
152 HBITMAP hPrevBmp = SelectObject(hMemDC, hBmp);
153 SetRect( &r, 0, 0, width, height );
154 FillRect(hMemDC, &r, bitmap ? GetStockObject(GRAY_BRUSH) : GetStockObject(WHITE_BRUSH));
155 SelectObject(hMemDC, hPrevBmp);
157 DeleteDC(hMemDC);
159 ReleaseDC(hwnd, hdc);
162 if (!hBmp) return FALSE;
164 SERVER_START_REQ( set_caret_window )
166 req->handle = wine_server_user_handle( hwnd );
167 req->width = width;
168 req->height = height;
169 if ((ret = !wine_server_call_err( req )))
171 prev = wine_server_ptr_handle( 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;
180 SERVER_END_REQ;
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 );
191 Caret.hBmp = hBmp;
192 Caret.timeout = GetProfileIntA( "windows", "CursorBlinkRate", 500 );
193 return TRUE;
197 /*****************************************************************
198 * DestroyCaret (USER32.@)
200 BOOL WINAPI DestroyCaret(void)
202 BOOL ret;
203 HWND prev = 0;
204 RECT r;
205 int old_state = 0;
206 int hidden = 0;
208 SERVER_START_REQ( set_caret_window )
210 req->handle = 0;
211 req->width = 0;
212 req->height = 0;
213 if ((ret = !wine_server_call_err( req )))
215 prev = wine_server_ptr_handle( 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;
224 SERVER_END_REQ;
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 );
233 Caret.hBmp = 0;
234 return ret;
238 /*****************************************************************
239 * SetCaretPos (USER32.@)
241 BOOL WINAPI SetCaretPos( INT x, INT y )
243 BOOL ret;
244 HWND hwnd = 0;
245 RECT r;
246 int old_state = 0;
247 int hidden = 0;
249 SERVER_START_REQ( set_caret_info )
251 req->flags = SET_CARET_POS|SET_CARET_STATE;
252 req->handle = 0;
253 req->x = x;
254 req->y = y;
255 req->hide = 0;
256 req->state = CARET_STATE_ON_IF_MOVED;
257 if ((ret = !wine_server_call_err( req )))
259 hwnd = wine_server_ptr_handle( 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;
268 SERVER_END_REQ;
269 if (ret && !hidden && (x != r.left || y != r.top))
271 if (old_state) CARET_DisplayCaret( hwnd, &r );
272 r.right += x - r.left;
273 r.bottom += y - r.top;
274 r.left = x;
275 r.top = y;
276 CARET_DisplayCaret( hwnd, &r );
277 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
279 return ret;
283 /*****************************************************************
284 * HideCaret (USER32.@)
286 BOOL WINAPI HideCaret( HWND hwnd )
288 BOOL ret;
289 RECT r;
290 int old_state = 0;
291 int hidden = 0;
293 SERVER_START_REQ( set_caret_info )
295 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
296 req->handle = wine_server_user_handle( hwnd );
297 req->x = 0;
298 req->y = 0;
299 req->hide = 1;
300 req->state = CARET_STATE_OFF;
301 if ((ret = !wine_server_call_err( req )))
303 hwnd = wine_server_ptr_handle( 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;
312 SERVER_END_REQ;
314 if (ret && !hidden)
316 if (old_state) CARET_DisplayCaret( hwnd, &r );
317 KillSystemTimer( hwnd, TIMERID );
319 return ret;
323 /*****************************************************************
324 * ShowCaret (USER32.@)
326 BOOL WINAPI ShowCaret( HWND hwnd )
328 BOOL ret;
329 RECT r;
330 int hidden = 0;
332 SERVER_START_REQ( set_caret_info )
334 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
335 req->handle = wine_server_user_handle( hwnd );
336 req->x = 0;
337 req->y = 0;
338 req->hide = -1;
339 req->state = CARET_STATE_ON;
340 if ((ret = !wine_server_call_err( req )))
342 hwnd = wine_server_ptr_handle( reply->full_handle );
343 r.left = reply->old_rect.left;
344 r.top = reply->old_rect.top;
345 r.right = reply->old_rect.right;
346 r.bottom = reply->old_rect.bottom;
347 hidden = reply->old_hide;
350 SERVER_END_REQ;
352 if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */
354 CARET_DisplayCaret( hwnd, &r );
355 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
357 return ret;
361 /*****************************************************************
362 * GetCaretPos (USER32.@)
364 BOOL WINAPI GetCaretPos( LPPOINT pt )
366 BOOL ret;
368 SERVER_START_REQ( set_caret_info )
370 req->flags = 0; /* don't set anything */
371 req->handle = 0;
372 req->x = 0;
373 req->y = 0;
374 req->hide = 0;
375 req->state = 0;
376 if ((ret = !wine_server_call_err( req )))
378 pt->x = reply->old_rect.left;
379 pt->y = reply->old_rect.top;
382 SERVER_END_REQ;
383 return ret;
387 /*****************************************************************
388 * SetCaretBlinkTime (USER32.@)
390 BOOL WINAPI SetCaretBlinkTime( UINT msecs )
392 TRACE("msecs=%d\n", msecs);
394 Caret.timeout = msecs;
395 /* if (Caret.hwnd) CARET_SetTimer(); FIXME */
396 return TRUE;
400 /*****************************************************************
401 * GetCaretBlinkTime (USER32.@)
403 UINT WINAPI GetCaretBlinkTime(void)
405 return Caret.timeout;