4 * Copyright 1993 Alexandre Julliard
9 #include "wine/winuser16.h"
16 #include "wine/server.h"
17 #include "debugtools.h"
19 DEFAULT_DEBUG_CHANNEL(timer);
22 typedef struct tagTIMER
26 UINT16 msg; /* WM_TIMER or WM_SYSTIMER */
33 #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
35 #define SYS_TIMER_RATE 55 /* min. timer rate in ms (actually 54.925)*/
37 static TIMER TimersArray[NB_TIMERS];
39 static CRITICAL_SECTION csTimer = CRITICAL_SECTION_INIT("csTimer");
42 /***********************************************************************
45 * Clear and remove a timer.
47 static void TIMER_ClearTimer( TIMER * pTimer )
53 WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER );
57 /***********************************************************************
58 * TIMER_RemoveWindowTimers
60 * Remove all timers for a given window.
62 void TIMER_RemoveWindowTimers( HWND hwnd )
67 EnterCriticalSection( &csTimer );
69 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
70 if ((pTimer->hwnd == hwnd) && pTimer->timeout)
71 TIMER_ClearTimer( pTimer );
73 LeaveCriticalSection( &csTimer );
77 /***********************************************************************
78 * TIMER_RemoveQueueTimers
80 * Remove all timers for a given queue.
82 void TIMER_RemoveQueueTimers( HQUEUE16 hqueue )
87 EnterCriticalSection( &csTimer );
89 for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
90 if ((pTimer->hq == hqueue) && pTimer->timeout)
91 TIMER_ClearTimer( pTimer );
93 LeaveCriticalSection( &csTimer );
97 /***********************************************************************
100 static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout,
101 WNDPROC16 proc, WINDOWPROCTYPE type, BOOL sys )
105 HWINDOWPROC winproc = 0;
107 if (hwnd && !(hwnd = WIN_IsCurrentThread( hwnd )))
109 SetLastError( ERROR_INVALID_WINDOW_HANDLE );
114 { /* timeout==0 is a legal argument UB 990821*/
115 WARN("Timeout== 0 not implemented, using timeout=1\n");
119 EnterCriticalSection( &csTimer );
121 /* Check if there's already a timer with the same hwnd and id */
123 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
124 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
125 (pTimer->timeout != 0))
127 TIMER_ClearTimer( pTimer );
131 if ( i == NB_TIMERS )
133 /* Find a free timer */
135 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
136 if (!pTimer->timeout) break;
138 if ( (i >= NB_TIMERS) ||
139 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) )
141 LeaveCriticalSection( &csTimer );
146 if (!hwnd) id = i + 1;
148 if (proc) WINPROC_SetProc( &winproc, proc, type, WIN_PROC_TIMER );
150 SERVER_START_REQ( set_win_timer )
153 req->msg = sys ? WM_SYSTIMER : WM_TIMER;
155 req->rate = max( timeout, SYS_TIMER_RATE );
156 req->lparam = (unsigned int)winproc;
157 wine_server_call( req );
164 pTimer->hq = InitThreadInput16( 0, 0 );
165 pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
167 pTimer->timeout = timeout;
168 pTimer->proc = winproc;
170 TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
171 pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
172 (DWORD)pTimer->proc );
174 LeaveCriticalSection( &csTimer );
176 if (!id) return TRUE;
181 /***********************************************************************
184 static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys )
189 SERVER_START_REQ( kill_win_timer )
192 req->msg = sys ? WM_SYSTIMER : WM_TIMER;
194 wine_server_call( req );
198 EnterCriticalSection( &csTimer );
202 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
203 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
204 (pTimer->timeout != 0)) break;
206 if ( (i >= NB_TIMERS) ||
207 (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) ||
208 (!sys && (pTimer->msg != WM_TIMER)) ||
209 (sys && (pTimer->msg != WM_SYSTIMER)) )
211 LeaveCriticalSection( &csTimer );
215 /* Delete the timer */
217 TIMER_ClearTimer( pTimer );
219 LeaveCriticalSection( &csTimer );
225 /***********************************************************************
228 UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
231 TRACE("%04x %d %d %08lx\n",
232 hwnd, id, timeout, (LONG)proc );
233 return TIMER_SetTimer( WIN_Handle32(hwnd), id, timeout, (WNDPROC16)proc,
234 WIN_PROC_16, FALSE );
238 /***********************************************************************
239 * SetTimer (USER32.@)
241 UINT WINAPI SetTimer( HWND hwnd, UINT id, UINT timeout,
244 TRACE("%04x %d %d %08lx\n",
245 hwnd, id, timeout, (LONG)proc );
246 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, WIN_PROC_32A, FALSE );
250 /***********************************************************************
253 BOOL TIMER_IsTimerValid( HWND hwnd, UINT id, HWINDOWPROC hProc )
259 hwnd = WIN_GetFullHandle( hwnd );
260 EnterCriticalSection( &csTimer );
262 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
263 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
264 (pTimer->proc == hProc))
270 LeaveCriticalSection( &csTimer );
275 /***********************************************************************
276 * SetSystemTimer (USER.11)
278 UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
281 TRACE("%04x %d %d %08lx\n",
282 hwnd, id, timeout, (LONG)proc );
283 return TIMER_SetTimer( WIN_Handle32(hwnd), id, timeout, (WNDPROC16)proc,
288 /***********************************************************************
289 * SetSystemTimer (USER32.@)
291 UINT WINAPI SetSystemTimer( HWND hwnd, UINT id, UINT timeout,
294 TRACE("%04x %d %d %08lx\n",
295 hwnd, id, timeout, (LONG)proc );
296 return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, WIN_PROC_32A, TRUE );
300 /***********************************************************************
301 * KillTimer (USER32.@)
303 BOOL WINAPI KillTimer( HWND hwnd, UINT id )
305 TRACE("%04x %d\n", hwnd, id );
306 return TIMER_KillTimer( hwnd, id, FALSE );
310 /***********************************************************************
311 * KillSystemTimer (USER32.@)
313 BOOL WINAPI KillSystemTimer( HWND hwnd, UINT id )
315 TRACE("%04x %d\n", hwnd, id );
316 return TIMER_KillTimer( hwnd, id, TRUE );