Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 1 | /* |
| 2 | * Timer functions |
| 3 | * |
| 4 | * Copyright 1993 Alexandre Julliard |
| 5 | */ |
| 6 | |
Marcus Meissner | 61afa33 | 1999-02-22 10:16:00 +0000 | [diff] [blame] | 7 | #include "winuser.h" |
Alexandre Julliard | b817f4f | 1996-03-14 18:08:34 +0000 | [diff] [blame] | 8 | #include "queue.h" |
Ulrich Weigand | 1babe5b | 1998-12-24 15:16:08 +0000 | [diff] [blame] | 9 | #include "task.h" |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 10 | #include "winproc.h" |
Ulrich Weigand | 9dcaeca | 1999-05-02 11:30:39 +0000 | [diff] [blame] | 11 | #include "services.h" |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 12 | #include "debug.h" |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 13 | |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 14 | DEFAULT_DEBUG_CHANNEL(timer) |
| 15 | |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 16 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 17 | typedef struct tagTIMER |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 18 | { |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 19 | HWND hwnd; |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 20 | HQUEUE16 hq; |
| 21 | UINT16 msg; /* WM_TIMER or WM_SYSTIMER */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 22 | UINT id; |
| 23 | UINT timeout; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 24 | struct tagTIMER *next; |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 25 | DWORD expires; /* Next expiration, or 0 if already expired */ |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 26 | HWINDOWPROC proc; |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 27 | } TIMER; |
| 28 | |
| 29 | #define NB_TIMERS 34 |
| 30 | #define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */ |
| 31 | |
| 32 | static TIMER TimersArray[NB_TIMERS]; |
| 33 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 34 | static TIMER * pNextTimer = NULL; /* Next timer to expire */ |
| 35 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 36 | static CRITICAL_SECTION csTimer; |
| 37 | |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 38 | /* Duration from 'time' until expiration of the timer */ |
| 39 | #define EXPIRE_TIME(pTimer,time) \ |
| 40 | (((pTimer)->expires <= (time)) ? 0 : (pTimer)->expires - (time)) |
| 41 | |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 42 | |
| 43 | /*********************************************************************** |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 44 | * TIMER_Init |
| 45 | * |
| 46 | * Initialize critical section for the timer. |
| 47 | */ |
| 48 | BOOL TIMER_Init( void ) |
| 49 | { |
| 50 | InitializeCriticalSection( &csTimer ); |
| 51 | MakeCriticalSectionGlobal( &csTimer ); |
| 52 | |
| 53 | return TRUE; |
| 54 | } |
| 55 | |
| 56 | |
| 57 | /*********************************************************************** |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 58 | * TIMER_InsertTimer |
| 59 | * |
| 60 | * Insert the timer at its place in the chain. |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 61 | */ |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 62 | static void TIMER_InsertTimer( TIMER * pTimer ) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 63 | { |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 64 | EnterCriticalSection( &csTimer ); |
| 65 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 66 | if (!pNextTimer || (pTimer->expires < pNextTimer->expires)) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 67 | { |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 68 | pTimer->next = pNextTimer; |
| 69 | pNextTimer = pTimer; |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 70 | } |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 71 | else |
| 72 | { |
| 73 | TIMER * ptr = pNextTimer; |
| 74 | while (ptr->next && (pTimer->expires >= ptr->next->expires)) |
| 75 | ptr = ptr->next; |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 76 | pTimer->next = ptr->next; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 77 | ptr->next = pTimer; |
| 78 | } |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 79 | |
| 80 | LeaveCriticalSection( &csTimer ); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 81 | } |
| 82 | |
| 83 | |
| 84 | /*********************************************************************** |
| 85 | * TIMER_RemoveTimer |
| 86 | * |
| 87 | * Remove the timer from the chain. |
| 88 | */ |
| 89 | static void TIMER_RemoveTimer( TIMER * pTimer ) |
| 90 | { |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 91 | TIMER **ppTimer = &pNextTimer; |
| 92 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 93 | EnterCriticalSection( &csTimer ); |
| 94 | |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 95 | while (*ppTimer && (*ppTimer != pTimer)) ppTimer = &(*ppTimer)->next; |
| 96 | if (*ppTimer) *ppTimer = pTimer->next; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 97 | pTimer->next = NULL; |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 98 | |
| 99 | LeaveCriticalSection( &csTimer ); |
| 100 | |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 101 | if (!pTimer->expires) QUEUE_DecTimerCount( pTimer->hq ); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 102 | } |
| 103 | |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 104 | |
| 105 | /*********************************************************************** |
| 106 | * TIMER_ClearTimer |
| 107 | * |
| 108 | * Clear and remove a timer. |
| 109 | */ |
| 110 | static void TIMER_ClearTimer( TIMER * pTimer ) |
| 111 | { |
| 112 | TIMER_RemoveTimer( pTimer ); |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 113 | pTimer->hwnd = 0; |
| 114 | pTimer->msg = 0; |
| 115 | pTimer->id = 0; |
| 116 | pTimer->timeout = 0; |
Alexandre Julliard | df2673b | 1997-03-29 17:20:20 +0000 | [diff] [blame] | 117 | WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER ); |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 118 | } |
| 119 | |
| 120 | |
Alexandre Julliard | c981d0b | 1996-03-31 16:40:13 +0000 | [diff] [blame] | 121 | /*********************************************************************** |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 122 | * TIMER_RemoveWindowTimers |
| 123 | * |
| 124 | * Remove all timers for a given window. |
| 125 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 126 | void TIMER_RemoveWindowTimers( HWND hwnd ) |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 127 | { |
| 128 | int i; |
| 129 | TIMER *pTimer; |
| 130 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 131 | EnterCriticalSection( &csTimer ); |
| 132 | |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 133 | for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++) |
| 134 | if ((pTimer->hwnd == hwnd) && pTimer->timeout) |
| 135 | TIMER_ClearTimer( pTimer ); |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 136 | |
| 137 | LeaveCriticalSection( &csTimer ); |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 138 | } |
| 139 | |
| 140 | |
| 141 | /*********************************************************************** |
| 142 | * TIMER_RemoveQueueTimers |
| 143 | * |
| 144 | * Remove all timers for a given queue. |
| 145 | */ |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 146 | void TIMER_RemoveQueueTimers( HQUEUE16 hqueue ) |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 147 | { |
| 148 | int i; |
| 149 | TIMER *pTimer; |
| 150 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 151 | EnterCriticalSection( &csTimer ); |
| 152 | |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 153 | for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++) |
| 154 | if ((pTimer->hq == hqueue) && pTimer->timeout) |
| 155 | TIMER_ClearTimer( pTimer ); |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 156 | |
| 157 | LeaveCriticalSection( &csTimer ); |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 158 | } |
| 159 | |
| 160 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 161 | /*********************************************************************** |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 162 | * TIMER_RestartTimers |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 163 | * |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 164 | * Restart an expired timer. |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 165 | */ |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 166 | static void TIMER_RestartTimer( TIMER * pTimer, DWORD curTime ) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 167 | { |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 168 | TIMER_RemoveTimer( pTimer ); |
| 169 | pTimer->expires = curTime + pTimer->timeout; |
| 170 | TIMER_InsertTimer( pTimer ); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 171 | } |
| 172 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 173 | /*********************************************************************** |
Ulrich Weigand | 9dcaeca | 1999-05-02 11:30:39 +0000 | [diff] [blame] | 174 | * TIMER_CheckTimers |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 175 | * |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 176 | * Mark expired timers and wake the appropriate queues. |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 177 | */ |
Ulrich Weigand | 9dcaeca | 1999-05-02 11:30:39 +0000 | [diff] [blame] | 178 | static void CALLBACK TIMER_CheckTimers( ULONG_PTR forceTimer ) |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 179 | { |
Ulrich Weigand | 9dcaeca | 1999-05-02 11:30:39 +0000 | [diff] [blame] | 180 | static HANDLE ServiceHandle = INVALID_HANDLE_VALUE; |
| 181 | static LONG ServiceTimeout = 0; |
| 182 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 183 | TIMER *pTimer; |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 184 | DWORD curTime = GetTickCount(); |
| 185 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 186 | EnterCriticalSection( &csTimer ); |
Ulrich Weigand | 9dcaeca | 1999-05-02 11:30:39 +0000 | [diff] [blame] | 187 | |
| 188 | TRACE(timer, "Called at %ld (%s)\n", curTime, forceTimer? "manual" : "auto" ); |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 189 | |
| 190 | pTimer = pNextTimer; |
| 191 | |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 192 | while (pTimer && !pTimer->expires) /* Skip already expired timers */ |
| 193 | pTimer = pTimer->next; |
| 194 | while (pTimer && (pTimer->expires <= curTime)) |
| 195 | { |
| 196 | pTimer->expires = 0; |
| 197 | QUEUE_IncTimerCount( pTimer->hq ); |
| 198 | pTimer = pTimer->next; |
| 199 | } |
Ulrich Weigand | 9dcaeca | 1999-05-02 11:30:39 +0000 | [diff] [blame] | 200 | |
| 201 | /* Install service callback with appropriate timeout, so that |
| 202 | we get called again once the next timer has expired */ |
| 203 | |
| 204 | if (pTimer) |
| 205 | { |
| 206 | LONG timeout = pTimer->expires - curTime; |
| 207 | |
| 208 | if ( forceTimer || timeout != ServiceTimeout ) |
| 209 | { |
| 210 | if ( ServiceHandle != INVALID_HANDLE_VALUE ) |
| 211 | SERVICE_Delete( ServiceHandle ); |
| 212 | |
| 213 | ServiceHandle = SERVICE_AddTimer( timeout * 1000L, |
| 214 | TIMER_CheckTimers, FALSE ); |
| 215 | ServiceTimeout = timeout; |
| 216 | |
| 217 | TRACE(timer, "Installed service callback with timeout %ld\n", timeout ); |
| 218 | } |
| 219 | } |
| 220 | else |
| 221 | { |
| 222 | if ( ServiceHandle != INVALID_HANDLE_VALUE ) |
| 223 | { |
| 224 | SERVICE_Delete( ServiceHandle ); |
| 225 | ServiceHandle = INVALID_HANDLE_VALUE; |
| 226 | ServiceTimeout = 0; |
| 227 | |
| 228 | TRACE(timer, "Deleted service callback\n" ); |
| 229 | } |
| 230 | } |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 231 | |
| 232 | LeaveCriticalSection( &csTimer ); |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 233 | } |
| 234 | |
| 235 | |
| 236 | /*********************************************************************** |
| 237 | * TIMER_GetTimerMsg |
| 238 | * |
| 239 | * Build a message for an expired timer. |
| 240 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 241 | BOOL TIMER_GetTimerMsg( MSG *msg, HWND hwnd, |
| 242 | HQUEUE16 hQueue, BOOL remove ) |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 243 | { |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 244 | TIMER *pTimer; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 245 | DWORD curTime = GetTickCount(); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 246 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 247 | EnterCriticalSection( &csTimer ); |
| 248 | |
| 249 | pTimer = pNextTimer; |
| 250 | |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 251 | if (hwnd) /* Find first timer for this window */ |
| 252 | while (pTimer && (pTimer->hwnd != hwnd)) pTimer = pTimer->next; |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 253 | else /* Find first timer for this queue */ |
| 254 | while (pTimer && (pTimer->hq != hQueue)) pTimer = pTimer->next; |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 255 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 256 | if (!pTimer || (pTimer->expires > curTime)) |
| 257 | { |
| 258 | LeaveCriticalSection( &csTimer ); |
| 259 | return FALSE; /* No timer */ |
| 260 | } |
| 261 | |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 262 | TRACE(timer, "Timer expired: %04x, %04x, %04x, %08lx\n", |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 263 | pTimer->hwnd, pTimer->msg, pTimer->id, (DWORD)pTimer->proc); |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 264 | |
Ulrich Weigand | 9dcaeca | 1999-05-02 11:30:39 +0000 | [diff] [blame] | 265 | if (remove) |
| 266 | { |
| 267 | TIMER_RestartTimer( pTimer, curTime ); /* Restart it */ |
| 268 | TIMER_CheckTimers( TRUE ); |
| 269 | } |
| 270 | |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 271 | /* Build the message */ |
Stephane Lussier | b3a99de | 1999-02-09 15:35:12 +0000 | [diff] [blame] | 272 | msg->hwnd = pTimer->hwnd; |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 273 | msg->message = pTimer->msg; |
Stephane Lussier | b3a99de | 1999-02-09 15:35:12 +0000 | [diff] [blame] | 274 | msg->wParam = pTimer->id; |
Alexandre Julliard | 8d24ae6 | 1994-04-05 21:42:43 +0000 | [diff] [blame] | 275 | msg->lParam = (LONG)pTimer->proc; |
| 276 | msg->time = curTime; |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 277 | |
| 278 | LeaveCriticalSection( &csTimer ); |
| 279 | |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 280 | return TRUE; |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 281 | } |
| 282 | |
| 283 | |
| 284 | /*********************************************************************** |
| 285 | * TIMER_SetTimer |
| 286 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 287 | static UINT TIMER_SetTimer( HWND hwnd, UINT id, UINT timeout, |
| 288 | WNDPROC16 proc, WINDOWPROCTYPE type, BOOL sys ) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 289 | { |
| 290 | int i; |
| 291 | TIMER * pTimer; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 292 | |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 293 | if (!timeout) return 0; |
Alexandre Julliard | 940d58c | 1994-09-16 09:24:37 +0000 | [diff] [blame] | 294 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 295 | EnterCriticalSection( &csTimer ); |
| 296 | |
Alexandre Julliard | 940d58c | 1994-09-16 09:24:37 +0000 | [diff] [blame] | 297 | /* Check if there's already a timer with the same hwnd and id */ |
| 298 | |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 299 | for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++) |
| 300 | if ((pTimer->hwnd == hwnd) && (pTimer->id == id) && |
| 301 | (pTimer->timeout != 0)) |
| 302 | { |
| 303 | /* Got one: set new values and return */ |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 304 | TIMER_RemoveTimer( pTimer ); |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 305 | pTimer->timeout = timeout; |
Alexandre Julliard | df2673b | 1997-03-29 17:20:20 +0000 | [diff] [blame] | 306 | WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER ); |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 307 | pTimer->proc = (HWINDOWPROC)0; |
Alexandre Julliard | df2673b | 1997-03-29 17:20:20 +0000 | [diff] [blame] | 308 | if (proc) WINPROC_SetProc( &pTimer->proc, proc, |
| 309 | type, WIN_PROC_TIMER ); |
Alexandre Julliard | 8b91563 | 1996-06-16 16:16:05 +0000 | [diff] [blame] | 310 | pTimer->expires = GetTickCount() + timeout; |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 311 | TIMER_InsertTimer( pTimer ); |
Ulrich Weigand | 9dcaeca | 1999-05-02 11:30:39 +0000 | [diff] [blame] | 312 | TIMER_CheckTimers( TRUE ); |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 313 | LeaveCriticalSection( &csTimer ); |
Alexandre Julliard | aca0578 | 1994-10-17 18:12:41 +0000 | [diff] [blame] | 314 | return id; |
| 315 | } |
Alexandre Julliard | 940d58c | 1994-09-16 09:24:37 +0000 | [diff] [blame] | 316 | |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 317 | /* Find a free timer */ |
| 318 | |
| 319 | for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++) |
| 320 | if (!pTimer->timeout) break; |
| 321 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 322 | if ( (i >= NB_TIMERS) || |
| 323 | (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) ) |
| 324 | { |
| 325 | LeaveCriticalSection( &csTimer ); |
| 326 | return 0; |
| 327 | } |
| 328 | |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 329 | if (!hwnd) id = i + 1; |
| 330 | |
| 331 | /* Add the timer */ |
| 332 | |
| 333 | pTimer->hwnd = hwnd; |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 334 | pTimer->hq = (hwnd) ? GetThreadQueue16( GetWindowThreadProcessId( hwnd, NULL ) ) |
| 335 | : GetFastQueue16( ); |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 336 | pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER; |
| 337 | pTimer->id = id; |
| 338 | pTimer->timeout = timeout; |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 339 | pTimer->expires = GetTickCount() + timeout; |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 340 | pTimer->proc = (HWINDOWPROC)0; |
Alexandre Julliard | df2673b | 1997-03-29 17:20:20 +0000 | [diff] [blame] | 341 | if (proc) WINPROC_SetProc( &pTimer->proc, proc, type, WIN_PROC_TIMER ); |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 342 | TRACE(timer, "Timer added: %p, %04x, %04x, %04x, %08lx\n", |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 343 | pTimer, pTimer->hwnd, pTimer->msg, pTimer->id, |
| 344 | (DWORD)pTimer->proc ); |
Alexandre Julliard | 5f721f8 | 1994-01-04 20:14:34 +0000 | [diff] [blame] | 345 | TIMER_InsertTimer( pTimer ); |
Ulrich Weigand | 9dcaeca | 1999-05-02 11:30:39 +0000 | [diff] [blame] | 346 | TIMER_CheckTimers( TRUE ); |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 347 | |
| 348 | LeaveCriticalSection( &csTimer ); |
| 349 | |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 350 | if (!id) return TRUE; |
| 351 | else return id; |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 352 | } |
| 353 | |
| 354 | |
| 355 | /*********************************************************************** |
| 356 | * TIMER_KillTimer |
| 357 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 358 | static BOOL TIMER_KillTimer( HWND hwnd, UINT id, BOOL sys ) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 359 | { |
| 360 | int i; |
| 361 | TIMER * pTimer; |
| 362 | |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 363 | EnterCriticalSection( &csTimer ); |
| 364 | |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 365 | /* Find the timer */ |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 366 | |
| 367 | for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++) |
| 368 | if ((pTimer->hwnd == hwnd) && (pTimer->id == id) && |
| 369 | (pTimer->timeout != 0)) break; |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 370 | |
| 371 | if ( (i >= NB_TIMERS) || |
| 372 | (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) || |
| 373 | (!sys && (pTimer->msg != WM_TIMER)) || |
| 374 | (sys && (pTimer->msg != WM_SYSTIMER)) ) |
| 375 | { |
| 376 | LeaveCriticalSection( &csTimer ); |
| 377 | return FALSE; |
| 378 | } |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 379 | |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 380 | /* Delete the timer */ |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 381 | |
Alexandre Julliard | ef702d8 | 1996-05-28 18:54:58 +0000 | [diff] [blame] | 382 | TIMER_ClearTimer( pTimer ); |
Stephane Lussier | 35ffc5d | 1999-03-25 13:23:26 +0000 | [diff] [blame] | 383 | |
| 384 | LeaveCriticalSection( &csTimer ); |
| 385 | |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 386 | return TRUE; |
| 387 | } |
| 388 | |
| 389 | |
| 390 | /*********************************************************************** |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 391 | * SetTimer16 (USER.10) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 392 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 393 | UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout, |
| 394 | TIMERPROC16 proc ) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 395 | { |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 396 | TRACE(timer, "%04x %d %d %08lx\n", |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 397 | hwnd, id, timeout, (LONG)proc ); |
| 398 | return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, |
| 399 | WIN_PROC_16, FALSE ); |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 400 | } |
| 401 | |
| 402 | |
| 403 | /*********************************************************************** |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 404 | * SetTimer32 (USER32.511) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 405 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 406 | UINT WINAPI SetTimer( HWND hwnd, UINT id, UINT timeout, |
| 407 | TIMERPROC proc ) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 408 | { |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 409 | TRACE(timer, "%04x %d %d %08lx\n", |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 410 | hwnd, id, timeout, (LONG)proc ); |
| 411 | return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, |
| 412 | WIN_PROC_32A, FALSE ); |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 413 | } |
| 414 | |
| 415 | |
| 416 | /*********************************************************************** |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 417 | * SetSystemTimer16 (USER.11) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 418 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 419 | UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout, |
| 420 | TIMERPROC16 proc ) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 421 | { |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 422 | TRACE(timer, "%04x %d %d %08lx\n", |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 423 | hwnd, id, timeout, (LONG)proc ); |
| 424 | return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, |
| 425 | WIN_PROC_16, TRUE ); |
| 426 | } |
| 427 | |
| 428 | |
| 429 | /*********************************************************************** |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 430 | * SetSystemTimer32 (USER32.509) |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 431 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 432 | UINT WINAPI SetSystemTimer( HWND hwnd, UINT id, UINT timeout, |
| 433 | TIMERPROC proc ) |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 434 | { |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 435 | TRACE(timer, "%04x %d %d %08lx\n", |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 436 | hwnd, id, timeout, (LONG)proc ); |
| 437 | return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, |
| 438 | WIN_PROC_32A, TRUE ); |
| 439 | } |
| 440 | |
| 441 | |
| 442 | /*********************************************************************** |
| 443 | * KillTimer16 (USER.12) |
| 444 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 445 | BOOL16 WINAPI KillTimer16( HWND16 hwnd, UINT16 id ) |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 446 | { |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 447 | TRACE(timer, "%04x %d\n", hwnd, id ); |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 448 | return TIMER_KillTimer( hwnd, id, FALSE ); |
| 449 | } |
| 450 | |
| 451 | |
| 452 | /*********************************************************************** |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 453 | * KillTimer32 (USER32.354) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 454 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 455 | BOOL WINAPI KillTimer( HWND hwnd, UINT id ) |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 456 | { |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 457 | TRACE(timer, "%04x %d\n", hwnd, id ); |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 458 | return TIMER_KillTimer( hwnd, id, FALSE ); |
| 459 | } |
| 460 | |
| 461 | |
| 462 | /*********************************************************************** |
| 463 | * KillSystemTimer16 (USER.182) |
| 464 | */ |
Alexandre Julliard | 670cdc4 | 1997-08-24 16:00:30 +0000 | [diff] [blame] | 465 | BOOL16 WINAPI KillSystemTimer16( HWND16 hwnd, UINT16 id ) |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 466 | { |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 467 | TRACE(timer, "%04x %d\n", hwnd, id ); |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 468 | return TIMER_KillTimer( hwnd, id, TRUE ); |
| 469 | } |
| 470 | |
| 471 | |
| 472 | /*********************************************************************** |
Alexandre Julliard | c7c217b | 1998-04-13 12:21:30 +0000 | [diff] [blame] | 473 | * KillSystemTimer32 (USER32.353) |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 474 | */ |
Alexandre Julliard | a396029 | 1999-02-26 11:11:13 +0000 | [diff] [blame] | 475 | BOOL WINAPI KillSystemTimer( HWND hwnd, UINT id ) |
Alexandre Julliard | ca22b33 | 1996-07-12 19:02:39 +0000 | [diff] [blame] | 476 | { |
Alexandre Julliard | a69b88b | 1998-03-15 20:29:56 +0000 | [diff] [blame] | 477 | TRACE(timer, "%04x %d\n", hwnd, id ); |
Alexandre Julliard | 401710d | 1993-09-04 10:09:32 +0000 | [diff] [blame] | 478 | return TIMER_KillTimer( hwnd, id, TRUE ); |
| 479 | } |