226 lines
5.6 KiB
C
226 lines
5.6 KiB
C
/*
|
|
* Timer functions
|
|
*
|
|
* Copyright 1993 Alexandre Julliard
|
|
*/
|
|
|
|
static char Copyright[] = "Copyright Alexandre Julliard, 1993";
|
|
|
|
#include "windows.h"
|
|
#include "message.h"
|
|
|
|
|
|
typedef struct tagTIMER
|
|
{
|
|
HWND hwnd;
|
|
WORD msg; /* WM_TIMER or WM_SYSTIMER */
|
|
WORD id;
|
|
WORD timeout;
|
|
struct tagTIMER *next;
|
|
DWORD expires;
|
|
FARPROC proc;
|
|
} TIMER;
|
|
|
|
#define NB_TIMERS 34
|
|
#define NB_RESERVED_TIMERS 2 /* for SetSystemTimer */
|
|
|
|
static TIMER TimersArray[NB_TIMERS];
|
|
|
|
static TIMER * pNextTimer = NULL; /* Next timer to expire */
|
|
|
|
|
|
/***********************************************************************
|
|
* TIMER_InsertTimer
|
|
*
|
|
* Insert the timer at its place in the chain.
|
|
*/
|
|
static void TIMER_InsertTimer( TIMER * pTimer )
|
|
{
|
|
if (!pNextTimer || (pTimer->expires < pNextTimer->expires))
|
|
{
|
|
pTimer->next = pNextTimer;
|
|
pNextTimer = pTimer;
|
|
}
|
|
else
|
|
{
|
|
TIMER * ptr = pNextTimer;
|
|
while (ptr->next && (pTimer->expires >= ptr->next->expires))
|
|
ptr = ptr->next;
|
|
pTimer->next = ptr;
|
|
ptr->next = pTimer;
|
|
}
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* TIMER_RemoveTimer
|
|
*
|
|
* Remove the timer from the chain.
|
|
*/
|
|
static void TIMER_RemoveTimer( TIMER * pTimer )
|
|
{
|
|
if (pTimer == pNextTimer) pNextTimer = pTimer->next;
|
|
else
|
|
{
|
|
TIMER * ptr = pNextTimer;
|
|
while (ptr && (ptr->next != pTimer)) ptr = ptr->next;
|
|
if (ptr) ptr->next = pTimer->next;
|
|
}
|
|
pTimer->next = NULL;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* TIMER_NextExpire
|
|
*
|
|
* Return time until next timer expiration (-1 if none).
|
|
*/
|
|
static DWORD TIMER_NextExpire( DWORD curTime )
|
|
{
|
|
if (!pNextTimer) return -1;
|
|
if (pNextTimer->expires <= curTime) return 0;
|
|
return pNextTimer->expires - curTime;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* TIMER_CheckTimer
|
|
*
|
|
* Check whether a timer has expired, and post a message if necessary.
|
|
* Return TRUE if msg posted, and return time until next expiration in 'next'.
|
|
*/
|
|
BOOL TIMER_CheckTimer( DWORD *next )
|
|
{
|
|
TIMER * pTimer = pNextTimer;
|
|
DWORD curTime = GetTickCount();
|
|
|
|
if ((*next = TIMER_NextExpire( curTime )) != 0) return FALSE;
|
|
|
|
PostMessage( pTimer->hwnd, pTimer->msg, pTimer->id, (LONG)pTimer->proc );
|
|
TIMER_RemoveTimer( pTimer );
|
|
|
|
/* If timeout == 0, the timer has been removed by KillTimer */
|
|
if (pTimer->timeout)
|
|
{
|
|
/* Restart the timer */
|
|
pTimer->expires = curTime + pTimer->timeout;
|
|
TIMER_InsertTimer( pTimer );
|
|
}
|
|
*next = TIMER_NextExpire( curTime );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* TIMER_SetTimer
|
|
*/
|
|
static WORD TIMER_SetTimer( HWND hwnd, WORD id, WORD timeout,
|
|
FARPROC proc, BOOL sys )
|
|
{
|
|
int i;
|
|
TIMER * pTimer;
|
|
|
|
if (!timeout) return 0;
|
|
if (!hwnd && !proc) return 0;
|
|
|
|
/* Find a free timer */
|
|
|
|
for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
|
|
if (!pTimer->timeout) break;
|
|
|
|
if (i >= NB_TIMERS) return 0;
|
|
if (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) return 0;
|
|
if (!hwnd) id = i + 1;
|
|
|
|
/* Add the timer */
|
|
|
|
pTimer->hwnd = hwnd;
|
|
pTimer->msg = sys ? WM_SYSTIMER : WM_TIMER;
|
|
pTimer->id = id;
|
|
pTimer->timeout = timeout;
|
|
pTimer->expires = GetTickCount() + timeout;
|
|
pTimer->proc = proc;
|
|
TIMER_InsertTimer( pTimer );
|
|
MSG_IncTimerCount( GetTaskQueue(0) );
|
|
return id;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* TIMER_KillTimer
|
|
*/
|
|
static BOOL TIMER_KillTimer( HWND hwnd, WORD id, BOOL sys )
|
|
{
|
|
int i;
|
|
TIMER * pTimer;
|
|
|
|
/* Find the timer */
|
|
|
|
for (i = 0, pTimer = TimersArray; i < NB_TIMERS; i++, pTimer++)
|
|
if ((pTimer->hwnd == hwnd) && (pTimer->id == id) &&
|
|
(pTimer->timeout != 0)) break;
|
|
if (i >= NB_TIMERS) return FALSE;
|
|
if (!sys && (i >= NB_TIMERS-NB_RESERVED_TIMERS)) return FALSE;
|
|
if (!sys && (pTimer->msg != WM_TIMER)) return FALSE;
|
|
else if (sys && (pTimer->msg != WM_SYSTIMER)) return FALSE;
|
|
|
|
/* Delete the timer */
|
|
|
|
pTimer->hwnd = 0;
|
|
pTimer->msg = 0;
|
|
pTimer->id = 0;
|
|
pTimer->timeout = 0;
|
|
pTimer->proc = 0;
|
|
TIMER_RemoveTimer( pTimer );
|
|
MSG_DecTimerCount( GetTaskQueue(0) );
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SetTimer (USER.10)
|
|
*/
|
|
WORD SetTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc )
|
|
{
|
|
#ifdef DEBUG_TIMER
|
|
printf( "SetTimer: %d %d %d %p\n", hwnd, id, timeout, proc );
|
|
#endif
|
|
return TIMER_SetTimer( hwnd, id, timeout, proc, FALSE );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* SetSystemTimer (USER.11)
|
|
*/
|
|
WORD SetSystemTimer( HWND hwnd, WORD id, WORD timeout, FARPROC proc )
|
|
{
|
|
#ifdef DEBUG_TIMER
|
|
printf( "SetSystemTimer: %d %d %d %p\n", hwnd, id, timeout, proc );
|
|
#endif
|
|
return TIMER_SetTimer( hwnd, id, timeout, proc, TRUE );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* KillTimer (USER.12)
|
|
*/
|
|
BOOL KillTimer( HWND hwnd, WORD id )
|
|
{
|
|
#ifdef DEBUG_TIMER
|
|
printf( "KillTimer: %d %d\n", hwnd, id );
|
|
#endif
|
|
return TIMER_KillTimer( hwnd, id, FALSE );
|
|
}
|
|
|
|
|
|
/***********************************************************************
|
|
* KillSystemTimer (USER.182)
|
|
*/
|
|
BOOL KillSystemTimer( HWND hwnd, WORD id )
|
|
{
|
|
#ifdef DEBUG_TIMER
|
|
printf( "KillSystemTimer: %d %d\n", hwnd, id );
|
|
#endif
|
|
return TIMER_KillTimer( hwnd, id, TRUE );
|
|
}
|