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