Moved some more 16-bit functions to user16.c.
[wine/multimedia.git] / dlls / user / caret.c
blob0d14194db428702a98f399e2994c2e6b33f78a76
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 #include "windef.h"
25 #include "winbase.h"
26 #include "wingdi.h"
27 #include "winuser.h"
28 #include "wine/server.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(caret);
33 typedef struct
35 HBITMAP hBmp;
36 UINT timeout;
37 } CARET;
39 static CARET Caret = { 0, 500 };
41 #define TIMERID 0xffff /* system timer id for the caret */
44 /*****************************************************************
45 * CARET_DisplayCaret
47 static void CARET_DisplayCaret( HWND hwnd, const RECT *r )
49 HDC hdc;
50 HDC hCompDC;
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);
55 if (hCompDC)
57 HBITMAP hPrevBmp;
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);
62 DeleteDC(hCompDC);
64 ReleaseDC( hwnd, hdc );
68 /*****************************************************************
69 * CARET_Callback
71 static void CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT id, DWORD ctime)
73 BOOL ret;
74 RECT r;
75 int old_state = 0;
76 int hidden = 0;
78 SERVER_START_REQ( set_caret_info )
80 req->flags = SET_CARET_STATE;
81 req->handle = hwnd;
82 req->x = 0;
83 req->y = 0;
84 req->hide = 0;
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;
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=%04x\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, (HBRUSH)((bitmap ? COLOR_GRAYTEXT : COLOR_WINDOW) + 1));
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 = hwnd;
167 req->width = width;
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;
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 = 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 = 1;
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;
268 SERVER_END_REQ;
269 if (ret && !hidden)
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 = hwnd;
297 req->x = 0;
298 req->y = 0;
299 req->hide = 1;
300 req->state = 0;
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;
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 old_state = 0;
331 int hidden = 0;
333 SERVER_START_REQ( set_caret_info )
335 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
336 req->handle = hwnd;
337 req->x = 0;
338 req->y = 0;
339 req->hide = -1;
340 req->state = 1;
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;
352 SERVER_END_REQ;
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 );
359 return ret;
363 /*****************************************************************
364 * GetCaretPos (USER32.@)
366 BOOL WINAPI GetCaretPos( LPPOINT pt )
368 BOOL ret;
370 SERVER_START_REQ( set_caret_info )
372 req->flags = 0; /* don't set anything */
373 req->handle = 0;
374 req->x = 0;
375 req->y = 0;
376 req->hide = 0;
377 req->state = 0;
378 if ((ret = !wine_server_call_err( req )))
380 pt->x = reply->old_rect.left;
381 pt->y = reply->old_rect.top;
384 SERVER_END_REQ;
385 return ret;
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 */
398 return TRUE;
402 /*****************************************************************
403 * GetCaretBlinkTime (USER32.@)
405 UINT WINAPI GetCaretBlinkTime(void)
407 return Caret.timeout;