[dasher: 20/43] Rm CMessageEvent, repl w/ CMessageDisplay superclass of CDasherInterfaceBase



commit b246be05c80ecd500b292485e2e2ebac4435d48f
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Thu Apr 7 11:26:36 2011 +0100

    Rm CMessageEvent, repl w/ CMessageDisplay superclass of CDasherInterfaceBase
    
    Platform-agnostic implementation in CDashIntfScreenMsgs stores message labels &
     renders onto Screen on top of View, scrolling up from bottom (each msg appears
     for LP_MESSAGE_TIME ms, in LP_MESSAGE_FONTSIZE), _without_pausing_Dasher_.
    Platforms may use this or provide own implementation w/ native widgets.
    
    Also tidied up repaint logic: RM m_bLastChanged+BP_REDRAW, Redraw() takes time,
      add virtual FinishRender(time).
    
    Gtk2: use CDashIntfScreenMsgs; GC message signal; move (commented-out) code for
      _modal_ dialogue from dasher_editor_internal into DasherControl, but not
      currently applicable as it steals focus & pauses Dasher.
    MacOSX,Win32: use CDashIntfScreenMsgs.
    iPhone: fading UILabel via CoreAnimation.
    
    Added currently the only client: AutoSpeedControl Message()s on adjusting speed.

 Data/GUI/dasher.compose.ui                   |    1 -
 Data/GUI/dasher.direct.ui                    |    1 -
 Data/GUI/dasher.fullscreen.ui                |    1 -
 Data/GUI/dasher.gameWIP.ui                   |    1 -
 Data/GUI/dasher.traditional.ui               |    1 -
 Data/GUI/dashermaemo.ui                      |    1 -
 Data/GUI/dashermaemofullscreen.ui            |    1 -
 Src/DasherCore/AutoSpeedControl.cpp          |   14 +++-
 Src/DasherCore/AutoSpeedControl.h            |    6 +-
 Src/DasherCore/DashIntfScreenMsgs.cpp        |   46 +++++++++++++
 Src/DasherCore/DashIntfScreenMsgs.h          |   49 ++++++++++++++
 Src/DasherCore/DasherCore_vc80.vcproj        |    8 ++
 Src/DasherCore/DasherInterfaceBase.cpp       |   92 ++++++++++++--------------
 Src/DasherCore/DasherInterfaceBase.h         |   34 +++++++---
 Src/DasherCore/DefaultFilter.cpp             |    2 +-
 Src/DasherCore/Event.h                       |   14 +----
 Src/DasherCore/Makefile.am                   |    3 +
 Src/DasherCore/Messages.h                    |   43 ++++++++++++
 Src/DasherCore/Parameters.h                  |    6 +-
 Src/Gtk2/DasherControl.cpp                   |   19 +++---
 Src/Gtk2/DasherControl.h                     |    5 +-
 Src/Gtk2/GtkDasherControl.h                  |    8 --
 Src/Gtk2/dasher_editor_internal.cpp          |   56 +++++++---------
 Src/Gtk2/dasher_main.cpp                     |   12 ----
 Src/MacOSX/COSXDasherControl.h               |    4 +-
 Src/MacOSX/COSXDasherControl.mm              |    5 --
 Src/MacOSX/Dasher.xcodeproj/project.pbxproj  |   16 ++++-
 Src/Win32/Dasher.h                           |    4 +-
 Src/iPhone/Classes/CDasherInterfaceBridge.h  |    1 +
 Src/iPhone/Classes/CDasherInterfaceBridge.mm |   13 ++--
 Src/iPhone/Classes/DasherAppDelegate.h       |    2 +-
 Src/iPhone/Classes/DasherAppDelegate.mm      |    2 +-
 Src/iPhone/Dasher.xcodeproj/project.pbxproj  |    8 ++
 33 files changed, 304 insertions(+), 175 deletions(-)
---
diff --git a/Data/GUI/dasher.compose.ui b/Data/GUI/dasher.compose.ui
index 9d96f30..daeaaa5 100644
--- a/Data/GUI/dasher.compose.ui
+++ b/Data/GUI/dasher.compose.ui
@@ -464,7 +464,6 @@
                             <signal handler="handle_request_settings" name="dasher_request_settings"/>
                             <signal handler="focus_in_event" name="focus_in_event"/>
                             <signal handler="on_lock_info" name="dasher_lock_info"/>
-                            <signal handler="on_message" name="dasher_message"/>
                             <signal handler="convert_cb" name="dasher_edit_convert"/>
                             <signal handler="protect_cb" name="dasher_edit_protect"/>
                             <signal handler="on_command" name="dasher_command"/>
diff --git a/Data/GUI/dasher.direct.ui b/Data/GUI/dasher.direct.ui
index 5ea8898..71855e2 100644
--- a/Data/GUI/dasher.direct.ui
+++ b/Data/GUI/dasher.direct.ui
@@ -61,7 +61,6 @@
                 <signal handler="handle_request_settings" name="dasher_request_settings"/>
                 <signal handler="focus_in_event" name="focus_in_event"/>
                 <signal handler="on_lock_info" name="dasher_lock_info"/>
-                <signal handler="on_message" name="dasher_message"/>
                 <signal handler="convert_cb" name="dasher_edit_convert"/>
                 <signal handler="protect_cb" name="dasher_edit_protect"/>
                 <signal handler="on_command" name="dasher_command"/>
diff --git a/Data/GUI/dasher.fullscreen.ui b/Data/GUI/dasher.fullscreen.ui
index bd7f228..99ab982 100644
--- a/Data/GUI/dasher.fullscreen.ui
+++ b/Data/GUI/dasher.fullscreen.ui
@@ -177,7 +177,6 @@
                     <signal handler="handle_request_settings" last_modification_time="Sun, 05 Mar 2006 19:47:12 GMT" name="dasher_request_settings"/>
                     <signal handler="focus_in_event" last_modification_time="Sun, 05 Mar 2006 19:47:28 GMT" name="focus_in_event"/>
                     <signal handler="on_lock_info" last_modification_time="Wed, 22 Mar 2006 10:38:44 GMT" name="dasher_lock_info"/>
-                    <signal handler="on_message" last_modification_time="Wed, 22 Mar 2006 14:24:04 GMT" name="dasher_message"/>
                     <signal handler="convert_cb" last_modification_time="Tue, 30 May 2006 14:21:15 GMT" name="dasher_edit_convert"/>
                     <signal handler="protect_cb" last_modification_time="Tue, 30 May 2006 14:21:26 GMT" name="dasher_edit_protect"/>
                     <signal handler="on_command" last_modification_time="Thu, 14 Sep 2006 12:13:36 GMT" name="dasher_command"/>
diff --git a/Data/GUI/dasher.gameWIP.ui b/Data/GUI/dasher.gameWIP.ui
index 2c52f0c..c45a632 100644
--- a/Data/GUI/dasher.gameWIP.ui
+++ b/Data/GUI/dasher.gameWIP.ui
@@ -652,7 +652,6 @@
                 <signal handler="handle_request_settings" last_modification_time="Sun, 05 Mar 2006 19:47:12 GMT" name="dasher_request_settings"/>
                 <signal handler="focus_in_event" last_modification_time="Sun, 05 Mar 2006 19:47:28 GMT" name="focus_in_event"/>
                 <signal handler="on_lock_info" last_modification_time="Wed, 22 Mar 2006 10:38:44 GMT" name="dasher_lock_info"/>
-                <signal handler="on_message" last_modification_time="Wed, 22 Mar 2006 14:24:04 GMT" name="dasher_message"/>
                 <signal handler="convert_cb" last_modification_time="Tue, 30 May 2006 14:21:15 GMT" name="dasher_edit_convert"/>
                 <signal handler="protect_cb" last_modification_time="Tue, 30 May 2006 14:21:26 GMT" name="dasher_edit_protect"/>
                 <signal handler="on_command" last_modification_time="Thu, 14 Sep 2006 12:13:36 GMT" name="dasher_command"/>
diff --git a/Data/GUI/dasher.traditional.ui b/Data/GUI/dasher.traditional.ui
index f0bfb27..76e5f09 100644
--- a/Data/GUI/dasher.traditional.ui
+++ b/Data/GUI/dasher.traditional.ui
@@ -248,7 +248,6 @@
                 <signal handler="handle_request_settings" name="dasher_request_settings"/>
                 <signal handler="focus_in_event" name="focus_in_event"/>
                 <signal handler="on_lock_info" name="dasher_lock_info"/>
-                <signal handler="on_message" name="dasher_message"/>
                 <signal handler="convert_cb" name="dasher_edit_convert"/>
                 <signal handler="protect_cb" name="dasher_edit_protect"/>
                 <signal handler="on_command" name="dasher_command"/>
diff --git a/Data/GUI/dashermaemo.ui b/Data/GUI/dashermaemo.ui
index 412c33c..8e04654 100644
--- a/Data/GUI/dashermaemo.ui
+++ b/Data/GUI/dashermaemo.ui
@@ -95,7 +95,6 @@
             <signal handler="handle_request_settings" name="dasher_request_settings"/>
             <signal handler="focus_in_event" name="focus_in_event"/>
             <signal handler="on_lock_info" name="dasher_lock_info"/>
-            <signal handler="on_message" name="dasher_message"/>
           </object>
           <packing>
             <property name="padding">0</property>
