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
28 #include "wine/server.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(caret
);
39 static CARET Caret
= { 0, 500 };
41 #define TIMERID 0xffff /* system timer id for the caret */
44 /*****************************************************************
47 static void CARET_DisplayCaret( HWND hwnd
, const RECT
*r
)
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
);
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
);
64 ReleaseDC( hwnd
, hdc
);
68 /*****************************************************************
71 static void CALLBACK
CARET_Callback( HWND hwnd
, UINT msg
, UINT id
, DWORD ctime
)
78 SERVER_START_REQ( set_caret_info
)
80 req
->flags
= SET_CARET_STATE
;
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
;
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
, (HBRUSH
)((bitmap
? COLOR_GRAYTEXT
: COLOR_WINDOW
) + 1));
155 SelectObject(hMemDC
, hPrevBmp
);
159 ReleaseDC(hwnd
, hdc
);
162 if (!hBmp
) return FALSE
;
164 SERVER_START_REQ( set_caret_window
)
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
;
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
= 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
;
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
;
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
;
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
;
316 if (old_state
) CARET_DisplayCaret( hwnd
, &r
);
317 KillSystemTimer( hwnd
, TIMERID
);
323 /*****************************************************************
324 * ShowCaret (USER32.@)
326 BOOL WINAPI
ShowCaret( HWND hwnd
)
333 SERVER_START_REQ( set_caret_info
)
335 req
->flags
= SET_CARET_HIDE
|SET_CARET_STATE
;
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
;
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
);
363 /*****************************************************************
364 * GetCaretPos (USER32.@)
366 BOOL WINAPI
GetCaretPos( LPPOINT pt
)
370 SERVER_START_REQ( set_caret_info
)
372 req
->flags
= 0; /* don't set anything */
378 if ((ret
= !wine_server_call_err( req
)))
380 pt
->x
= reply
->old_rect
.left
;
381 pt
->y
= reply
->old_rect
.top
;
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 */
402 /*****************************************************************
403 * GetCaretBlinkTime (USER32.@)
405 UINT WINAPI
GetCaretBlinkTime(void)
407 return Caret
.timeout
;