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
30 #include "wine/server.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(caret);
41 static CARET Caret = { 0, 500 };
43 #define TIMERID 0xffff /* system timer id for the caret */
46 /*****************************************************************
49 static void CARET_DisplayCaret( HWND hwnd, const RECT *r )
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);
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);
66 ReleaseDC( hwnd, hdc );
70 /*****************************************************************
73 static void CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT id, DWORD ctime)
80 SERVER_START_REQ( set_caret_info )
82 req->flags = SET_CARET_STATE;
87 req->state = -1; /* toggle current state */
88 if ((ret = !wine_server_call( req )))
90 hwnd = reply->full_handle;
91 r.left = reply->old_rect.left;
92 r.top = reply->old_rect.top;
93 r.right = reply->old_rect.right;
94 r.bottom = reply->old_rect.bottom;
95 old_state = reply->old_state;
96 hidden = reply->old_hide;
101 if (ret && !hidden) CARET_DisplayCaret( hwnd, &r );
105 /*****************************************************************
106 * CreateCaret (USER32.@)
108 BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap, INT width, INT height )
117 TRACE("hwnd=%p\n", hwnd);
119 if (!hwnd) return FALSE;
121 if (bitmap && (bitmap != (HBITMAP)1))
124 if (!GetObjectA( bitmap, sizeof(bmp), &bmp )) return FALSE;
126 height = bmp.bmHeight;
128 hBmp = CreateBitmapIndirect(&bmp);
131 /* copy the bitmap */
132 LPBYTE buf = HeapAlloc(GetProcessHeap(), 0, bmp.bmWidthBytes * bmp.bmHeight);
133 GetBitmapBits(bitmap, bmp.bmWidthBytes * bmp.bmHeight, buf);
134 SetBitmapBits(hBmp, bmp.bmWidthBytes * bmp.bmHeight, buf);
135 HeapFree(GetProcessHeap(), 0, buf);
142 if (!width) width = GetSystemMetrics(SM_CXBORDER);
143 if (!height) height = GetSystemMetrics(SM_CYBORDER);
145 /* create the uniform bitmap on the fly */
149 HDC hMemDC = CreateCompatibleDC(hdc);
152 if ((hBmp = CreateCompatibleBitmap(hMemDC, width, height )))
154 HBITMAP hPrevBmp = SelectObject(hMemDC, hBmp);
155 SetRect( &r, 0, 0, width, height );
156 FillRect(hMemDC, &r, (HBRUSH)((bitmap ? COLOR_GRAYTEXT : COLOR_WINDOW) + 1));
157 SelectObject(hMemDC, hPrevBmp);
161 ReleaseDC(hwnd, hdc);
164 if (!hBmp) return FALSE;
166 SERVER_START_REQ( set_caret_window )
170 req->height = height;
171 if ((ret = !wine_server_call_err( req )))
173 prev = reply->previous;
174 r.left = reply->old_rect.left;
175 r.top = reply->old_rect.top;
176 r.right = reply->old_rect.right;
177 r.bottom = reply->old_rect.bottom;
178 old_state = reply->old_state;
179 hidden = reply->old_hide;
183 if (!ret) return FALSE;
185 if (prev && !hidden) /* hide the previous one */
187 /* FIXME: won't work if prev belongs to a different process */
188 KillSystemTimer( prev, TIMERID );
189 if (old_state) CARET_DisplayCaret( prev, &r );
192 if (Caret.hBmp) DeleteObject( Caret.hBmp );
194 Caret.timeout = GetProfileIntA( "windows", "CursorBlinkRate", 500 );
199 /*****************************************************************
200 * DestroyCaret (USER32.@)
202 BOOL WINAPI DestroyCaret(void)
210 SERVER_START_REQ( set_caret_window )
215 if ((ret = !wine_server_call_err( req )))
217 prev = reply->previous;
218 r.left = reply->old_rect.left;
219 r.top = reply->old_rect.top;
220 r.right = reply->old_rect.right;
221 r.bottom = reply->old_rect.bottom;
222 old_state = reply->old_state;
223 hidden = reply->old_hide;
228 if (ret && prev && !hidden)
230 /* FIXME: won't work if prev belongs to a different process */
231 KillSystemTimer( prev, TIMERID );
232 if (old_state) CARET_DisplayCaret( prev, &r );
234 if (Caret.hBmp) DeleteObject( Caret.hBmp );
240 /*****************************************************************
241 * SetCaretPos (USER32.@)
243 BOOL WINAPI SetCaretPos( INT x, INT y )
251 SERVER_START_REQ( set_caret_info )
253 req->flags = SET_CARET_POS|SET_CARET_STATE;
259 if ((ret = !wine_server_call_err( req )))
261 hwnd = reply->full_handle;
262 r.left = reply->old_rect.left;
263 r.top = reply->old_rect.top;
264 r.right = reply->old_rect.right;
265 r.bottom = reply->old_rect.bottom;
266 old_state = reply->old_state;
267 hidden = reply->old_hide;
273 if (old_state) CARET_DisplayCaret( hwnd, &r );
274 r.right += x - r.left;
275 r.bottom += y - r.top;
278 CARET_DisplayCaret( hwnd, &r );
279 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
285 /*****************************************************************
286 * HideCaret (USER32.@)
288 BOOL WINAPI HideCaret( HWND hwnd )
295 SERVER_START_REQ( set_caret_info )
297 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
303 if ((ret = !wine_server_call_err( req )))
305 hwnd = reply->full_handle;
306 r.left = reply->old_rect.left;
307 r.top = reply->old_rect.top;
308 r.right = reply->old_rect.right;
309 r.bottom = reply->old_rect.bottom;
310 old_state = reply->old_state;
311 hidden = reply->old_hide;
318 if (old_state) CARET_DisplayCaret( hwnd, &r );
319 KillSystemTimer( hwnd, TIMERID );
325 /*****************************************************************
326 * ShowCaret (USER32.@)
328 BOOL WINAPI ShowCaret( HWND hwnd )
335 SERVER_START_REQ( set_caret_info )
337 req->flags = SET_CARET_HIDE|SET_CARET_STATE;
343 if ((ret = !wine_server_call_err( req )))
345 hwnd = 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 old_state = reply->old_state;
351 hidden = reply->old_hide;
356 if (ret && (hidden == 1)) /* hidden was 1 so it's now 0 */
358 CARET_DisplayCaret( hwnd, &r );
359 SetSystemTimer( hwnd, TIMERID, Caret.timeout, CARET_Callback );
365 /*****************************************************************
366 * GetCaretPos (USER32.@)
368 BOOL WINAPI GetCaretPos( LPPOINT pt )
372 SERVER_START_REQ( set_caret_info )
374 req->flags = 0; /* don't set anything */
380 if ((ret = !wine_server_call_err( req )))
382 pt->x = reply->old_rect.left;
383 pt->y = reply->old_rect.top;
391 /*****************************************************************
392 * SetCaretBlinkTime (USER32.@)
394 BOOL WINAPI SetCaretBlinkTime( UINT msecs )
396 TRACE("msecs=%d\n", msecs);
398 Caret.timeout = msecs;
399 /* if (Caret.hwnd) CARET_SetTimer(); FIXME */
404 /*****************************************************************
405 * GetCaretBlinkTime (USER32.@)
407 UINT WINAPI GetCaretBlinkTime(void)
409 return Caret.timeout;