home *** CD-ROM | disk | FTP | other *** search
/ Monster Media 1994 #1 / monster.zip / monster / PROG_GEN / FACETV.ZIP / TIMERCTL.CPP < prev    next >
C/C++ Source or Header  |  1994-01-05  |  8KB  |  329 lines

  1. /************************************************************************
  2. **
  3. ** @(#)timerctl.cpp    01/05/94    Chris Ahlstrom
  4. **
  5. **    C++ Borland/Microsoft
  6. **
  7. **    Defines the default routines for the base class TimerControl.
  8. ** This class implements a pretty simple and straightforward way
  9. ** of handling multiple timers.  The default routines, though, can't
  10. ** really manage more than one DOS timer at once.  However, the objects
  11. ** make good repositories for timing information for each timer that
  12. ** might be needed consecutively in a DOS application.
  13. **
  14. **    The Windows version of the class, WinTimerControl, can implement
  15. ** more than one timer simultaneously.
  16. **
  17. **    One issue to consider is how to implement multiple consecutive
  18. ** timers -- should the duration of each be simply that which is needed,
  19. ** or should it be the cumulative sum of all previous timers, plus
  20. ** the duration of the current timer?
  21. **
  22. *************************************************************************/
  23.  
  24. #define TIMERCTL_cpp
  25.  
  26. #if !defined(_Windows)                    // { _Windows
  27.  
  28. #include <dos.h>            // DOS delay()
  29.  
  30. #else                            // }{ _Windows
  31.  
  32. void
  33. delay(int msec)                // Windows fake delay()
  34. {
  35. }
  36.  
  37. #endif                            // } _Windows
  38.  
  39. #include <stdio.h>            // sprintf()
  40.  
  41. #include "timerctl.h"            // TimerControl class declaration
  42.  
  43.  
  44. /************************************************************************
  45. ** TimerControl constructors and destructor
  46. **
  47. **    A couple of notes.... First, although the duration can be
  48. ** specified to msec precision, the timer used is the DOS timer,
  49. ** which ticks about 18 times per second.  Hence it has a true coarseness
  50. ** of about 50 ms.
  51. **
  52. *************************************************************************/
  53.  
  54. TimerControl::TimerControl        // constructor
  55. (
  56.     void *master,            // points to TDeskTop or HWND
  57.     int number,                // ID code for the timer
  58.     unsigned duration,            // minimum duration of timer (msec)
  59.     int count                // times to allow timer-handling
  60. ) :
  61.     Handle        (master),        // window/desktop handle
  62.     ID            (number),        // ID code of timer
  63.     Duration        (duration),        // duration of timer (ms)
  64.     Count        (count),        // times to handle the timer
  65.     Useable        (0),            // is timer working?
  66.     Next        (0),            // pointer to next timer
  67.     errorCode        (0),            // no errors to start with
  68.     errorMsg        ((char *)0),        // no message to start with
  69.     errorMsgList    (&timerErrors[0]),    // a list of messages
  70.     errorMsgCount    (ERR_TIMER_MAX)        // the number of them
  71. {
  72.     (void) setupTimer(Duration);
  73. }
  74.  
  75.  
  76. TimerControl::~TimerControl ()
  77. {
  78. }
  79.  
  80.  
  81. /************************************************************************
  82. ** TimerControl::setupTimer()
  83. **
  84. **    The DOS version does nothing except alter the nominal duration.
  85. ** It returns a 1 if the setup succeeded, and a 0 otherwise.
  86. **
  87. *************************************************************************/
  88.  
  89. int
  90. TimerControl::setupTimer
  91. (
  92.     unsigned duration
  93. )
  94. {
  95.     int errcode = 0;
  96.  
  97.     if (duration > 0)
  98.     {
  99.     Duration    = duration;
  100.     Useable        = 1;
  101.     }
  102.     else
  103.     {
  104.     Duration    = 0;
  105.     Useable        = 0;
  106.     errcode        = ERR_TIMER_SETUP;
  107.     }
  108.     setErrorCode(errcode);
  109.     return errcode;
  110. }
  111.  
  112.  
  113. /************************************************************************
  114. ** TimerControl::timerDelay()
  115. **
  116. **    Delays for the Duration, without exiting immediately.
  117. ** While active, no other DOS functions can be executed.  Returns
  118. ** an error code if necessary.
  119. **
  120. *************************************************************************/
  121.  
  122. int
  123. TimerControl::timerDelay ()
  124. {
  125.     int errcode = 0;
  126.  
  127.     if (Useable)
  128.     delay(Duration);
  129.     else
  130.     errcode = ERR_TIMER_DELAY;
  131.  
  132.     (void) decrementCount();
  133.     setErrorCode(errcode);
  134.     return errcode;
  135. }
  136.  
  137.  
  138. /************************************************************************
  139. ** TimerControl::disableTimer()
  140. **
  141. **    Renders the timer unuseable.
  142. **
  143. *************************************************************************/
  144.  
  145. int
  146. TimerControl::disableTimer ()
  147. {
  148.     int errcode = 0;
  149.  
  150.     if (Useable)
  151.     Useable = 0;
  152.     else
  153.     errcode = ERR_TIMER_DISABLE;
  154.  
  155.     setErrorCode(errcode);
  156.     return errcode;
  157. }
  158.  
  159.  
  160. /************************************************************************
  161. ** TimerControl::decrementCount()
  162. **
  163. **    Provides access to the Count value.  The current value is
  164. ** returned, and Count is decremented.  However, if Count is
  165. ** TIMER_IGNORE_COUNT, then nothing is done, and 1 is returned.
  166. **
  167. *************************************************************************/
  168.  
  169. int
  170. TimerControl::decrementCount ()
  171. {
  172.     int count = Count;
  173.  
  174.     if (count == TIMER_IGNORE_COUNT)
  175.     count = 1;
  176.     else
  177.     {
  178.     if (count > 0)
  179.     {
  180.         count--;
  181.         Count = count;
  182.     }
  183.     else if (count == 0)
  184.         disableTimer();
  185.     }
  186.     return count;
  187. }
  188.  
  189.  
  190. /************************************************************************
  191. ** TimerControl::attach()
  192. **
  193. **    Lets a timer attach another timer to itself, useful for
  194. ** implementing a singly-linked list of timers.
  195. **
  196. ** TimerControl::next()
  197. **
  198. **    Returns the next timer.
  199. **
  200. ** TimerControl friend deleteTimer()
  201. **
  202. **    This function destroys the linked list of TimerControls,
  203. ** starting at the timer specified (it usually had better be the
  204. ** first timer).  It calls itself recursively to get to the last
  205. ** field, then starts deleting backwards.
  206. **
  207. *************************************************************************/
  208.  
  209. int
  210. TimerControl::attach
  211. (
  212.     TimerControl *lasttimer
  213. )
  214. {
  215.     int errcode = 0;
  216.  
  217.     if (lasttimer)
  218.     lasttimer->Next = this;
  219.     else
  220.     errcode = ERR_TIMER_CANT_INSERT;
  221.  
  222.     return errcode;
  223. }
  224.  
  225.  
  226. TimerControl *
  227. TimerControl::next ()
  228. {
  229.     return Next;
  230. }
  231.  
  232.  
  233. void
  234. deleteTimer
  235. (
  236.     TimerControl *timer
  237. )
  238. {
  239.     if (timer)
  240.     {
  241.     if (timer->Next)
  242.         deleteTimer(timer->Next);
  243.     delete timer;
  244.     }
  245. }
  246.  
  247.  
  248. /************************************************************************
  249. ** TimerControl::isError()
  250. **
  251. **    Returns a 1 if the errorCode is non-zero.
  252. **
  253. **    Should not need overriding, unless some quantum increase
  254. ** in robustness is need for a particular object.  I don't even
  255. ** know if you can override an inline function.
  256. **
  257. **    This function is meant as a much faster alternative to calling
  258. ** getError() to see if there is an error message pending.
  259. **
  260. **    Use isError() if you know that there's no built-in error return
  261. ** code for a particular function.
  262. **
  263. **    See the header file timerctl.h for the definition.
  264. **
  265. *************************************************************************/
  266.  
  267.  
  268.  
  269. /************************************************************************
  270. ** TimerControl::getErrorMsg()
  271. **
  272. **    Simply returns a pointer to the latest error message.  If there
  273. ** is no error pending, a NULL is returned.
  274. **
  275. **    This routine should not need to be overridden.
  276. **
  277. *************************************************************************/
  278.  
  279. const char *
  280. TimerControl::getErrorMsg (void)    // get pointer to message
  281. {
  282.     if (errorCode)
  283.     return errorMsg;        // hopefully, it's not null
  284.     else
  285.     return (char *) 0;        // hopefully, it's null <grin>
  286. }
  287.  
  288.  
  289. /************************************************************************
  290. ** TimerControl::setErrorCode()
  291. **
  292. **    All routines that perform a function that can err should
  293. ** call this routine to set both errorCode and errorMsg, even if there
  294. ** is no error.
  295. **
  296. **    This routine should not need to be overridden.  However,
  297. ** it should be overridden when the source of messages is not the
  298. ** errorMsgList.  See xbpa4.cpp for a good example.
  299. **
  300. *************************************************************************/
  301.  
  302. #define DEFAULTMESSAGEFORMAT    "%%Error code %d; see source code."
  303.  
  304. static char defaultMessage[48];        // for assembling basic message
  305.  
  306. void
  307. TimerControl::setErrorCode
  308. (
  309.     int index
  310. )
  311. {
  312.     if (errorMsgCount <= 0)
  313.     {
  314.     if (index != 0)
  315.     {
  316.         sprintf(defaultMessage, DEFAULTMESSAGEFORMAT, index);
  317.         errorMsg = defaultMessage;
  318.     }
  319.     }
  320.     else
  321.     {
  322.     if (index > 0 && index < errorMsgCount)
  323.         errorMsg = errorMsgList[index];    // hopefully, it's not null
  324.     else
  325.         errorMsg = (char *) 0;        // no list for this device
  326.     }
  327.     errorCode = index;
  328. }
  329.