[dasher: 20/28] Merge removal of parameters: no more non-persistent parameters!



commit 23df7467a47bf911b4c2d0a72c1ce5532d40fd3c
Merge: 57f734d 8edc818
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Mon Oct 3 14:50:19 2011 +0100

    Merge removal of parameters: no more non-persistent parameters!
    
    (branch 'files' 8edc8186d07db99a1e inc RM LP_BOOSTFACTOR, SP_{USER,SYSTEM}_LOC;
     +branch 'game' 57f734d6916f0e0236 inc RM BP_GAME_MODE, BP_DASHER_PAUSED)

 Src/Common/Globber.cpp                       |   35 ++++++
 Src/Common/Globber.h                         |   17 +++
 Src/Common/Makefile.am                       |    2 +
 Src/DasherCore/AbstractXMLParser.cpp         |   55 ++++++---
 Src/DasherCore/AbstractXMLParser.h           |   40 ++++++-
 Src/DasherCore/Alphabet/AlphIO.cpp           |   19 +---
 Src/DasherCore/Alphabet/AlphIO.h             |    9 +-
 Src/DasherCore/AlphabetManager.cpp           |   21 ++--
 Src/DasherCore/BasicLog.cpp                  |    3 +-
 Src/DasherCore/ColourIO.cpp                  |   20 +---
 Src/DasherCore/ColourIO.h                    |   13 ++-
 Src/DasherCore/ControlManager.cpp            |  169 ++++++++++++--------------
 Src/DasherCore/ControlManager.h              |   28 +++--
 Src/DasherCore/DasherInterfaceBase.cpp       |   22 +---
 Src/DasherCore/DasherInterfaceBase.h         |   55 +++------
 Src/DasherCore/DasherModel.cpp               |   16 +--
 Src/DasherCore/DasherModel.h                 |    5 +
 Src/DasherCore/DasherNode.h                  |   11 ++-
 Src/DasherCore/DefaultFilter.cpp             |    4 +-
 Src/DasherCore/DynamicButtons.cpp            |    2 +-
 Src/DasherCore/DynamicFilter.cpp             |   37 +++++--
 Src/DasherCore/DynamicFilter.h               |   21 +++-
 Src/DasherCore/FileWordGenerator.cpp         |   13 ++-
 Src/DasherCore/FileWordGenerator.h           |   29 ++---
 Src/DasherCore/FrameRate.cpp                 |   23 ++---
 Src/DasherCore/FrameRate.h                   |   23 ++--
 Src/DasherCore/Makefile.am                   |    1 +
 Src/DasherCore/Messages.cpp                  |   50 ++++++++
 Src/DasherCore/Messages.h                    |    4 +
 Src/DasherCore/NodeCreationManager.cpp       |   48 ++++----
 Src/DasherCore/OneButtonDynamicFilter.cpp    |    2 +-
 Src/DasherCore/Parameters.cpp                |    3 -
 Src/DasherCore/Parameters.h                  |    4 +-
 Src/DasherCore/Trainer.cpp                   |   90 +++-----------
 Src/DasherCore/Trainer.h                     |   18 +--
 Src/DasherCore/TwoButtonDynamicFilter.cpp    |   14 +--
 Src/DasherCore/TwoButtonDynamicFilter.h      |    2 +-
 Src/DasherCore/TwoPushDynamicFilter.cpp      |   35 +++---
 Src/Gtk2/DasherControl.cpp                   |  113 +++++-------------
 Src/Gtk2/DasherControl.h                     |    8 +-
 Src/MacOSX/COSXDasherControl.h               |    9 +-
 Src/MacOSX/COSXDasherControl.mm              |   76 +++---------
 Src/MacOSX/Dasher.xcodeproj/project.pbxproj  |   12 ++
 Src/MacOSX/TODO                              |    2 +-
 Src/Win32/Dasher.cpp                         |  103 ++++++----------
 Src/Win32/Dasher.h                           |    5 +-
 Src/iPhone/Classes/CDasherInterfaceBridge.h  |    8 +-
 Src/iPhone/Classes/CDasherInterfaceBridge.mm |   77 +++++-------
 Src/iPhone/Dasher.xcodeproj/project.pbxproj  |   10 ++
 49 files changed, 663 insertions(+), 723 deletions(-)
---
diff --cc Src/DasherCore/ControlManager.h
index c3bcae9,4968d9a..4743bcf
--- a/Src/DasherCore/ControlManager.h
+++ b/Src/DasherCore/ControlManager.h
@@@ -60,9 -60,10 +60,10 @@@ namespace Dasher 
      class CContNode : public CDasherNode {
      public:
        CControlBase *mgr() {return m_pMgr;}
 -      CContNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, NodeTemplate *pTemplate, CControlBase *pMgr);
 +      CContNode(int iOffset, int iColour, NodeTemplate *pTemplate, CControlBase *pMgr);
  
        bool bShove() {return false;}
+       double SpeedMul() {return 0.5;}
        ///
        /// Provide children for the supplied node
        ///
