//-------------------------------------------------------------------
// OWL Extensions (OWLEXT) Class Library
// Copyright(c) 1996 by Manic Software.
// All rights reserved.
//
// TTimer
//
// This file implements TTimer, a class that enapsulates SetTimer API.
// The reason for using a hidden window, as opposed to a timer proc, is
// that in Win16, timer procs can be called from other application's
// context.  Since this is usually a very bad thing, we use a window to
// get WM_TIMER messages.  Either would probably work in Win32, but we
// want to work in both if possible.
//
// Original code by Don Griffin; used with permission.
//-------------------------------------------------------------------
#include <owlext\pch.h>
#pragma hdrstop
 
#include <owl/appdict.h>
 
#include <owlext/timer.h>
 
using namespace owl;
 
namespace OwlExt {
 
//--------------------------------------------------------------------------
 
#define  IDT_TIMER      100
 
class TTimerWindow : public TWindow
{
  DECLARE_RESPONSE_TABLE (TTimerWindow);
 
public:
  TTimerWindow ();
  ~TTimerWindow ();
 
  TTimer    * mFirst;
 
private:
  void SetupWindow () override;
  void CleanupWindow () override;
  void            EvTimer (uint);
};
 
DEFINE_RESPONSE_TABLE1 (TTimerWindow, TWindow)
EV_WM_TIMER,
END_RESPONSE_TABLE;
 
TTimerWindow::TTimerWindow ()
:
TWindow (GetApplicationObject()->GetMainWindow(), _T(""))
{
  ModifyStyle(WS_VISIBLE|WS_CHILD,WS_POPUP);
}
 
TTimerWindow::~TTimerWindow ()
{
  Destroy ();
}
 
 
void TTimerWindow::SetupWindow ()
{
  TWindow::SetupWindow ();
 
  SetTimer (IDT_TIMER, 50);  // 50ms is about the best resolution possible
}
 
void TTimerWindow::CleanupWindow ()
{
  KillTimer (IDT_TIMER);
 
  TWindow::CleanupWindow ();
}
 
void TTimerWindow::EvTimer (uint)
{
  TTimer::DoTicks ();
}
 
 
//--------------------------------------------------------------------------
 
static TTimerWindow   * sTimerWindow;
TTimer                * TTimer::sFirst;
 
 
TTimer::TTimer (uint duration)
:
mDuration (duration),
mLastTick (::GetTickCount())
{
  if (! sTimerWindow) {
    sTimerWindow = new TTimerWindow;
    PRECONDITION (sTimerWindow);  // new should throw and we never get here...
    sTimerWindow->Create ();
  }
 
  mProcessing = false;
 
  //  Add ourselves to the timer chain:
  mNext = sFirst;
  sFirst = this;
}
 
 
TTimer::~TTimer ()
{
  const bool ok = sTimerWindow != 0;
  WARN (!ok, _T ("TTimer::~TTimer: Terminating due to failed precondition."));
  if (!ok) std::terminate ();
 
  TTimer    * prev = 0;
  TTimer    * rover = sFirst;
 
  while (rover){
    if (rover == this){
      if (prev)
        prev->mNext = mNext;
      else
        sFirst = mNext;
 
      break;
    }
 
    prev = rover;
    rover = rover->mNext;
  }
  const bool found = rover != 0; // We walked the list and should find ourselves!
  WARN (!found, _T ("TTimer::~TTimer: Terminating due to failed precondition."));
  if (!found) std::terminate ();
 
  //  See if we were the last TTimer object:
  if (! sFirst){
    delete sTimerWindow; // don't need this guy anymore...
    sTimerWindow = 0;
  }
}
 
void TTimer::DoTick (uint32 tickCount)
{
  if (mLastTick + mDuration < tickCount)
  {
    mLastTick = tickCount;
 
    //  If the Tick method yields time, we may be called again.
    //  We prevent re-entrancy here:
    if (! mProcessing)
    {
      mProcessing = true;
 
      Tick ();
 
      if (IsTimer())  // we may have been deleted!
        mProcessing = false;
    }
  }
}
 
void TTimer::DoTicks ()
{
  TTimer    * timer = sFirst;
  TTimer    * nextTimer;
  uint32      tickCount  = ::GetTickCount();
 
 
  PRECONDITION (timer);
 
  while (timer)
  {
    nextTimer = timer->mNext;
    timer->DoTick (tickCount);
    timer = nextTimer;
  }
}
 
bool TTimer::IsTimer (TTimer *timer)
{
  TTimer    * rover = sFirst;
 
  while (rover)
  {
    if (rover == timer)
      return true;
    rover = rover->mNext;
  }
 
  return false;
}
 
} // OwlExt namespace
 

V730 Not all members of a class are initialized inside the constructor. Consider inspecting: mFirst.