Do not clear the drawing area for etched static controls.
[wine.git] / windows / timer.c
blobb46be521caafe7d46df09b5544b42e657eb7583c
1 /*
2 * Timer functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 #include "wine/winuser16.h"
8 #include "winuser.h"
9 #include "queue.h"
10 #include "task.h"
11 #include "winproc.h"
12 #include "services.h"
13 #include "message.h"
14 #include "debugtools.h"
16 DEFAULT_DEBUG_CHANNEL(timer)
19 typedef struct tagTIMER
21 HWND hwnd;
22 HQUEUE16 hq;
23 UINT16 msg; /* WM_TIMER or WM_SYSTIMER */
24 UINT id;
25 UINT timeout;
26 HANDLE hService;
27 BOOL expired;
28 HWINDOWPROC proc;
29 } TIMER;
31 #define NB_TIMERS 34
32 #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
34 #define SYS_TIMER_RATE 54925
36 static TIMER TimersArray[NB_TIMERS];
38 static CRITICAL_SECTION csTimer;
41 /***********************************************************************
42 * TIMER_Init
44 * Initialize critical section for the timer.
46 BOOL TIMER_Init( void )
48 InitializeCriticalSection( &csTimer );
49 MakeCriticalSectionGlobal( &csTimer );
51 return TRUE;
55 /***********************************************************************
56 * TIMER_ClearTimer
58 * Clear and remove a timer.
60 static void TIMER_ClearTimer( TIMER * pTimer )
62 if ( pTimer->hService != INVALID_HANDLE_VALUE )
64 SERVICE_Delete( pTimer->hService );
65 pTimer->hService = INVALID_HANDLE_VALUE;
68 if ( pTimer->expired )
70 QUEUE_DecTimerCount( pTimer->hq );
71 pTimer->expired = FALSE;
74 pTimer->hwnd = 0;
75 pTimer->msg = 0;
76 pTimer->id = 0;
77 pTimer->timeout = 0;
78 WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER );
82 /***********************************************************************
83 * TIMER_RemoveWindowTimers
85 * Remove all timers for a given window.
87 void TIMER_RemoveWindowTimers( HWND hwnd )
89 int i;
90 TIMER *pTimer;
92 EnterCriticalSection( &csTimer );
94 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
95 if ((pTimer->hwnd == hwnd) && pTimer->timeout)
96 TIMER_ClearTimer( pTimer );
98 LeaveCriticalSection( &csTimer );
102 /***********************************************************************
103 * TIMER_RemoveQueueTimers
105 * Remove all timers for a given queue.
107 void TIMER_RemoveQueueTimers( HQUEUE16 hqueue )
109 int i;
110 TIMER *pTimer;
112 EnterCriticalSection( &csTimer );
114 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
115 if ((pTimer->hq == hqueue) && pTimer->timeout)
116 TIMER_ClearTimer( pTimer );
118 LeaveCriticalSection( &csTimer );
122 /***********************************************************************
123 * TIMER_CheckTimer
125 static void CALLBACK TIMER_CheckTimer( ULONG_PTR timer_ptr )
127 TIMER *pTimer = (TIMER *)timer_ptr;
128 HQUEUE16 wakeQueue = 0;
130 EnterCriticalSection( &csTimer );
132 /* Paranoid check to prevent a race condition ... */
133 if ( !pTimer->timeout )
135 LeaveCriticalSection( &csTimer );
136 return;
139 if ( !pTimer->expired )
141 TRACE("Timer expired: %04x, %04x, %04x, %08lx\n",
142 pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
144 pTimer->expired = TRUE;
145 wakeQueue = pTimer->hq;
148 LeaveCriticalSection( &csTimer );
150 /* Note: This has to be done outside the csTimer critical section,
151 otherwise we'll get deadlocks. */
153 if ( wakeQueue )
154 QUEUE_IncTimerCount( wakeQueue );
158 /***********************************************************************
159 * TIMER_GetTimerMsg
161 * Build a message for an expired timer.
163 BOOL TIMER_GetTimerMsg( MSG *msg, HWND hwnd,
164 HQUEUE16 hQueue, BOOL remove )
166 TIMER *pTimer;
167 int i;
169 EnterCriticalSection( &csTimer );
171 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
172 if ( pTimer->timeout != 0 && pTimer->expired
173 && (hwnd? (pTimer->hwnd == hwnd) : (pTimer->hq == hQueue)) )
174 break;
176 if ( i == NB_TIMERS )
178 LeaveCriticalSection( &csTimer );
179 return FALSE; /* No timer */
182 TRACE("Timer got message: %04x, %04x, %04x, %08lx\n",
183 pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc);
185 if (remove)
186 pTimer->expired = FALSE;
188 /* Build the message */
189 msg->hwnd = pTimer->hwnd;
190 msg->message = pTimer->msg;
191 msg->wParam = pTimer->id;
192 msg->lParam = (LONG)pTimer->proc;
193 msg->time = GetTickCount();
195 LeaveCriticalSection( &csTimer );
197 return TRUE;
201 /***********************************************************************
202 * TIMER_SetTimer
204 static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
205 WNDPROC16 proc, WINDOWPROCTYPE type, BOOL sys )
207 int i;
208 TIMER * pTimer;
210 if (!timeout)
211 { /* timeout==0 is a legal argument UB 990821*/
212 WARN("Timeout== 0 not implemented, using timeout=1\n");
213 timeout=1;
215 EnterCriticalSection( &csTimer );
217 /* Check if there's already a timer with the same hwnd and id */
219 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
220 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
221 (pTimer->timeout != 0))
223 TIMER_ClearTimer( pTimer );
224 break;
227 if ( i == NB_TIMERS )
229 /* Find a free timer */
231 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
232 if (!pTimer->timeout) break;
234 if ( (i >= NB_TIMERS) ||
235 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) )
237 LeaveCriticalSection( &csTimer );
238 return 0;
242 if (!hwnd) id = i + 1;
244 /* Add the timer */
246 pTimer->hwnd = hwnd;
247 pTimer->hq = (hwnd) ? GetThreadQueue16( GetWindowThreadProcessId( hwnd, NULL ) )
248 : GetFastQueue16( );
249 pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
250 pTimer->id = id;
251 pTimer->timeout = timeout;
252 pTimer->proc = (HWINDOWPROC)0;
253 if (proc) WINPROC_SetProc( &pTimer->proc, proc, type, WIN_PROC_TIMER );
255 pTimer->expired = FALSE;
256 pTimer->hService = SERVICE_AddTimer( MAX( timeout * 1000L, SYS_TIMER_RATE ),
257 TIMER_CheckTimer, (ULONG_PTR)pTimer );
259 TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
260 pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
261 (DWORD)pTimer->proc );
263 LeaveCriticalSection( &csTimer );
265 if (!id) return TRUE;
266 else return id;
270 /***********************************************************************
271 * TIMER_KillTimer
273 static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys )
275 int i;
276 TIMER * pTimer;
278 EnterCriticalSection( &csTimer );
280 /* Find the timer */
282 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
283 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
284 (pTimer->timeout != 0)) break;
286 if ( (i >= NB_TIMERS) ||
287 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) ||
288 (!sys && (pTimer->msg != WM_TIMER)) ||
289 (sys && (pTimer->msg != WM_SYSTIMER)) )
291 LeaveCriticalSection( &csTimer );
292 return FALSE;
295 /* Delete the timer */
297 TIMER_ClearTimer( pTimer );
299 LeaveCriticalSection( &csTimer );
301 return TRUE;
305 /***********************************************************************
306 * SetTimer16 (USER.10)
308 UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
309 TIMERPROC16 proc )
311 TRACE("%04x %d %d %08lx\n",
312 hwnd, id, timeout, (LONG)proc );
313 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
314 WIN_PROC_16, FALSE );
318 /***********************************************************************
319 * SetTimer32 (USER32.511)
321 UINT WINAPI SetTimer( HWND hwnd, UINT id, UINT timeout,
322 TIMERPROC proc )
324 TRACE("%04x %d %d %08lx\n",
325 hwnd, id, timeout, (LONG)proc );
326 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
327 WIN_PROC_32A, FALSE );
331 /***********************************************************************
332 * SetSystemTimer16 (USER.11)
334 UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
335 TIMERPROC16 proc )
337 TRACE("%04x %d %d %08lx\n",
338 hwnd, id, timeout, (LONG)proc );
339 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
340 WIN_PROC_16, TRUE );
344 /***********************************************************************
345 * SetSystemTimer32 (USER32.509)
347 UINT WINAPI SetSystemTimer( HWND hwnd, UINT id, UINT timeout,
348 TIMERPROC proc )
350 TRACE("%04x %d %d %08lx\n",
351 hwnd, id, timeout, (LONG)proc );
352 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc,
353 WIN_PROC_32A, TRUE );
357 /***********************************************************************
358 * KillTimer16 (USER.12)
360 BOOL16 WINAPI KillTimer16( HWND16 hwnd, UINT16 id )
362 TRACE("%04x %d\n", hwnd, id );
363 return TIMER_KillTimer( hwnd, id, FALSE );
367 /***********************************************************************
368 * KillTimer32 (USER32.354)
370 BOOL WINAPI KillTimer( HWND hwnd, UINT id )
372 TRACE("%04x %d\n", hwnd, id );
373 return TIMER_KillTimer( hwnd, id, FALSE );
377 /***********************************************************************
378 * KillSystemTimer16 (USER.182)
380 BOOL16 WINAPI KillSystemTimer16( HWND16 hwnd, UINT16 id )
382 TRACE("%04x %d\n", hwnd, id );
383 return TIMER_KillTimer( hwnd, id, TRUE );
387 /***********************************************************************
388 * KillSystemTimer32 (USER32.353)
390 BOOL WINAPI KillSystemTimer( HWND hwnd, UINT id )
392 TRACE("%04x %d\n", hwnd, id );
393 return TIMER_KillTimer( hwnd, id, TRUE );