diff --git a/Data/GUI/dashermaemofullscreen.ui b/Data/GUI/dashermaemofullscreen.ui
index fce3c41..8189fab 100644
--- a/Data/GUI/dashermaemofullscreen.ui
+++ b/Data/GUI/dashermaemofullscreen.ui
@@ -222,7 +222,6 @@
                 <signal handler="handle_request_settings" last_modification_time="Sun, 05 Mar 2006 19:47:12 GMT" name="dasher_request_settings"/>
                 <signal handler="focus_in_event" last_modification_time="Sun, 05 Mar 2006 19:47:28 GMT" name="focus_in_event"/>
                 <signal handler="on_lock_info" last_modification_time="Wed, 22 Mar 2006 10:38:44 GMT" name="dasher_lock_info"/>
-                <signal handler="on_message" last_modification_time="Wed, 22 Mar 2006 14:24:04 GMT" name="dasher_message"/>
                 <signal handler="convert_cb" last_modification_time="Tue, 30 May 2006 14:21:15 GMT" name="dasher_edit_convert"/>
                 <signal handler="protect_cb" last_modification_time="Tue, 30 May 2006 14:21:26 GMT" name="dasher_edit_protect"/>
               </object>
diff --git a/Src/DasherCore/AutoSpeedControl.cpp b/Src/DasherCore/AutoSpeedControl.cpp
index 5c5de33..a8dfe8a 100644
--- a/Src/DasherCore/AutoSpeedControl.cpp
+++ b/Src/DasherCore/AutoSpeedControl.cpp
@@ -9,6 +9,7 @@
 #include <cmath>
 #include <cfloat>
 #include <iostream>
