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
)
83 SERVER_START_REQ( set_caret_info
)
85 req
->flags
= SET_CARET_STATE
;
90 req
->state
= -1; /* toggle current state */
91 if ((ret
= !wine_server_call( req
)))
93 hwnd
= reply
->full_handle
;
94 r
.left
= reply
->old_rect
.left
;
95 r
.top
= reply
->old_rect
.top
;
96 r
.right
= reply
->old_rect
.right
;
97 r
.bottom
= reply
->old_rect
.bottom
;
98 old_state
= reply
->old_state
;
99 hidden
= reply
->old_hide
;
104 if (ret
&& !hidden
) CARET_DisplayCaret( hwnd
, &r
);
108 /*****************************************************************
109 * CreateCaret (USER32.@)
111 BOOL WINAPI
CreateCaret( HWND hwnd
, HBITMAP bitmap
, INT width
, INT height
)
120 TRACE("hwnd=%p\n", hwnd
);
122 if (!hwnd
) return FALSE
;
124 if (bitmap
&& (bitmap
!= (HBITMAP
)1))
127 if (!GetObjectA( bitmap
, sizeof(bmp
), &bmp
)) return FALSE
;
129 height
= bmp
.bmHeight
;
131 hBmp
= CreateBitmapIndirect(&bmp
);
134 /* copy the bitmap */
135 LPBYTE buf
= HeapAlloc(GetProcessHeap(), 0, bmp
.bmWidthBytes
* bmp
.bmHeight
);
136 GetBitmapBits(bitmap
, bmp
.bmWidthBytes
* bmp
.bmHeight
, buf
);
137 SetBitmapBits(hBmp
, bmp
.bmWidthBytes
* bmp
.bmHeight
, buf
);
138 HeapFree(GetProcessHeap(), 0, buf
);
145 if (!width
) width
= GetSystemMetrics(SM_CXBORDER
);
146 if (!height
) height
= GetSystemMetrics(SM_CYBORDER
);
148 /* create the uniform bitmap on the fly */
152 HDC hMemDC
= CreateCompatibleDC(hdc
);
155 if ((hBmp
= CreateCompatibleBitmap(hMemDC
, width
, height
)))
157 HBITMAP hPrevBmp
= SelectObject(hMemDC
, hBmp
);
158 SetRect( &r
, 0, 0, width
, height
);
159 FillRect(hMemDC
, &r
, ULongToHandle((bitmap
? COLOR_GRAYTEXT
: COLOR_WINDOW
) + 1));
160 SelectObject(hMemDC
, hPrevBmp
);
164 ReleaseDC(hwnd
, hdc
);
167 if (!hBmp
) return FALSE
;
169 SERVER_START_REQ( set_caret_window
)
173 req
->height
= height
;
174 if ((ret
= !wine_server_call_err( req
)))
176 prev
= reply
->previous
;
177 r
.left
= reply
->old_rect
.left
;
178 r
.top
= reply
->old_rect
.top
;
179 r
.right
= reply
->old_rect
.right
;
180 r
.bottom
= reply
->old_rect
.bottom
;
181 old_state
= reply
->old_state
;
182 hidden
= reply
->old_hide
;
186 if (!ret
) return FALSE
;
188 if (prev
&& !hidden
) /* hide the previous one */
190 /* FIXME: won't work if prev belongs to a different process */
191 KillSystemTimer( prev
, TIMERID
);
192 if (old_state
) CARET_DisplayCaret( prev
, &r
);
195 if (Caret
.hBmp
) DeleteObject( Caret
.hBmp
);
197 Caret
.timeout
= GetProfileIntA( "windows", "CursorBlinkRate", 500 );
202 /*****************************************************************
203 * DestroyCaret (USER32.@)
205 BOOL WINAPI
DestroyCaret(void)
213 SERVER_START_REQ( set_caret_window
)
218 if ((ret
= !wine_server_call_err( req
)))
220 prev
= reply
->previous
;
221 r
.left
= reply
->old_rect
.left
;
222 r
.top
= reply
->old_rect
.top
;
223 r
.right
= reply
->old_rect
.right
;
224 r
.bottom
= reply
->old_rect
.bottom
;
225 old_state
= reply
->old_state
;
226 hidden
= reply
->old_hide
;
231 if (ret
&& prev
&& !hidden
)
233 /* FIXME: won't work if prev belongs to a different process */
234 KillSystemTimer( prev
, TIMERID
);
235 if (old_state
) CARET_DisplayCaret( prev
, &r
);
237 if (Caret
.hBmp
) DeleteObject( Caret
.hBmp
);
243 /*****************************************************************
244 * SetCaretPos (USER32.@)
246 BOOL WINAPI
SetCaretPos( INT x
, INT y
)
254 SERVER_START_REQ( set_caret_info
)
256 req
->flags
= SET_CARET_POS
|SET_CARET_STATE
;
262 if ((ret
= !wine_server_call_err( req
)))
264 hwnd
= reply
->full_handle
;
265 r
.left
= reply
->old_rect
.left
;
266 r
.top
= reply
->old_rect
.top
;
267 r
.right
= reply
->old_rect
.right
;
268 r
.bottom
= reply
->old_rect
.bottom
;
269 old_state
= reply
->old_state
;
270 hidden
= reply
->old_hide
;
276 if (old_state
) CARET_DisplayCaret( hwnd
, &r
);
277 r
.right
+= x
- r
.left
;
278 r
.bottom
+= y
- r
.top
;
281 CARET_DisplayCaret( hwnd
, &r
);
282 SetSystemTimer( hwnd
, TIMERID
, Caret
.timeout
, CARET_Callback
);
288 /*****************************************************************
289 * HideCaret (USER32.@)
291 BOOL WINAPI
HideCaret( HWND hwnd
)
298 SERVER_START_REQ( set_caret_info
)
300 req
->flags
= SET_CARET_HIDE
|SET_CARET_STATE
;
306 if ((ret
= !wine_server_call_err( req
)))
308 hwnd
= reply
->full_handle
;
309 r
.left
= reply
->old_rect
.left
;
310 r
.top
= reply
->old_rect
.top
;
311 r
.right
= reply
->old_rect
.right
;
312 r
.bottom
= reply
->old_rect
.bottom
;
313 old_state
= reply
->old_state
;
314 hidden
= reply
->old_hide
;
321 if (old_state
) CARET_DisplayCaret( hwnd
, &r
);
322 KillSystemTimer( hwnd
, TIMERID
);
328 /*****************************************************************
329 * ShowCaret (USER32.@)
331 BOOL WINAPI
ShowCaret( HWND hwnd
)
338 SERVER_START_REQ( set_caret_info
)
340 req
->flags
= SET_CARET_HIDE
|SET_CARET_STATE
;
346 if ((ret
= !wine_server_call_err( req
)))
348 hwnd
= reply
->full_handle
;
349 r
.left
= reply
->old_rect
.left
;
350 r
.top
= reply
->old_rect
.top
;
351 r
.right
= reply
->old_rect
.right
;
352 r
.bottom
= reply
->old_rect
.bottom
;
353 old_state
= reply
->old_state
;
354 hidden
= reply
->old_hide
;
359 if (ret
&& (hidden
== 1)) /* hidden was 1 so it's now 0 */
361 CARET_DisplayCaret( hwnd
, &r
);
362 SetSystemTimer( hwnd
, TIMERID
, Caret
.timeout
, CARET_Callback
);
368 /*****************************************************************
369 * GetCaretPos (USER32.@)
371 BOOL WINAPI
GetCaretPos( LPPOINT pt
)
375 SERVER_START_REQ( set_caret_info
)
377 req
->flags
= 0; /* don't set anything */
383 if ((ret
= !wine_server_call_err( req
)))
385 pt
->x
= reply
->old_rect
.left
;
386 pt
->y
= reply
->old_rect
.top
;
394 /*****************************************************************
395 * SetCaretBlinkTime (USER32.@)
397 BOOL WINAPI
SetCaretBlinkTime( UINT msecs
)
399 TRACE("msecs=%d\n", msecs
);
401 Caret
.timeout
= msecs
;
402 /* if (Caret.hwnd) CARET_SetTimer(); FIXME */
407 /*****************************************************************
408 * GetCaretBlinkTime (USER32.@)
410 UINT WINAPI
GetCaretBlinkTime(void)
412 return Caret
.timeout
;