diff --cc Src/DasherCore/DasherInterfaceBase.cpp
index 2b33c57,529fa85..95e78f2
--- a/Src/DasherCore/DasherInterfaceBase.cpp
+++ b/Src/DasherCore/DasherInterfaceBase.cpp
@@@ -307,34 -322,6 +302,31 @@@ void CDasherInterfaceBase::HandleEvent(
    }
  }
  
 +void CDasherInterfaceBase::EnterGameMode(CGameModule *pGameModule) {
 +  DASHER_ASSERT(m_pGameModule == NULL);
 +  if (CWordGeneratorBase *pWords = m_pNCManager->GetAlphabetManager()->GetGameWords()) {
 +    if (!pGameModule) pGameModule=CreateGameModule();
 +    m_pGameModule=pGameModule;
 +    m_pGameModule->SetWordGenerator(m_pNCManager->GetAlphabet(), pWords);
 +    m_pNCManager->updateControl();
 +  } else {
 +    ///TRANSLATORS: %s is the name of the alphabet; the string "GameTextFile"
 +    /// refers to a setting name in gsettings or equivalent, and should not be translated.
-     const char *msg=_("Could not find game sentences file for %s - check alphabet definition, or override with GameTextFile setting");
-     char *buf(new char[strlen(msg)+m_pNCManager->GetAlphabet()->GetID().length()]);
-     sprintf(buf,msg,m_pNCManager->GetAlphabet()->GetID().c_str());
-     Message(buf,true);
-     delete buf;
++    FormatMessageWithString(_("Could not find game sentences file for %s - check alphabet definition, or override with GameTextFile setting"),
++                            m_pNCManager->GetAlphabet()->GetID().c_str());
 +    delete pGameModule; //does nothing if null.
 +  }
 +}
 +
 +void CDasherInterfaceBase::LeaveGameMode() {
 +  DASHER_ASSERT(m_pGameModule);
 +  CGameModule *pMod = m_pGameModule;
 +  m_pGameModule=NULL; //point at which we officially exit game mode
 +  delete pMod;
 +  m_pNCManager->updateControl();
 +  SetBuffer(0);
 +}
 +
  CDasherInterfaceBase::WordSpeaker::WordSpeaker(CDasherInterfaceBase *pIntf) : TransientObserver<const CEditEvent *>(pIntf) {
  }
  
diff --cc Src/DasherCore/DasherInterfaceBase.h
index 20f64b5,50d56ef..4bbee72
--- a/Src/DasherCore/DasherInterfaceBase.h
+++ b/Src/DasherCore/DasherInterfaceBase.h
@@@ -359,40 -353,27 +359,55 @@@ public
    /// public so e.g. iPhone can flush the buffer when app is backgrounded.
    void WriteTrainFileFull();
  
 -  ///
 -  /// Obtain the size in bytes of a file - the way to do this is
 -  /// dependent on the OS (TODO: Check this - any posix on Windows?)
 -  ///
 -  virtual int GetFileSize(const std::string &strFileName) = 0;
 -
 -  
+   /// @name Platform dependent utility functions
+   /// These functions provide various platform dependent functions
+   /// required by the core. A derived class is created for each
+   /// supported platform which implements these.
+   // @{
++
 +  ///
 +  /// Obtain the size in bytes of a file - the way to do this is
 +  /// dependent on the OS (TODO: Check this - any posix on Windows?)
 +  ///
 +  virtual int GetFileSize(const std::string &strFileName) = 0;
- 
+   
+   ///Look for files, matching a filename pattern, in whatever system and/or user
+   /// locations as may exist - e.g. on disk, in app package, on web, whatever.
+   /// TODO, can we add a default implementation that looks on the Dasher website?
+   /// \param pattern string matching just filename (not path), potentially
+   /// including '*'s (as per glob)
+   virtual void ScanFiles(AbstractParser *parser, const std::string &strPattern) = 0;
 -    
++  
+   // @}
++  
 +  ///Gets a pointer to the game module. This is the correct way to determine
 +  /// whether game mode is currently on or off.
 +  /// \return pointer to current game module, if game mode on; or null, if off.
 +  CGameModule *GetGameModule() {
 +    return m_pGameModule;
 +  }
 +
 +  ///Call to enter game mode. The correct procedure for UI activation of game
 +  /// mode, is to first create a game module (the method CreateGameModule is
 +  /// provided for this purpose), and then prompt the user to change any
 +  /// ModuleSettings for that GameModule (hence needing to create it first in
 +  /// order to determine what settings it has); if the user clicks ok,
 +  /// then the created module can be passed to this method. (If the user instead
 +  /// clicks cancel, then the module should be deleted.)
 +  /// Note method is virtual, so subclasses can override e.g. to detect entering
 +  /// game mode (they should call this method, then check GetGameModule()).
 +  /// \param pGameModule concrete instance of GameModule to use. This can be null,
 +  /// in which case we will use the module returned by CreateGameModule (e.g.
 +  /// this is done for demo filter). However
 +  /// \param pGameModule newly-constructed GameModule to use, or NULL to use one
 +  /// returned from CreateGameModule; in either case, will be deleted when we
 +  /// leave game mode.
 +  virtual void EnterGameMode(CGameModule *pGameModule);
 +  
 +  ///Exits game mode, including deleting the game module that was in use.
 +  /// virtual so subclasses can override to detect leaving game mode.
 +  void LeaveGameMode();
 +  
  protected:
  
    /// @name Startup
