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