+#include <sstream>
 
 #ifndef WITH_DARWIN
 double round(double dVal) {
@@ -23,9 +24,10 @@ double round(double dVal) {
 #endif
 
 using namespace Dasher;
+using std::ostringstream;
 
-CAutoSpeedControl::CAutoSpeedControl(Dasher::CEventHandler * pEventHandler, CSettingsStore * pSettingsStore)
-  : CDasherComponent(pEventHandler, pSettingsStore) {
+CAutoSpeedControl::CAutoSpeedControl(CMessageDisplay *pMsgs, Dasher::CEventHandler * pEventHandler, CSettingsStore * pSettingsStore)
+  : CDasherComponent(pEventHandler, pSettingsStore), m_pMsgs(pMsgs) {
   //scale #samples by #samples = m_dSamplesScale / (current bitrate) + m_dSampleOffset
   m_dSampleScale = 1.5;
   m_dSampleOffset = 1.3;
@@ -207,7 +209,13 @@ void CAutoSpeedControl::SpeedControl(myint iDasherX, myint iDasherY, CDasherView
       UpdateMinRadius();
       UpdateBitrate();
       long lBitrateTimes100 =  long(round(m_dBitrate * 100)); //Dasher settings want long numerical parameters
-      SetLongParameter(LP_MAX_BITRATE, lBitrateTimes100);
+      if (lBitrateTimes100 != GetLongParameter(LP_MAX_BITRATE)) {
+        ostringstream os;
+        os << "Auto-" << ((lBitrateTimes100 > GetLongParameter(LP_MAX_BITRATE)) ? "increasing" : "decreasing");
+        os << " speed to " << (lBitrateTimes100/100.0);
+        m_pMsgs->Message(os.str());
+        SetLongParameter(LP_MAX_BITRATE, lBitrateTimes100);
+      }
       m_nSpeedCounter = 0;
 
     }
diff --git a/Src/DasherCore/AutoSpeedControl.h b/Src/DasherCore/AutoSpeedControl.h
index c7a1582..74dddfc 100644
--- a/Src/DasherCore/AutoSpeedControl.h
+++ b/Src/DasherCore/AutoSpeedControl.h
@@ -4,7 +4,7 @@
 #include "DasherComponent.h"
 #include "DasherTypes.h"
 #include "DasherView.h"
-
+#include "Messages.h"
 #include <deque>
 
 /// \defgroup AutoSpeed Auto speed control
@@ -12,7 +12,7 @@
 namespace Dasher {
 class CAutoSpeedControl : public Dasher::CDasherComponent {
  public:
-  CAutoSpeedControl(Dasher::CEventHandler * pEventHandler, CSettingsStore * pSettingsStore);
+  CAutoSpeedControl(CMessageDisplay *pMsgs, Dasher::CEventHandler *pEventHandler, CSettingsStore *pSettingsStore);
   
   ///
   /// AUTO-SPEED-CONTROL
@@ -78,6 +78,8 @@ class CAutoSpeedControl : public Dasher::CDasherComponent {
   
   //variables for adaptive radius calculations...
   double m_dSigma1, m_dSigma2, m_dMinRadius;
+  
+  CMessageDisplay *m_pMsgs;
 
 };
 }
diff --git a/Src/DasherCore/DashIntfScreenMsgs.cpp b/Src/DasherCore/DashIntfScreenMsgs.cpp
new file mode 100644
index 0000000..1f05f43
--- /dev/null
+++ b/Src/DasherCore/DashIntfScreenMsgs.cpp
@@ -0,0 +1,46 @@
+#include "DashIntfScreenMsgs.h"
+
+using namespace Dasher;
+
+void CDashIntfScreenMsgs::Message(const string &strText) {
+  m_dqMessages.push_back(pair<CDasherScreen::Label*,unsigned long>(m_DasherScreen->MakeLabel(strText, GetLongParameter(LP_MESSAGE_FONTSIZE)), 0));
+}
+
+bool CDashIntfScreenMsgs::FinishRender(unsigned long ulTime) {
+  bool bMsgsChanged=false;
+  //Finally any messages. Newest that will fit at bottom, proceeding upwards
+  while (!m_dqMessages.empty() && m_dqMessages.front().second && ulTime-m_dqMessages.front().second>GetLongParameter(LP_MESSAGE_TIME)) {
+    //message has been displayed for long enough.
+    m_dqMessages.pop_front(); // => stop displaying it
+    bMsgsChanged=true;
+  }
+  if (!m_dqMessages.empty()) {
+    //still messages to display...first find out longest-ago N that will fit
+    const unsigned int iFontSize(GetLongParameter(LP_MESSAGE_FONTSIZE));
+    screenint iY = m_DasherScreen->GetHeight();
+    const screenint iMinY((iY*3)/4), iSW(m_DasherScreen->GetWidth());
+    for (deque<pair<CDasherScreen::Label*, unsigned long> >::iterator it = m_dqMessages.begin(); it!=m_dqMessages.end() && iY>iMinY; it++) {
+      if (it->second==0) {it->second = ulTime; bMsgsChanged=true;} //display message for first time
+      iY-=m_DasherScreen->TextSize(it->first, iFontSize).second;
+    }
+    //then render oldest first proceeding downwards
+    for (deque<pair<CDasherScreen::Label*, unsigned long> >::iterator it = m_dqMessages.begin(); it!=m_dqMessages.end() && it->second!=0; it++) {
+      pair<screenint,screenint> textDims = m_DasherScreen->TextSize(it->first, iFontSize);
+      //black (5) rectangle:
+      m_DasherScreen->DrawRectangle((iSW - textDims.first)/2, iY, (iSW+textDims.first)/2, iY+textDims.second, 5, -1, -1);
+      //white (0) text:
+      m_DasherScreen->DrawString(it->first, (iSW-textDims.first)/2, iY, iFontSize, 0);
+      iY+=textDims.second;
+    }
+  }
+  return bMsgsChanged;
+}
+
+void CDashIntfScreenMsgs::ChangeScreen(CDasherScreen *pNewScreen) {
+  CDasherInterfaceBase::ChangeScreen(pNewScreen);
+  for (deque<pair<CDasherScreen::Label*,unsigned long> >::iterator it=m_dqMessages.begin(); it!=m_dqMessages.end(); it++) {
+    const CDasherScreen::Label *pOldLabel(it->first);
+    it->first = pNewScreen->MakeLabel(pOldLabel->m_strText, pOldLabel->m_iWrapSize);
+    delete pOldLabel;
+  }
+}
diff --git a/Src/DasherCore/DashIntfScreenMsgs.h b/Src/DasherCore/DashIntfScreenMsgs.h
new file mode 100644
index 0000000..48bde43
--- /dev/null
+++ b/Src/DasherCore/DashIntfScreenMsgs.h
@@ -0,0 +1,49 @@
+// DashIntfScreenMsgs.h
+//
+// Created 2011 by Alan Lawrence
+// Copyright (c) 2011 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 __DASH_INTF_SCREEN_MSGS_H__
+#define __DASH_INTF_SCREEN_MSGS_H__
+
+#include "DasherInterfaceBase.h"
+
+namespace Dasher {
+class CDashIntfScreenMsgs : public CDasherInterfaceBase {
+public:
+  /// Stores the message for Redraw to render onto the Screen on top of the view
+  virtual void Message(const std::string &strText);
+  
+  /// Override to render (on top of nodes+decorations) any messages, for
+  /// LP_MESSAGE_TIME ms, before removing from queue.
+  bool FinishRender(unsigned long ulTime);
+
+  ///Override to re-MakeLabel any messages.
+  void ChangeScreen(CDasherScreen *pNewScreen);
+
+private:
+  ///Messages to be displayed to the user, longest-ago at the front,
+  /// along with the timestamp of the frame at which each was first displayed
+  /// to the user, or 0 if not yet displayed.
+  std::deque<pair<CDasherScreen::Label*, unsigned long> > m_dqMessages;
+  
+};
+
+}
+#endif
diff --git a/Src/DasherCore/DasherCore_vc80.vcproj b/Src/DasherCore/DasherCore_vc80.vcproj
index 83a02dc..fc64d7d 100644
--- a/Src/DasherCore/DasherCore_vc80.vcproj
+++ b/Src/DasherCore/DasherCore_vc80.vcproj
@@ -1867,6 +1867,14 @@
 			>
 		</File>
 		<File
+			RelativePath=".\DashIntfScreenMsgs.cpp"
+			>
+		</File>
+		<File
+			RelativePath=".\DashIntfScreenMsgs.h"
+			>
+		</File>
+		<File
 			RelativePath=".\DefaultFilter.cpp"
 			>
 		</File>
diff --git a/Src/DasherCore/DasherInterfaceBase.cpp b/Src/DasherCore/DasherInterfaceBase.cpp
index 02a4043..4d357a8 100644
--- a/Src/DasherCore/DasherInterfaceBase.cpp
+++ b/Src/DasherCore/DasherInterfaceBase.cpp
@@ -111,8 +111,6 @@ CDasherInterfaceBase::CDasherInterfaceBase() : m_pLockLabel(NULL) {
   // Create an event handler.
   m_pEventHandler = new CEventHandler(this);
 
-  m_bLastChanged = true;
-
 #ifndef _WIN32_WCE
   // Global logging object we can use from anywhere
   g_pLogger = new CFileLogger("dasher.log",
@@ -444,8 +442,7 @@ void CDasherInterfaceBase::Stop() {
   if (GetBoolParameter(BP_DASHER_PAUSED)) return; //already paused, no need to do anything.
   SetBoolParameter(BP_DASHER_PAUSED, true);
 
-  // Request a full redraw at the next time step.
-  SetBoolParameter(BP_REDRAW, true);
+  ScheduleRedraw();
 
 #ifndef _WIN32_WCE
   if (m_pUserLog != NULL)
@@ -508,10 +505,12 @@ void CDasherInterfaceBase::NewFrame(unsigned long iTime, bool bForceRedraw) {
   // if(m_iCurrentState != ST_NORMAL)
   //  return;
 
-  bool bChanged(false), bWasPaused(GetBoolParameter(BP_DASHER_PAUSED));
-  CExpansionPolicy *pol=m_defaultPolicy;
-  if(m_pDasherView != 0) {
-    if (isLocked()) {
+  if(m_DasherScreen) {
+    //ok, can draw _something_. Try and see what we can :).
+
+    bool bBlit = false; //set to true if we actually render anything different i.e. that needs blitting to display
+
+    if (isLocked() || !m_pDasherView) {
       //Hmmm. If we're locked, NewFrame is never actually called - the thread
       // that would be rendering frames, is the same one doing the training.
       // So the following is never actually executed atm, but may be a simple
@@ -524,8 +523,12 @@ void CDasherInterfaceBase::NewFrame(unsigned long iTime, bool bForceRedraw) {
       pair<screenint,screenint> dims = m_DasherScreen->TextSize(m_pLockLabel, iSize);
       m_DasherScreen->DrawString(m_pLockLabel, (iSW-dims.first)/2, (iSH-dims.second)/2, iSize, 4);
       m_DasherScreen->SendMarker(1); //decorations - don't draw any
-      m_DasherScreen->Display();
+      bBlit = true;
     } else {
+      bool bChanged(false), bWasPaused(GetBoolParameter(BP_DASHER_PAUSED));
+      CExpansionPolicy *pol=m_defaultPolicy;
+  
+      //1. Move around in the model
       if (m_pUserLog != NULL) {
         //ACL note that as of 15/5/09, splitting UpdatePosition into two,
         //DasherModel no longer guarantees to empty these two if it didn't do anything.
@@ -549,49 +552,49 @@ void CDasherInterfaceBase::NewFrame(unsigned long iTime, bool bForceRedraw) {
           bChanged = m_pInputFilter->Timer(iTime, m_pDasherView, m_pInput, m_pDasherModel, 0, 0, &pol);
         }
       }
+      //2. Render...
       //check: if we were paused before, and the input filter didn't unpause,
       // then nothing can have changed:
       DASHER_ASSERT(!bWasPaused || !GetBoolParameter(BP_DASHER_PAUSED) || !bChanged);
-     
-      // Flags at this stage:
-      //
-      // - bChanged = the display was updated, so needs to be rendered to the display
-      // - m_bLastChanged = bChanged was true last time around
-      // - m_bRedrawScheduled = Display invalidated internally
-      // - bForceRedraw = Display invalidated externally
-     
-      // TODO: Would be good to sort out / check through the redraw logic properly
-     
-      bForceRedraw |= m_bLastChanged || bChanged || m_bRedrawScheduled;
-      m_bLastChanged = bChanged; //will also be set in Redraw if any nodes were expanded.
-     
-      Redraw(bForceRedraw, *pol);
-     
-      m_bRedrawScheduled = false;
-     
+
+      //If we've been told to render another frame via ScheduleRedraw,
+      // that's the same as passing in true to NewFrame.
+      if (m_bRedrawScheduled) bForceRedraw=true;
+      m_bRedrawScheduled=false;
+
+      //If we moved, definitely need to render the nodes. We also make sure
+      // to render at least one more frame - think that's a bit of policy
+      // just to be on the safe side, and may not be strictly necessary...
+      if (bChanged) bForceRedraw=m_bRedrawScheduled=true;
+
+      //2. Render nodes decorations, messages
+      bBlit = Redraw(iTime, bForceRedraw, *pol);
+
       // This just passes the time through to the framerate tracker, so we
       // know how often new frames are being drawn.
       if(m_pDasherModel != 0)
         m_pDasherModel->RecordFrame(iTime);
     }
+    if (FinishRender(iTime)) bBlit = true;
+    if (bBlit) m_DasherScreen->Display();
   }
 
   bReentered=false;
 }
 
-void CDasherInterfaceBase::Redraw(bool bRedrawNodes, CExpansionPolicy &policy) {
-  // No point continuing if there's nothing to draw on...
-  if(!m_pDasherView)
-    return;
+bool CDasherInterfaceBase::Redraw(unsigned long ulTime, bool bRedrawNodes, CExpansionPolicy &policy) {
+  DASHER_ASSERT(m_pDasherView);
 
   // Draw the nodes
   if(bRedrawNodes) {
     m_pDasherView->Screen()->SendMarker(0);
-	if (m_pDasherModel) {
-		m_pDasherModel->RenderToView(m_pDasherView,policy);
-		m_bLastChanged |= policy.apply(m_pNCManager, m_pDasherModel);
-        }
+    if (m_pDasherModel) {
+      m_pDasherModel->RenderToView(m_pDasherView,policy);
+      if (policy.apply(m_pNCManager, m_pDasherModel)) //if anything was expanded or collapsed
+        ScheduleRedraw(); //render at least one more frame after this
+    }
   }
+  //From here on, we'll use bRedrawNodes just to denote whether we need to blit the display...
 
   // Draw the decorations
   m_pDasherView->Screen()->SendMarker(1);
@@ -599,20 +602,15 @@ void CDasherInterfaceBase::Redraw(bool bRedrawNodes, CExpansionPolicy &policy) {
   if(GameMode::CDasherGameMode* pTeacher = GameMode::CDasherGameMode::GetTeacher())
     pTeacher->DrawGameDecorations(m_pDasherView);
 
-  bool bDecorationsChanged(false);
-
   if(m_pInputFilter) {
-    bDecorationsChanged = m_pInputFilter->DecorateView(m_pDasherView, m_pInput);
+    if (m_pInputFilter->DecorateView(m_pDasherView, m_pInput)) bRedrawNodes=true;
   }
 
-  bool bActionButtonsChanged(false);
 #ifdef EXPERIMENTAL_FEATURES
-  bActionButtonsChanged = DrawActionButtons();
+  if (DrawActionButtons()) bRedrawNodes=true;
 #endif
-
-  // Only blit the image to the display if something has actually changed
-  if(bRedrawNodes || bDecorationsChanged || bActionButtonsChanged)
-    m_pDasherView->Screen()->Display();
+  
+  return bRedrawNodes;
 }
 
 void CDasherInterfaceBase::ChangeAlphabet() {
@@ -671,12 +669,8 @@ void CDasherInterfaceBase::ScreenResized(CDasherScreen *pScreen) {
   m_pDasherView->ScreenResized(m_DasherScreen);
 
   PositionActionButtons();
-  BudgettingPolicy pol(GetLongParameter(LP_NODE_BUDGET)); //maintain budget, but allow arbitrary amount of work.
-  Redraw(true, pol); // (we're assuming resolution changes are occasional, i.e.
-	// we don't need to worry about maintaining the frame rate, so we can do
-	// as much work as necessary. However, it'd probably be better still to
-  // get a node queue from the input filter, as that might have a different
-  // policy / budget.
+  //Really, would like to do a Redraw _immediately_, but this will have to do.
+  ScheduleRedraw();
 }
 
 void CDasherInterfaceBase::ChangeView() {
diff --git a/Src/DasherCore/DasherInterfaceBase.h b/Src/DasherCore/DasherInterfaceBase.h
index f5674c6..441cd6f 100644
--- a/Src/DasherCore/DasherInterfaceBase.h
+++ b/Src/DasherCore/DasherInterfaceBase.h
@@ -31,6 +31,7 @@
 // TODO - there is a list of things to be configurable in my notes
 // Check that everything that is not self-contained within the GUI is covered.
 
+#include "Messages.h"
 #include "../Common/NoClones.h"
 #include "../Common/ModuleSettings.h"
 #include "ActionButton.h"
@@ -65,8 +66,10 @@ class CNodeCreationManager;
 
 /// The central class in the core of Dasher. Ties together the rest of
 /// the platform independent stuff and provides a single interface for
-/// the UI to use.
-class Dasher::CDasherInterfaceBase:private NoClones
+/// the UI to use. Note: CMessageDisplay unimplemented; platforms should
+/// provide their own methods using appropriate GUI components, or subclass
+/// CDashIntfScreenMsgs instead.
+class Dasher::CDasherInterfaceBase : public CMessageDisplay, private NoClones
 {
 public:
   CDasherInterfaceBase();
@@ -224,7 +227,7 @@ public:
   /// by OS, e.g. for non-european languages)
   ///\return the offset, into the edit buffer of the cursor *after* the move.
   virtual unsigned int ctrlMove(bool bForwards, CControlManager::EditDistance dist)=0;
- 
+
   ///Called to execute a control-mode "delete" command.
   ///\param bForwards true to delete forwards (right), false for backwards
   ///\param dist how much to delete: character, word, line, file. (Usually defined
@@ -232,7 +235,7 @@ public:
   ///\return the offset, into the edit buffer, of the cursor *after* the delete
   /// (for forwards deletion, this will be the same as the offset *before*)
   virtual unsigned int ctrlDelete(bool bForwards, CControlManager::EditDistance dist)=0;
- 
+
   class TextAction {
   public:
     TextAction(CDasherInterfaceBase *pMgr);
@@ -299,7 +302,7 @@ public:
   /// and Realize may occur in either order; if ChangeScreen comes after, Resize will create a 
   /// tree with null Labels, which will have to be rebuilt in the call to ChangeScreen.
   /// \param NewScreen Pointer to the new CDasherScreen.
-  void ChangeScreen(CDasherScreen * NewScreen);
+  virtual void ChangeScreen(CDasherScreen * NewScreen);
   
   ///Call when the screen dimensions have been changed, to recalculate scaling factors etc.
   /// \param pScreen the screen whose dimensions have changed. TODO we expect this to be
@@ -469,10 +472,21 @@ protected:
 
   /// Draw a new Dasher frame, regardless of whether we're paused etc.
   /// \param iTime Current time in ms.
-  /// \param bForceRedraw
-  /// \todo See comments in cpp file for some functionality which needs to be re-implemented
+  /// \param bForceRedraw Passing in true is equivalent to calling ScheduleRedraw() first,
+  /// and forces the nodes/canvas to be re-rendered (even if we haven't moved).
   void NewFrame(unsigned long iTime, bool bForceRedraw);
 
+  ///Renders the current state of the nodes (optionally), decorations, etc. (Does not move around the nodes.)
+  /// \param ulTime Time of rendering, for time-dependent decorations (e.g. messages)
+  /// \param bRedrawNodes whether to re-render the nodes (expensive!)
+  /// \param policy if redrawing nodes, use this to expand/collapse nodes, and set m_bLastChanged if any were.
+  bool Redraw(unsigned long ulTime, bool bRedrawNodes, CExpansionPolicy &policy);
+
+  ///Called at the end of each frame, after lock-message / nodes+decorations have been rendered.
+  /// Default does nothing, but subclasses can override if they need to do anything else.
+  /// \return true if anything has been rendered to the Screen such that it needs to be blitted
+  /// (i.e. Display() called) - the default just returns false.
+  virtual bool FinishRender(unsigned long ulTime) {return false;}
 
   enum ETransition {
     TR_MODEL_INIT = 0,
@@ -506,6 +520,7 @@ protected:
   CEventHandler *m_pEventHandler;
   CSettingsStore *m_pSettingsStore;
 
+  CDasherScreen *m_DasherScreen;
  private:
 
   //The default expansion policy to use - an amortized policy depending on the LP_NODE_BUDGET parameter.
@@ -582,7 +597,7 @@ protected:
   void ChangeAlphabet();
   void ChangeColours();
   void ChangeView();
-  void Redraw(bool bRedrawNodes, CExpansionPolicy &policy);
+
   void SetupActionButtons();
   void DestroyActionButtons();
   void PositionActionButtons();
@@ -598,7 +613,6 @@ protected:
   /// Various objects which are 'owned' by the core.
   /// @{
   CDasherModel *m_pDasherModel;
-  CDasherScreen *m_DasherScreen;
   CDasherView *m_pDasherView;
   CDasherInput *m_pInput;
   CInputFilter* m_pInputFilter;
@@ -627,8 +641,6 @@ protected:
 
   /// @}
 
-  bool m_bLastChanged;
-
   std::set<TextAction *> m_vTextActions;
 };
 /// @}
diff --git a/Src/DasherCore/DefaultFilter.cpp b/Src/DasherCore/DefaultFilter.cpp
index 0a149a8..787c7f3 100644
--- a/Src/DasherCore/DefaultFilter.cpp
+++ b/Src/DasherCore/DefaultFilter.cpp
@@ -27,7 +27,7 @@ bool CDefaultFilter::GetSettings(SModuleSettings **sets, int *iCount) {
 CDefaultFilter::CDefaultFilter(Dasher::CEventHandler * pEventHandler, CSettingsStore *pSettingsStore, CDasherInterfaceBase *pInterface, ModuleID_t iID, const char *szName)
   : CInputFilter(pEventHandler, pSettingsStore, pInterface, iID, szName) {
   m_pStartHandler = 0;
-  m_pAutoSpeedControl = new CAutoSpeedControl(m_pEventHandler, m_pSettingsStore);
+  m_pAutoSpeedControl = new CAutoSpeedControl(pInterface, m_pEventHandler, m_pSettingsStore);
 
   // Initialize autocalibration (i.e. seen nothing yet)
   m_iSum = 0;
diff --git a/Src/DasherCore/Event.h b/Src/DasherCore/Event.h
index fabcac1..6c7c5a1 100644
--- a/Src/DasherCore/Event.h
+++ b/Src/DasherCore/Event.h
@@ -10,12 +10,11 @@ namespace Dasher {
   class CEvent;
   class CParameterNotificationEvent;
   class CEditEvent;
-  class CMessageEvent;
   class CScreenGeomEvent;
 }
 
 enum {
-  EV_PARAM_NOTIFY = 1, EV_EDIT, EV_MESSAGE, EV_SCREEN_GEOM
+  EV_PARAM_NOTIFY = 1, EV_EDIT, EV_SCREEN_GEOM
 };
 
 /// \ingroup Core
@@ -49,17 +48,6 @@ public:
   const int m_iOffset;
 };
 
-class Dasher::CMessageEvent : public Dasher::CEvent {
-public:
-  CMessageEvent(const std::string &strMessage, int iID, int iType)
-  : CEvent(EV_MESSAGE), m_strMessage(strMessage), m_iID(iID), m_iType(iType) {
-  };
-  
-  const std::string m_strMessage;
-  const int m_iID;
-  const int m_iType;
-};
-
 ///Generated whenever the screen geometry changes: e.g. aspect ratio,
 /// size, degree of nonlinearity, orientation, or generally whenever
 /// values returned by Dasher2Screen/Screen2Dasher might have changed
diff --git a/Src/DasherCore/Makefile.am b/Src/DasherCore/Makefile.am
index 5ce69b0..4507093 100644
--- a/Src/DasherCore/Makefile.am
+++ b/Src/DasherCore/Makefile.am
@@ -56,6 +56,8 @@ libdashercore_a_SOURCES = \
 		DasherInput.h \
 		DasherInterfaceBase.cpp \
 		DasherInterfaceBase.h \
+		DashIntfScreenMsgs.h \
+		DashIntfScreenMsgs.cpp \
 		DasherModel.cpp \
 		DasherModel.h \
 		DasherModule.cpp \
@@ -91,6 +93,7 @@ libdashercore_a_SOURCES = \
 		MandarinAlphMgr.h \
 		MemoryLeak.cpp \
 		MemoryLeak.h \
+		Messages.h \
 		ModuleManager.cpp \
 		ModuleManager.h \
 		NodeCreationManager.cpp \
diff --git a/Src/DasherCore/Messages.h b/Src/DasherCore/Messages.h
new file mode 100644
index 0000000..bef3b69
--- /dev/null
+++ b/Src/DasherCore/Messages.h
@@ -0,0 +1,43 @@
+// Messages.h
+//
+// Created 2011 by Alan Lawrence
+// Copyright (c) 2011 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 __MESSAGES_H__
+#define __MESSAGES_H__
+
+///Abstract superclass = interface for displaying messages to the user.
+///Each platform must implement: see CDasherInterfaceBase, CDashIntfScreenMsgs
+
+#include <string>
+
+/// \ingroup Core
+/// @{
+
+class CMessageDisplay {
+public:
+  ///Displays a message to the user - somehow. This should not interrupt the user:
+  /// if Dasher is in motion, it should continue just as if no message were displayed.
+  /// \param strText text of message to display. TODO, do we want an enum for seriousness?
+  virtual void Message(const std::string &strText)=0;
+};
+
+/// @}
+
+#endif
diff --git a/Src/DasherCore/Parameters.h b/Src/DasherCore/Parameters.h
index 39609af..231c878 100644
--- a/Src/DasherCore/Parameters.h
+++ b/Src/DasherCore/Parameters.h
@@ -36,7 +36,7 @@ enum {
   BP_COLOUR_MODE, BP_MOUSEPOS_MODE,
   BP_PALETTE_CHANGE,
   BP_AUTOCALIBRATE, BP_REMAP_XTREME, BP_DASHER_PAUSED,
-  BP_GAME_MODE, BP_REDRAW, BP_LM_DICTIONARY, 
+  BP_GAME_MODE, BP_LM_DICTIONARY, 
   BP_LM_LETTER_EXCLUSION, BP_AUTO_SPEEDCONTROL,
   BP_LM_ADAPTIVE, BP_SOCKET_INPUT_ENABLE, BP_SOCKET_DEBUG, 
   BP_CIRCLE_START, BP_GLOBAL_KEYBOARD, BP_NONLINEAR_Y,
@@ -53,7 +53,7 @@ enum {
 enum { 
   LP_ORIENTATION = END_OF_BPS, LP_REAL_ORIENTATION, LP_MAX_BITRATE, LP_FRAMERATE,
   LP_VIEW_ID, LP_LANGUAGE_MODEL_ID, LP_DASHER_FONTSIZE, LP_MESSAGE_FONTSIZE, LP_SHAPE_TYPE,
-  LP_UNIFORM, LP_YSCALE, LP_MOUSEPOSDIST, LP_STOP_IDLETIME,
+  LP_UNIFORM, LP_YSCALE, LP_MOUSEPOSDIST, LP_STOP_IDLETIME, LP_MESSAGE_TIME,
   LP_LM_MAX_ORDER, LP_LM_EXCLUSION,
   LP_LM_UPDATE_EXCLUSION, LP_LM_ALPHA, LP_LM_BETA,
   LP_LM_MIXTURE, LP_NORMALIZATION, LP_LINE_WIDTH, LP_GEOMETRY,
@@ -143,7 +143,6 @@ static bp_table boolparamtable[] = {
   {BP_REMAP_XTREME, "RemapXtreme", PERS, false, "Pointer at extreme Y translates more and zooms less"},
   {BP_DASHER_PAUSED, "DasherPaused", !PERS, true, "Dasher Paused"},
   {BP_GAME_MODE, "GameMode", !PERS, false, "Dasher Game Mode"},
-  {BP_REDRAW, "Redraw", !PERS, false, "Force a full redraw at the next timer event"},
   {BP_LM_DICTIONARY, "Dictionary", PERS, true, "Whether the word-based language model uses a dictionary"},
   {BP_LM_LETTER_EXCLUSION, "LetterExclusion", PERS, true, "Whether to do letter exclusion in the word-based model"},
   {BP_AUTO_SPEEDCONTROL, "AutoSpeedControl", PERS, true, "AutoSpeedControl"},
@@ -199,6 +198,7 @@ static lp_table longparamtable[] = {
   {LP_YSCALE, "YScaling", PERS, 0, "YScaling"},
   {LP_MOUSEPOSDIST, "MousePositionBoxDistance", PERS, 50, "MousePositionBoxDistance"},
   {LP_STOP_IDLETIME, "StopIdleTime", PERS, 1000, "StopIdleTime" },
+  {LP_MESSAGE_TIME, "MessageTime", PERS, 2500, "Time for which non-modal messages are displayed, in ms"},
   {LP_LM_MAX_ORDER, "LMMaxOrder", PERS, 5, "LMMaxOrder"},
   {LP_LM_EXCLUSION, "LMExclusion", PERS, 0, "LMExclusion"},
   {LP_LM_UPDATE_EXCLUSION, "LMUpdateExclusion", PERS, 1, "LMUpdateExclusion"},
diff --git a/Src/Gtk2/DasherControl.cpp b/Src/Gtk2/DasherControl.cpp
index acc2821..a3cfae9 100644
--- a/Src/Gtk2/DasherControl.cpp
+++ b/Src/Gtk2/DasherControl.cpp
@@ -359,15 +359,6 @@ void CDasherControl::ExternalEventHandler(Dasher::CEvent *pEvent) {
       g_signal_emit_by_name(GTK_WIDGET(m_pDasherControl), "dasher_edit_protect");
     }
   }
-  else if(pEvent->m_iEventType == EV_MESSAGE) {
-    CMessageEvent *pMessageEvent(static_cast<CMessageEvent *>(pEvent));
-    DasherMessageInfo sInfo;
-    sInfo.szMessage = pMessageEvent->m_strMessage.c_str();
-    sInfo.iID = pMessageEvent->m_iID;
-    sInfo.iType = pMessageEvent->m_iType;
-
-    g_signal_emit_by_name(GTK_WIDGET(m_pDasherControl), "dasher_message", &sInfo);
-  }
 };
 
 void CDasherControl::SetLockStatus(const string &strText, int iPercent) {
@@ -382,6 +373,16 @@ void CDasherControl::SetLockStatus(const string &strText, int iPercent) {
     g_signal_emit_by_name(GTK_WIDGET(m_pDasherControl), "dasher_lock_info", &sInfo);
 }
 
+//TODO do we want to do something like this?
+// ATM the only message is actually from the auto-speed control,
+// so definitely _doesn't_ want to be modal; could introduce a boolean
+// 'ok to interrupt user?' param to Message()?
+//void CDasherControl::Message(const std::string &strText)
+//  GtkMessageDialog *pDialog = GTK_MESSAGE_DIALOG(gtk_message_dialog_new(0, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, strText.c_str()));
+//  gtk_dialog_run(GTK_DIALOG(pDialog));
+//  gtk_widget_destroy(GTK_WIDGET(pDialog));
+//}
+
 unsigned int CDasherControl::ctrlMove(bool bForwards, CControlManager::EditDistance dist) {
   return gtk_dasher_control_ctrl_move(m_pDasherControl,bForwards,dist);
 }
diff --git a/Src/Gtk2/DasherControl.h b/Src/Gtk2/DasherControl.h
index 2187e03..55fbad0 100644
--- a/Src/Gtk2/DasherControl.h
+++ b/Src/Gtk2/DasherControl.h
@@ -26,7 +26,7 @@
 //#include "KeyboardHelper.h"
 
 //#include "../DasherCore/DasherSettingsInterface.h"
-#include "../DasherCore/DasherInterfaceBase.h"
+#include "../DasherCore/DashIntfScreenMsgs.h"
 #include "GnomeSettingsStore.h"
 #include "../DasherCore/UserLog.h"
 
@@ -34,10 +34,9 @@
 /// \brief C++ core of the Dasher GTK UI component.
 ///
 /// Class representing the Dasher UI component (ie the canvas and speed slider)
-/// \todo It would really be more sensible for CDasherControl to inheret from CDasherInterface rather than contain a pointer to it
 ///
 
-class CDasherControl : public CDasherInterfaceBase {
+class CDasherControl : public CDashIntfScreenMsgs {
 
 public:
 
diff --git a/Src/Gtk2/GtkDasherControl.h b/Src/Gtk2/GtkDasherControl.h
index da074f5..d1bf4c4 100644
--- a/Src/Gtk2/GtkDasherControl.h
+++ b/Src/Gtk2/GtkDasherControl.h
@@ -19,14 +19,6 @@ struct _DasherLockInfo {
   unsigned long time;
 };
 
-typedef struct _DasherMessageInfo DasherMessageInfo;
-
-struct _DasherMessageInfo {
-  const gchar *szMessage;
-  gint iID;
-  gint iType;
-};
-
 G_BEGIN_DECLS
 #define GTK_DASHER_TYPE_CONTROL         (gtk_dasher_control_get_type())
 #define GTK_DASHER_CONTROL(obj)         (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_DASHER_TYPE_CONTROL, GtkDasherControl ))
diff --git a/Src/Gtk2/dasher_editor_internal.cpp b/Src/Gtk2/dasher_editor_internal.cpp
index 9052143..067d724 100644
--- a/Src/Gtk2/dasher_editor_internal.cpp
+++ b/Src/Gtk2/dasher_editor_internal.cpp
@@ -130,7 +130,6 @@ static void dasher_editor_internal_add_action(DasherEditor *pSelf, DasherAction
 static EditorAction *dasher_editor_internal_get_action_by_id(DasherEditor *pSelf, int iID);
 static void dasher_editor_internal_rebuild_action_pane(DasherEditor *pSelf);
 static void dasher_editor_internal_action_save_state(DasherEditor *pSelf, EditorAction *pAction);
-//static void dasher_editor_internal_display_message(DasherEditor *pSelf, DasherMessageInfo *pMessageInfo);
 static void dasher_editor_internal_check_activity(DasherEditor *pSelf, EditorAction *pAction);
 #endif
 
@@ -208,7 +207,6 @@ extern "C" void main_window_realized(DasherMain *pMain, gpointer pUserData);
 extern "C" void action_button_callback(GtkWidget *pWidget, gpointer pUserData);
 extern "C" void mark_set_handler(GtkWidget *widget, GtkTextIter *pIter, GtkTextMark *pMark, gpointer pUserData);
 extern "C" void handle_stop_event(GtkDasherControl *pDasherControl, gpointer data);
-extern "C" void on_message(GtkDasherControl *pDasherControl, gpointer pMessageInfo, gpointer pUserData);
 extern "C" void on_command(GtkDasherControl *pDasherControl, gchar *szCommand, gpointer pUserData);
 extern "C" void handle_request_settings(GtkDasherControl * pDasherControl, gpointer data);
 extern "C" void gtk2_edit_delete_callback(GtkDasherControl *pDasherControl, const gchar *szText, int iOffset, gpointer user_data);
@@ -303,7 +301,7 @@ dasher_editor_internal_finalize(GObject *pObject) {
 
   if(pCurrentAction) {
     bool bStarted = false;
-  
+
     while(!bStarted || (pCurrentAction != pPrivate->pActionRing)) {
       bStarted = true;
       dasher_action_deactivate(pCurrentAction->pAction);
@@ -411,7 +409,7 @@ dasher_editor_internal_handle_stop(DasherEditor *pSelf) {
 
   if(pCurrentAction) {
     bool bStarted = false;
-  
+
     while(!bStarted || (pCurrentAction != pPrivate->pActionRing)) {
       bStarted = true;
       if(pCurrentAction->bAuto)
@@ -523,7 +521,7 @@ dasher_editor_internal_action_set_control(DasherEditor *pSelf, int iActionID, bo
 //       gtk_dasher_control_connect_node(GTK_DASHER_CONTROL(pDasherWidget), pAction->iControlID, Dasher::CControlManager::CTL_USER, -2);
 //     else
 //       gtk_dasher_control_disconnect_node(GTK_DASHER_CONTROL(pDasherWidget), pAction->iControlID, Dasher::CControlManager::CTL_USER);
-  
+
 //     dasher_editor_internal_action_save_state(pSelf, pAction);
 //   }
 }
@@ -536,7 +534,7 @@ EditorAction *pAction;
   if(pAction) {
     pAction->bAuto = bValue;
     dasher_editor_internal_check_activity(pSelf, pAction);
-  
+
     dasher_editor_internal_action_save_state(pSelf, pAction);
   }
 }
@@ -554,8 +552,8 @@ dasher_editor_internal_grab_focus(DasherEditor *pSelf) {
 static void
 dasher_editor_internal_create_buffer(DasherEditor *pSelf) {
   DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
-  
-  
+
+
   pPrivate->pOutputTag = gtk_text_buffer_create_tag(pPrivate->pBuffer, NULL, NULL);
 
 #if GTK_CHECK_VERSION(2,8,0)
@@ -585,14 +583,14 @@ dasher_editor_internal_output(DasherEditor *pSelf, const gchar *szText, int iOff
   if(!strcmp(szText, " ")) {
     gboolean bActionIterStarted = false;
     EditorAction *pActionIter = pPrivate->pActionRing;
-  
+
     while((pActionIter != pPrivate->pActionRing) || !bActionIterStarted) {
       bActionIterStarted = true;
-    
+
       if(!strcmp(dasher_action_get_name(pActionIter->pAction), "Speak")) {
         dasher_action_preview(pActionIter->pAction, DASHER_EDITOR(pSelf));
       }
-    
+
       pActionIter = pActionIter->pNext;
     }
   }
@@ -958,7 +956,7 @@ void
 dasher_editor_internal_handle_font(DasherEditor *pSelf, const gchar *szFont) {
   if(strcmp(szFont, "")) {
     DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
-  
+
     PangoFontDescription *pFD = pango_font_description_from_string(szFont);
     gtk_widget_modify_font(GTK_WIDGET(pPrivate->pTextView), pFD);
   }
@@ -1071,7 +1069,7 @@ dasher_editor_internal_setup_actions(DasherEditor *pSelf) {
     while((szFilename = g_dir_read_name(pDirectory))) {
       dasher_editor_internal_add_action(pSelf, DASHER_ACTION(dasher_action_script_new(szUserScriptDir, szFilename)));
     }
-  
+
     g_dir_close(pDirectory);
   }
 
@@ -1087,7 +1085,7 @@ dasher_editor_internal_setup_actions(DasherEditor *pSelf) {
     while((szFilename = g_dir_read_name(pDirectory))) {
       dasher_editor_internal_add_action(pSelf, DASHER_ACTION(dasher_action_script_new(szSystemScriptDir, szFilename)));
     }
-  
+
     g_dir_close(pDirectory);
   }
 
@@ -1116,9 +1114,9 @@ dasher_editor_internal_setup_actions(DasherEditor *pSelf) {
 //     if(pCurrentAction->bControl) {
 //       gtk_dasher_control_register_node( GTK_DASHER_CONTROL(pDasherWidget), Dasher::CControlManager::CTL_USER + iControlOffset, dasher_action_get_name(pCurrentAction->pAction), -1 );
 //       gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget), Dasher::CControlManager::CTL_USER + iControlOffset, Dasher::CControlManager::CTL_USER, -2);
-    
+
 //       int iNSub(dasher_action_get_sub_count(pCurrentAction->pAction));
-    
+
 //       if(iNSub == 0) {
 // 	gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget), -1, Dasher::CControlManager::CTL_USER + iControlOffset, -2);
 //       }
@@ -1129,12 +1127,12 @@ dasher_editor_internal_setup_actions(DasherEditor *pSelf) {
 // 	  gtk_dasher_control_connect_node( GTK_DASHER_CONTROL(pDasherWidget), -1, Dasher::CControlManager::CTL_USER + iControlOffset + i + 1, -2);
 // 	}
 //       }
-    
+
 //       pCurrentAction->iControlID = Dasher::CControlManager::CTL_USER + iControlOffset;
 //       pCurrentAction->iNSub = iNSub;
 //       iControlOffset += iNSub + 1;
 //     }
-    
+
 //     pCurrentAction = pCurrentAction->pNext;
 //   }
 
@@ -1250,11 +1248,11 @@ dasher_editor_internal_rebuild_action_pane(DasherEditor *pSelf) {
     if(pCurrentAction->bShow) {
       GtkButton *pNewButton = GTK_BUTTON(gtk_button_new_with_label(dasher_action_get_name(pCurrentAction->pAction)));
       gtk_widget_show(GTK_WIDGET(pNewButton));
-    
+
       pUserData = new void *[2];
       pUserData[0] = (void *)pSelf;
       pUserData[1] = (void *)(pCurrentAction->pAction);
-    
+
       g_signal_connect(G_OBJECT(pNewButton), "clicked", G_CALLBACK(action_button_callback), pUserData);
 #ifdef WITH_MAEMO
       // For Maemo we want the packing to expand
@@ -1268,14 +1266,6 @@ dasher_editor_internal_rebuild_action_pane(DasherEditor *pSelf) {
 }
 #endif /* XXXPRLWACTIONSAREFIXED */
 
-// TODO: This shouldn't be a part of the editor
-//static void
-//dasher_editor_internal_display_message(DasherEditor *pSelf, DasherMessageInfo *pMessageInfo) {
-//  GtkMessageDialog *pDialog = GTK_MESSAGE_DIALOG(gtk_message_dialog_new(0, GTK_DIALOG_MODAL, GTK_MESSAGE_INFO, GTK_BUTTONS_OK, pMessageInfo->szMessage));
-//  gtk_dialog_run(GTK_DIALOG(pDialog));
-//  gtk_widget_destroy(GTK_WIDGET(pDialog));
-//}
-
 #ifdef XXXPRLWACTIONSAREFIXED
 static void
 dasher_editor_internal_check_activity(DasherEditor *pSelf, EditorAction *pAction) {
@@ -1367,11 +1357,11 @@ dasher_editor_internal_command_save(DasherEditor *pSelf, gboolean bPrompt, gbool
 						     GTK_RESPONSE_ACCEPT,
 						     GTK_STOCK_CANCEL,
 						     GTK_RESPONSE_CANCEL, NULL);
-  
+
 #ifdef HAVE_GIO
     gtk_file_chooser_set_local_only(GTK_FILE_CHOOSER(filesel), FALSE);
 #endif
-  
+
     if(gtk_dialog_run(GTK_DIALOG(filesel)) == GTK_RESPONSE_ACCEPT) {
 #ifdef HAVE_GIO
       szFilename = gtk_file_chooser_get_uri(GTK_FILE_CHOOSER(filesel));
@@ -1383,7 +1373,7 @@ dasher_editor_internal_command_save(DasherEditor *pSelf, gboolean bPrompt, gbool
       gtk_widget_destroy(filesel);
       return;
     }
-  
+
     gtk_widget_destroy(filesel);
   }
   else {
@@ -1678,7 +1668,7 @@ static void edit_find(bool bForwards, CControlManager::EditDistance iDist, Dashe
       gtk_text_iter_backward_word_start(pPos);
       break;
     case CControlManager::EDIT_LINE:
-  
+
       if(!gtk_text_view_backward_display_line_start(GTK_TEXT_VIEW(pPrivate->pTextView), pPos))
         gtk_text_view_backward_display_line(GTK_TEXT_VIEW(pPrivate->pTextView), pPos);
       break;
@@ -1710,7 +1700,7 @@ dasher_editor_internal_ctrl_delete(DasherEditor *pSelf, bool bForwards, CControl
 
 static gint
 dasher_editor_internal_ctrl_move(DasherEditor *pSelf, bool bForwards, CControlManager::EditDistance iDist) {
-  DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf); 
+  DasherEditorInternalPrivate *pPrivate = DASHER_EDITOR_INTERNAL_GET_PRIVATE(pSelf);
   GtkTextIter sPos;
 
   gtk_text_buffer_get_iter_at_mark(pPrivate->pBuffer, &sPos, gtk_text_buffer_get_insert(pPrivate->pBuffer));
diff --git a/Src/Gtk2/dasher_main.cpp b/Src/Gtk2/dasher_main.cpp
index 419ee83..4f137c6 100644
--- a/Src/Gtk2/dasher_main.cpp
+++ b/Src/Gtk2/dasher_main.cpp
@@ -1352,18 +1352,6 @@ handle_stop_event(GtkDasherControl *pDasherControl, gpointer data) {
 }
 
 extern "C" void 
-on_message(GtkDasherControl *pDasherControl, gpointer pMessageInfo, gpointer pUserData) { 
-  // TODO: I don't believe that this is widely used, but possibly need to reimplement
-
-//   if(g_pDasherMain) {
-//     DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
-
-//     if(pPrivate->pEditor)
-//        dasher_editor_display_message(pPrivate->pEditor, (DasherMessageInfo *)pMessageInfo);
-//   }
-}
-
-extern "C" void 
 on_command(GtkDasherControl *pDasherControl, gchar *szCommand, gpointer pUserData) {
   if(g_pDasherMain) {
     DasherMainPrivate *pPrivate = DASHER_MAIN_GET_PRIVATE(g_pDasherMain);
diff --git a/Src/MacOSX/COSXDasherControl.h b/Src/MacOSX/COSXDasherControl.h
index 077b19b..15807c2 100644
--- a/Src/MacOSX/COSXDasherControl.h
+++ b/Src/MacOSX/COSXDasherControl.h
@@ -10,7 +10,7 @@
 #import "../DasherCore/SocketInput.h"
 
 // #import "../DasherCore/DasherSettingsInterface.h"
-#import "../DasherCore/DasherInterfaceBase.h"
+#import "../DasherCore/DashIntfScreenMsgs.h"
 #import "COSXMouseInput.h"
 
 @class DasherApp;
@@ -22,7 +22,7 @@
 /// Class representing the Dasher UI component (ie the canvas and speed slider)
 ///
 
-class COSXDasherControl : public CDasherInterfaceBase {
+class COSXDasherControl : public CDashIntfScreenMsgs {
   
 public:
   
diff --git a/Src/MacOSX/COSXDasherControl.mm b/Src/MacOSX/COSXDasherControl.mm
index e50c849..51dd2e7 100644
--- a/Src/MacOSX/COSXDasherControl.mm
+++ b/Src/MacOSX/COSXDasherControl.mm
@@ -182,11 +182,6 @@ void COSXDasherControl::ExternalEventHandler(Dasher::CEvent *pEvent) {
       }
       break;
     }
-    case EV_MESSAGE: {
-      CMessageEvent *messageEvent(static_cast < CMessageEvent * >(pEvent));
-      NSLog(@"ExternalEventHandler, m_iEventType = EV_MESSAGE, mess: %@, id = %d, type = %d", NSStringFromStdString(messageEvent->m_strMessage), messageEvent->m_iID, messageEvent->m_iType);
-      break;
-    }
     case EV_SCREEN_GEOM:
       //no need to do anything, so avoid log message
       break;
diff --git a/Src/MacOSX/Dasher.xcodeproj/project.pbxproj b/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
index 9e34cca..8a82f1d 100755
--- a/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
+++ b/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
@@ -346,6 +346,9 @@
 		339794D5120F2A9600CEA168 /* AlphInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 339794D3120F2A9600CEA168 /* AlphInfo.h */; };
 		33ABFEC60FC379EA00EA2BA5 /* ButtonMultiPress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33ABFEC40FC379EA00EA2BA5 /* ButtonMultiPress.cpp */; };
 		33ABFEC70FC379EA00EA2BA5 /* ButtonMultiPress.h in Headers */ = {isa = PBXBuildFile; fileRef = 33ABFEC50FC379EA00EA2BA5 /* ButtonMultiPress.h */; };
+		33B3431813A8A951009AE0D5 /* DashIntfScreenMsgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33B3431613A8A951009AE0D5 /* DashIntfScreenMsgs.cpp */; };
+		33B3431913A8A951009AE0D5 /* DashIntfScreenMsgs.h in Headers */ = {isa = PBXBuildFile; fileRef = 33B3431713A8A951009AE0D5 /* DashIntfScreenMsgs.h */; };
+		33B3431B13A8A970009AE0D5 /* Messages.h in Headers */ = {isa = PBXBuildFile; fileRef = 33B3431A13A8A970009AE0D5 /* Messages.h */; };
 		33E173C70F3E0B6400D19B38 /* Makefile.am in Resources */ = {isa = PBXBuildFile; fileRef = 33E173A70F3E0B6400D19B38 /* Makefile.am */; };
 		33E173C80F3E0B6400D19B38 /* training_albanian_SQ.txt in Resources */ = {isa = PBXBuildFile; fileRef = 33E173A80F3E0B6400D19B38 /* training_albanian_SQ.txt */; };
 		33E173CB0F3E0B6400D19B38 /* training_bengali_BD.txt in Resources */ = {isa = PBXBuildFile; fileRef = 33E173AB0F3E0B6400D19B38 /* training_bengali_BD.txt */; };
@@ -461,8 +464,6 @@
 		1948BE450C226CFD001DFA32 /* FileLogger.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FileLogger.cpp; sourceTree = "<group>"; };
 		1948BE460C226CFD001DFA32 /* FileLogger.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FileLogger.h; sourceTree = "<group>"; };
 		1948BE470C226CFD001DFA32 /* FrameRate.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FrameRate.h; sourceTree = "<group>"; };
-		1948BE480C226CFD001DFA32 /* GnomeSettingsStore.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GnomeSettingsStore.cpp; sourceTree = "<group>"; };
-		1948BE490C226CFD001DFA32 /* GnomeSettingsStore.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GnomeSettingsStore.h; sourceTree = "<group>"; };
 		1948BE4C0C226CFD001DFA32 /* InputFilter.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = InputFilter.h; sourceTree = "<group>"; };
 		1948BE510C226CFD001DFA32 /* CTWLanguageModel.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CTWLanguageModel.cpp; sourceTree = "<group>"; };
 		1948BE520C226CFD001DFA32 /* CTWLanguageModel.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CTWLanguageModel.h; sourceTree = "<group>"; };
@@ -743,6 +744,9 @@
 		339794D3120F2A9600CEA168 /* AlphInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlphInfo.h; sourceTree = "<group>"; };
 		33ABFEC40FC379EA00EA2BA5 /* ButtonMultiPress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ButtonMultiPress.cpp; sourceTree = "<group>"; };
 		33ABFEC50FC379EA00EA2BA5 /* ButtonMultiPress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ButtonMultiPress.h; sourceTree = "<group>"; };
+		33B3431613A8A951009AE0D5 /* DashIntfScreenMsgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DashIntfScreenMsgs.cpp; sourceTree = "<group>"; };
+		33B3431713A8A951009AE0D5 /* DashIntfScreenMsgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DashIntfScreenMsgs.h; sourceTree = "<group>"; };
+		33B3431A13A8A970009AE0D5 /* Messages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Messages.h; sourceTree = "<group>"; };
 		33E173A70F3E0B6400D19B38 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
 		33E173A80F3E0B6400D19B38 /* training_albanian_SQ.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = training_albanian_SQ.txt; sourceTree = "<group>"; };
 		33E173AB0F3E0B6400D19B38 /* training_bengali_BD.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = training_bengali_BD.txt; sourceTree = "<group>"; };
@@ -919,6 +923,8 @@
 				1948BE2A0C226CFD001DFA32 /* DasherInput.h */,
 				1948BE2B0C226CFD001DFA32 /* DasherInterfaceBase.cpp */,
 				1948BE2C0C226CFD001DFA32 /* DasherInterfaceBase.h */,
+				33B3431613A8A951009AE0D5 /* DashIntfScreenMsgs.cpp */,
+				33B3431713A8A951009AE0D5 /* DashIntfScreenMsgs.h */,
 				1948BE2D0C226CFD001DFA32 /* DasherModel.cpp */,
 				1948BE2E0C226CFD001DFA32 /* DasherModel.h */,
 				1948BE2F0C226CFD001DFA32 /* DasherModule.cpp */,
@@ -946,12 +952,11 @@
 				1948BE470C226CFD001DFA32 /* FrameRate.h */,
 				1921DB6C0C7ECB9900E6DAA5 /* GameScorer.cpp */,
 				1921DB6D0C7ECB9900E6DAA5 /* GameScorer.h */,
-				1948BE480C226CFD001DFA32 /* GnomeSettingsStore.cpp */,
-				1948BE490C226CFD001DFA32 /* GnomeSettingsStore.h */,
 				1948BE4C0C226CFD001DFA32 /* InputFilter.h */,
 				1948BE4D0C226CFD001DFA32 /* LanguageModelling */,
 				1948BE680C226CFD001DFA32 /* MemoryLeak.cpp */,
 				1948BE690C226CFD001DFA32 /* MemoryLeak.h */,
+				33B3431A13A8A970009AE0D5 /* Messages.h */,
 				1948BE6B0C226CFD001DFA32 /* ModuleManager.cpp */,
 				1948BE6C0C226CFD001DFA32 /* ModuleManager.h */,
 				1948BE6D0C226CFD001DFA32 /* NodeCreationManager.cpp */,
@@ -1434,6 +1439,8 @@
 				339794D5120F2A9600CEA168 /* AlphInfo.h in Headers */,
 				330B91641292FE700022831C /* ModuleSettingsController.h in Headers */,
 				33F6C9EA133241A000745B06 /* AbstractXMLParser.h in Headers */,
+				33B3431913A8A951009AE0D5 /* DashIntfScreenMsgs.h in Headers */,
+				33B3431B13A8A970009AE0D5 /* Messages.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1781,6 +1788,7 @@
 				339794D4120F2A9600CEA168 /* AlphInfo.cpp in Sources */,
 				330B91621292FE520022831C /* ModuleSettingsController.mm in Sources */,
 				33F6C9EB133241A000745B06 /* AbstractXMLParser.cpp in Sources */,
+				33B3431813A8A951009AE0D5 /* DashIntfScreenMsgs.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
diff --git a/Src/Win32/Dasher.h b/Src/Win32/Dasher.h
index 1ff11a9..b56a38c 100644
--- a/Src/Win32/Dasher.h
+++ b/Src/Win32/Dasher.h
@@ -1,7 +1,7 @@
 #pragma once
 
 #include "Common/wincommon.h"
-#include "../DasherCore/DasherInterfaceBase.h"
+#include "../DasherCore/DashIntfScreenMsgs.h"
 #include "../DasherCore/UserLog.h"
 
 #ifdef _WIN32_WCE
@@ -29,7 +29,7 @@ class CEdit;
 class CDasherWindow;
 
 namespace Dasher {
-class CDasher : public CDasherInterfaceBase 
+class CDasher : public CDashIntfScreenMsgs
 {
 public:
   CDasher(HWND Parent, CDasherWindow *pWindow, CEdit *pEdit);
diff --git a/Src/iPhone/Classes/CDasherInterfaceBridge.h b/Src/iPhone/Classes/CDasherInterfaceBridge.h
index f30d398..869c4cc 100644
--- a/Src/iPhone/Classes/CDasherInterfaceBridge.h
+++ b/Src/iPhone/Classes/CDasherInterfaceBridge.h
@@ -55,6 +55,7 @@ public:
   unsigned int ctrlMove(bool bForwards, CControlManager::EditDistance dist);
   unsigned int ctrlDelete(bool bForwards, CControlManager::EditDistance dist);
   void SetLockStatus(const string &strText, int iPercent);
+  void Message(const string &strText);
 private:
   virtual void ScanAlphabetFiles(std::vector<std::string> &vFileList);
   virtual void ScanColourFiles(std::vector<std::string> &vFileList);
diff --git a/Src/iPhone/Classes/CDasherInterfaceBridge.mm b/Src/iPhone/Classes/CDasherInterfaceBridge.mm
index fa399a9..4ad74d1 100644
--- a/Src/iPhone/Classes/CDasherInterfaceBridge.mm
+++ b/Src/iPhone/Classes/CDasherInterfaceBridge.mm
@@ -182,12 +182,9 @@ void CDasherInterfaceBridge::ExternalEventHandler(Dasher::CEvent *pEvent) {
       }
 	  }
         break;
-    case EV_MESSAGE:
-	  {
-      CMessageEvent *messageEvent(static_cast < CMessageEvent * >(pEvent));
-      [dasherApp displayMessage:NSStringFromStdString(messageEvent->m_strMessage) ID:messageEvent->m_iID Type:messageEvent->m_iType];
-      break;
-	}
+   case EV_SCREEN_GEOM:
+     //no need to do anything
+     break;
     default:
       NSLog(@"ExternalEventHandler, UNKNOWN m_iEventType = %d", pEvent->m_iEventType);
       break;
@@ -195,6 +192,10 @@ void CDasherInterfaceBridge::ExternalEventHandler(Dasher::CEvent *pEvent) {
   
 }
 
+void CDasherInterfaceBridge::Message(const string &strMessage) {
+  [dasherApp displayMessage:NSStringFromStdString(strMessage)];
+}
+
 void CDasherInterfaceBridge::SetLockStatus(const string &strText, int iPercent) {
   NSString *dispMsg = nil;
   if (iPercent != -1) {
diff --git a/Src/iPhone/Classes/DasherAppDelegate.h b/Src/iPhone/Classes/DasherAppDelegate.h
index 0cbe972..0aec79f 100644
--- a/Src/iPhone/Classes/DasherAppDelegate.h
+++ b/Src/iPhone/Classes/DasherAppDelegate.h
@@ -51,7 +51,7 @@
 - (void)notifySpeedChange;
 - (NSString *)textAtOffset:(unsigned int)offset Length:(unsigned int)length;
 - (void)setLockText:(NSString *)s;
-- (void)displayMessage:(NSString *)msg ID:(int)iId Type:(int)type;
+- (void)displayMessage:(NSString *)msg;
 - (void)setLandscapeSupported:(BOOL)supported;
 + (DasherAppDelegate *)theApp;
 
diff --git a/Src/iPhone/Classes/DasherAppDelegate.mm b/Src/iPhone/Classes/DasherAppDelegate.mm
index 2d87c6a..a22f0d1 100644
--- a/Src/iPhone/Classes/DasherAppDelegate.mm
+++ b/Src/iPhone/Classes/DasherAppDelegate.mm
@@ -250,7 +250,7 @@ static SModuleSettings _miscSettings[] = { //note iStep and string description a
   [text becomeFirstResponder];
 }
 
-- (void)displayMessage:(NSString *)msg ID:(int)iId Type:(int)type {
+- (void)displayMessage:(NSString *)msg {
   //set initial state - overriding any animation in progress...
   messageLabel.text = msg;
   messageLabel.alpha = 1.0;
diff --git a/Src/iPhone/Dasher.xcodeproj/project.pbxproj b/Src/iPhone/Dasher.xcodeproj/project.pbxproj
index 53558e8..162556a 100755
--- a/Src/iPhone/Dasher.xcodeproj/project.pbxproj
+++ b/Src/iPhone/Dasher.xcodeproj/project.pbxproj
@@ -254,6 +254,7 @@
 		3378A267133543B800A96C5D /* control.xml in Resources */ = {isa = PBXBuildFile; fileRef = 3378A266133543B800A96C5D /* control.xml */; };
 		337ECC1B10DD5E0700D0C6A5 /* ExpansionPolicy.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 337ECC1910DD5E0700D0C6A5 /* ExpansionPolicy.cpp */; };
 		339F8A330FF5088000282847 /* CalibrationController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 339F8A320FF5088000282847 /* CalibrationController.mm */; };
+		33B3430813A8A927009AE0D5 /* DashIntfScreenMsgs.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33B3430613A8A927009AE0D5 /* DashIntfScreenMsgs.cpp */; };
 		33C71AF20FF7B51700A20992 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 33C71AF10FF7B51700A20992 /* Default.png */; };
 		33CBB397101F422200510BF9 /* PPMPYLanguageModel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33CBB395101F422200510BF9 /* PPMPYLanguageModel.cpp */; };
 		33CBB4CD101F9E5F00510BF9 /* training_czechC_CS.txt in Resources */ = {isa = PBXBuildFile; fileRef = 33CBB4C7101F9E5F00510BF9 /* training_czechC_CS.txt */; };
@@ -702,6 +703,9 @@
 		337ECC1A10DD5E0700D0C6A5 /* ExpansionPolicy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpansionPolicy.h; sourceTree = "<group>"; };
 		339F8A310FF5088000282847 /* CalibrationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CalibrationController.h; sourceTree = "<group>"; };
 		339F8A320FF5088000282847 /* CalibrationController.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CalibrationController.mm; sourceTree = "<group>"; };
+		33B342F313A8A8B2009AE0D5 /* Messages.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Messages.h; sourceTree = "<group>"; };
+		33B3430613A8A927009AE0D5 /* DashIntfScreenMsgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DashIntfScreenMsgs.cpp; sourceTree = "<group>"; };
+		33B3430713A8A927009AE0D5 /* DashIntfScreenMsgs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DashIntfScreenMsgs.h; sourceTree = "<group>"; };
 		33C71AF10FF7B51700A20992 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; };
 		33CBB395101F422200510BF9 /* PPMPYLanguageModel.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PPMPYLanguageModel.cpp; sourceTree = "<group>"; };
 		33CBB396101F422200510BF9 /* PPMPYLanguageModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PPMPYLanguageModel.h; sourceTree = "<group>"; };
@@ -1197,6 +1201,8 @@
 				3344FD9B0F71717C00506EAA /* DasherInput.h */,
 				3344FD9C0F71717C00506EAA /* DasherInterfaceBase.cpp */,
 				3344FD9D0F71717C00506EAA /* DasherInterfaceBase.h */,
+				33B3430613A8A927009AE0D5 /* DashIntfScreenMsgs.cpp */,
+				33B3430713A8A927009AE0D5 /* DashIntfScreenMsgs.h */,
 				3344FD9E0F71717C00506EAA /* DasherModel.cpp */,
 				3344FD9F0F71717C00506EAA /* DasherModel.h */,
 				3344FDA00F71717C00506EAA /* DasherModule.cpp */,
@@ -1230,6 +1236,7 @@
 				3344FDC40F71717C00506EAA /* LanguageModelling */,
 				3344FDDE0F71717C00506EAA /* MemoryLeak.cpp */,
 				3344FDDF0F71717C00506EAA /* MemoryLeak.h */,
+				33B342F313A8A8B2009AE0D5 /* Messages.h */,
 				3344FDE00F71717C00506EAA /* ModuleManager.cpp */,
 				3344FDE10F71717C00506EAA /* ModuleManager.h */,
 				3344FDE20F71717C00506EAA /* NodeCreationManager.cpp */,
@@ -1713,6 +1720,7 @@
 				3324F7BF129D744D00EE6A22 /* ActionConfigurator.mm in Sources */,
 				3378A23F1335425300A96C5D /* AbstractXMLParser.cpp in Sources */,
 				333FDB5A139FB413009D018A /* ConvertingAlphMgr.cpp in Sources */,
+				33B3430813A8A927009AE0D5 /* DashIntfScreenMsgs.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};



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