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
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_PTR id
, DWORD ctime
)
79 SERVER_START_REQ( set_caret_info
)
81 req
->flags
= SET_CARET_STATE
;
82 req
->handle
= wine_server_user_handle( hwnd
);
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
;
99 if (ret
&& !hidden
) CARET_DisplayCaret( hwnd
, &r
);
103 /*****************************************************************
104 * CreateCaret (USER32.@)
106 BOOL WINAPI
CreateCaret( HWND hwnd
, HBITMAP bitmap
, INT width
, INT height
)
115 TRACE("hwnd=%p\n", hwnd
);
117 if (!hwnd
) return FALSE
;
119 if (bitmap
&& (bitmap
!= (HBITMAP
)1))
122 if (!GetObjectA( bitmap
, sizeof(bmp
), &bmp
)) return FALSE
;
124 height
= bmp
.bmHeight
;
126 hBmp
= CreateBitmapIndirect(&bmp
);
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
);
140 if (!width
) width
= GetSystemMetrics(SM_CXBORDER
);
141 if (!height
) height
= GetSystemMetrics(SM_CYBORDER
);
143 /* create the uniform bitmap on the fly */
147 HDC hMemDC
= CreateCompatibleDC(hdc
);
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
);
159 ReleaseDC(hwnd
, hdc
);
162 if (!hBmp
) return FALSE
;
164 SERVER_START_REQ( set_caret_window
)
166 req
->handle
= wine_server_user_handle( hwnd
);
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
;
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
);
192 Caret
.timeout
= GetProfileIntA( "windows", "CursorBlinkRate", 500 );
197 /*****************************************************************
198 * DestroyCaret (USER32.@)
200 BOOL WINAPI
DestroyCaret(void)
208 SERVER_START_REQ( set_caret_window
)
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
;
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
);
238 /*****************************************************************
239 * SetCaretPos (USER32.@)
241 BOOL WINAPI
SetCaretPos( INT x
, INT y
)
249 SERVER_START_REQ( set_caret_info
)
251 req
->flags
= SET_CARET_POS
|SET_CARET_STATE
;
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
;
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
;
276 CARET_DisplayCaret( hwnd
, &r
);
277 SetSystemTimer( hwnd
, TIMERID
, Caret
.timeout
, CARET_Callback
);
283 /*****************************************************************
284 * HideCaret (USER32.@)
286 BOOL WINAPI
HideCaret( HWND hwnd
)
293 SERVER_START_REQ( set_caret_info
)
295 req
->flags
= SET_CARET_HIDE
|SET_CARET_STATE
;
296 req
->handle
= wine_server_user_handle( hwnd
);
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
;
316 if (old_state
) CARET_DisplayCaret( hwnd
, &r
);
317 KillSystemTimer( hwnd
, TIMERID
);
323 /*****************************************************************
324 * ShowCaret (USER32.@)
326 BOOL WINAPI
ShowCaret( HWND hwnd
)
332 SERVER_START_REQ( set_caret_info
)
334 req
->flags
= SET_CARET_HIDE
|SET_CARET_STATE
;
335 req
->handle
= wine_server_user_handle( hwnd
);
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
;
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
);
361 /*****************************************************************
362 * GetCaretPos (USER32.@)
364 BOOL WINAPI
GetCaretPos( LPPOINT pt
)
368 SERVER_START_REQ( set_caret_info
)
370 req
->flags
= 0; /* don't set anything */
376 if ((ret
= !wine_server_call_err( req
)))
378 pt
->x
= reply
->old_rect
.left
;
379 pt
->y
= reply
->old_rect
.top
;
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 */
400 /*****************************************************************
401 * GetCaretBlinkTime (USER32.@)
403 UINT WINAPI
GetCaretBlinkTime(void)
405 return Caret
.timeout
;