diff --cc Src/DasherCore/DasherModel.cpp
index 505ef59,a2d5d63..81fee12
--- a/Src/DasherCore/DasherModel.cpp
+++ b/Src/DasherCore/DasherModel.cpp
@@@ -198,10 -196,11 +196,9 @@@ void CDasherModel::ClearRootQueue() 
    }
  }
  
 -void CDasherModel::SetOffset(int iOffset, CAlphabetManager *pMgr, CDasherView *pView, bool bForce) {
 -  //if we don't have a root, always "re"build the tree!
 -  // (if we have a root, only rebuild to move location or if bForce says to)
 -  if (m_Root && iOffset == GetOffset() && !bForce) return;
 +void CDasherModel::SetNode(CDasherNode *pNewRoot) {
  
-   if (m_pLastOutput) m_pLastOutput->Leave();
 +  AbortOffset();
    ClearRootQueue();
    delete m_Root;
  
@@@ -212,9 -226,6 +209,8 @@@
  
    // Set the root coordinates so that the root node is an appropriate
    // size and we're not in any of the children
-   m_Root->Enter(); //(but we are in the node itself)
-   m_Root->SetFlag(NF_SEEN, true);
++  m_Root->SetFlag(NF_SEEN, true); //(but we are in the node itself)
 +  m_pLastOutput = m_Root;
  
    double dFraction( 1 - (1 - m_Root->MostProbableChild() / static_cast<double>(NORMALIZATION)) / 2.0 );
  
@@@ -232,12 -245,123 +228,16 @@@ int CDasherModel::GetOffset() 
    return m_pLastOutput ? m_pLastOutput->offset()+1 : m_Root ? m_Root->offset()+1 : 0;
  };
  
+ CDasherNode *CDasherModel::Get_node_under_crosshair() {
+   return m_pLastOutput;
+ }
+ 
 -void CDasherModel::Get_new_root_coords(dasherint X, dasherint Y, dasherint &r1, dasherint &r2, int iSteps, dasherint iMinSize) {
 -  DASHER_ASSERT(m_Root != NULL);
 -  // Avoid X == 0, as this corresponds to infinite zoom
 -  if (X <= 0) X = 1;
 -
 -  // If X is too large we risk overflow errors, so limit it
 -  dasherint iMaxX = (1 << 29) / iSteps;
 -  if (X > iMaxX) X = iMaxX;
 -
 -  // Mouse coords X, Y
 -  // const dasherint Y1 = 0;
 -  const dasherint Y2(MAX_Y);
 -
 -  // Calculate what the extremes of the viewport will be when the
 -  // point under the cursor is at the cross-hair. This is where
 -  // we want to be in iSteps updates
 -
 -  dasherint y1(Y - (Y2 * X) / (2 * ORIGIN_X));
 -  dasherint y2(Y + (Y2 * X) / (2 * ORIGIN_Y));
 -  dasherint oy1(y1),oy2(y2); //back these up to use later
 -  // iSteps is the number of update steps we need to get the point
 -  // under the cursor over to the cross hair. Calculated in order to
 -  // keep a constant bit-rate.
 -
 -  DASHER_ASSERT(iSteps > 0);
 -
 -  // Calculate the new values of y1 and y2 required to perform a single update
 -  // step.
 -  {
 -    const dasherint denom = Y2 + (iSteps - 1) * (y2 - y1),
 -      newy1 = y1 * Y2 / denom,
 -      newy2 = ((y2 * iSteps - y1 * (iSteps - 1)) * Y2) / denom;
 -
 -    y1 = newy1;
 -    y2 = newy2;
 -  }
 -
 -  // Calculate the minimum size of the viewport corresponding to the
 -  // maximum zoom.
 -
 -  if((y2 - y1) < iMinSize) {
 -    const dasherint newy1 = y1 * (Y2 - iMinSize) / (Y2 - (y2 - y1)),
 -      newy2 = newy1 + iMinSize;
 -
 -    y1 = newy1;
 -    y2 = newy2;
 -  }
 -  
 -  //okay, we now have target bounds for the viewport, after allowing for framerate etc.
 -  // we now go there in one step...
 -  
 -  // new root{min,max} r1,r2, old root{min,max} R1,R2
 -  const dasherint R1 = m_Rootmin;
 -  const dasherint R2 = m_Rootmax;  
 -
 -  // If |(0,Y2)| = |(y1,y2)|, the "zoom factor" is 1, so we just translate.
 -  if (Y2 == y2 - y1)
 -    {
 -      r1 = R1 - y1;
 -      r2 = R2 - y1;
 -      return;
 -    }
 -
 -  // There is a point C on the y-axis such the ratios (y1-C):(Y1-C) and
 -  // (y2-C):(Y2-C) are equal - iow that divides the "target" region y1-y2
 -  // into the same proportions as it divides the screen (0-Y2). I.e., this
 -  // is the center of expansion - the point on the y-axis which everything
 -  // moves away from (or towards, if reversing).
 -
 -  //We prefer to compute C from the _original_ (y1,y2) pair, as this is more
 -  // accurate (and avoids drifting up/down when heading straight along the
 -  // x-axis in dynamic button modes). However...
 -  if (((y2-y1) < Y2) ^ ((oy2-oy1) < Y2)) {
 -    //Sometimes (very occasionally), the calculation of a single-step above
 -    // can turn a zoom-in into a zoom-out, or vice versa, when the movement
 -    // is mostly translation. In which case, must compute C consistently with
 -    // the (scaled, single-step) movement we are going to perform, or else we
 -    // will end up suddenly going the wrong way along the y-axis (i.e., the
 -    // sense of translation will be reversed) !
 -    oy1=y1; oy2=y2;
 -  }
 -  const dasherint C = (oy1 * Y2) / (oy1 + Y2 - oy2);
 -
 -  r1 = ((R1 - C) * Y2) / (y2 - y1) + C;
 -  r2 = ((R2 - C) * Y2) / (y2 - y1) + C;
 -}
 -
  bool CDasherModel::NextScheduledStep()
  {
 -  DASHER_ASSERT (!GetBoolParameter(BP_DASHER_PAUSED) || m_deGotoQueue.size()==0);
    if (m_deGotoQueue.size() == 0) return false;
 -  myint iNewMin, iNewMax;
 -  iNewMin = m_deGotoQueue.front().iN1;
 -  iNewMax = m_deGotoQueue.front().iN2;
 +  myint newRootmin(m_deGotoQueue.front().iN1), newRootmax(m_deGotoQueue.front().iN2);
    m_deGotoQueue.pop_front();
  
 -  UpdateBounds(iNewMin, iNewMax);
 -  if (m_deGotoQueue.size() == 0) SetBoolParameter(BP_DASHER_PAUSED, true);
 -  return true;
 -}
 -
 -void CDasherModel::OneStepTowards(myint miMousex, myint miMousey, int iSteps, dasherint iMinSize) {
 -  DASHER_ASSERT(!GetBoolParameter(BP_DASHER_PAUSED));
 -
 -  myint iNewMin, iNewMax;
 -  // works out next viewpoint
 -  Get_new_root_coords(miMousex, miMousey, iNewMin, iNewMax, iSteps, iMinSize);
 -  
 -  UpdateBounds(iNewMin, iNewMax);
 -}
 -
 -void CDasherModel::UpdateBounds(myint newRootmin, myint newRootmax) {
 -
    m_dTotalNats += log((newRootmax - newRootmin) / static_cast<double>(m_Rootmax - m_Rootmin));
  
    m_iDisplayOffset = (m_iDisplayOffset * 90) / 100;
diff --cc Src/DasherCore/DefaultFilter.cpp
index 3ba3ab0,300a1b2..7ab512b
--- a/Src/DasherCore/DefaultFilter.cpp
+++ b/Src/DasherCore/DefaultFilter.cpp
@@@ -132,8 -133,9 +132,8 @@@ void CDefaultFilter::Timer(unsigned lon
      if (m_bTurbo) dSpeedMul*=1.75;
      
      OneStepTowards(m_pDasherModel, m_iLastX,m_iLastY, Time, dSpeedMul);
 -    bDidSomething = true;
  
-     if (GetLongParameter(LP_BOOSTFACTOR)==100 && dSpeedMul==1.0)
+     if (dSpeedMul==1.0)
        m_pAutoSpeedControl->SpeedControl(m_iLastX, m_iLastY, pView);
    }
  
diff --cc Src/DasherCore/DynamicButtons.cpp
index a337021,109102e..241e834
--- a/Src/DasherCore/DynamicButtons.cpp
+++ b/Src/DasherCore/DynamicButtons.cpp
@@@ -37,18 -37,19 +37,18 @@@ void CDynamicButtons::Timer(unsigned lo
      m_bKeyHandled = true;
      //return true; //ACL although that's what old DynamicButtons did, surely we should progress normally?
    }
 -  if (isPaused()) return false;
 +  if (isPaused()) return;
    if (isReversing()) {
-     OneStepTowards(m_pDasherModel, 41943,2048, iTime, SlowStartSpeedMul(iTime));
+     OneStepTowards(m_pDasherModel, 41943,2048, iTime, FrameSpeedMul(m_pDasherModel, iTime));
 -    return true;
 -  }
 -  //moving forwards. Check auto speed control...
 -  if (GetBoolParameter(BP_AUTO_SPEEDCONTROL) && m_uSpeedControlTime < iTime)
 -  {
 -	  if (m_uSpeedControlTime > 0) //has actually been set?
 -        SetLongParameter(LP_MAX_BITRATE, GetLongParameter(LP_MAX_BITRATE) * (1.0 + GetLongParameter(LP_DYNAMIC_SPEED_INC)/100.0));
 -	  m_uSpeedControlTime = iTime + 1000*GetLongParameter(LP_DYNAMIC_SPEED_FREQ);
 +  } else {
 +    //moving forwards. Check auto speed control...
 +    if (GetBoolParameter(BP_AUTO_SPEEDCONTROL) && m_uSpeedControlTime < iTime) {
 +        if (m_uSpeedControlTime > 0) //has actually been set?
 +          SetLongParameter(LP_MAX_BITRATE, GetLongParameter(LP_MAX_BITRATE) * (1.0 + GetLongParameter(LP_DYNAMIC_SPEED_INC)/100.0));
 +        m_uSpeedControlTime = iTime + 1000*GetLongParameter(LP_DYNAMIC_SPEED_FREQ);
 +    }
 +    TimerImpl(iTime, pDasherView, m_pDasherModel, pol);
    }
 -  return TimerImpl(iTime, pDasherView, m_pDasherModel, pol);
  }
  
  void CDynamicButtons::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
diff --cc Src/DasherCore/DynamicFilter.cpp
index aa73f10,5ebff90..9984181
--- a/Src/DasherCore/DynamicFilter.cpp
+++ b/Src/DasherCore/DynamicFilter.cpp
@@@ -24,34 -24,53 +24,53 @@@
  using namespace Dasher;
  
  CDynamicFilter::CDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName)
