home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Monster Media 1994 #1
/
monster.zip
/
monster
/
PROG_GEN
/
FACETV.ZIP
/
TIMERCTL.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-05
|
8KB
|
329 lines
/************************************************************************
**
** @(#)timerctl.cpp 01/05/94 Chris Ahlstrom
**
** C++ Borland/Microsoft
**
** Defines the default routines for the base class TimerControl.
** This class implements a pretty simple and straightforward way
** of handling multiple timers. The default routines, though, can't
** really manage more than one DOS timer at once. However, the objects
** make good repositories for timing information for each timer that
** might be needed consecutively in a DOS application.
**
** The Windows version of the class, WinTimerControl, can implement
** more than one timer simultaneously.
**
** One issue to consider is how to implement multiple consecutive
** timers -- should the duration of each be simply that which is needed,
** or should it be the cumulative sum of all previous timers, plus
** the duration of the current timer?
**
*************************************************************************/
#define TIMERCTL_cpp
#if !defined(_Windows) // { _Windows
#include <dos.h> // DOS delay()
#else // }{ _Windows
void
delay(int msec) // Windows fake delay()
{
}
#endif // } _Windows
#include <stdio.h> // sprintf()
#include "timerctl.h" // TimerControl class declaration
/************************************************************************
** TimerControl constructors and destructor
**
** A couple of notes.... First, although the duration can be
** specified to msec precision, the timer used is the DOS timer,
** which ticks about 18 times per second. Hence it has a true coarseness
** of about 50 ms.
**
*************************************************************************/
TimerControl::TimerControl // constructor
(
void *master, // points to TDeskTop or HWND
int number, // ID code for the timer
unsigned duration, // minimum duration of timer (msec)
int count // times to allow timer-handling
) :
Handle (master), // window/desktop handle
ID (number), // ID code of timer
Duration (duration), // duration of timer (ms)
Count (count), // times to handle the timer
Useable (0), // is timer working?
Next (0), // pointer to next timer
errorCode (0), // no errors to start with
errorMsg ((char *)0), // no message to start with
errorMsgList (&timerErrors[0]), // a list of messages
errorMsgCount (ERR_TIMER_MAX) // the number of them
{
(void) setupTimer(Duration);
}
TimerControl::~TimerControl ()
{
}
/************************************************************************
** TimerControl::setupTimer()
**
** The DOS version does nothing except alter the nominal duration.
** It returns a 1 if the setup succeeded, and a 0 otherwise.
**
*************************************************************************/
int
TimerControl::setupTimer
(
unsigned duration
)
{
int errcode = 0;
if (duration > 0)
{
Duration = duration;
Useable = 1;
}
else
{
Duration = 0;
Useable = 0;
errcode = ERR_TIMER_SETUP;
}
setErrorCode(errcode);
return errcode;
}
/************************************************************************
** TimerControl::timerDelay()
**
** Delays for the Duration, without exiting immediately.
** While active, no other DOS functions can be executed. Returns
** an error code if necessary.
**
*************************************************************************/
int
TimerControl::timerDelay ()
{
int errcode = 0;
if (Useable)
delay(Duration);
else
errcode = ERR_TIMER_DELAY;
(void) decrementCount();
setErrorCode(errcode);
return errcode;
}
/************************************************************************
** TimerControl::disableTimer()
**
** Renders the timer unuseable.
**
*************************************************************************/
int
TimerControl::disableTimer ()
{
int errcode = 0;
if (Useable)
Useable = 0;
else
errcode = ERR_TIMER_DISABLE;
setErrorCode(errcode);
return errcode;
}
/************************************************************************
** TimerControl::decrementCount()
**
** Provides access to the Count value. The current value is
** returned, and Count is decremented. However, if Count is
** TIMER_IGNORE_COUNT, then nothing is done, and 1 is returned.
**
*************************************************************************/
int
TimerControl::decrementCount ()
{
int count = Count;
if (count == TIMER_IGNORE_COUNT)
count = 1;
else
{
if (count > 0)
{
count--;
Count = count;
}
else if (count == 0)
disableTimer();
}
return count;
}
/************************************************************************
** TimerControl::attach()
**
** Lets a timer attach another timer to itself, useful for
** implementing a singly-linked list of timers.
**
** TimerControl::next()
**
** Returns the next timer.
**
** TimerControl friend deleteTimer()
**
** This function destroys the linked list of TimerControls,
** starting at the timer specified (it usually had better be the
** first timer). It calls itself recursively to get to the last
** field, then starts deleting backwards.
**
*************************************************************************/
int
TimerControl::attach
(
TimerControl *lasttimer
)
{
int errcode = 0;
if (lasttimer)
lasttimer->Next = this;
else
errcode = ERR_TIMER_CANT_INSERT;
return errcode;
}
TimerControl *
TimerControl::next ()
{
return Next;
}
void
deleteTimer
(
TimerControl *timer
)
{
if (timer)
{
if (timer->Next)
deleteTimer(timer->Next);
delete timer;
}
}
/************************************************************************
** TimerControl::isError()
**
** Returns a 1 if the errorCode is non-zero.
**
** Should not need overriding, unless some quantum increase
** in robustness is need for a particular object. I don't even
** know if you can override an inline function.
**
** This function is meant as a much faster alternative to calling
** getError() to see if there is an error message pending.
**
** Use isError() if you know that there's no built-in error return
** code for a particular function.
**
** See the header file timerctl.h for the definition.
**
*************************************************************************/
/************************************************************************
** TimerControl::getErrorMsg()
**
** Simply returns a pointer to the latest error message. If there
** is no error pending, a NULL is returned.
**
** This routine should not need to be overridden.
**
*************************************************************************/
const char *
TimerControl::getErrorMsg (void) // get pointer to message
{
if (errorCode)
return errorMsg; // hopefully, it's not null
else
return (char *) 0; // hopefully, it's null <grin>
}
/************************************************************************
** TimerControl::setErrorCode()
**
** All routines that perform a function that can err should
** call this routine to set both errorCode and errorMsg, even if there
** is no error.
**
** This routine should not need to be overridden. However,
** it should be overridden when the source of messages is not the
** errorMsgList. See xbpa4.cpp for a good example.
**
*************************************************************************/
#define DEFAULTMESSAGEFORMAT "%%Error code %d; see source code."
static char defaultMessage[48]; // for assembling basic message
void
TimerControl::setErrorCode
(
int index
)
{
if (errorMsgCount <= 0)
{
if (index != 0)
{
sprintf(defaultMessage, DEFAULTMESSAGEFORMAT, index);
errorMsg = defaultMessage;
}
}
else
{
if (index > 0 && index < errorMsgCount)
errorMsg = errorMsgList[index]; // hopefully, it's not null
else
errorMsg = (char *) 0; // no list for this device
}
errorCode = index;
}