[dasher: 17/21] Merge ipad-multitouch/framerate with main branch fixes & parameter tidies



commit f4d302ec4e4178594c8028660371ab3f0a4a74bd
Merge: 02202c6 0a54b71
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Thu Jul 14 14:34:25 2011 +0100

    Merge ipad-multitouch/framerate with main branch fixes & parameter tidies
    
    Conflicts from removing UserLog* from KeyDown methods vs changing int->unsigned
    time & removing bPos/iX/iY; also from RM BP_SMOOTH_OFFSET vs DynamicButtons

 Data/GUI/dasher.preferences.ui               |  121 ++---
 Src/DasherCore/AlphabetManager.cpp           |   10 +-
 Src/DasherCore/AlphabetManager.h             |    2 +-
 Src/DasherCore/AlternatingDirectMode.cpp     |   10 +-
 Src/DasherCore/AlternatingDirectMode.h       |    2 +-
 Src/DasherCore/BasicLog.cpp                  |    2 +-
 Src/DasherCore/BasicLog.h                    |    3 +-
 Src/DasherCore/ButtonMode.cpp                |   94 ++--
 Src/DasherCore/ButtonMode.h                  |    6 +-
 Src/DasherCore/ButtonMultiPress.cpp          |    6 +-
 Src/DasherCore/ButtonMultiPress.h            |    2 +-
 Src/DasherCore/CircleStartHandler.cpp        |   11 +-
 Src/DasherCore/ClickFilter.cpp               |   11 +-
 Src/DasherCore/ClickFilter.h                 |    2 +-
 Src/DasherCore/CompassMode.cpp               |   31 +-
 Src/DasherCore/ControlManager.cpp            |    3 +-
 Src/DasherCore/ConversionHelper.cpp          |    8 +-
 Src/DasherCore/ConversionHelper.h            |    2 +-
 Src/DasherCore/ConversionManager.cpp         |    7 +-
 Src/DasherCore/ConversionManager.h           |    4 +-
 Src/DasherCore/DasherButtons.cpp             |    8 +-
 Src/DasherCore/DasherButtons.h               |    6 +-
 Src/DasherCore/DasherInterfaceBase.cpp       |   26 +-
 Src/DasherCore/DasherInterfaceBase.h         |    4 +
 Src/DasherCore/DasherModel.cpp               |   73 +--
 Src/DasherCore/DasherModel.h                 |   11 +-
 Src/DasherCore/DasherNode.h                  |    2 +-
 Src/DasherCore/DasherView.cpp                |    3 +-
 Src/DasherCore/DasherView.h                  |    6 +-
 Src/DasherCore/DasherViewSquare.cpp          |  143 +++---
 Src/DasherCore/DasherViewSquare.h            |   14 +-
 Src/DasherCore/DasherViewSquare.inl          |   22 +-
 Src/DasherCore/DefaultFilter.cpp             |   29 +-
 Src/DasherCore/DefaultFilter.h               |    2 +-
 Src/DasherCore/DynamicButtons.cpp            |   32 +-
 Src/DasherCore/DynamicButtons.h              |   14 +-
 Src/DasherCore/DynamicFilter.cpp             |    2 +-
 Src/DasherCore/GameModule.cpp                |    4 +-
 Src/DasherCore/InputFilter.h                 |    4 +-
 Src/DasherCore/MandarinAlphMgr.cpp           |    4 +-
 Src/DasherCore/MandarinAlphMgr.h             |    2 +-
 Src/DasherCore/NodeCreationManager.cpp       |   18 +-
 Src/DasherCore/OneButtonDynamicFilter.cpp    |   10 +-
 Src/DasherCore/OneButtonDynamicFilter.h      |    4 +-
 Src/DasherCore/OneButtonFilter.cpp           |    2 +-
 Src/DasherCore/OneButtonFilter.h             |    2 +-
 Src/DasherCore/OneDimensionalFilter.cpp      |   22 +-
 Src/DasherCore/Parameters.cpp                |    9 +-
 Src/DasherCore/Parameters.h                  |   10 +-
 Src/DasherCore/StylusFilter.cpp              |    4 +-
 Src/DasherCore/StylusFilter.h                |    2 +-
 Src/DasherCore/TwoButtonDynamicFilter.cpp    |   42 +--
 Src/DasherCore/TwoButtonDynamicFilter.h      |   13 +-
 Src/DasherCore/TwoPushDynamicFilter.cpp      |    8 +-
 Src/DasherCore/TwoPushDynamicFilter.h        |    4 +-
 Src/DasherCore/UserLog.h                     |    4 +-
 Src/DasherCore/UserLogBase.cpp               |    5 +-
 Src/DasherCore/UserLogBase.h                 |    2 +-
 Src/Gtk2/Preferences.cpp                     |  181 +------
 Src/Gtk2/dasher_editor_internal.cpp          |    2 +-
 Src/Gtk2/dasher_main.cpp                     |    2 +-
 Src/iPhone/Classes/CDasherInterfaceBridge.mm |    3 +-
 Src/iPhone/Classes/DasherAppDelegate.h       |    1 -
 Src/iPhone/Classes/IPhoneFilters.h           |    6 +-
 Src/iPhone/Classes/IPhoneFilters.mm          |   10 +-
 Src/iPhone/Classes/IPhoneInputs.h            |    4 +-
 Src/iPhone/Classes/IPhoneInputs.mm           |    6 +-
 po/POTFILES.in                               |   15 +-
 po/sl.po                                     |  259 +++++-----
 po/tr.po                                     |  721 +++++++++++++++++---------
 70 files changed, 1078 insertions(+), 1041 deletions(-)
---
diff --cc Src/DasherCore/BasicLog.cpp
index 6bb4677,4550bb7..3b04771
--- a/Src/DasherCore/BasicLog.cpp
+++ b/Src/DasherCore/BasicLog.cpp
@@@ -14,7 -14,7 +14,7 @@@
  
  using namespace Dasher;
  