- : CInputFilter(pInterface, iID, szName), CSettingsUser(pCreator), m_bPaused(true), m_pFramerate(pFramerate) {
+ : CInputFilter(pInterface, iID, szName), CSettingsUser(pCreator),
 -m_pFramerate(pFramerate), m_dLastBits(-1) {
++  m_bPaused(true), m_pFramerate(pFramerate), m_dLastBits(-1) {
  }
  
  bool CDynamicFilter::OneStepTowards(CDasherModel *pModel, myint y1, myint y2, unsigned long iTime, double dSpeedMul) {
    if (dSpeedMul<=0.0) return false; //going nowhere
    m_pFramerate->RecordFrame(iTime); //Hmmm, even if we don't do anything else?
  
-   double dRXMax = m_pFramerate->GetMaxZoomFactor();
-   // Adjust for slow start etc. TODO: can we fix to use integer math (or at least no pow?)
-   if (dSpeedMul!=1.0) dRXMax=pow(dRXMax, dSpeedMul);
+   //The maximum number of bits we should allow to be entered in this frame:
+   // (after adjusting for slow start, turbo mode, control node slowdown, etc.)
+   double dBits = m_pFramerate->GetMaxBitsPerFrame()*dSpeedMul;
+ 
+   //Compute max expansion, i.e. the minimum size we should allow the range 0..MAX_Y
+   // to be shrunk down to, for this frame. We cache the most-recent result to
+   // avoid an exp() (and a division): in the majority of cases this doesn't change
+   // between frames, but only does so when the maxbitrate changes, or dspeedmul
+   // changes (e.g. continuously during slow start, or when entering/leaving turbo
+   // mode or a control node).
+   if (dBits != m_dLastBits) m_iLastMinSize = static_cast<myint>(CDasherModel::MAX_Y / exp(m_dLastBits = dBits));
+   //However, note measurements on iPhone suggest even one exp() per frame is not
+   // a significant overhead; so the caching may be unnecessary, but it's easy.
    
-   pModel->ScheduleOneStep(y1, y2, static_cast<int>(m_pFramerate->Steps() / dSpeedMul), static_cast<myint>(CDasherModel::MAX_Y/dRXMax));
+   //If we wanted to take things further we could generalize this cache to cover
+   // exp()s done in the dynamic button modes too, and thus to allow them to adjust
+   // lag, guide markers, etc., according to the dSpeedMul in use. (And/or
+   // to do slow-start more efficiently by interpolating cache values.)
 -  pModel->OneStepTowards(y1, y2,
 -                         static_cast<int>(m_pFramerate->Steps() / dSpeedMul),
 -                         m_iLastMinSize);
++  pModel->ScheduleOneStep(y1, y2,
++                          static_cast<int>(m_pFramerate->Steps() / dSpeedMul),
++                          m_iLastMinSize);
    return true;
  }
  
- double CDynamicFilter::SlowStartSpeedMul(unsigned long iTime) {
+ double CDynamicFilter::FrameSpeedMul(CDasherModel *pModel, unsigned long iTime) {
+   CDasherNode *n = pModel->Get_node_under_crosshair();
+   double d = n ? n->SpeedMul() : 1.0;
    if(GetBoolParameter(BP_SLOW_START)) {
      if ((iTime - m_iStartTime) < GetLongParameter(LP_SLOW_START_TIME))
-       return 0.1 * (1 + 9 * ((iTime - m_iStartTime) / static_cast<double>(GetLongParameter(LP_SLOW_START_TIME))));
+       d *= 0.1 * (1 + 9 * ((iTime - m_iStartTime) / static_cast<double>(GetLongParameter(LP_SLOW_START_TIME))));
    }
-   //no slow start, or finished.
-   return 1.0;
+   //else, no slow start, or finished.
+   return d;
  }
  
 -void CDynamicFilter::Unpause(unsigned long Time) {
 -  if (!GetBoolParameter(BP_DASHER_PAUSED)) return; //already running, no need to / can't really do anything
 +void CDynamicFilter::run(unsigned long Time) {
 +  if (!isPaused()) return; //already running, no need to / can't really do anything
    
 -  SetBoolParameter(BP_DASHER_PAUSED, false);
 +  m_bPaused = false;
  
    m_pFramerate->Reset_framerate(Time);
    m_iStartTime = Time;
diff --cc Src/DasherCore/DynamicFilter.h
index a5c2119,0569a57..67f217e
--- a/Src/DasherCore/DynamicFilter.h
+++ b/Src/DasherCore/DynamicFilter.h
@@@ -38,26 -38,36 +38,43 @@@ class CDynamicFilter : public CInputFil
    CDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName);
  
    virtual bool supportsPause() {return true;}
 -
 +  
 +  void pause() {m_bPaused = true;}
 +  
   protected:
+   ///wraps Model's one-step method to compute the number of steps and minsize
+   /// (from framerate) that the Model requires, from just the frame time and a
+   /// multiplier to speed.
+   /// \param dSpeedMul multiply normal speed of movement by this; 1.0 = normal speed,
+   /// 0.0 = go nowhere. This allows for slow start, turbo mode, control nodes being
+   /// more "viscous", etc. Values <=0.0 will result in no movement
+   /// \return true if dSpeedMul>0.0, false if <=0.0.
    bool OneStepTowards(CDasherModel *pModel, myint y1, myint y2, unsigned long iTime, double dSpeedMul);
-   double SlowStartSpeedMul(unsigned long iTime);
+   
+   ///Calculates a multiplier by which to adjust our speed (for a given frame).
+   /// Defalut implementation implements slow-start (i.e. a multiplier increasing
+   /// from zero to one over the slow-start-time) as well as by checking the speedMul
+   /// of the node under the cursor.
+   virtual double FrameSpeedMul(CDasherModel *pModel, unsigned long iTime);
  
 -  /// Starts moving.  Clears BP_DASHER_PAUSED.
 -  /// (But does nothing if BP_DASHER_PAUSED is currently set).
 +  ///Starts moving, i.e. just records that we are no longer paused,
 +  /// for the next call to Timer. Protected, to prevent external calls 
 +  /// so subclasses have control over all calls, as a call to run() may not be
 +  /// appropriate without performing other setup first.
    /// \param Time Time in ms, used to keep a constant frame rate and
    /// initialize slow start.
 -  void Unpause(unsigned long iTime);
++
 +  virtual void run(unsigned long iTime);
 +  bool isPaused() {return m_bPaused;}
+   
+   CFrameRate * const m_pFramerate;
   private:
-   CFrameRate *m_pFramerate;
    //Time at which Unpause() was called, used for Slow Start.
    unsigned long m_iStartTime;
 +  bool m_bPaused;
+   //Number of bits (we allowed) to be entered in previous frame - to cache exp()
+   double m_dLastBits;
+   double m_iLastMinSize;
  };
  }
  #endif
diff --cc Src/DasherCore/OneButtonDynamicFilter.cpp
index cb813fd,a72a49a..f3a3919
--- a/Src/DasherCore/OneButtonDynamicFilter.cpp
+++ b/Src/DasherCore/OneButtonDynamicFilter.cpp
@@@ -108,8 -108,9 +108,8 @@@ void COneButtonDynamicFilter::KeyUp(uns
    CButtonMultiPress::KeyUp(Time, iId, pDasherView, pInput, pModel);
  }
  
 -bool COneButtonDynamicFilter::TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
 +void COneButtonDynamicFilter::TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
-   OneStepTowards(m_pDasherModel, m_iTargetX[m_iTarget], m_iTargetY[m_iTarget], Time, SlowStartSpeedMul(Time));
+   OneStepTowards(m_pDasherModel, m_iTargetX[m_iTarget], m_iTargetY[m_iTarget], Time, FrameSpeedMul(m_pDasherModel, Time));
 -  return true;
  }
  
  void COneButtonDynamicFilter::ActionButton(unsigned long iTime, int iButton, int iType, CDasherModel *pModel) {
diff --cc Src/DasherCore/TwoButtonDynamicFilter.cpp
index 4be5a14,9182827..3497991
--- a/Src/DasherCore/TwoButtonDynamicFilter.cpp
+++ b/Src/DasherCore/TwoButtonDynamicFilter.cpp
@@@ -49,9 -49,9 +49,9 @@@ static SModuleSettings sSettings[] = 
  };
  
  CTwoButtonDynamicFilter::CTwoButtonDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate)
 -  : CButtonMultiPress(pCreator, pInterface, pFramerate, 14, _("Two Button Dynamic Mode")), m_iMouseButton(-1)
 +  : CButtonMultiPress(pCreator, pInterface, pFramerate, 14, _("Two Button Dynamic Mode")), CSettingsObserver(pCreator), m_iMouseButton(-1)
  {
-   //ensure that m_dLagMul is properly initialised
+   //ensure that m_dLagBits is properly initialised
    HandleEvent(LP_DYNAMIC_BUTTON_LAG);
  }
  
