Release 940201
[wine.git] / windows / timer.c
blob2a40bec2c285d5364f2e1350f4e24d5a49c4cc15
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 */
32 /***********************************************************************
33 * TIMER_InsertTimer
35 * Insert the timer at its place in the chain.
37 static void TIMER_InsertTimer( TIMER * pTimer )
39 if (!pNextTimer || (pTimer->expires < pNextTimer->expires))
41 pTimer->next = pNextTimer;
42 pNextTimer = pTimer;
44 else
46 TIMER * ptr = pNextTimer;
47 while (ptr->next && (pTimer->expires >= ptr->next->expires))
48 ptr = ptr->next;
49 pTimer->next = ptr;
50 ptr->next = pTimer;
55 /***********************************************************************
56 * TIMER_RemoveTimer
58 * Remove the timer from the chain.
60 static void TIMER_RemoveTimer( TIMER * pTimer )
62 if (pTimer == pNextTimer) pNextTimer = pTimer->next;
63 else
65 TIMER * ptr = pNextTimer;
66 while (ptr && (ptr->next != pTimer)) ptr = ptr->next;
67 if (ptr) ptr->next = pTimer->next;
69 pTimer->next = NULL;
73 /***********************************************************************
74 * TIMER_NextExpire
76 * Return time until next timer expiration (-1 if none).
78 static DWORD TIMER_NextExpire( DWORD curTime )
80 if (!pNextTimer) return -1;
81 if (pNextTimer->expires <= curTime) return 0;
82 return pNextTimer->expires - curTime;
86 /***********************************************************************
87 * TIMER_CheckTimer
89 * Check whether a timer has expired, and post a message if necessary.
90 * Return TRUE if msg posted, and return time until next expiration in 'next'.
92 BOOL TIMER_CheckTimer( DWORD *next )
94 TIMER * pTimer = pNextTimer;
95 DWORD curTime = GetTickCount();
97 if ((*next = TIMER_NextExpire( curTime )) != 0) return FALSE;
99 PostMessage( pTimer->hwnd, pTimer->msg, pTimer->id, (LONG)pTimer->proc );
100 TIMER_RemoveTimer( pTimer );
102 /* If timeout == 0, the timer has been removed by KillTimer */
103 if (pTimer->timeout)
105 /* Restart the timer */
106 pTimer->expires = curTime + pTimer->timeout;
107 TIMER_InsertTimer( pTimer );
109 *next = TIMER_NextExpire( curTime );
110 return TRUE;
114 /***********************************************************************
115 * TIMER_SetTimer
117 static WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout,
118 FARPROC proc, BOOL sys )
120 int i;
121 TIMER * pTimer;
123 if (!timeout) return 0;
124 if (!hwnd && !proc) return 0;
126 /* Find a free timer */
128 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
129 if (!pTimer->timeout) break;
131 if (i >= NB_TIMERS) return 0;
132 if (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) return 0;
133 if (!hwnd) id = i + 1;
135 /* Add the timer */
137 pTimer->hwnd = hwnd;
138 pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
139 pTimer->id = id;
140 pTimer->timeout = timeout;
141 pTimer->expires = GetTickCount() + timeout;
142 pTimer->proc = proc;
143 TIMER_InsertTimer( pTimer );
144 MSG_IncTimerCount( GetTaskQueue(0) );
145 if (!id)
146 return TRUE;
147 else
148 return id;
152 /***********************************************************************
153 * TIMER_KillTimer
155 static BOOL TIMER_KillTimer( HWND hwnd, WORD id, BOOL sys )
157 int i;
158 TIMER * pTimer;
160 /* Find the timer */
162 for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
163 if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
164 (pTimer->timeout != 0)) break;
165 if (i >= NB_TIMERS) return FALSE;
166 if (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) return FALSE;
167 if (!sys && (pTimer->msg != WM_TIMER)) return FALSE;
168 else if (sys && (pTimer->msg != WM_SYSTIMER)) return FALSE;
170 /* Delete the timer */
172 pTimer->hwnd = 0;
173 pTimer->msg = 0;
174 pTimer->id = 0;
175 pTimer->timeout = 0;
176 pTimer->proc = 0;
177 TIMER_RemoveTimer( pTimer );
178 MSG_DecTimerCount( GetTaskQueue(0) );
179 return TRUE;
183 /***********************************************************************
184 * SetTimer (USER.10)
186 WORD SetTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc )
188 #ifdef DEBUG_TIMER
189 printf( "SetTimer: %d %d %d %p\n", hwnd, id, timeout, proc );
190 #endif
191 return TIMER_SetTimer( hwnd, id, timeout, proc, FALSE );
195 /***********************************************************************
196 * SetSystemTimer (USER.11)
198 WORD SetSystemTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc )
200 #ifdef DEBUG_TIMER
201 printf( "SetSystemTimer: %d %d %d %p\n", hwnd, id, timeout, proc );
202 #endif
203 return TIMER_SetTimer( hwnd, id, timeout, proc, TRUE );
207 /***********************************************************************
208 * KillTimer (USER.12)
210 BOOL KillTimer( HWND hwnd, WORD id )
212 #ifdef DEBUG_TIMER
213 printf( "KillTimer: %d %d\n", hwnd, id );
214 #endif
215 return TIMER_KillTimer( hwnd, id, FALSE );
219 /***********************************************************************
220 * KillSystemTimer (USER.182)
222 BOOL KillSystemTimer( HWND hwnd, WORD id )
224 #ifdef DEBUG_TIMER
225 printf( "KillSystemTimer: %d %d\n", hwnd, id );
226 #endif
227 return TIMER_KillTimer( hwnd, id, TRUE );