Release 940405
[wine.git] / windows / timer.c
blob641bbe05bf835c5ac3a4043343647c2db44340ae
1 /*
2 * Timer functions
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include "windows.h"
10 #include "message.h"
13 typedef struct tagTIMER
15 HWND hwnd;
16 WORD msg; /* WM_TIMER or WM_SYSTIMER */
17 WORD id;
18 WORD timeout;
19 struct tagTIMER *next;
20 DWORD expires;
21 FARPROC proc;
22 } TIMER;
24 #define NB_TIMERS 34
25 #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
27 static TIMER TimersArray[NB_TIMERS];
29 static TIMER * pNextTimer = NULL; /* Next timer to expire */
31 /* Duration from 'time' until expiration of the timer */
32 #define EXPIRE_TIME(pTimer,time) \
33 (((pTimer)->expires <= (time)) ? 0 : (pTimer)->expires - (time))
36 /***********************************************************************
37 * TIMER_InsertTimer
39 * Insert the timer at its place in the chain.
41 static void TIMER_InsertTimer( TIMER * pTimer )
43 if (!pNextTimer || (pTimer->expires < pNextTimer->expires))
45 pTimer->next = pNextTimer;
46 pNextTimer = pTimer;
48 else
50 TIMER * ptr = pNextTimer;
51 while (ptr->next && (pTimer->expires >= ptr->next->expires))
52 ptr = ptr->next;
53 pTimer->next = ptr->next;
54 ptr->next = pTimer;
59 /***********************************************************************
60 * TIMER_RemoveTimer
62 * Remove the timer from the chain.
64 static void TIMER_RemoveTimer( TIMER * pTimer )
66 if (pTimer == pNextTimer) pNextTimer = pTimer->next;
67 else
69 TIMER * ptr = pNextTimer;
70 while (ptr && (ptr->next != pTimer)) ptr = ptr->next;
71 if (ptr) ptr->next = pTimer->next;
73 pTimer->next = NULL;
77 /***********************************************************************
78 * TIMER_RestartTimers
80 * Restart an expired timer.
82 static void TIMER_RestartTimer( TIMER * pTimer, DWORD curTime )
84 TIMER_RemoveTimer( pTimer );
85 pTimer->expires = curTime + pTimer->timeout;
86 TIMER_InsertTimer( pTimer );
90 /***********************************************************************
91 * TIMER_CheckTimer
93 * Check whether a timer has expired, and create a message if necessary.
94 * Otherwise, return time until next timer expiration in 'next'.
95 * If 'hwnd' is not NULL, only consider timers for this window.
96 * If 'remove' is TRUE, remove all expired timers up to the returned one.
98 BOOL TIMER_CheckTimer( LONG *next, MSG *msg, HWND hwnd, BOOL remove )
100 TIMER * pTimer = pNextTimer;
101 DWORD curTime = GetTickCount();
103 if (hwnd) /* Find first timer for this window */
104 while (pTimer && (pTimer->hwnd != hwnd)) pTimer = pTimer->next;
106 if (!pTimer) *next = -1;
107 else *next = EXPIRE_TIME( pTimer, curTime );
108 if (*next != 0) return FALSE; /* No timer expired */
110 if (remove) /* Restart all timers before pTimer, and then pTimer itself */
112 while (pNextTimer != pTimer) TIMER_RestartTimer( pNextTimer, curTime );
113 TIMER_RestartTimer( pTimer, curTime );
116 /* Build the message */
117 msg->hwnd = pTimer->hwnd;
118 msg->message = pTimer->msg;
119 msg->wParam = pTimer->id;
120 msg->lParam = (LONG)pTimer->proc;
121 msg->time = curTime;
122 return TRUE;
126 /***********************************************************************
127 * TIMER_SetTimer
129 static WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout,
130 FARPROC proc, BOOL sys )
132 int i;
133 TIMER * pTimer;
135 if (!timeout) return 0;
136 if (!hwnd && !proc) return 0;
138 /* Find a free timer */
140 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
141 if (!pTimer->timeout) break;
143 if (i >= NB_TIMERS) return 0;
144 if (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) return 0;
145 if (!hwnd) id = i + 1;
147 /* Add the timer */
149 pTimer->hwnd = hwnd;
150 pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
151 pTimer->id = id;
152 pTimer->timeout = timeout;
153 pTimer->expires = GetTickCount() + timeout;
154 pTimer->proc = proc;
155 TIMER_InsertTimer( pTimer );
156 MSG_IncTimerCount( GetTaskQueue(0) );
157 if (!id)
158 return TRUE;
159 else
160 return id;
164 /***********************************************************************
165 * TIMER_KillTimer
167 static BOOL TIMER_KillTimer( HWND hwnd, WORD id, BOOL sys )
169 int i;
170 TIMER * pTimer;
172 /* Find the timer */
174 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
175 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
176 (pTimer->timeout != 0)) break;
177 if (i >= NB_TIMERS) return FALSE;
178 if (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) return FALSE;
179 if (!sys && (pTimer->msg != WM_TIMER)) return FALSE;
180 else if (sys && (pTimer->msg != WM_SYSTIMER)) return FALSE;
182 /* Delete the timer */
184 pTimer->hwnd = 0;
185 pTimer->msg = 0;
186 pTimer->id = 0;
187 pTimer->timeout = 0;
188 pTimer->proc = 0;
189 TIMER_RemoveTimer( pTimer );
190 MSG_DecTimerCount( GetTaskQueue(0) );
191 return TRUE;
195 /***********************************************************************
196 * SetTimer (USER.10)
198 WORD SetTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc )
200 #ifdef DEBUG_TIMER
201 printf( "SetTimer: %d %d %d %p\n", hwnd, id, timeout, proc );
202 #endif
203 return TIMER_SetTimer( hwnd, id, timeout, proc, FALSE );
207 /***********************************************************************
208 * SetSystemTimer (USER.11)
210 WORD SetSystemTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc )
212 #ifdef DEBUG_TIMER
213 printf( "SetSystemTimer: %d %d %d %p\n", hwnd, id, timeout, proc );
214 #endif
215 return TIMER_SetTimer( hwnd, id, timeout, proc, TRUE );
219 /***********************************************************************
220 * KillTimer (USER.12)
222 BOOL KillTimer( HWND hwnd, WORD id )
224 #ifdef DEBUG_TIMER
225 printf( "KillTimer: %d %d\n", hwnd, id );
226 #endif
227 return TIMER_KillTimer( hwnd, id, FALSE );
231 /***********************************************************************
232 * KillSystemTimer (USER.182)
234 BOOL KillSystemTimer( HWND hwnd, WORD id )
236 #ifdef DEBUG_TIMER
237 printf( "KillSystemTimer: %d %d\n", hwnd, id );
238 #endif
239 return TIMER_KillTimer( hwnd, id, TRUE );