@@@ -117,8 -117,9 +117,8 @@@ void CTwoButtonDynamicFilter::KeyUp(uns
    CButtonMultiPress::KeyUp(Time, iId, pView, pInput,pModel);
  }
  
 -bool CTwoButtonDynamicFilter::TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
 +void CTwoButtonDynamicFilter::TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
-   OneStepTowards(m_pDasherModel, 100,2048, Time, SlowStartSpeedMul(Time));
+   OneStepTowards(m_pDasherModel, 100,2048, Time, FrameSpeedMul(m_pDasherModel, Time));
 -  return true;
  }
  
  void CTwoButtonDynamicFilter::ActionButton(unsigned long iTime, int iButton, int iType, CDasherModel *pModel) {
diff --cc Src/DasherCore/TwoButtonDynamicFilter.h
index 451391e,ab7fe77..044ac17
--- a/Src/DasherCore/TwoButtonDynamicFilter.h
+++ b/Src/DasherCore/TwoButtonDynamicFilter.h
@@@ -48,9 -48,9 +48,9 @@@ class CTwoButtonDynamicFilter : public 
  	
   private:
    unsigned int maxClickCount() {return GetBoolParameter(BP_2B_INVERT_DOUBLE) ? 3 : 2;}
 -  virtual bool TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
 +  virtual void TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
    virtual void ActionButton(unsigned long iTime, int iButton, int iType, CDasherModel *pModel);
-   double m_dLagMul;
+   double m_dLagBits;
    ///id of physical key, whose pressing we have emulated, in response
    /// to a mouse down event on one or other half of the canvas...
    int m_iMouseButton;
diff --cc Src/DasherCore/TwoPushDynamicFilter.cpp
index e6bf99c,059241b..413e267
--- a/Src/DasherCore/TwoPushDynamicFilter.cpp
+++ b/Src/DasherCore/TwoPushDynamicFilter.cpp
@@@ -218,8 -224,10 +222,9 @@@ bool doSet(int &var, const int val
    return true;
  }
  
 -bool CTwoPushDynamicFilter::TimerImpl(unsigned long iTime, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol)
 -{
 +void CTwoPushDynamicFilter::TimerImpl(unsigned long iTime, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
    DASHER_ASSERT(isRunning());
+   const double dSpeedMul(FrameSpeedMul(m_pDasherModel, iTime));
    if (m_dNatsSinceFirstPush > -std::numeric_limits<double>::infinity()) // first button has been pushed
    {
      double dLogGrowth(m_pDasherModel->GetNats() - m_dNatsSinceFirstPush), dOuter(GetLongParameter(LP_TWO_PUSH_OUTER)),
@@@ -253,12 -261,13 +258,12 @@@
        m_bDecorationChanged |= doSet(m_iActiveMarker, 1 /*down*/);
      else m_bDecorationChanged |= doSet(m_iActiveMarker, -1 /*in middle (neither/both) or too short*/);
    }
-   OneStepTowards(m_pDasherModel, 100, 2048, iTime, SlowStartSpeedMul(iTime));
+   OneStepTowards(m_pDasherModel, 100, 2048, iTime, dSpeedMul);
 -  return true;
  }
  
 -void CTwoPushDynamicFilter::run() {
 +void CTwoPushDynamicFilter::run(unsigned long iTime) {
    m_dNatsSinceFirstPush = -std::numeric_limits<double>::infinity();
 -  CDynamicButtons::run();
 +  CDynamicButtons::run(iTime);
  }
  
  bool CTwoPushDynamicFilter::GetSettings(SModuleSettings **pSettings, int *iCount) {
diff --cc Src/Gtk2/DasherControl.h
index f0de292,354052b..bf9d106
--- a/Src/Gtk2/DasherControl.h
+++ b/Src/Gtk2/DasherControl.h
@@@ -165,13 -165,10 +165,10 @@@ public
    ///Override to emit Gtk2 signal
    virtual void SetLockStatus(const string &strText, int iPercent);
  
 -  CGameModule *CreateGameModule(CDasherView *pView, CDasherModel *pModel);
 +  CGameModule *CreateGameModule();
  private:
-   virtual void ScanAlphabetFiles(std::vector<std::string> &vFileList);
-   virtual void ScanColourFiles(std::vector<std::string> &vFileList);
-   virtual void SetupPaths();
+   virtual void ScanFiles(AbstractParser *parser, const std::string &strPattern);
    virtual void CreateModules();
-   virtual void SetupUI();
  
    GtkWidget *m_pVBox;
    GtkWidget *m_pCanvas;
diff --cc Src/MacOSX/COSXDasherControl.h
index 5a65c7b,07e35b4..d435460
--- a/Src/MacOSX/COSXDasherControl.h
+++ b/Src/MacOSX/COSXDasherControl.h
@@@ -54,16 -54,12 +54,13 @@@ public
    void ClearAllContext();
    std::string GetContext(unsigned int iOffset, unsigned int iLength);
    virtual int GetFileSize(const std::string &strFileName);
 -  void HandleEvent(int iParameter);
 +  void EnterGameMode(CGameModule *pModule);
 +  void LeaveGameMode();
    void SetEdit(id<DasherEdit> pEdit);
 -  CGameModule *CreateGameModule(CDasherView *pView, CDasherModel *pModel);
 +  CGameModule *CreateGameModule();
  private:
-   virtual void ScanAlphabetFiles(std::vector<std::string> &vFileList);
-   virtual void ScanColourFiles(std::vector<std::string> &vFileList);
-   virtual void SetupPaths();
+   virtual void ScanFiles(AbstractParser *parser, const std::string &strPattern);
    virtual void CreateModules();
-   virtual void SetupUI();
    virtual bool SupportsSpeech();
    virtual void Speak(const std::string &strText, bool bInterrupt);
    virtual bool SupportsClipboard() {return true;}
diff --cc Src/MacOSX/Dasher.xcodeproj/project.pbxproj
index 4155ef4,4f95fde..8373ac2
--- a/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
+++ b/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
@@@ -1466,7 -1476,7 +1475,8 @@@
  				33FC1D2C13ACE7E7007642CD /* ScreenGameModule.h in Headers */,
  				33C3BDD213854CC000C768E0 /* DasherTextView.h in Headers */,
  				33DDB9E113B8AF360001C52D /* DynamicButtons.h in Headers */,
 +				333B409512088AFA00235721 /* DemoFilter.h in Headers */,
+ 				E7641878142A48C70031FC91 /* Globber.h in Headers */,
  			);
  			runOnlyForDeploymentPostprocessing = 0;
  		};
@@@ -1823,7 -1834,8 +1833,9 @@@
  				33FC1D2B13ACE7E7007642CD /* ScreenGameModule.cpp in Sources */,
  				33C3BDD313854CC000C768E0 /* DasherTextView.mm in Sources */,
  				33DDB9E013B8AF360001C52D /* DynamicButtons.cpp in Sources */,
 +				333B409412088AFA00235721 /* DemoFilter.cpp in Sources */,
+ 				E7641875142A48AD0031FC91 /* Globber.cpp in Sources */,
+ 				E7C68E691430824D00440B5B /* Messages.cpp in Sources */,
  			);
  			runOnlyForDeploymentPostprocessing = 0;
  		};
