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
25 #include "wine/port.h"
33 #include "wine/server.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(caret
);
44 static CARET Caret
= { 0, 500 };
46 #define TIMERID 0xffff /* system timer id for the caret */
49 /*****************************************************************
52 static void CARET_DisplayCaret( HWND hwnd
, const RECT
*r
)
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
);
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
);
69 ReleaseDC( hwnd
, hdc
);
73 /*****************************************************************
76 static void CALLBACK
CARET_Callback( HWND hwnd
, UINT msg
, UINT_PTR id
, DWORD ctime
)
82 SERVER_START_REQ( set_caret_info
)
84 req
->flags
= SET_CARET_STATE
;
85 req
->handle
= wine_server_user_handle( hwnd
);
89 req
->state
= CARET_STATE_TOGGLE
;
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
;
102 if (ret
&& !hidden
) CARET_DisplayCaret( hwnd
, &r
);
106 /*****************************************************************
107 * CreateCaret (USER32.@)
109 BOOL WINAPI
CreateCaret( HWND hwnd
, HBITMAP bitmap
, INT width
, INT height
)
118 TRACE("hwnd=%p\n", hwnd
);
120 if (!hwnd
) return FALSE
;
122 if (bitmap
&& (bitmap
!= (HBITMAP
)1))
125 if (!GetObjectA( bitmap
, sizeof(bmp
), &bmp
)) return FALSE
;
127 height
= bmp
.bmHeight
;
129 hBmp
= CreateBitmapIndirect(&bmp
);
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
);
143 if (!width
) width
= GetSystemMetrics(SM_CXBORDER
);
144 if (!height
) height
= GetSystemMetrics(SM_CYBORDER
);
146 /* create the uniform bitmap on the fly */
150 HDC hMemDC
= CreateCompatibleDC(hdc
);
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
);
162 ReleaseDC(hwnd
, hdc
);
165 if (!hBmp
) return FALSE
;
167 SERVER_START_REQ( set_caret_window
)
169 req
->handle
= wine_server_user_handle( hwnd
);
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
;
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
);
195 Caret
.timeout
= GetProfileIntA( "windows", "CursorBlinkRate", 500 );
200 /*****************************************************************
201 * DestroyCaret (USER32.@)
203 BOOL WINAPI
DestroyCaret(void)
211 SERVER_START_REQ( set_caret_window
)
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
;
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
);
241 /*****************************************************************
242 * SetCaretPos (USER32.@)
244 BOOL WINAPI
SetCaretPos( INT x
, INT y
)
252 SERVER_START_REQ( set_caret_info
)
254 req
->flags
= SET_CARET_POS
|SET_CARET_STATE
;
259 req
->state
= CARET_STATE_ON_IF_MOVED
;
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
;
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
;
279 CARET_DisplayCaret( hwnd
, &r
);
280 SetSystemTimer( hwnd
, TIMERID
, Caret
.timeout
, CARET_Callback
);
286 /*****************************************************************
287 * HideCaret (USER32.@)
289 BOOL WINAPI
HideCaret( HWND hwnd
)
296 SERVER_START_REQ( set_caret_info
)
298 req
->flags
= SET_CARET_HIDE
|SET_CARET_STATE
;
299 req
->handle
= wine_server_user_handle( hwnd
);
303 req
->state
= CARET_STATE_OFF
;
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
;
319 if (old_state
) CARET_DisplayCaret( hwnd
, &r
);
320 KillSystemTimer( hwnd
, TIMERID
);
326 /*****************************************************************
327 * ShowCaret (USER32.@)
329 BOOL WINAPI
ShowCaret( HWND hwnd
)
335 SERVER_START_REQ( set_caret_info
)
337 req
->flags
= SET_CARET_HIDE
|SET_CARET_STATE
;
338 req
->handle
= wine_server_user_handle( hwnd
);
342 req
->state
= CARET_STATE_ON
;
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
;
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
);
364 /*****************************************************************
365 * GetCaretPos (USER32.@)
367 BOOL WINAPI
GetCaretPos( LPPOINT pt
)
371 SERVER_START_REQ( set_caret_info
)
373 req
->flags
= 0; /* don't set anything */
379 if ((ret
= !wine_server_call_err( req
)))
381 pt
->x
= reply
->old_rect
.left
;
382 pt
->y
= reply
->old_rect
.top
;
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 */
403 /*****************************************************************
404 * GetCaretBlinkTime (USER32.@)
406 UINT WINAPI
GetCaretBlinkTime(void)
408 return Caret
.timeout
;