Fix some types and function prototypes according to Platform SDK
[wine] / windows / timer.c
1 /*
2  * Timer functions
3  *
4  * Copyright 1993 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "windef.h"
22 #include "wingdi.h"
23 #include "wine/winuser16.h"
24 #include "winuser.h"
25 #include "winerror.h"
26
27 #include "winproc.h"
28 #include "message.h"
29 #include "win.h"
30 #include "wine/server.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(timer);
34
35
36 typedef struct tagTIMER
37 {
38     HWND           hwnd;
39     DWORD          thread;
40     UINT           msg;  /* WM_TIMER or WM_SYSTIMER */
41     UINT           id;
42     UINT           timeout;
43     HWINDOWPROC    proc;
44 } TIMER;
45
46 #define NB_TIMERS            34
47 #define NB_RESERVED_TIMERS    2  /* for SetSystemTimer */
48
49 #define SYS_TIMER_RATE  55   /* min. timer rate in ms (actually 54.925)*/
50
51 static TIMER TimersArray[NB_TIMERS];
52
53 static CRITICAL_SECTION csTimer = CRITICAL_SECTION_INIT("csTimer");
54
55
56 /***********************************************************************
57  *           TIMER_ClearTimer
58  *
59  * Clear and remove a timer.
60  */
61 static void TIMER_ClearTimer( TIMER * pTimer )
62 {
63     pTimer->hwnd    = 0;
64     pTimer->msg     = 0;
65     pTimer->id      = 0;
66     pTimer->timeout = 0;
67     WINPROC_FreeProc( pTimer->proc, WIN_PROC_TIMER );
68 }
69
70
71 /***********************************************************************
72  *           TIMER_RemoveWindowTimers
73  *
74  * Remove all timers for a given window.
75  */
76 void TIMER_RemoveWindowTimers( HWND hwnd )
77 {
78     int i;
79     TIMER *pTimer;
80
81     EnterCriticalSection( &csTimer );
82
83     for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
84         if ((pTimer->hwnd == hwnd) && pTimer->timeout)
85             TIMER_ClearTimer( pTimer );
86
87     LeaveCriticalSection( &csTimer );
88 }
89
90
91 /***********************************************************************
92  *           TIMER_RemoveThreadTimers
93  *
94  * Remove all timers for the current thread.
95  */
96 void TIMER_RemoveThreadTimers(void)
97 {
98     int i;
99     TIMER *pTimer;
100
101     EnterCriticalSection( &csTimer );
102
103     for (i = NB_TIMERS, pTimer = TimersArray; i > 0; i--, pTimer++)
104         if ((pTimer->thread == GetCurrentThreadId()) && pTimer->timeout)
105             TIMER_ClearTimer( pTimer );
106
107     LeaveCriticalSection( &csTimer );
108 }
109
110
111 /***********************************************************************
112  *           TIMER_SetTimer
113  */
114 static UINT_PTR TIMER_SetTimer( HWND hwnd, UINT_PTR id, UINT timeout,
115                               WNDPROC16 proc, WINDOWPROCTYPE type, BOOL sys )
116 {
117     int i;
118     TIMER * pTimer;
119     HWINDOWPROC winproc = 0;
120
121     if (hwnd && !(hwnd = WIN_IsCurrentThread( hwnd )))
122     {
123         SetLastError( ERROR_INVALID_WINDOW_HANDLE );
124         return 0;
125     }
126
127     if (!timeout)
128       {       /* timeout==0 is a legal argument  UB 990821*/
129        WARN("Timeout== 0 not implemented, using timeout=1\n");
130         timeout=1;
131       }
132
133     EnterCriticalSection( &csTimer );
134
135       /* Check if there's already a timer with the same hwnd and id */
136
137     for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
138         if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
139             (pTimer->timeout != 0))
140         {
141             TIMER_ClearTimer( pTimer );
142             break;
143         }
144
145     if ( i == NB_TIMERS )
146     {
147           /* Find a free timer */
148
149         for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
150             if (!pTimer->timeout) break;
151
152         if ( (i >= NB_TIMERS) ||
153              (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) )
154         {
155             LeaveCriticalSection( &csTimer );
156             return 0;
157         }
158     }
159
160     if (!hwnd) id = i + 1;
161
162     if (proc) WINPROC_SetProc( &winproc, proc, type, WIN_PROC_TIMER );
163
164     SERVER_START_REQ( set_win_timer )
165     {
166         req->win    = hwnd;
167         req->msg    = sys ? WM_SYSTIMER : WM_TIMER;
168         req->id     = id;
169         req->rate   = max( timeout, SYS_TIMER_RATE );
170         req->lparam = (unsigned int)winproc;
171         wine_server_call( req );
172     }
173     SERVER_END_REQ;
174
175       /* Add the timer */
176
177     pTimer->hwnd    = hwnd;
178     pTimer->thread  = GetCurrentThreadId();
179     pTimer->msg     = sys ? WM_SYSTIMER : WM_TIMER;
180     pTimer->id      = id;
181     pTimer->timeout = timeout;
182     pTimer->proc    = winproc;
183
184     TRACE("Timer added: %p, %04x, %04x, %04x, %08lx\n",
185                    pTimer, pTimer->hwnd, pTimer->msg, pTimer->id,
186                    (DWORD)pTimer->proc );
187
188     LeaveCriticalSection( &csTimer );
189
190     if (!id) return TRUE;
191     else return id;
192 }
193
194
195 /***********************************************************************
196  *           TIMER_KillTimer
197  */
198 static BOOL TIMER_KillTimer( HWND hwnd, UINT_PTR id, BOOL sys )
199 {
200     int i;
201     TIMER * pTimer;
202
203     SERVER_START_REQ( kill_win_timer )
204     {
205         req->win = hwnd;
206         req->msg = sys ? WM_SYSTIMER : WM_TIMER;
207         req->id  = id;
208         wine_server_call( req );
209     }
210     SERVER_END_REQ;
211
212     EnterCriticalSection( &csTimer );
213
214     /* Find the timer */
215
216     for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
217         if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
218             (pTimer->timeout != 0)) break;
219
220     if ( (i >= NB_TIMERS) ||
221          (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) ||
222          (!sys && (pTimer->msg != WM_TIMER)) ||
223          (sys && (pTimer->msg != WM_SYSTIMER)) )
224     {
225         LeaveCriticalSection( &csTimer );
226         return FALSE;
227     }
228
229     /* Delete the timer */
230
231     TIMER_ClearTimer( pTimer );
232
233     LeaveCriticalSection( &csTimer );
234
235     return TRUE;
236 }
237
238
239 /***********************************************************************
240  *              SetTimer (USER.10)
241  */
242 UINT16 WINAPI SetTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
243                           TIMERPROC16 proc )
244 {
245     TRACE("%04x %d %d %08lx\n",
246                    hwnd, id, timeout, (LONG)proc );
247     return TIMER_SetTimer( WIN_Handle32(hwnd), id, timeout, (WNDPROC16)proc,
248                            WIN_PROC_16, FALSE );
249 }
250
251
252 /***********************************************************************
253  *              SetTimer (USER32.@)
254  */
255 UINT_PTR WINAPI SetTimer( HWND hwnd, UINT_PTR id, UINT timeout,
256                           TIMERPROC proc )
257 {
258     TRACE("%04x %d %d %08lx\n",
259                    hwnd, id, timeout, (LONG)proc );
260     return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, WIN_PROC_32A, FALSE );
261 }
262
263
264 /***********************************************************************
265  *           TIMER_IsTimerValid
266  */
267 BOOL TIMER_IsTimerValid( HWND hwnd, UINT_PTR id, HWINDOWPROC hProc )
268 {
269     int i;
270     TIMER *pTimer;
271     BOOL ret = FALSE;
272
273     hwnd = WIN_GetFullHandle( hwnd );
274     EnterCriticalSection( &csTimer );
275
276     for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
277         if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
278             (pTimer->proc == hProc))
279         {
280             ret = TRUE;
281             break;
282         }
283
284    LeaveCriticalSection( &csTimer );
285    return ret;
286 }
287
288
289 /***********************************************************************
290  *              SetSystemTimer (USER.11)
291  */
292 UINT16 WINAPI SetSystemTimer16( HWND16 hwnd, UINT16 id, UINT16 timeout,
293                                 TIMERPROC16 proc )
294 {
295     TRACE("%04x %d %d %08lx\n",
296                    hwnd, id, timeout, (LONG)proc );
297     return TIMER_SetTimer( WIN_Handle32(hwnd), id, timeout, (WNDPROC16)proc,
298                            WIN_PROC_16, TRUE );
299 }
300
301
302 /***********************************************************************
303  *              SetSystemTimer (USER32.@)
304  */
305 UINT_PTR WINAPI SetSystemTimer( HWND hwnd, UINT_PTR id, UINT timeout,
306                                 TIMERPROC proc )
307 {
308     TRACE("%04x %d %d %08lx\n",
309                    hwnd, id, timeout, (LONG)proc );
310     return TIMER_SetTimer( hwnd, id, timeout, (WNDPROC16)proc, WIN_PROC_32A, TRUE );
311 }
312
313
314 /***********************************************************************
315  *              KillTimer (USER32.@)
316  */
317 BOOL WINAPI KillTimer( HWND hwnd, UINT_PTR id )
318 {
319     TRACE("%04x %d\n", hwnd, id );
320     return TIMER_KillTimer( hwnd, id, FALSE );
321 }
322
323
324 /***********************************************************************
325  *              KillSystemTimer (USER32.@)
326  */
327 BOOL WINAPI KillSystemTimer( HWND hwnd, UINT_PTR id )
328 {
329     TRACE("%04x %d\n", hwnd, id );
330     return TIMER_KillTimer( hwnd, id, TRUE );
331 }