diff --cc Src/iPhone/Classes/CDasherInterfaceBridge.h
index 34acb4b,ef5e625..775dc2d
--- a/Src/iPhone/Classes/CDasherInterfaceBridge.h
+++ b/Src/iPhone/Classes/CDasherInterfaceBridge.h
@@@ -68,22 -68,19 +68,22 @@@ public
    void editProtect(Dasher::CDasherNode *pNode);
    ///Override for asynchronous messages only...TODO?
    void Message(const string &strText, bool bInterrupt);
 -  Dasher::CGameModule *CreateGameModule(Dasher::CDasherView *pView,Dasher::CDasherModel *pModel);
 +  Dasher::CGameModule *CreateGameModule();
 +  
 +  void HandleEvent(int iParameter);
 +  void EnterGameMode(Dasher::CGameModule *pGameModule);
 +  void LeaveGameMode();
++
+   void ScanFiles(AbstractParser *parser, const std::string &strPattern);
  private:
-   virtual void ScanAlphabetFiles(std::vector<std::string> &vFileList);
-   virtual void ScanColourFiles(std::vector<std::string> &vFileList);
-   virtual void SetupPaths();
    virtual void CreateModules();
-   virtual void SetupUI();
    
    ///
    /// Pass events coming from the core to the appropriate handler.
    ///
    
 -  void HandleEvent(int iParameter);
 -  
+   const NSString * const userPath;
+ 
    DasherAppDelegate *dasherApp;   // objc counterpart
    	
    Dasher::CIPhoneMouseInput *m_pMouseDevice;
diff --cc Src/iPhone/Dasher.xcodeproj/project.pbxproj
index 733f194,f461384..d66ff9d
--- a/Src/iPhone/Dasher.xcodeproj/project.pbxproj
+++ b/Src/iPhone/Dasher.xcodeproj/project.pbxproj
@@@ -1728,7 -1737,8 +1736,9 @@@
  				33DFE416137AA32300F86CDE /* WordGeneratorBase.cpp in Sources */,
  				3360335813ABDF3700417DFE /* ScreenGameModule.cpp in Sources */,
  				33B6825013CA4CC300F0A952 /* DynamicButtons.cpp in Sources */,
 +				338B38FF1432071C0023A224 /* DemoFilter.cpp in Sources */,
+ 				33557FC4142B484E002C600E /* Globber.cpp in Sources */,
+ 				33558058142B7206002C600E /* Messages.cpp in Sources */,
  			);
  			runOnlyForDeploymentPostprocessing = 0;
  		};



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]