/* C K N A L M  --  Kermit alarm functions for Windows 95 systems */

/*
  Author: Jeffrey Altman (jaltman@secure-endpoints.com),
            Secure Endpoints Inc., New York City.

  Copyright (C) 1996,2004 Trustees of Columbia University in the City of New
  York.
*/

/* We are performing this ugly hack only because Windows 95 can not implement 
   a timer that works accurately on all computer systems with Console
   Applications.  This code should not be used for Windows NT or other Win32
   implementations
*/

#include <windows.h>

#define TIMER_COUNT 65
struct _timerInfo
{
   UINT   id ;
   ULONG  interval ;
   LPTIMECALLBACK pTimeProc ;
   DWORD  userdata ;
   LONG   event ;
   BOOL   inuse ;
} timers[TIMER_COUNT] =
{{0,0,0,0,0,0},{1,0,0,0,0,0},{2,0,0,0,0,0},{3,0,0,0,0,0},{4,0,0,0,0,0},{5,0,0,0,0,0},
 {6,0,0,0,0,0},{7,0,0,0,0,0},{8,0,0,0,0,0},{9,0,0,0,0,0},
 {10,0,0,0,0,0},{11,0,0,0,0,0},{12,0,0,0,0,0},{13,0,0,0,0,0},{14,0,0,0,0,0},{15,0,0,0,0,0},
 {16,0,0,0,0,0},{17,0,0,0,0,0},{18,0,0,0,0,0},{19,0,0,0,0,0},
 {20,0,0,0,0,0},{21,0,0,0,0,0},{22,0,0,0,0,0},{23,0,0,0,0,0},{24,0,0,0,0,0},{25,0,0,0,0,0},
 {26,0,0,0,0,0},{27,0,0,0,0,0},{28,0,0,0,0,0},{29,0,0,0,0,0},
 {30,0,0,0,0,0},{31,0,0,0,0,0},{32,0,0,0,0,0},{33,0,0,0,0,0},{34,0,0,0,0,0},{35,0,0,0,0,0},
 {36,0,0,0,0,0},{37,0,0,0,0,0},{38,0,0,0,0,0},{39,0,0,0,0,0},
 {40,0,0,0,0,0},{41,0,0,0,0,0},{42,0,0,0,0,0},{43,0,0,0,0,0},{44,0,0,0,0,0},{45,0,0,0,0,0},
 {46,0,0,0,0,0},{47,0,0,0,0,0},{48,0,0,0,0,0},{49,0,0,0,0,0},
 {50,0,0,0,0,0},{51,0,0,0,0,0},{52,0,0,0,0,0},{53,0,0,0,0,0},{54,0,0,0,0,0},{55,0,0,0,0,0},
 {56,0,0,0,0,0},{57,0,0,0,0,0},{58,0,0,0,0,0},{59,0,0,0,0,0},
 {60,0,0,0,0,0},{61,0,0,0,0,0},{62,0,0,0,0,0},{63,0,0,0,0,0},{64,0,0,0,0,0}
};

void
TimerThread( void * data )
{
   int tt = 0, interval = 250 , t = 0, tr = 0 ;
   struct _timerInfo * ti = (struct _timerInfo *) data ;
   tt = (ti->interval / interval) ;
   tr = (ti->interval % interval) ;
   if ( tt )
      interval += tr / tt ;
   else
   {
      tt = 1 ;
      interval = tr ;
   }

   do {
      for ( t = 0 ; t < tt ; t++ )
      {
         Sleep( interval ) ;
         if ( ti->event < 0 )
         {
            ti->inuse = 0 ;
            _endthread();
         }
      }
      if ( ti->event < 0 )
         break;
      (*ti->pTimeProc)( ti->id, 0, ti->userdata, 0, 0 ) ;
   } while ( ti->event == TIME_PERIODIC );
   ti->inuse = 0 ;
   _endthread() ;
}

UINT
ckTimerStart( UINT interval, UINT precision, LPTIMECALLBACK pTimeProc, DWORD userdata, UINT event )
{
   int i = 1;
   while ( timers[i].inuse )
   {
      if ( ++i >= TIMER_COUNT )
      {
         i = 1 ;
         Sleep(100) ;
      }
   }
   timers[i].interval = interval ;
   timers[i].pTimeProc = pTimeProc ;
   timers[i].userdata = userdata ;
   timers[i].event = event ;
   timers[i].inuse = 1 ;

   if ( (HANDLE) _beginthread( TimerThread, 65536, &timers[i] ) != (HANDLE) INVALID_HANDLE_VALUE )
      return i ;
   else
      return 0 ;
}

UINT
ckTimerKill( UINT i )
{
   if ( timers[i].inuse )
       timers[i].event = -1 ;
   return 1;
}