- CBasicLog::CBasicLog(CSettingsUser *pCreateFrom, CDasherInterfaceBase *pIntf) : CUserLogBase(pCreateFrom, pIntf) {
 -CBasicLog::CBasicLog(CSettingsUser *pCreateFrom, CDasherInterfaceBase *pIntf) : CSettingsUser(pCreateFrom), CUserLogBase(pIntf) {
++CBasicLog::CBasicLog(CSettingsUser *pCreateFrom, CDasherInterfaceBase *pIntf) : CUserLogBase(pCreateFrom,pIntf) {
    m_iSymbolCount = 0;
    m_bStarted = false;
  }
diff --cc Src/DasherCore/BasicLog.h
index 49e4aec,7c07842..34de634
--- a/Src/DasherCore/BasicLog.h
+++ b/Src/DasherCore/BasicLog.h
@@@ -5,9 -6,9 +6,9 @@@
  
  /// \ingroup Logging
  /// @{
 -class CBasicLog : protected Dasher::CSettingsUser, public CUserLogBase {
 +class CBasicLog : public CUserLogBase {
   public:
-   CBasicLog(Dasher::CSettingsUser *pCreateFrom, Dasher::CDasherInterfaceBase *pIntf);
+   CBasicLog(CSettingsUser *pCreateFrom, Dasher::CDasherInterfaceBase *pIntf);
    ~CBasicLog();
  
    virtual void AddParam(const string& strName, const string& strValue, int iOptionMask = 0) {};
diff --cc Src/DasherCore/ButtonMode.cpp
index 69157c8,834675e..735dc04
--- a/Src/DasherCore/ButtonMode.cpp
+++ b/Src/DasherCore/ButtonMode.cpp
@@@ -188,29 -166,43 +166,42 @@@ bool CButtonMode::Timer(unsigned long T
    return CDasherButtons::Timer(Time, pView, pInput, pModel, pol);
  }
  
- void CButtonMode::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog)
- {
-   if (iId == 100 && !m_bMenu) {
 -void CButtonMode::KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY)
 -{
++void CButtonMode::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
+   if (iId == 100) {
      //Mouse!
-     myint iDasherX, iDasherY;
-     pInput->GetDasherCoords(iDasherX, iDasherY, pView);
-     for (int i = 0; i < m_iNumBoxes; i++)
-     {
-       if (iDasherY < m_pBoxes[i].iDisplayBottom &&
-           iDasherY > m_pBoxes[i].iDisplayTop &&
-           iDasherX < (m_pBoxes[i].iDisplayBottom - m_pBoxes[i].iDisplayTop)) {
-         //user has clicked in box! Simulate press of appropriate (direct-mode) button...
-         CDasherButtons::KeyDown(iTime, (i==m_iNumBoxes-1) ? 1 : i+2, pView, pInput, pModel, pUserLog);
-         return;
+     if (m_bMenu) {
+       bool bScan;
+       if (GetLongParameter(LP_BUTTON_SCAN_TIME))
+         bScan = false; //auto-scan, any click selects
+       else {
+         //top scans, bottom selects
+         screenint iScreenX, iScreenY;
+         pInput->GetScreenCoords(iScreenX, iScreenY, pView);
+         bScan = iScreenY < pView->Screen()->GetHeight()/2;
+       }
+       CDasherButtons::KeyDown(iTime, bScan ? 1 : 2, pView, pInput, pModel);
+       return;
+     } else {
+       myint iDasherX, iDasherY;
+       pInput->GetDasherCoords(iDasherX, iDasherY, pView);
+       //look for a click _in_ a box -> activate box
+       for (int i = 0; i < m_iNumBoxes; i++) {
+         if (iDasherY < m_pBoxes[i].iDisplayBottom &&
+             iDasherY > m_pBoxes[i].iDisplayTop &&
+             iDasherX < (m_pBoxes[i].iDisplayBottom - m_pBoxes[i].iDisplayTop)) {
+           //user has clicked in box! Simulate press of appropriate (direct-mode) button...
+           CDasherButtons::KeyDown(iTime, (i==m_iNumBoxes-1) ? 1 : i+2, pView, pInput, pModel);
+           return;
+         }
        }
+       //not in any box. Fall through, just to be conservative...
      }
-     //not in any box. Fall through, just to be conservative...
    }
-   CInputFilter::KeyDown(iTime, iId, pView, pInput, pModel, pUserLog);
 -  CInputFilter::KeyDown(iTime, iId, pView, pInput, pModel, bPos, iX, iY);
++  CInputFilter::KeyDown(iTime, iId, pView, pInput, pModel);
  }
  
- void CButtonMode::DirectKeyDown(int iTime, int iId, CDasherView *pView, CDasherModel *pModel, CUserLogBase *pUserLog) {
-   CDasherButtons::DirectKeyDown(iTime, iId, pView, pModel, pUserLog);
+ void CButtonMode::DirectKeyDown(int iTime, int iId, CDasherView *pView, CDasherModel *pModel) {
+   CDasherButtons::DirectKeyDown(iTime, iId, pView, pModel);
   if (iId!=100) m_iLastTime = iTime;
  }
  
diff --cc Src/DasherCore/ButtonMode.h
index 1c24798,c314619..c913c21
--- a/Src/DasherCore/ButtonMode.h
+++ b/Src/DasherCore/ButtonMode.h
@@@ -28,7 -28,7 +28,7 @@@ class CButtonMode : public CDasherButto
    bool DecorateView(CDasherView *pView, CDasherInput *pInput);
  
    //override to get mouse clicks/taps back again
-   virtual void KeyDown(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
 -  virtual void KeyDown(int Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY);
++  virtual void KeyDown(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
    
    bool GetSettings(SModuleSettings **pSettings, int *iCount);
   protected: 
diff --cc Src/DasherCore/ButtonMultiPress.cpp
index ca83c8f,728ee33..5af586d
--- a/Src/DasherCore/ButtonMultiPress.cpp
+++ b/Src/DasherCore/ButtonMultiPress.cpp
@@@ -23,11 -23,11 +23,11 @@@
  
  using namespace Dasher;
  
 -CButtonMultiPress::CButtonMultiPress(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, ModuleID_t iID, const char *szName)
 -  : CDynamicFilter(pCreator, pInterface, iID, szName) {
 +CButtonMultiPress::CButtonMultiPress(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName)
 +  : CDynamicButtons(pCreator, pInterface, pFramerate, iID, szName) {
  }
  
- void CButtonMultiPress::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
 -void CButtonMultiPress::KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
++void CButtonMultiPress::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
  
    if (m_bKeyDown) return;
  
@@@ -57,7 -57,7 +57,7 @@@
    // Record press...
    m_deQueueTimes.push_back(iTime);
    // ... and process normally; if it changes the state, pause()/reverse()'ll clear the queue
-   CDynamicButtons::KeyDown(iTime, iId, pView, pInput, pModel, pUserLog);
 -  CDynamicFilter::KeyDown(iTime, iId, pView, pInput, pModel);
++  CDynamicButtons::KeyDown(iTime, iId, pView, pInput, pModel);
  }
  
  void CButtonMultiPress::pause()
diff --cc Src/DasherCore/ButtonMultiPress.h
index bc7a7d8,9d56c92..bdc8848
--- a/Src/DasherCore/ButtonMultiPress.h
+++ b/Src/DasherCore/ButtonMultiPress.h
@@@ -26,14 -26,14 +26,14 @@@
  namespace Dasher {
  /// \ingroup InputFilter
  /// @{
 -///DynamicFilter which detects multiple presses of the same button occurring in a short space of time
 +/// DynamicButtons filter which detects multiple presses of the same button occurring in a short space of time
  /// (such multi-presses are then passed onto the standard 'ActionButton' method, with iType equal
  /// to the number of presses, for subclasses to handle/decide how to respond.)
 -class CButtonMultiPress : public CDynamicFilter {
 +class CButtonMultiPress : public CDynamicButtons {
   public:
 -  CButtonMultiPress(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, ModuleID_t iID, const char *szName);
 +  CButtonMultiPress(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName);
  
-   virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
 -  virtual void KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
++  virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
  
   protected:
    virtual unsigned int maxClickCount()=0;
diff --cc Src/DasherCore/ClickFilter.cpp
index f359299,bf26554..4c55cd6
--- a/Src/DasherCore/ClickFilter.cpp
+++ b/Src/DasherCore/ClickFilter.cpp
@@@ -80,10 -79,10 +79,10 @@@ void CZoomAdjuster::AdjustZoomCoords(my
  }
  
  bool CClickFilter::Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol) {
 -  return pModel->NextScheduledStep(Time);
 +  return pModel->NextScheduledStep();
  }
  
- void CClickFilter::KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog, bool bPos, int iX, int iY) {
 -void CClickFilter::KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY) {
++void CClickFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
    switch(iId) {
    case 100: // Mouse clicks
      {
diff --cc Src/DasherCore/ClickFilter.h
index 3a1716d,e89f022..6cb9e0e
--- a/Src/DasherCore/ClickFilter.h
+++ b/Src/DasherCore/ClickFilter.h
@@@ -24,7 -24,7 +24,7 @@@ class CClickFilter : public CInputFilte
  
    virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput);
    virtual bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pDasherModel, CExpansionPolicy **pol);
-   virtual void KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog, bool bPos, int iX, int iY);
 -  virtual void KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY);
++  virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
    virtual bool GetSettings(SModuleSettings **pSettings, int *iCount);
    
   private:
diff --cc Src/DasherCore/DasherButtons.cpp
index ec8bd19,e52b9a2..0643cdb
--- a/Src/DasherCore/DasherButtons.cpp
+++ b/Src/DasherCore/DasherButtons.cpp
@@@ -36,10 -36,10 +36,10 @@@ void CDasherButtons::Activate() 
    // which depends on it, tho...
    if (!m_pBoxes) SetupBoxes();
  
-   m_iScanTime = std::numeric_limits<int>::min();
+   m_iScanTime = std::numeric_limits<unsigned long>::min();
  }
  
- void CDasherButtons::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
 -void CDasherButtons::KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
++void CDasherButtons::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
  
    if(m_bMenu) {
      switch(iId) {
diff --cc Src/DasherCore/DasherButtons.h
index dccfa77,cff04ad..ca5836c
--- a/Src/DasherCore/DasherButtons.h
+++ b/Src/DasherCore/DasherButtons.h
@@@ -27,7 -27,7 +27,7 @@@ class CDasherButtons : public CInputFil
  
    virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput)=0;
    
-   void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
 -  void KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
++  void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
    bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
    void Activate();
    
diff --cc Src/DasherCore/DasherInterfaceBase.cpp
index ace3b07,3cf0b2e..ebaeaa4
--- a/Src/DasherCore/DasherInterfaceBase.cpp
+++ b/Src/DasherCore/DasherInterfaceBase.cpp
@@@ -709,7 -754,7 +721,7 @@@ void CDasherInterfaceBase::KeyDown(unsi
      return;
  
    if(m_pInputFilter) {
-     m_pInputFilter->KeyDown(iTime, iId, m_pDasherView, m_pInput, m_pDasherModel, m_pUserLog);
 -    m_pInputFilter->KeyDown(iTime, iId, m_pDasherView, m_pInput, m_pDasherModel, bPos, iX, iY);
++    m_pInputFilter->KeyDown(iTime, iId, m_pDasherView, m_pInput, m_pDasherModel);
    }
  
    if(m_pInput) {
diff --cc Src/DasherCore/DasherInterfaceBase.h
index 82c93a5,40e7157..71f1cf8
--- a/Src/DasherCore/DasherInterfaceBase.h
+++ b/Src/DasherCore/DasherInterfaceBase.h
@@@ -477,6 -494,19 +477,10 @@@ protected
    void ChangeColours();
    void ChangeView();
  
+   //Compute the screen orientation to use - i.e. combining the user's
+   // preference with the alphabet.
+   Opts::ScreenOrientations ComputeOrientation();
+ 
 -  void SetupActionButtons();
 -  void DestroyActionButtons();
 -  void PositionActionButtons();
 -  bool DrawActionButtons();
 -
 -  std::vector<CActionButton *> m_vLeftButtons;
 -  std::vector<CActionButton *> m_vRightButtons;
 -
 -
    class WordSpeaker : public TransientObserver<const CEditEvent *> {
    public:
      WordSpeaker(CDasherInterfaceBase *pIntf);
diff --cc Src/DasherCore/DasherModel.cpp
index fab05df,73e6bf5..1127e8d
--- a/Src/DasherCore/DasherModel.cpp
+++ b/Src/DasherCore/DasherModel.cpp
@@@ -50,9 -51,12 +50,9 @@@ static char THIS_FILE[] = __FILE__
  
  // CDasherModel
  
 -CDasherModel::CDasherModel(CSettingsUser *pCreateFrom,
 -			   CDasherInterfaceBase *pDasherInterface)
 -  : CFrameRate(pCreateFrom), m_pDasherInterface(pDasherInterface) {
 -
 -  DASHER_ASSERT(m_pDasherInterface != NULL);
 -
 +CDasherModel::CDasherModel(CSettingsUser *pCreateFrom)
- : CSettingsUserObserver(pCreateFrom) {
++: CSettingsUser(pCreateFrom) {
 +  
    m_pLastOutput = m_Root = NULL;
  
    m_Rootmin = 0;
@@@ -89,19 -92,20 +88,6 @@@ CDasherModel::~CDasherModel() 
    }
  }
  
--void CDasherModel::HandleEvent(int iParameter) {
-   switch (iParameter) {
-   case BP_SMOOTH_OFFSET:
-     if (!GetBoolParameter(BP_SMOOTH_OFFSET))
-       //smoothing has just been turned off. End any transition/jump currently
-       // in progress at it's current point
-       AbortOffset();
-     break;
-   default:
-     break;
-   }
- }
- 
 -  CFrameRate::HandleEvent(iParameter);
 -
 -  switch (iParameter) {
 -  case BP_DASHER_PAUSED:
 -    if(GetBoolParameter(BP_SLOW_START))
 -      m_iStartTime = 0;
 -    //else, leave m_iStartTime as is - will result in no slow start
 -    break;
 -  default:
 -    break;
 -  }
 -}
 -
  void CDasherModel::Make_root(CDasherNode *pNewRoot) {
    //  std::cout << "Make root" << std::endl;
  
@@@ -252,12 -256,15 +238,12 @@@ void CDasherModel::SetOffset(int iOffse
    // GetMinWidth, if so called LimitRoot w/that width - i.e., make sure iWidth
    // is no more than that minimum. Should we do something similar here???
  
-   int iWidth( static_cast<int>( (GetLongParameter(LP_MAX_Y) / (2.0*dFraction)) ) );
+   int iWidth( static_cast<int>( MAX_Y / (2.0*dFraction) ) );
  
-   m_Rootmin = GetLongParameter(LP_MAX_Y) / 2 - iWidth / 2;
-   m_Rootmax = GetLongParameter(LP_MAX_Y) / 2 + iWidth / 2;
+   m_Rootmin = MAX_Y / 2 - iWidth / 2;
+   m_Rootmax = MAX_Y / 2 + iWidth / 2;
  
    m_iDisplayOffset = 0;
 -
 -  // TODO: See if this is better positioned elsewhere
 -  m_pDasherInterface->ScheduleRedraw();
  }
  
  int CDasherModel::GetOffset() {
@@@ -274,11 -295,13 +260,9 @@@ void CDasherModel::Get_new_root_coords(
    if (X > iMaxX) X = iMaxX;
  
    // Mouse coords X, Y
 -  // new root{min,max} r1,r2, old root{min,max} R1,R2
 -  const dasherint R1 = m_Rootmin;
 -  const dasherint R2 = m_Rootmax;
    // const dasherint Y1 = 0;
-   dasherint Y2(GetLongParameter(LP_MAX_Y));
-   dasherint iOX(GetLongParameter(LP_OX));
-   dasherint iOY(GetLongParameter(LP_OY));
+   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
diff --cc Src/DasherCore/DasherModel.h
index 23d2038,01070a4..529bab3
--- a/Src/DasherCore/DasherModel.h
+++ b/Src/DasherCore/DasherModel.h
@@@ -64,20 -61,23 +64,17 @@@ namespace Dasher 
  ///
  /// The class is Observable in that it broadcasts a pointer to a CDasherNode when the node's
  /// children are created.
- class Dasher::CDasherModel: private CSettingsUserObserver, public Observable<CDasherNode*>, private NoClones
 -class Dasher::CDasherModel:public Dasher::CFrameRate, public Observable<CDasherNode*>, private NoClones
++class Dasher::CDasherModel: private CSettingsUser, public Observable<CDasherNode*>, private NoClones
  {
   public:
+   static const unsigned int NORMALIZATION = 1<<16;
+   static const myint ORIGIN_X=2048, ORIGIN_Y=2048, MAX_Y=4096;
+ 
    /// Constructs a new CDasherModel. Note, must be followed by a call to
    /// SetOffset() before the model can be used.
 -  CDasherModel(CSettingsUser *pCreateFrom, CDasherInterfaceBase *pDashIface);
 +  CDasherModel(CSettingsUser *pCreateFrom);
    ~CDasherModel();
  
--  ///
--  /// Event handler
--  ///
--
--  void HandleEvent(int iParameter);
--
    /// @name Dymanic evolution
    /// Routines detailing the timer dependent evolution of the model
    /// @{
diff --cc Src/DasherCore/DefaultFilter.cpp
index 0be7b5b,6c67143..0da8445
--- a/Src/DasherCore/DefaultFilter.cpp
+++ b/Src/DasherCore/DefaultFilter.cpp
@@@ -143,7 -141,7 +144,7 @@@ bool CDefaultFilter::Timer(unsigned lon
    return bDidSomething;
  }
  
- void CDefaultFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
 -void CDefaultFilter::KeyDown(int iTime, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {
++void CDefaultFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {
  
    switch(iId) {
    case 0: // Start on space
diff --cc Src/DasherCore/DefaultFilter.h
index d64a9b3,1cbab7b..f42c90e
--- a/Src/DasherCore/DefaultFilter.h
+++ b/Src/DasherCore/DefaultFilter.h
@@@ -18,8 -18,7 +18,8 @@@ class CDefaultFilter : public CDynamicF
  
    virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput);
    virtual bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol);
-   virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
 -  virtual void KeyDown(int iTime, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel);
++  virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel);
 +  virtual void KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
    virtual void Activate();
    virtual void Deactivate();
    bool GetSettings(SModuleSettings **, int *);
diff --cc Src/DasherCore/DynamicButtons.cpp
index 9b8941f,0000000..fa35644
mode 100644,000000..100644
--- a/Src/DasherCore/DynamicButtons.cpp
+++ b/Src/DasherCore/DynamicButtons.cpp
@@@ -1,156 -1,0 +1,162 @@@
 +// DynamicButtons.cpp
 +//
 +// Copyright (c) 2007 The Dasher Team
 +//
 +// This file is part of Dasher.
 +//
 +// Dasher is free software; you can redistribute it and/or modify
 +// it under the terms of the GNU General Public License as published by
 +// the Free Software Foundation; either version 2 of the License, or
 +// (at your option) any later version.
 +//
 +// Dasher is distributed in the hope that it will be useful,
 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +// GNU General Public License for more details.
 +//
 +// You should have received a copy of the GNU General Public License
 +// along with Dasher; if not, write to the Free Software 
 +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 +
 +#include "DasherInterfaceBase.h"
 +#include "DynamicButtons.h"
 +
 +using namespace Dasher;
 +
 +CDynamicButtons::CDynamicButtons(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName)
-   : CDynamicFilter(pCreator, pInterface, pFramerate, iID, szName), CSettingsObserver(pCreator) {
++  : CDynamicFilter(pCreator, pInterface, pFramerate, iID, szName), CSettingsObserver(pCreator), m_pModel(NULL) {
 +  m_bDecorationChanged = true;
 +  m_bKeyDown = false;
 +  pause();
 +}
 +
 +bool CDynamicButtons::Timer(unsigned long iTime, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol)
 +{
 +  if(m_bKeyDown && !m_bKeyHandled && ((iTime - m_iKeyDownTime) > GetLongParameter(LP_HOLD_TIME))) {
-     Event(iTime, m_iHeldId, 1, m_pDasherModel, m_pUserLog);
++    Event(iTime, m_iHeldId, 1, m_pDasherModel);
 +    m_bKeyHandled = true;
 +    //return true; //ACL although that's what old DynamicButtons did, surely we should progress normally?
 +  }
 +  if (isPaused()) return false;
 +  if (isReversing()) {
 +    OneStepTowards(m_pDasherModel, 41943,2048, iTime, SlowStartSpeedMul(iTime));
 +    return true;
 +  }
 +  //moving forwards. Check auto speed control...
 +  unsigned int uTime = static_cast<unsigned int>(iTime);
 +  if (GetBoolParameter(BP_AUTO_SPEEDCONTROL) && m_uSpeedControlTime < uTime)
 +  {
 +	  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 = uTime + 1000*GetLongParameter(LP_DYNAMIC_SPEED_FREQ);
 +  }
 +  return TimerImpl(iTime, pDasherView, m_pDasherModel, pol);
 +}
 +
- void CDynamicButtons::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
-   
-   m_pUserLog = pUserLog;
-   
++void CDynamicButtons::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
++
 +  if(((iId == 0) || (iId == 1) || (iId == 100)) && !GetBoolParameter(BP_BACKOFF_BUTTON))
 +    return;
 +
 +  if(m_bKeyDown)
 +    return;
 +
 +  // Pass the basic key down event to the handler
-   Event(iTime, iId, 0, pModel, pUserLog);
++  Event(iTime, iId, 0, pModel);
 +    
 +  // Store the key down time so that long presses can be determined
 +  // TODO: This is going to cause problems if multiple buttons are
 +  // held down at once
 +  m_iKeyDownTime = iTime;
 +
 +  m_iHeldId = iId;
 +  m_bKeyDown = true;
 +  m_bKeyHandled = false;
 +}
 +
 +void CDynamicButtons::KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
 +  if (iId == m_iHeldId) m_bKeyDown = false;
 +}
 +
- void CDynamicButtons::Event(int iTime, int iButton, int iType, CDasherModel *pModel, CUserLogBase *pUserLog) {
++void CDynamicButtons::Event(int iTime, int iButton, int iType, CDasherModel *pModel) {
 +  // Types known at this point in inheritance hierarchy:
 +  // 0 = ordinary click
 +  // 1 = long click
 +  
 +  // TODO: Check that state diagram implemented here is what we
 +  // decided upon
 +
 +  // What happens next depends on the state:
 +  if (isPaused()) {
 +    //Any button causes a restart
-     if(pUserLog)
++    if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
 +      pUserLog->KeyDown(iButton, iType, 1);
 +    run();
 +    Unpause(iTime);
 +  } else if (isReversing()) {
 +    //Any button pauses
-     if(pUserLog)
++    if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
 +      pUserLog->KeyDown(iButton, iType, 2);
 +    
 +    m_pInterface->Stop();
 +    //change in BP_DASHER_PAUSED calls pause().
 +  } else {
 +    //running; examine event/button-press type
 +    switch(iType) {
 +    case 0: //single press
 +      if((iButton == 0) || (iButton == 100)) {
 +        //dedicated pause button
-         if(pUserLog)
++        if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
 +          pUserLog->KeyDown(iButton, iType, 2);
 +        m_pInterface->Stop();
 +        break;
 +      }
 +      else if(iButton == 1) {
 +        //dedicated reverse button
-         if(pUserLog)
++        if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
 +          pUserLog->KeyDown(iButton, iType, 6);
 +        reverse();
 +        break;
 +      }
 +      //else - any non-special button - fall through
 +    default: //or, Any special kind of event - long, double, triple, ... 
-       ActionButton(iTime, iButton, iType, pModel, pUserLog);
++      ActionButton(iTime, iButton, iType, pModel);
 +    }
 +  }
 +}
 +
 +void CDynamicButtons::HandleEvent(int iParameter) {
 +  if (iParameter==BP_DASHER_PAUSED) {
 +    if (GetBoolParameter(BP_DASHER_PAUSED))
 +      pause(); //make sure we're in sync
 +    else if (m_pInterface->GetActiveInputMethod()==this && isPaused())
 +      //if we're active: can't unpause, as we don't know which way to go, run or reverse?
 +      SetBoolParameter(BP_DASHER_PAUSED, true);
 +  }
 +}
 +
++void CDynamicButtons::pause() {
++  m_iState = 0;
++  if (m_pModel) m_pModel->AbortOffset();
++}
++
 +void CDynamicButtons::reverse()
 +{
 +  m_iState = 1;
 +  if (GetBoolParameter(BP_AUTO_SPEEDCONTROL)) {
 +    //treat reversing as a sign of distress --> slow down!
 +    SetLongParameter(LP_MAX_BITRATE, GetLongParameter(LP_MAX_BITRATE) *
 +					 (1.0 - GetLongParameter(LP_DYNAMIC_SPEED_DEC)/100.0));
 +  }
 +}
 +
 +void CDynamicButtons::run()
 +{
 +  if (m_iState<2) //wasn't running previously
 +    m_uSpeedControlTime = 0; //will be set in Timer()
 +  m_iState = 2;
 +}
 +
++void CDynamicButtons::ApplyOffset(CDasherModel *pModel, int iOffset) {
++  (m_pModel=pModel)->Offset(iOffset);
++}
diff --cc Src/DasherCore/DynamicButtons.h
index 06c7cf6,0000000..40c6c9f
mode 100644,000000..100644
--- a/Src/DasherCore/DynamicButtons.h
+++ b/Src/DasherCore/DynamicButtons.h
@@@ -1,67 -1,0 +1,69 @@@
 +// DynamicFilter.h
 +//
 +// Copyright (c) 2007 The Dasher Team
 +//
 +// This file is part of Dasher.
 +//
 +// Dasher is free software; you can redistribute it and/or modify
 +// it under the terms of the GNU General Public License as published by
 +// the Free Software Foundation; either version 2 of the License, or
 +// (at your option) any later version.
 +//
 +// Dasher is distributed in the hope that it will be useful,
 +// but WITHOUT ANY WARRANTY; without even the implied warranty of
 +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 +// GNU General Public License for more details.
 +//
 +// You should have received a copy of the GNU General Public License
 +// along with Dasher; if not, write to the Free Software
 +// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 +
 +#ifndef __DynamicButtons_h__
 +#define __DynamicButtons_h__
 +
 +#include "DynamicFilter.h"
 +
 +/// \ingroup InputFilter
 +/// @{
 +namespace Dasher {
 +///filter with three states: paused, reversing, running. Hold any button down to reverse.
 +class CDynamicButtons : public CDynamicFilter, public CSettingsObserver {
 + public:
 +  CDynamicButtons(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName);
 +
 +  ///when reversing, backs off; when paused, does nothing; when running, delegates to TimerImpl
 +  virtual bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
 +
-   virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
++  virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
 +  virtual void KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
 +
 +  //respond to changes to BP_DASHER_PAUSED to keep m_iState in sync
 +  virtual void HandleEvent(int iParameter);
 + protected:
-   virtual void ActionButton(int iTime, int iButton, int iType, CDasherModel *pModel, CUserLogBase *pUserLog) = 0;
-   virtual void Event(int iTime, int iButton, int iType, CDasherModel *pModel, CUserLogBase *pUserLog);
++  virtual void ActionButton(int iTime, int iButton, int iType, CDasherModel *pModel) = 0;
++  virtual void Event(int iTime, int iButton, int iType, CDasherModel *pModel);
 +
 +  bool m_bKeyDown;
 +  bool m_bKeyHandled;
 +  bool m_bDecorationChanged;
 +  bool isPaused() {return m_iState == 0;}
 +  bool isReversing() {return m_iState == 1;}
 +  bool isRunning() {return m_iState==2;}
-   virtual void pause() {m_iState = 0;}
++  virtual void pause();
 +  virtual void reverse();
 +  virtual void run();
 +
 +  virtual bool TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) = 0;
 +
++  ///Subclasses should all this (rather than pModel->Offset()) to offset the model
++  /// (it also stores the model, to abort the offset upon pause if necessary)
++  void ApplyOffset(CDasherModel *pModel, int iOffset);
 +  private:
 +    int m_iState; // 0 = paused, 1 = reversing, >=2 = running (extensible by subclasses)
 +    int m_iHeldId;
 +    int m_iKeyDownTime;
 +    unsigned int m_uSpeedControlTime;
- 
-     CUserLogBase *m_pUserLog;
++    CDasherModel *m_pModel;
 +};
 +}
 +#endif
diff --cc Src/DasherCore/DynamicFilter.cpp
index 8f8b0ef,2163bfc..026f17c
--- a/Src/DasherCore/DynamicFilter.cpp
+++ b/Src/DasherCore/DynamicFilter.cpp
@@@ -23,35 -23,141 +23,35 @@@
  
  using namespace Dasher;
  
 -CDynamicFilter::CDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, ModuleID_t iID, const char *szName)
 -  : CInputFilter(pInterface, iID, szName), CSettingsUserObserver(pCreator), m_pModel(NULL) {
 -  m_bDecorationChanged = true;
 -  m_bKeyDown = false;
 -  pause();
 +CDynamicFilter::CDynamicFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName) : CInputFilter(pInterface, iID, szName), CSettingsUser(pCreator), m_pFramerate(pFramerate) {
  }
  
 -bool CDynamicFilter::Timer(unsigned long iTime, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol)
 -{
 -  if(m_bKeyDown && !m_bKeyHandled && ((iTime - m_iKeyDownTime) > GetLongParameter(LP_HOLD_TIME))) {
 -    Event(iTime, m_iHeldId, 1, m_pDasherModel);
 -    m_bKeyHandled = true;
 -    //return true; //ACL although that's what old DynamicFilter did, surely we should progress normally?
 -  }
 -  if (isPaused()) return false;
 -  if (isReversing()) {
 -    m_pDasherModel->OneStepTowards(41943,2048, iTime);
 -    return true;
 -  }
 -  //moving forwards. Check auto speed control...
 -  unsigned int uTime = static_cast<unsigned int>(iTime);
 -  if (GetBoolParameter(BP_AUTO_SPEEDCONTROL) && m_uSpeedControlTime < uTime)
 -  {
 -	  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 = uTime + 1000*GetLongParameter(LP_DYNAMIC_SPEED_FREQ);
 -  }
 -  return TimerImpl(iTime, pDasherView, m_pDasherModel, pol);
 -}
 -
 -void CDynamicFilter::KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
 -    
 -  if(((iId == 0) || (iId == 1) || (iId == 100)) && !GetBoolParameter(BP_BACKOFF_BUTTON))
 -    return;
 -
 -  if(m_bKeyDown)
 -    return;
 -
 -  // Pass the basic key down event to the handler
 -  Event(iTime, iId, 0, pModel);
 -    
 -  // Store the key down time so that long presses can be determined
 -  // TODO: This is going to cause problems if multiple buttons are
 -  // held down at once
 -  m_iKeyDownTime = iTime;
 -
 -  m_iHeldId = iId;
 -  m_bKeyDown = true;
 -  m_bKeyHandled = false;
 -}
 -
 -void CDynamicFilter::KeyUp(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
 -  if (iId == m_iHeldId) m_bKeyDown = false;
 -}
 +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?
  
 -void CDynamicFilter::Event(int iTime, int iButton, int iType, CDasherModel *pModel) {
 -  // Types known at this point in inheritance hierarchy:
 -  // 0 = ordinary click
 -  // 1 = long click
 +  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);
    
-   pModel->OneStepTowards(y1, y2, static_cast<int>(m_pFramerate->Steps() / dSpeedMul), static_cast<myint>(GetLongParameter(LP_MAX_Y)/dRXMax));
 -  // TODO: Check that state diagram implemented here is what we
 -  // decided upon
 -
 -  // What happens next depends on the state:
 -  if (isPaused()) {
 -    //Any button causes a restart
 -    if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
 -      pUserLog->KeyDown(iButton, iType, 1);
 -    run();
 -    m_pInterface->Unpause(iTime);
 -  } else if (isReversing()) {
 -    //Any button pauses
 -    if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
 -      pUserLog->KeyDown(iButton, iType, 2);
 -    
 -    m_pInterface->Stop();
 -    //change in BP_DASHER_PAUSED calls pause().
 -  } else {
 -    //running; examine event/button-press type
 -    switch(iType) {
 -    case 0: //single press
 -      if((iButton == 0) || (iButton == 100)) {
 -        //dedicated pause button
 -        if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
 -          pUserLog->KeyDown(iButton, iType, 2);
 -        m_pInterface->Stop();
 -        break;
 -      }
 -      else if(iButton == 1) {
 -        //dedicated reverse button
 -        if(CUserLogBase *pUserLog=m_pInterface->GetUserLogPtr())
 -          pUserLog->KeyDown(iButton, iType, 6);
 -        reverse();
 -        break;
 -      }
 -      //else - any non-special button - fall through
 -    default: //or, Any special kind of event - long, double, triple, ... 
 -      ActionButton(iTime, iButton, iType, pModel);
 -    }
 -  }
 -}
 -
 -void CDynamicFilter::HandleEvent(int iParameter) {
 -  if (iParameter==BP_DASHER_PAUSED) {
 -    if (GetBoolParameter(BP_DASHER_PAUSED))
 -      pause(); //make sure we're in sync
 -    else if (m_pInterface->GetActiveInputMethod()==this && isPaused())
 -      //if we're active: can't unpause, as we don't know which way to go, run or reverse?
 -      SetBoolParameter(BP_DASHER_PAUSED, true);
 -  }
++  pModel->OneStepTowards(y1, y2, static_cast<int>(m_pFramerate->Steps() / dSpeedMul), static_cast<myint>(CDasherModel::MAX_Y/dRXMax));
 +  return true;
  }
  
 -void CDynamicFilter::pause() {
 -  m_iState = 0;
 -  if (m_pModel) m_pModel->AbortOffset();
 -}
 -
 -void CDynamicFilter::reverse()
 -{
 -  m_iState = 1;
 -  if (GetBoolParameter(BP_AUTO_SPEEDCONTROL)) {
 -    //treat reversing as a sign of distress --> slow down!
 -    SetLongParameter(LP_MAX_BITRATE, GetLongParameter(LP_MAX_BITRATE) *
 -					 (1.0 - GetLongParameter(LP_DYNAMIC_SPEED_DEC)/100.0));
 +double CDynamicFilter::SlowStartSpeedMul(unsigned long iTime) {
 +  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))));
    }
 +  //no slow start, or finished.
 +  return 1.0;
  }
  
 -void CDynamicFilter::run()
 -{
 -  if (m_iState<2) //wasn't running previously
 -    m_uSpeedControlTime = 0; //will be set in Timer()
 -  m_iState = 2;
 -}
 +void CDynamicFilter::Unpause(unsigned long Time) {
 +  if (!GetBoolParameter(BP_DASHER_PAUSED)) return; //already running, no need to / can't really do anything
 +  
 +  SetBoolParameter(BP_DASHER_PAUSED, false);
  
 -void CDynamicFilter::ApplyOffset(CDasherModel *pModel, int iOffset) {
 -  (m_pModel=pModel)->Offset(iOffset);
 +  m_pFramerate->Reset_framerate(Time);
 +  m_iStartTime = Time;
  }
 -
diff --cc Src/DasherCore/InputFilter.h
index 316ffe1,1a4521a..38ceadc
--- a/Src/DasherCore/InputFilter.h
+++ b/Src/DasherCore/InputFilter.h
@@@ -21,9 -21,12 +21,9 @@@ class CInputFilter : public CDasherModu
  
    virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput) { return false; };
  
-   virtual void KeyDown(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {}
 -  virtual void KeyDown(int Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY) {
 -    KeyDown(Time, iId, pDasherView, pInput, pModel);
 -  };
 -  virtual void KeyUp(int Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY) {
 -    KeyUp(Time, iId, pDasherView, pInput, pModel);
 -  };
++  virtual void KeyDown(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {}
 +  
 +  virtual void KeyUp(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {}
  
    virtual bool Timer(unsigned long Time, CDasherView *m_pDasherView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol)=0;// { return false; };
  
@@@ -37,7 -40,10 +37,7 @@@
    virtual bool supportsPause() {return false;}
    
   protected:
-   CDasherInterfaceBase *m_pInterface;
+   CDasherInterfaceBase * const m_pInterface;
 -
 -  virtual void KeyDown(int Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {};
 -  virtual void KeyUp(int Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {};
  };
  }
  /// @}
diff --cc Src/DasherCore/OneButtonDynamicFilter.cpp
index dcade6a,4ffc3b7..dd50637
--- a/Src/DasherCore/OneButtonDynamicFilter.cpp
+++ b/Src/DasherCore/OneButtonDynamicFilter.cpp
@@@ -97,15 -97,16 +97,15 @@@ bool COneButtonDynamicFilter::DecorateV
    return bRV;
  }
  
- void COneButtonDynamicFilter::KeyDown(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
 -void COneButtonDynamicFilter::KeyDown(int Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY) {
++void COneButtonDynamicFilter::KeyDown(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {
    if (iId == 100 && !GetBoolParameter(BP_BACKOFF_BUTTON))
      //mouse click - will be ignored by superclass method.
      //simulate press of button 2...
 -    CButtonMultiPress::KeyDown(Time, 2, pDasherView, pInput, pModel);
 -  else
 -    CInputFilter::KeyDown(Time, iId, pDasherView, pInput, pModel, bPos, iX, iY);
 +    iId=2;
-   CButtonMultiPress::KeyDown(Time, 2, pDasherView, pInput, pModel, pUserLog);
++  CButtonMultiPress::KeyDown(Time, iId, pDasherView, pInput, pModel);
  }
  
 -void COneButtonDynamicFilter::KeyUp(int Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY) {
 +void COneButtonDynamicFilter::KeyUp(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel) {
    if (iId == 100 && !GetBoolParameter(BP_BACKOFF_BUTTON))
      //mouse click - will be ignored by superclass method.
      //simulate press of button 2...
diff --cc Src/DasherCore/OneButtonDynamicFilter.h
index e1bb675,29d8ba8..4de1ceb
--- a/Src/DasherCore/OneButtonDynamicFilter.h
+++ b/Src/DasherCore/OneButtonDynamicFilter.h
@@@ -36,8 -36,8 +36,8 @@@ class COneButtonDynamicFilter : public 
    virtual bool GetSettings(SModuleSettings **pSettings, int *iCount);
  
    //override to get mouse clicks / taps back again...
-   virtual void KeyDown(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
 -  virtual void KeyDown(int Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY);
 -  virtual void KeyUp(int Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY);
++  virtual void KeyDown(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
 +  virtual void KeyUp(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
  
   private:
    unsigned int maxClickCount() {return 2;} //double-click to reverse
diff --cc Src/DasherCore/OneButtonFilter.cpp
index e734d47,f5e8a60..6ebd8c8
--- a/Src/DasherCore/OneButtonFilter.cpp
+++ b/Src/DasherCore/OneButtonFilter.cpp
@@@ -67,10 -67,10 +67,10 @@@ bool COneButtonFilter::Timer(unsigned l
      }
    }
  
 -  return m_pDasherModel->NextScheduledStep(Time);
 +  return m_pDasherModel->NextScheduledStep();
  }
  
- void COneButtonFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
 -void COneButtonFilter::KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
++void COneButtonFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
    if (bStarted) {
      if (iLocation == 0) {
        //back up by one zoom step.
diff --cc Src/DasherCore/OneButtonFilter.h
index e607b46,747fffc..66b4dcf
--- a/Src/DasherCore/OneButtonFilter.h
+++ b/Src/DasherCore/OneButtonFilter.h
@@@ -13,7 -13,7 +13,7 @@@ class COneButtonFilter : public CInputF
  
    virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput);
    virtual bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
-   virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
 -  virtual void KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
++  virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
    bool GetSettings(SModuleSettings **pSettings, int *iCount);
   private:
    ///true iff the scan line is moving down/up, or is in the 'reverse' stage
diff --cc Src/DasherCore/OneDimensionalFilter.cpp
index 86b8d48,b36d6bd..464363c
--- a/Src/DasherCore/OneDimensionalFilter.cpp
+++ b/Src/DasherCore/OneDimensionalFilter.cpp
@@@ -8,8 -8,8 +8,8 @@@ using namespace Dasher
    : COneDimensionalFilter(pSettingsStore, pInterface, m_pDasherModel, 4, _("One Dimensional Mode")) {
  }*/
  
 -COneDimensionalFilter::COneDimensionalFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, ModuleID_t iID, const char *szName)
 -  : CDefaultFilter(pCreator, pInterface, iID, szName), forwardmax(CDasherModel::MAX_Y/2.5) {
 +COneDimensionalFilter::COneDimensionalFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, const char *szName)
-   : CDefaultFilter(pCreator, pInterface, pFramerate, iID, szName), forwardmax(GetLongParameter(LP_MAX_Y)/2.5) {
++  : CDefaultFilter(pCreator, pInterface, pFramerate, iID, szName), forwardmax(CDasherModel::MAX_Y/2.5) {
  }
  
  void COneDimensionalFilter::ApplyTransform(myint &iDasherX, myint &iDasherY, CDasherView *pView) {
@@@ -86,8 -86,8 +86,8 @@@ CStartHandler *COneDimensionalFilter::M
          if (GetBoolParameter(BP_DASHER_PAUSED)) {
            //put start circle at center of 1D transform, rather than center of screen
            // (leave m_iScreenRadius, in pixels, as computed by above)
-           const myint rad(GetLongParameter(LP_CIRCLE_PERCENT) * GetLongParameter(LP_OY) / 100); //~~rad/2 in dasher-coords
-           pView->Dasher2Screen(GetLongParameter(LP_OX)-static_cast<COneDimensionalFilter*>(m_pFilter)->forwardmax+rad, GetLongParameter(LP_OY),m_screenCircleCenter.x, m_screenCircleCenter.y);
+           const myint rad(GetLongParameter(LP_CIRCLE_PERCENT) * CDasherModel::ORIGIN_Y / 100); //~~rad/2 in dasher-coords
 -          pView->Dasher2Screen(CDasherModel::ORIGIN_X-filter->forwardmax+rad, CDasherModel::ORIGIN_Y,m_screenCircleCenter.x, m_screenCircleCenter.y);
++          pView->Dasher2Screen(CDasherModel::ORIGIN_X-static_cast<COneDimensionalFilter*>(m_pFilter)->forwardmax+rad, CDasherModel::ORIGIN_Y,m_screenCircleCenter.x, m_screenCircleCenter.y);
          } 
        }
        void HandleEvent(int iParameter) {
diff --cc Src/DasherCore/Parameters.h
index eb13213,170016b..0a171bd
--- a/Src/DasherCore/Parameters.h
+++ b/Src/DasherCore/Parameters.h
@@@ -68,9 -71,12 +68,9 @@@ enum 
  
  enum {
    SP_ALPHABET_ID = END_OF_LPS, SP_ALPHABET_1, SP_ALPHABET_2, SP_ALPHABET_3, SP_ALPHABET_4, 
-   SP_COLOUR_ID, SP_DEFAULT_COLOUR_ID, SP_DASHER_FONT, SP_SYSTEM_LOC, SP_USER_LOC, SP_GAME_TEXT_FILE,
+   SP_COLOUR_ID, SP_DASHER_FONT, SP_SYSTEM_LOC, SP_USER_LOC, SP_GAME_TEXT_FILE,
    SP_SOCKET_INPUT_X_LABEL, SP_SOCKET_INPUT_Y_LABEL, SP_INPUT_FILTER, SP_INPUT_DEVICE,
    SP_BUTTON_0, SP_BUTTON_1, SP_BUTTON_2, SP_BUTTON_3, SP_BUTTON_4, SP_BUTTON_10, SP_JOYSTICK_DEVICE,
 -#ifdef TARGET_OS_IPHONE
 -  SP_CUSTOM_TILT, SP_VERTICAL_TILT,
 -#endif
    END_OF_SPS
  };
  
diff --cc Src/DasherCore/StylusFilter.cpp
index edc4a3e,4d512e9..5f043c0
--- a/Src/DasherCore/StylusFilter.cpp
+++ b/Src/DasherCore/StylusFilter.cpp
@@@ -22,16 -22,15 +22,16 @@@ bool CStylusFilter::Timer(unsigned lon
    return CDefaultFilter::Timer(iTime, pView, pInput, pModel, pol);
  }
  
- void CStylusFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
 -void CStylusFilter::KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
++void CStylusFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
    if(iId == 100) {
      pModel->ClearScheduledSteps();
 -    m_pInterface->Unpause(iTime);
 +    Unpause(iTime);
      m_iKeyDownTime = iTime;
 -  }
 +  } else
-     CDefaultFilter::KeyDown(iTime, iId, pView, pInput, pModel, pUserLog);
++    CDefaultFilter::KeyDown(iTime, iId, pView, pInput, pModel);
  }
  
 -void CStylusFilter::KeyUp(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
 +void CStylusFilter::KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
    if(iId == 100) {
      if (iTime - m_iKeyDownTime < GetLongParameter(LP_TAP_TIME)) {
        pInput->GetDasherCoords(m_iLastX, m_iLastY, pView);
diff --cc Src/DasherCore/StylusFilter.h
index 1b6fa90,6da5758..16c7fce
--- a/Src/DasherCore/StylusFilter.h
+++ b/Src/DasherCore/StylusFilter.h
@@@ -14,8 -14,8 +14,8 @@@ class CStylusFilter : public CDefaultFi
    /// - motion requires continually holding stylus against screen
    virtual bool supportsPause() {return false;}
    virtual bool Timer(unsigned long Time, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CExpansionPolicy **pol);
-   virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
 -  virtual void KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
 -  virtual void KeyUp(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
++  virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
 +  virtual void KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
   protected:
    ///Transform coordinates of a click, to get location to zoom into.
    /// Default is to call the same CZoomAdjuster::AdjustZoomCoords as CClickFilter
diff --cc Src/DasherCore/TwoButtonDynamicFilter.cpp
index 7400488,3224405..3f0321f
--- a/Src/DasherCore/TwoButtonDynamicFilter.cpp
+++ b/Src/DasherCore/TwoButtonDynamicFilter.cpp
@@@ -92,26 -92,22 +92,26 @@@ bool CTwoButtonDynamicFilter::DecorateV
    return bRV;
  }
  
- void CTwoButtonDynamicFilter::KeyDown(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
 -void CTwoButtonDynamicFilter::KeyDown(int Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY) {
 -	if (iId == 100 && !GetBoolParameter(BP_BACKOFF_BUTTON))
 -		//mouse click - will be ignored by superclass method.
++void CTwoButtonDynamicFilter::KeyDown(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
 +	if (iId == 100 && !GetBoolParameter(BP_BACKOFF_BUTTON)) {
 +    //mouse click - will be ignored by superclass method.
  		//simulate press of button 2/3 according to whether click in top/bottom half
 -		CButtonMultiPress::KeyDown(Time, (iY < pView->Screen()->GetHeight()/2) ? 2 : 3, pView, pInput, pModel);
 -	else
 -		CInputFilter::KeyDown(Time, iId, pView, pInput, pModel, bPos, iX, iY);
 +    myint iDasherX, iDasherY;
 +    m_pInterface->GetActiveInputDevice()->GetDasherCoords(iDasherX, iDasherY, pView);
-     iId = (iDasherY < GetLongParameter(LP_OY)) ? 2 : 3;
++    iId = (iDasherY < CDasherModel::ORIGIN_Y) ? 2 : 3;
 +  }
-   CButtonMultiPress::KeyDown(Time, iId, pView, pInput, pModel, pUserLog);
++  CButtonMultiPress::KeyDown(Time, iId, pView, pInput, pModel);
  }
  
 -void CTwoButtonDynamicFilter::KeyUp(int Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY) {
 -	if (iId == 100 && !GetBoolParameter(BP_BACKOFF_BUTTON))
 -		//mouse click - will be ignored by superclass method.
 +void CTwoButtonDynamicFilter::KeyUp(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
 +	if (iId == 100 && !GetBoolParameter(BP_BACKOFF_BUTTON)) {
 +    //mouse click - will be ignored by superclass method.
  		//simulate press of button 2/3 according to whether click in top/bottom half
 -		CButtonMultiPress::KeyUp(Time, (iY < pView->Screen()->GetHeight()/2) ? 2 : 3, pView, pInput,pModel);
 -	else
 -		CInputFilter::KeyUp(Time, iId, pView, pInput, pModel, bPos, iX, iY);
 +    myint iDasherX, iDasherY;
 +    m_pInterface->GetActiveInputDevice()->GetDasherCoords(iDasherX, iDasherY, pView);
-     iId = (iDasherY < GetLongParameter(LP_OY)) ? 2 : 3;
++    iId = (iDasherY < CDasherModel::ORIGIN_Y) ? 2 : 3;
 +  }
 +  CButtonMultiPress::KeyUp(Time, iId, pView, pInput,pModel);
  }
  
  bool CTwoButtonDynamicFilter::TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol) {
diff --cc Src/DasherCore/TwoButtonDynamicFilter.h
index a74c784,aa71eaa..901290e
--- a/Src/DasherCore/TwoButtonDynamicFilter.h
+++ b/Src/DasherCore/TwoButtonDynamicFilter.h
@@@ -45,13 -42,9 +42,9 @@@ class CTwoButtonDynamicFilter : public 
    virtual void HandleEvent(int iParameter);
    
   protected:
-   virtual void run();
-   virtual void pause();
-   virtual void reverse();
- 
    //override to inspect x,y coords of mouse clicks/taps
-   virtual void KeyDown(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
 -  virtual void KeyDown(int Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY);
 -  virtual void KeyUp(int Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY);
++  virtual void KeyDown(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel);
 +  virtual void KeyUp(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel);
  	
   private:
    unsigned int maxClickCount() {return GetBoolParameter(BP_2B_INVERT_DOUBLE) ? 3 : 2;}
diff --cc Src/DasherCore/TwoPushDynamicFilter.cpp
index a719b66,1922e09..446b548
--- a/Src/DasherCore/TwoPushDynamicFilter.cpp
+++ b/Src/DasherCore/TwoPushDynamicFilter.cpp
@@@ -167,23 -167,25 +167,23 @@@ m_bDecorationChanged = true
    }
  }
  
- void CTwoPushDynamicFilter::KeyDown(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
 -void CTwoPushDynamicFilter::KeyDown(int Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY) {
++void CTwoPushDynamicFilter::KeyDown(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
    if (iId == 100 && !GetBoolParameter(BP_BACKOFF_BUTTON))
      //mouse click - will be ignored by superclass method.
      //simulate press of button 2...
 -    CDynamicFilter::KeyDown(Time, 2, pView, pInput, pModel);
 -  else
 -    CInputFilter::KeyDown(Time, iId, pView, pInput, pModel, bPos, iX, iY);
 +    iId=2;
-   CDynamicButtons::KeyDown(Time, iId, pView, pInput, pModel, pUserLog);
++  CDynamicButtons::KeyDown(Time, iId, pView, pInput, pModel);
  }
  
 -void CTwoPushDynamicFilter::KeyUp(int Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY) {
 +void CTwoPushDynamicFilter::KeyUp(unsigned long Time, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
    if (iId == 100 && !GetBoolParameter(BP_BACKOFF_BUTTON))
 -  //mouse click - will be ignored by superclass method.
 -  //simulate press of button 2...
 -    CDynamicFilter::KeyUp(Time, 2, pView, pInput, pModel);
 -  else
 -    CInputFilter::KeyUp(Time, iId, pView, pInput, pModel, bPos, iX, iY);
 +    //mouse click - will be ignored by superclass method.
 +    //simulate press of button 2...
 +    iId=2;
 +  CDynamicButtons::KeyUp(Time, iId, pView, pInput, pModel);
  }
  
- void CTwoPushDynamicFilter::ActionButton(int iTime, int iButton, int iType, CDasherModel *pModel, CUserLogBase *pUserLog) {
+ void CTwoPushDynamicFilter::ActionButton(int iTime, int iButton, int iType, CDasherModel *pModel) {
    // Types:
    // 0 = ordinary click
    // 1 = long click
diff --cc Src/DasherCore/TwoPushDynamicFilter.h
index 3835b7d,2bd73fd..825a5ec
--- a/Src/DasherCore/TwoPushDynamicFilter.h
+++ b/Src/DasherCore/TwoPushDynamicFilter.h
@@@ -36,8 -36,8 +36,8 @@@ class CTwoPushDynamicFilter : public CD
    virtual bool GetSettings(SModuleSettings **pSettings, int *iCount);
  
    //override to get mouse clicks / taps back again...
-   virtual void KeyDown(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
 -  virtual void KeyDown(int Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY);
 -  virtual void KeyUp(int Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel, bool bPos, int iX, int iY);
++  virtual void KeyDown(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel);
 +  virtual void KeyUp(unsigned long Time, int iId, CDasherView *pDasherView, CDasherInput *pInput, CDasherModel *pModel);
  
   protected:
    virtual bool TimerImpl(unsigned long Time, CDasherView *m_pDasherView, CDasherModel *m_pDasherModel, CExpansionPolicy **pol);
diff --cc Src/DasherCore/UserLog.h
index df5441c,292cbf2..fd12675
--- a/Src/DasherCore/UserLog.h
+++ b/Src/DasherCore/UserLog.h
@@@ -72,9 -72,9 +72,9 @@@ typedef vector<VECTOR_STRING>::iterato
  /// \ingroup Logging
  /// @{
  
--// We need to be notified when parameters we are logging get changed, so we'll
--// watch for <int> events from the SettingsStore too.
 -class CUserLog : public CUserLogBase, public Dasher::CSettingsUserObserver {
++// We need to be notified when parameters we are logging get changed, but UserLogBase
++// is already watching BP_DASHER_PAUSED
 +class CUserLog : public CUserLogBase {
  public:
    CUserLog(Dasher::CSettingsUser *pCreateFrom, Observable<const Dasher::CEditEvent *> *pHandler, int iLogTypeMask);
  
diff --cc Src/DasherCore/UserLogBase.cpp
index 2dd9f4b,0628c7a..14b9787
--- a/Src/DasherCore/UserLogBase.cpp
+++ b/Src/DasherCore/UserLogBase.cpp
@@@ -14,7 -14,7 +14,8 @@@
  
  using namespace Dasher;
  
- CUserLogBase::CUserLogBase(CSettingsUser *pCreateFrom, Observable<const CEditEvent *> *pHandler) : CSettingsUserObserver(pCreateFrom), TransientObserver<const CEditEvent *>(pHandler), m_iNumDeleted(0) {
 -CUserLogBase::CUserLogBase(Observable<const CEditEvent *> *pHandler) : TransientObserver<const CEditEvent *>(pHandler), m_iNumDeleted(0) {
++CUserLogBase::CUserLogBase(CSettingsUser *pCreateFrom, Observable<const CEditEvent *> *pHandler)
++: CSettingsUserObserver(pCreateFrom), TransientObserver<const CEditEvent *>(pHandler), m_iNumDeleted(0) {
  };
  
  void CUserLogBase::HandleEvent(const CEditEvent *evt) {
diff --cc Src/DasherCore/UserLogBase.h
index 414340b,02503aa..177bd2c
--- a/Src/DasherCore/UserLogBase.h
+++ b/Src/DasherCore/UserLogBase.h
@@@ -16,9 -16,9 +16,9 @@@ namespace Dasher 
  
  /// \defgroup Logging Logging routines
  /// @{
 -class CUserLogBase : protected TransientObserver<const Dasher::CEditEvent *> {
 +class CUserLogBase : protected Dasher::CSettingsUserObserver, protected TransientObserver<const Dasher::CEditEvent *> {
   public:
-   CUserLogBase(Dasher::CSettingsUser *pCreateFrom, Observable<const Dasher::CEditEvent*> *pHandler);
 -  CUserLogBase(Observable<const Dasher::CEditEvent*> *pHandler);
++  CUserLogBase(CSettingsUser *pCreateFrom, Observable<const Dasher::CEditEvent*> *pHandler);
  
    virtual void AddParam(const std::string& strName, const std::string& strValue, int iOptionMask = 0) = 0;
    virtual void AddParam(const std::string& strName, double dValue, int iOptionMask = 0) = 0;
diff --cc Src/iPhone/Classes/CDasherInterfaceBridge.mm
index fdfa06c,65fdd46..d452bd6
--- a/Src/iPhone/Classes/CDasherInterfaceBridge.mm
+++ b/Src/iPhone/Classes/CDasherInterfaceBridge.mm
@@@ -18,7 -18,7 +18,8 @@@
  #import "ButtonMode.h"
  #import "TwoButtonDynamicFilter.h"
  #import "TwoPushDynamicFilter.h"
 +#import "EAGLView.h"
+ #import "GameModule.h"
  #import <iostream>
  #import <fcntl.h>
  
@@@ -77,13 -70,13 +78,13 @@@ CDasherInterfaceBridge::CDasherInterfac
  }
  
  void CDasherInterfaceBridge::CreateModules() {
 -	//create the default set...a good idea?!?!
 -
 -  RegisterModule(m_pUndoubledTouch = new UndoubledTouch());
 +	//don't create the default set...just the ones accessible from the GUI.
 +  RegisterModule(m_pUndoubledTouch = new UndoubledTouch([dasherApp glView]));
  	RegisterModule(m_pMouseDevice = 
- 				new CIPhoneMouseInput(this,[dasherApp glView]));
 -				new CIPhoneMouseInput(this));
++				new CIPhoneMouseInput([dasherApp glView]));
  	RegisterModule(m_pTiltDevice = 
  				new CIPhoneTiltInput());
 +  RegisterModule(m_pTwoFingerDevice=new CIPhoneTwoFingerInput([dasherApp glView]));
    SetDefaultInputDevice(m_pMouseDevice);
                   
    RegisterModule(new CButtonMode(this, this, true, 9, "Menu Mode"));
diff --cc Src/iPhone/Classes/IPhoneFilters.h
index 6ceaf5a,20e2133..507536e
--- a/Src/iPhone/Classes/IPhoneFilters.h
+++ b/Src/iPhone/Classes/IPhoneFilters.h
@@@ -21,17 -33,13 +21,17 @@@ extern NSString *DOUBLE_TOUCH_X
  
  #define TILT_FILTER "IPhone Tilt Filter"
  #define TOUCH_FILTER "IPhone Touch Filter"
 +#define TWO_FINGER_FILTER "Two-finger filter"
 +
 +namespace Dasher {
 +
  class CIPhoneTiltFilter : public COneDimensionalFilter, private IPhonePrefsObserver {
  public:
 -	CIPhoneTiltFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, ModuleID_t iID, CDasherInput *pTouch);
 +	CIPhoneTiltFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID, CDasherInput *pTouch);
    ///override to enable hold-to-go
- 	virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
 -	virtual void KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
++	virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
    ///override to enable hold-to-go
 -	virtual void KeyUp(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
 +	virtual void KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
  
    ///respond to BP_DASHER_PAUSED by engaging wakelock (if !hold-to-go)
    virtual void HandleEvent(int iParameter);
@@@ -65,13 -73,4 +65,13 @@@ private
    bool bUseTiltX;
  };
  
 +class CIPhoneTwoFingerFilter : public CDefaultFilter {
 +public:
 +  CIPhoneTwoFingerFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID);
 +  virtual void KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
-   virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog);
++  virtual void KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel);
 +  virtual bool DecorateView(CDasherView *pView, CDasherInput *pInput);
 +};
 +
 +}
- /// @}
+ /// @}
diff --cc Src/iPhone/Classes/IPhoneFilters.mm
index 8347fad,3c341a3..c46a1fe
--- a/Src/iPhone/Classes/IPhoneFilters.mm
+++ b/Src/iPhone/Classes/IPhoneFilters.mm
@@@ -41,13 -82,13 +41,13 @@@ void CIPhoneTiltFilter::ApplyTransform(
    }
  }
  
- void CIPhoneTiltFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
 -void CIPhoneTiltFilter::KeyDown(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
++void CIPhoneTiltFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
  	if(iId == 100 && bHoldToGo)
 -		m_pInterface->Unpause(iTime);
 +		Unpause(iTime);
-   else COneDimensionalFilter::KeyDown(iTime, iId, pView, pInput, pModel, pUserLog);
+   else COneDimensionalFilter::KeyDown(iTime, iId, pView, pInput, pModel);
  }
  
 -void CIPhoneTiltFilter::KeyUp(int iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
 +void CIPhoneTiltFilter::KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
  	if(iId == 100 && bHoldToGo)
  		m_pInterface->Stop();
    else COneDimensionalFilter::KeyUp(iTime, iId, pView, pInput, pModel);
@@@ -131,35 -172,3 +131,35 @@@ void CIPhoneTouchFilter::ApplyTransform
    }
    CStylusFilter::ApplyTransform(iDasherX, iDasherY, pView);
  }
 +
 +CIPhoneTwoFingerFilter::CIPhoneTwoFingerFilter(CSettingsUser *pCreator, CDasherInterfaceBase *pInterface, CFrameRate *pFramerate, ModuleID_t iID)
 +: CDefaultFilter(pCreator, pInterface, pFramerate, iID, TWO_FINGER_FILTER) {
 +}
 +
- void CIPhoneTwoFingerFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel, CUserLogBase *pUserLog) {
++void CIPhoneTwoFingerFilter::KeyDown(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
 +  if (iId==101) Unpause(iTime);
-   else if (iId!=100) CDefaultFilter::KeyDown(iTime, iId, pView, pInput, pModel, pUserLog);
++  else if (iId!=100) CDefaultFilter::KeyDown(iTime, iId, pView, pInput, pModel);
 +}
 +
 +void CIPhoneTwoFingerFilter::KeyUp(unsigned long iTime, int iId, CDasherView *pView, CDasherInput *pInput, CDasherModel *pModel) {
 +  if (iId==101) m_pInterface->Stop();
 +  else if (iId!=100) CDefaultFilter::KeyUp(iTime, iId, pView, pInput, pModel);
 +}
 +
 +bool CIPhoneTwoFingerFilter::DecorateView(CDasherView *pView, CDasherInput *pInput) {
 +  if (GetBoolParameter(BP_DRAW_MOUSE_LINE)) {
 +    myint x[2], y[2];
 +    x[0] = m_iLastX; x[1] = 0;
 +    y[0] = m_iLastY;
 +    for (y[1] = m_iLastY - m_iLastX; ;) {
 +      if (GetBoolParameter(BP_CURVE_MOUSE_LINE))
 +        pView->DasherSpaceLine(x[0], y[0], x[1], y[1], GetLongParameter(LP_LINE_WIDTH), 1);
 +      else
 +        pView->DasherPolyline(x, y, 2, GetLongParameter(LP_LINE_WIDTH), 1);
 +      if (y[1] == m_iLastY + m_iLastX) break;
 +      y[1] = m_iLastY + m_iLastX;
 +    }
 +    return true;
 +  }
 +  return false;
- }
++}
diff --cc Src/iPhone/Classes/IPhoneInputs.h
index b2c8a69,178dd99..b9f0083
--- a/Src/iPhone/Classes/IPhoneInputs.h
+++ b/Src/iPhone/Classes/IPhoneInputs.h
@@@ -64,29 -51,17 +64,29 @@@ private
  
  class UndoubledTouch : public CScreenCoordInput {
  public:
 -  UndoubledTouch();
 +  UndoubledTouch(EAGLView *pView);
    bool GetScreenCoords(screenint &iX, screenint &iY, CDasherView *pView);
  protected:
 -  UndoubledTouch(ModuleID_t iId, const char *szName);
 +  UndoubledTouch(ModuleID_t iId, const char *szName, EAGLView *pView);
 +  EAGLView * const m_pView;
  };
  
- class CIPhoneMouseInput : public UndoubledTouch, protected CSettingsUser, private IPhonePrefsObserver {
 -class CIPhoneMouseInput : public UndoubledTouch, protected CSettingsUser {
++class CIPhoneMouseInput : public UndoubledTouch, private IPhonePrefsObserver {
  public:
- 	CIPhoneMouseInput(CSettingsUser *pCreator, EAGLView *pView);
 -	CIPhoneMouseInput(CSettingsUser *pCreator);
++	CIPhoneMouseInput(EAGLView *pView);
    
    bool GetScreenCoords(screenint &iX, screenint &iY, CDasherView *pView);
 +private:
 +  void iPhonePrefsChanged(NSString *str);
 +  bool m_bDoubleX;
  };
 +  
 +  class CIPhoneTwoFingerInput : public CDasherCoordInput {
 +  public:
 +    CIPhoneTwoFingerInput(EAGLView *pView);
 +    bool GetDasherCoords(myint &iX, myint &iY, CDasherView *pView);
 +  protected:
 +    EAGLView * const m_pGlView;
 +  };
  }
  
diff --cc Src/iPhone/Classes/IPhoneInputs.mm
index 48ef83d,92536d7..5f0dfad
--- a/Src/iPhone/Classes/IPhoneInputs.mm
+++ b/Src/iPhone/Classes/IPhoneInputs.mm
@@@ -178,17 -112,16 +178,17 @@@ bool UndoubledTouch::GetScreenCoords(sc
  }
  
  
- CIPhoneMouseInput::CIPhoneMouseInput(CSettingsUser *pCreator, EAGLView *pView) 
- 	: UndoubledTouch(9, TOUCH_INPUT, pView), CSettingsUser(pCreator) {
 -CIPhoneMouseInput::CIPhoneMouseInput(CSettingsUser *pCreator) 
 -	: UndoubledTouch(9, TOUCH_INPUT), CSettingsUser(pCreator) {
++CIPhoneMouseInput::CIPhoneMouseInput(EAGLView *pView) 
++	: UndoubledTouch(9, TOUCH_INPUT, pView) {
 +    ObserveKeys(DOUBLE_TOUCH_X, nil);
  };
  
  bool CIPhoneMouseInput::GetScreenCoords(screenint &iX, screenint &iY, CDasherView *pView) {
    if (!UndoubledTouch::GetScreenCoords(iX,iY, pView)) return false;
    CDasherScreen *scr(pView->Screen());
    //double x/y
 -  if (GetBoolParameter(BP_DOUBLE_X)) {
 +  if ([[NSUserDefaults standardUserDefaults] boolForKey:DOUBLE_TOUCH_X]) {
-     switch (GetLongParameter(LP_REAL_ORIENTATION)) {
+     switch (pView->GetOrientation()) {
        case Opts::LeftToRight:
          iX=min(iX*2, scr->GetWidth());
          break;



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