Only modify the ancestor if you find it.
[wine] / windows / caret.c
1 /*
2  * Caret functions
3  *
4  * Copyright 1993 David Metcalfe
5  * Copyright 1996 Frans van Dorsselaer
6  */
7
8 #include "windef.h"
9 #include "winbase.h"
10 #include "wingdi.h"
11 #include "winuser.h"
12 #include "wine/wingdi16.h"
13 #include "wine/winuser16.h"
14 #include "win.h"
15 #include "debugtools.h"
16
17 DEFAULT_DEBUG_CHANNEL(caret);
18
19 typedef struct
20 {
21     HWND     hwnd;
22     UINT     hidden;
23     BOOL     on;
24     INT      x;
25     INT      y;
26     INT      width;
27     INT      height;
28     HBRUSH   hBrush;
29     UINT     timeout;
30     UINT     timerid;
31 } CARET;
32
33 typedef enum
34 {
35     CARET_OFF = 0,
36     CARET_ON,
37     CARET_TOGGLE
38 } DISPLAY_CARET;
39
40 static CARET Caret = { 0, 0, FALSE, 0, 0, 2, 12, 0, 500, 0 };
41
42 /*****************************************************************
43  *              CARET_GetHwnd
44  */
45 HWND CARET_GetHwnd(void)
46 {
47     return Caret.hwnd;
48 }
49
50 /*****************************************************************
51  *              CARET_GetRect
52  */
53 void CARET_GetRect(LPRECT lprc)
54 {
55     lprc->right = (lprc->left = Caret.x) + Caret.width - 1;
56     lprc->bottom = (lprc->top = Caret.y) + Caret.height - 1;
57 }
58
59 /*****************************************************************
60  *               CARET_DisplayCaret
61  */
62 static void CARET_DisplayCaret( DISPLAY_CARET status )
63 {
64     HDC hdc;
65     HBRUSH hPrevBrush;
66
67     if (Caret.on && (status == CARET_ON)) return;
68     if (!Caret.on && (status == CARET_OFF)) return;
69
70     /* So now it's always a toggle */
71
72     Caret.on = !Caret.on;
73     /* do not use DCX_CACHE here, for x,y,width,height are in logical units */
74     if (!(hdc = GetDCEx( Caret.hwnd, 0, DCX_USESTYLE /*| DCX_CACHE*/ ))) return;
75     hPrevBrush = SelectObject( hdc, Caret.hBrush );
76     PatBlt( hdc, Caret.x, Caret.y, Caret.width, Caret.height, PATINVERT );
77     SelectObject( hdc, hPrevBrush );
78     ReleaseDC( Caret.hwnd, hdc );
79 }
80
81   
82 /*****************************************************************
83  *               CARET_Callback
84  */
85 static VOID CALLBACK CARET_Callback( HWND hwnd, UINT msg, UINT id, DWORD ctime)
86 {
87     TRACE("hwnd=%04x, timerid=%d, caret=%d\n",
88                   hwnd, id, Caret.on);
89     CARET_DisplayCaret(CARET_TOGGLE);
90 }
91
92
93 /*****************************************************************
94  *               CARET_SetTimer
95  */
96 static void CARET_SetTimer(void)
97 {
98     if (Caret.timerid) KillSystemTimer( (HWND)0, Caret.timerid );
99     Caret.timerid = SetSystemTimer( (HWND)0, 0, Caret.timeout,
100                                       CARET_Callback );
101 }
102
103
104 /*****************************************************************
105  *               CARET_ResetTimer
106  */
107 static void CARET_ResetTimer(void)
108 {
109     if (Caret.timerid) 
110     {
111         KillSystemTimer( (HWND)0, Caret.timerid );
112         Caret.timerid = SetSystemTimer( (HWND)0, 0, Caret.timeout,
113                                           CARET_Callback );
114     }
115 }
116
117
118 /*****************************************************************
119  *               CARET_KillTimer
120  */
121 static void CARET_KillTimer(void)
122 {
123     if (Caret.timerid) 
124     {
125         KillSystemTimer( (HWND)0, Caret.timerid );
126         Caret.timerid = 0;
127     }
128 }
129
130
131 /*****************************************************************
132  *              CreateCaret (USER32.@)
133  */
134 BOOL WINAPI CreateCaret( HWND hwnd, HBITMAP bitmap,
135                              INT width, INT height )
136 {
137     TRACE("hwnd=%04x\n", hwnd);
138
139     if (!hwnd) return FALSE;
140
141     /* if cursor already exists, destroy it */
142     if (Caret.hwnd) DestroyCaret();
143
144     if (bitmap && (bitmap != 1))
145     {
146         BITMAP bmp;
147         if (!GetObjectA( bitmap, sizeof(bmp), &bmp )) return FALSE;
148         Caret.width = bmp.bmWidth;
149         Caret.height = bmp.bmHeight;
150         /* FIXME: we should make a copy of the bitmap instead of a brush */
151         Caret.hBrush = CreatePatternBrush( bitmap );
152     }
153     else
154     {
155         Caret.width = width ? width : GetSystemMetrics(SM_CXBORDER);
156         Caret.height = height ? height : GetSystemMetrics(SM_CYBORDER);
157         Caret.hBrush = CreateSolidBrush(bitmap ?
158                                           GetSysColor(COLOR_GRAYTEXT) :
159                                           GetSysColor(COLOR_WINDOW) );
160     }
161
162     Caret.hwnd = WIN_GetFullHandle( hwnd );
163     Caret.hidden = 1;
164     Caret.on = FALSE;
165     Caret.x = 0;
166     Caret.y = 0;
167
168     Caret.timeout = GetProfileIntA( "windows", "CursorBlinkRate", 500 );
169     return TRUE;
170 }
171    
172
173 /*****************************************************************
174  *              DestroyCaret (USER.164)
175  */
176 void WINAPI DestroyCaret16(void)
177 {
178     DestroyCaret();
179 }
180
181
182 /*****************************************************************
183  *              DestroyCaret (USER32.@)
184  */
185 BOOL WINAPI DestroyCaret(void)
186 {
187     if (!Caret.hwnd) return FALSE;
188
189     TRACE("hwnd=%04x, timerid=%d\n",
190                 Caret.hwnd, Caret.timerid);
191
192     CARET_KillTimer();
193     CARET_DisplayCaret(CARET_OFF);
194     DeleteObject( Caret.hBrush );
195     Caret.hwnd = 0;
196     return TRUE;
197 }
198
199
200 /*****************************************************************
201  *              SetCaretPos (USER.165)
202  */
203 void WINAPI SetCaretPos16( INT16 x, INT16 y )
204 {
205     SetCaretPos( x, y );
206 }
207
208
209 /*****************************************************************
210  *              SetCaretPos (USER32.@)
211  */
212 BOOL WINAPI SetCaretPos( INT x, INT y)
213 {
214     if (!Caret.hwnd) return FALSE;
215     if ((x == Caret.x) && (y == Caret.y)) return TRUE;
216
217     TRACE("x=%d, y=%d\n", x, y);
218
219     CARET_KillTimer();
220     CARET_DisplayCaret(CARET_OFF);
221     Caret.x = x;
222     Caret.y = y;
223     if (!Caret.hidden)
224     {
225         CARET_DisplayCaret(CARET_ON);
226         CARET_SetTimer();
227     }
228     return TRUE;
229 }
230
231
232 /*****************************************************************
233  *              HideCaret (USER32.@)
234  */
235 BOOL WINAPI HideCaret( HWND hwnd )
236 {
237     if (!Caret.hwnd) return FALSE;
238     if (hwnd && (Caret.hwnd != WIN_GetFullHandle(hwnd))) return FALSE;
239
240     TRACE("hwnd=%04x, hidden=%d\n",
241                   hwnd, Caret.hidden);
242
243     CARET_KillTimer();
244     CARET_DisplayCaret(CARET_OFF);
245     Caret.hidden++;
246     return TRUE;
247 }
248
249
250 /*****************************************************************
251  *              ShowCaret (USER32.@)
252  */
253 BOOL WINAPI ShowCaret( HWND hwnd )
254 {
255     if (!Caret.hwnd) return FALSE;
256     if (hwnd && (Caret.hwnd != WIN_GetFullHandle(hwnd))) return FALSE;
257
258     TRACE("hwnd=%04x, hidden=%d\n",
259                 hwnd, Caret.hidden);
260
261     if (Caret.hidden)
262     {
263         Caret.hidden--;
264         if (!Caret.hidden)
265         {
266             CARET_DisplayCaret(CARET_ON);
267             CARET_SetTimer();
268         }
269     }
270     return TRUE;
271 }
272
273
274 /*****************************************************************
275  *              SetCaretBlinkTime (USER.168)
276  */
277 void WINAPI SetCaretBlinkTime16( UINT16 msecs )
278 {
279     SetCaretBlinkTime( msecs );
280 }
281
282 /*****************************************************************
283  *              SetCaretBlinkTime (USER32.@)
284  */
285 BOOL WINAPI SetCaretBlinkTime( UINT msecs )
286 {
287     if (!Caret.hwnd) return FALSE;
288
289     TRACE("hwnd=%04x, msecs=%d\n",
290                 Caret.hwnd, msecs);
291
292     Caret.timeout = msecs;
293     CARET_ResetTimer();
294     return TRUE;
295 }
296
297
298 /*****************************************************************
299  *              GetCaretBlinkTime (USER.169)
300  */
301 UINT16 WINAPI GetCaretBlinkTime16(void)
302 {
303     return (UINT16)GetCaretBlinkTime();
304 }
305
306
307 /*****************************************************************
308  *              GetCaretBlinkTime (USER32.@)
309  */
310 UINT WINAPI GetCaretBlinkTime(void)
311 {
312     return Caret.timeout;
313 }
314
315
316 /*****************************************************************
317  *              GetCaretPos (USER.183)
318  */
319 VOID WINAPI GetCaretPos16( LPPOINT16 pt )
320 {
321     if (!Caret.hwnd || !pt) return;
322
323     TRACE("hwnd=%04x, pt=%p, x=%d, y=%d\n",
324                   Caret.hwnd, pt, Caret.x, Caret.y);
325     pt->x = (INT16)Caret.x;
326     pt->y = (INT16)Caret.y;
327 }
328
329
330 /*****************************************************************
331  *              GetCaretPos (USER32.@)
332  */
333 BOOL WINAPI GetCaretPos( LPPOINT pt )
334 {
335     if (!Caret.hwnd || !pt) return FALSE;
336     pt->x = Caret.x;
337     pt->y = Caret.y;
338     return TRUE;
339 }