[dasher: 26/43] CMessageDisplay: add bool param 4 non-/modal; use instead of many cout/cerr's
- From: Patrick Welche <pwelche src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [dasher: 26/43] CMessageDisplay: add bool param 4 non-/modal; use instead of many cout/cerr's
- Date: Thu, 23 Jun 2011 18:57:56 +0000 (UTC)
commit af8fa9f41433fe21e7f6247727662941c6c67e1b
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date: Mon Jun 13 18:28:41 2011 +0100
CMessageDisplay: add bool param 4 non-/modal; use instead of many cout/cerr's
Message(string,bool): true = modal/interrupt user, false = non-modal/don't
CDashIntfScreenMsgs renders modal messages on canvas too, but in yellow;
and keeps around until user restarts Dasher (by calling Unpause(time)).
Src/DasherCore/AbstractXMLParser.cpp | 28 ++++++---
Src/DasherCore/AbstractXMLParser.h | 8 ++-
Src/DasherCore/Alphabet/AlphIO.cpp | 10 ++--
Src/DasherCore/Alphabet/AlphIO.h | 2 +-
Src/DasherCore/Alphabet/AlphInfo.h | 1 +
Src/DasherCore/Alphabet/AlphabetMap.cpp | 27 +++++----
Src/DasherCore/Alphabet/AlphabetMap.h | 6 ++-
Src/DasherCore/AlphabetManager.cpp | 2 +-
Src/DasherCore/AlphabetManager.h | 4 +-
Src/DasherCore/AutoSpeedControl.cpp | 15 +++--
Src/DasherCore/ColourIO.cpp | 10 ++--
Src/DasherCore/ColourIO.h | 2 +-
Src/DasherCore/ControlManager.cpp | 8 +-
Src/DasherCore/ControlManager.h | 3 +-
Src/DasherCore/ConversionManager.cpp | 8 +-
Src/DasherCore/ConversionManager.h | 4 +-
Src/DasherCore/DashIntfScreenMsgs.cpp | 81 ++++++++++++++++++++------
Src/DasherCore/DashIntfScreenMsgs.h | 28 +++++++--
Src/DasherCore/DasherInterfaceBase.cpp | 6 +-
Src/DasherCore/DasherInterfaceBase.h | 2 +-
Src/DasherCore/MandarinAlphMgr.cpp | 4 +-
Src/DasherCore/Messages.h | 15 ++++-
Src/DasherCore/NodeCreationManager.cpp | 27 +++++++--
Src/DasherCore/SocketInput.cpp | 4 +-
Src/DasherCore/SocketInput.h | 2 +-
Src/DasherCore/SocketInputBase.cpp | 39 +++++++------
Src/DasherCore/SocketInputBase.h | 9 ++-
Src/DasherCore/Trainer.cpp | 59 ++++++++++++-------
Src/DasherCore/Trainer.h | 15 ++---
Src/Gtk2/DasherControl.cpp | 2 +-
Src/Win32/Dasher.cpp | 2 +-
Src/Win32/Sockets/SocketInput.cpp | 4 +-
Src/Win32/Sockets/SocketInput.h | 2 +-
Src/iPhone/Classes/CDasherInterfaceBridge.h | 13 +++-
Src/iPhone/Classes/CDasherInterfaceBridge.mm | 7 ++-
35 files changed, 298 insertions(+), 161 deletions(-)
---
diff --git a/Src/DasherCore/AbstractXMLParser.cpp b/Src/DasherCore/AbstractXMLParser.cpp
index bf85e0b..14a567d 100644
--- a/Src/DasherCore/AbstractXMLParser.cpp
+++ b/Src/DasherCore/AbstractXMLParser.cpp
@@ -8,10 +8,12 @@
*/
#include "AbstractXMLParser.h"
-#ifdef DEBUG
-#include <iostream>
-#endif
-bool AbstractXMLParser::ParseFile(const std::string &strFilename) {
+
+#include <string.h>
+
+using std::string;
+
+bool AbstractXMLParser::ParseFile(CMessageDisplay *pMsgs, const std::string &strFilename) {
FILE *Input;
if((Input = fopen(strFilename.c_str(), "r")) == (FILE *) 0) {
// could not open file
@@ -26,24 +28,30 @@ bool AbstractXMLParser::ParseFile(const std::string &strFilename) {
XML_SetElementHandler(Parser, XML_StartElement, XML_EndElement);
XML_SetCharacterDataHandler(Parser, XML_CharacterData);
-
+ bool bRes(true);
char Buffer[1024];
int Done;
do {
size_t len = fread(Buffer, 1, sizeof(Buffer), Input);
Done = len < sizeof(Buffer);
if(XML_Parse(Parser, Buffer, len, Done) == XML_STATUS_ERROR) {
- //TODO, should we make sure we return false, if this happens?
-#ifdef DEBUG
- std::cout << "Parse error! on " << std::string(Buffer,len) << std::endl;
-#endif
+ bRes=false;
+ if (pMsgs) {
+ const char *msg=_("XML Error %s in file %s somewhere in block: %s");
+ const XML_LChar *xmle=XML_ErrorString(XML_GetErrorCode(Parser)); //think XML_LChar==char, depends on preprocessor variables...
+ char *buf(new char[strlen(msg)+ strlen(xmle) + strFilename.length() + len + 3]);
+ //constructing a string here to get a null terminator. Can we put a null into Buffer instead?
+ sprintf(buf, msg, xmle, strFilename.c_str(), string(Buffer,len).c_str());
+ pMsgs->Message(buf,true);
+ delete buf;
+ }
break;
}
} while (!Done);
XML_ParserFree(Parser);
fclose(Input);
- return true;
+ return bRes;
}
void AbstractXMLParser::XmlCData(const XML_Char *str, int len) {
diff --git a/Src/DasherCore/AbstractXMLParser.h b/Src/DasherCore/AbstractXMLParser.h
index 0a4a335..6f64fa1 100644
--- a/Src/DasherCore/AbstractXMLParser.h
+++ b/Src/DasherCore/AbstractXMLParser.h
@@ -15,6 +15,8 @@
#include <config.h>
#endif
+#include "Messages.h"
+
#include <string>
#include <expat.h>
@@ -24,8 +26,10 @@
class AbstractXMLParser {
public:
///Parse (the whole) file - done in chunks to avoid loading the whole thing into memory.
- /// \return true if the file was opened+parsed; false if not (i.e. filename did not exist)
- bool ParseFile(const std::string &strFilename);
+ /// \param pInterface if non-null, any errors _besides_ file-not-found, will be passed
+ /// to the Message(,true) method to report to the user.
+ /// \return true if the file was opened+parsed OK; false if there was an error (e.g. FNF)
+ bool ParseFile(CMessageDisplay *pMsgs, const std::string &strFilename);
protected:
///Subclass should override to handle a start tag
virtual void XmlStartHandler(const XML_Char *name, const XML_Char **atts)=0;
diff --git a/Src/DasherCore/Alphabet/AlphIO.cpp b/Src/DasherCore/Alphabet/AlphIO.cpp
index d854552..f26d321 100644
--- a/Src/DasherCore/Alphabet/AlphIO.cpp
+++ b/Src/DasherCore/Alphabet/AlphIO.cpp
@@ -36,7 +36,7 @@ static char THIS_FILE[] = __FILE__;
#endif
#endif
-CAlphIO::CAlphIO(const std::string &SystemLocation, const std::string &UserLocation, const std::vector<std::string> &Filenames)
+CAlphIO::CAlphIO(CMessageDisplay *pMsgs, const std::string &SystemLocation, const std::string &UserLocation, const std::vector<std::string> &Filenames)
: LoadMutable(false), CData("") {
Alphabets["Default"]=CreateDefault();
@@ -63,17 +63,17 @@ CAlphIO::CAlphIO(const std::string &SystemLocation, const std::string &UserLocat
}
LoadMutable = false;
- ParseFile(SystemLocation + "alphabet.xml");
+ ParseFile(pMsgs, SystemLocation + "alphabet.xml");
if(Filenames.size() > 0) {
for(unsigned int i = 0; i < Filenames.size(); i++) {
- ParseFile(SystemLocation + Filenames[i]);
+ ParseFile(pMsgs, SystemLocation + Filenames[i]);
}
}
LoadMutable = true;
- ParseFile(UserLocation + "alphabet.xml");
+ ParseFile(pMsgs, UserLocation + "alphabet.xml");
if(Filenames.size() > 0) {
for(unsigned int i = 0; i < Filenames.size(); i++) {
- ParseFile(UserLocation + Filenames[i]);
+ ParseFile(pMsgs, UserLocation + Filenames[i]);
}
}
}
diff --git a/Src/DasherCore/Alphabet/AlphIO.h b/Src/DasherCore/Alphabet/AlphIO.h
index 7d969fc..908ec0e 100644
--- a/Src/DasherCore/Alphabet/AlphIO.h
+++ b/Src/DasherCore/Alphabet/AlphIO.h
@@ -50,7 +50,7 @@ namespace Dasher {
class Dasher::CAlphIO : private AbstractXMLParser {
public:
- CAlphIO(const std::string &SystemLocation, const std::string &UserLocation, const std::vector < std::string > &Filenames);
+ CAlphIO(CMessageDisplay *pMsgs, const std::string &SystemLocation, const std::string &UserLocation, const std::vector < std::string > &Filenames);
~CAlphIO();
void GetAlphabets(std::vector < std::string > *AlphabetList) const;
std::string GetDefault();
diff --git a/Src/DasherCore/Alphabet/AlphInfo.h b/Src/DasherCore/Alphabet/AlphInfo.h
index 7e137af..7cbbc1a 100644
--- a/Src/DasherCore/Alphabet/AlphInfo.h
+++ b/Src/DasherCore/Alphabet/AlphInfo.h
@@ -66,6 +66,7 @@ private:
std::string Foreground;
};
public:
+ const std::string &GetID() const {return AlphID;}
/// Return number of text symbols - inc space and para, but no control/conversion start/end
/// Note symbol numbers are 1-indexed; 0 is reserved to indicate an "unknown symbol" (-1 = End-Of-Stream),
/// and for element 0 of the probability array to contain a 0.
diff --git a/Src/DasherCore/Alphabet/AlphabetMap.cpp b/Src/DasherCore/Alphabet/AlphabetMap.cpp
index 8adf97b..a873bd9 100644
--- a/Src/DasherCore/Alphabet/AlphabetMap.cpp
+++ b/Src/DasherCore/Alphabet/AlphabetMap.cpp
@@ -75,8 +75,8 @@ int utf8_length::operator[](const unsigned char i) const
////////////////////////////////////////////////////////////////////////////
-CAlphabetMap::SymbolStream::SymbolStream(std::istream &_in)
-: pos(0), len(0), in(_in) {
+CAlphabetMap::SymbolStream::SymbolStream(std::istream &_in, CMessageDisplay *pMsgs)
+: pos(0), len(0), in(_in), m_pMsgs(pMsgs) {
readMore();
}
@@ -112,19 +112,24 @@ inline int CAlphabetMap::SymbolStream::findNext() {
if (int numChars = m_utf8_count_array[buf[pos]]) {
if (pos+numChars > len) {
//no more bytes in file (would have tried to read earlier), but not enough for char
-#ifdef DEBUG
- std::cerr << "Incomplete UTF-8 character beginning 0x" << hex << buf[pos] << dec;
- std::cerr << "(expecting " << numChars << " bytes but only " << (len-pos) << ")" << std::endl;
-#endif
- pos=len;
+ if (m_pMsgs) {
+ const char *msg(_("File ends with incomplete UTF-8 character beginning 0x%x (expecting %i bytes but only %i)"));
+ char *mbuf(new char[strlen(msg) + 4]);
+ sprintf(mbuf, msg, static_cast<unsigned int>(buf[pos] & 0xff), numChars, len-pos);
+ m_pMsgs->Message(mbuf,true);
+ delete mbuf;
+ }
return 0;
}
return numChars;
}
-#ifdef DEBUG
- std::cerr << "Read invalid UTF-8 character 0x" << hex << buf[pos]
- << dec << std::endl;
-#endif
+ if (m_pMsgs) {
+ const char *msg(_("Read invalid UTF-8 character 0x%x"));
+ char *mbuf(new char[strlen(msg) + 2]);
+ sprintf(mbuf, msg, static_cast<unsigned int>(buf[pos] & 0xff));
+ m_pMsgs->Message(mbuf,true);
+ delete mbuf;
+ }
++pos;
}
}
diff --git a/Src/DasherCore/Alphabet/AlphabetMap.h b/Src/DasherCore/Alphabet/AlphabetMap.h
index 4ba04bc..181786c 100644
--- a/Src/DasherCore/Alphabet/AlphabetMap.h
+++ b/Src/DasherCore/Alphabet/AlphabetMap.h
@@ -72,6 +72,8 @@ namespace Dasher {
///
/// IAM 08/2002
+#include "../Messages.h"
+
class Dasher::CAlphabetMap {
public:
@@ -83,7 +85,8 @@ public:
class SymbolStream {
public:
- SymbolStream(std::istream &_in);
+ ///pMsgs used for reporting errors in utf8 encoding
+ SymbolStream(std::istream &_in, CMessageDisplay *pMsgs=NULL);
///Gets the next symbol in the stream, using the specified AlphabetMap
/// to convert unicode characters to symbols.
/// \return 0 for unknown symbol (not in map); -1 for EOF; else symbol#.
@@ -116,6 +119,7 @@ public:
char buf[1024];
off_t pos, len;
std::istream ∈
+ CMessageDisplay * const m_pMsgs;
};
// Fills Symbols with the symbols corresponding to Input. {{{ Note that this
diff --git a/Src/DasherCore/AlphabetManager.cpp b/Src/DasherCore/AlphabetManager.cpp
index 05c73da..9bc7f32 100644
--- a/Src/DasherCore/AlphabetManager.cpp
+++ b/Src/DasherCore/AlphabetManager.cpp
@@ -88,7 +88,7 @@ void CAlphabetManager::CreateLanguageModel(CEventHandler *pEventHandler, CSettin
}
CTrainer *CAlphabetManager::GetTrainer() {
- return new CTrainer(m_pLanguageModel, m_pAlphabet, m_pAlphabetMap);
+ return new CTrainer(m_pInterface, m_pLanguageModel, m_pAlphabet, m_pAlphabetMap);
}
void CAlphabetManager::MakeLabels(CDasherScreen *pScreen) {
diff --git a/Src/DasherCore/AlphabetManager.h b/Src/DasherCore/AlphabetManager.h
index 01fbf12..be98812 100644
--- a/Src/DasherCore/AlphabetManager.h
+++ b/Src/DasherCore/AlphabetManager.h
@@ -232,6 +232,8 @@ namespace Dasher {
/// scheme for symbols not specifying a colour, and (b) implements
/// colour-cycling by phase (two cycles, using the LSBit of offset)
virtual int GetColour(symbol sym, int iOffset) const;
+
+ CDasherInterfaceBase * const m_pInterface;
CLanguageModel *m_pLanguageModel;
@@ -255,8 +257,6 @@ namespace Dasher {
/// and graft itself in in place of a new node, when appropriate.
void IterateChildGroups(CAlphNode *pParent, const SGroupInfo *pParentGroup, CAlphBase *buildAround);
- CDasherInterfaceBase *m_pInterface;
-
///Last node (owned by this manager) that was output; if a node
/// is Undo()ne, this is set to its parent. This is used to detect
/// context switches.
diff --git a/Src/DasherCore/AutoSpeedControl.cpp b/Src/DasherCore/AutoSpeedControl.cpp
index a8dfe8a..10a8be3 100644
--- a/Src/DasherCore/AutoSpeedControl.cpp
+++ b/Src/DasherCore/AutoSpeedControl.cpp
@@ -8,8 +8,8 @@
#include <cmath>
#include <cfloat>
-#include <iostream>
-#include <sstream>
+
+#include <string.h>
#ifndef WITH_DARWIN
double round(double dVal) {
@@ -24,7 +24,6 @@ double round(double dVal) {
#endif
using namespace Dasher;
-using std::ostringstream;
CAutoSpeedControl::CAutoSpeedControl(CMessageDisplay *pMsgs, Dasher::CEventHandler * pEventHandler, CSettingsStore * pSettingsStore)
: CDasherComponent(pEventHandler, pSettingsStore), m_pMsgs(pMsgs) {
@@ -210,10 +209,12 @@ void CAutoSpeedControl::SpeedControl(myint iDasherX, myint iDasherY, CDasherView
UpdateBitrate();
long lBitrateTimes100 = long(round(m_dBitrate * 100)); //Dasher settings want long numerical parameters
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());
+ const char *msg((lBitrateTimes100 > GetLongParameter(LP_MAX_BITRATE)) ?
+ _("Auto-increasing speed to %0.2f") : _("Auto-decreasing speed to %0.2f"));
+ char *buf(new char[strlen(msg) + 5]);
+ sprintf(buf, msg, (lBitrateTimes100/100.0));
+ m_pMsgs->Message(buf,false);
+ delete buf;
SetLongParameter(LP_MAX_BITRATE, lBitrateTimes100);
}
m_nSpeedCounter = 0;
diff --git a/Src/DasherCore/ColourIO.cpp b/Src/DasherCore/ColourIO.cpp
index 1b68df1..5df2232 100644
--- a/Src/DasherCore/ColourIO.cpp
+++ b/Src/DasherCore/ColourIO.cpp
@@ -23,22 +23,22 @@ static char THIS_FILE[] = __FILE__;
// TODO: Share information with AlphIO class?
-CColourIO::CColourIO(const std::string &SystemLocation, const std::string &UserLocation, std::vector<std::string> &Filenames)
+CColourIO::CColourIO(CMessageDisplay *pMsgs, const string &SystemLocation, const string &UserLocation, const vector<string> &Filenames)
:BlankInfo(), LoadMutable(false), CData("") {
CreateDefault();
LoadMutable = false;
- ParseFile(SystemLocation + "colour.xml");
+ ParseFile(pMsgs, SystemLocation + "colour.xml");
if(Filenames.size() > 0) {
for(unsigned int i = 0; i < Filenames.size(); i++) {
- ParseFile(SystemLocation + Filenames[i]);
+ ParseFile(pMsgs, SystemLocation + Filenames[i]);
}
}
LoadMutable = true;
- ParseFile(UserLocation + "colour.xml");
+ ParseFile(pMsgs, UserLocation + "colour.xml");
if(Filenames.size() > 0) {
for(unsigned int i = 0; i < Filenames.size(); i++) {
- ParseFile(UserLocation + Filenames[i]);
+ ParseFile(pMsgs, UserLocation + Filenames[i]);
}
}
}
diff --git a/Src/DasherCore/ColourIO.h b/Src/DasherCore/ColourIO.h
index 1d03e58..e707a4d 100644
--- a/Src/DasherCore/ColourIO.h
+++ b/Src/DasherCore/ColourIO.h
@@ -39,7 +39,7 @@ public:
std::vector < int >Blues;
};
- CColourIO(const std::string &SystemLocation, const std::string &UserLocation, std::vector < std::string > &Filenames);
+ CColourIO(CMessageDisplay *pMsgs, const std::string &SystemLocation, const std::string &UserLocation, const std::vector < std::string > &Filenames);
void GetColours(std::vector < std::string > *ColourList) const;
const ColourInfo & GetInfo(const std::string & ColourID);
private:
diff --git a/Src/DasherCore/ControlManager.cpp b/Src/DasherCore/ControlManager.cpp
index 7fd77b1..3ac66f4 100644
--- a/Src/DasherCore/ControlManager.cpp
+++ b/Src/DasherCore/ControlManager.cpp
@@ -158,7 +158,7 @@ public:
vector<CControlBase::Action*> actions;
};
-bool CControlParser::LoadFile(const string &strFileName) {
+bool CControlParser::LoadFile(CMessageDisplay *pMsgs, const string &strFileName) {
///Template used for all node defns read in from XML - just
/// execute a list of Actions.
@@ -237,7 +237,7 @@ bool CControlParser::LoadFile(const string &strFileName) {
};
ParseHandler p(this);
- if (!p.ParseFile(strFileName)) return false;
+ if (!p.ParseFile(pMsgs, strFileName)) return false;
p.resolveRefs();
return true;
}
@@ -257,8 +257,8 @@ CControlManager::CControlManager(CEventHandler *pEventHandler, CSettingsStore *p
m_pStop->successors.push_back(GetRootTemplate());
//TODO, have a parameter to try first, and if that fails:
- if(!LoadFile(m_pNCManager->GetStringParameter(SP_USER_LOC) + "control.xml")) {
- LoadFile(m_pNCManager->GetStringParameter(SP_SYSTEM_LOC)+"control.xml");
+ if(!LoadFile(m_pInterface, m_pNCManager->GetStringParameter(SP_USER_LOC) + "control.xml")) {
+ LoadFile(m_pInterface, m_pNCManager->GetStringParameter(SP_SYSTEM_LOC)+"control.xml");
//if that fails, we'll have no editing functions. Fine -
// doesn't seem vital enough to hardcode a fallback as well!
}
diff --git a/Src/DasherCore/ControlManager.h b/Src/DasherCore/ControlManager.h
index 3cf0676..793784e 100644
--- a/Src/DasherCore/ControlManager.h
+++ b/Src/DasherCore/ControlManager.h
@@ -146,9 +146,10 @@ namespace Dasher {
///Loads all node definitions from the specified filename, adding them to
/// any loaded from previous calls. (However, files processed independently:
/// e.g. names defined in one file will not be seen from another)
+ /// \param pMsgs Used to report errors via Message(,true) (i.e. modal)
/// \param strFilename name+full-path of xml file to load
/// \return true if the file was opened successfully; false if not.
- bool LoadFile(const std::string &strFilename);
+ bool LoadFile(CMessageDisplay *pMsgs, const std::string &strFilename);
/// \return all node definitions that have been loaded by this CControlParser.
const vector<CControlBase::NodeTemplate*> &parsedNodes();
///Subclasses may override to parse other nodes (besides "node", "ref" and "alph").
diff --git a/Src/DasherCore/ConversionManager.cpp b/Src/DasherCore/ConversionManager.cpp
index b3b7f37..4e66155 100644
--- a/Src/DasherCore/ConversionManager.cpp
+++ b/Src/DasherCore/ConversionManager.cpp
@@ -126,14 +126,14 @@ CConversionManager::CConvNode::~CConvNode() {
m_pMgr->Unref();
}
-void CConversionManager::RecursiveDumpTree(SCENode *pCurrent, unsigned int iDepth) {
+void CConversionManager::RecursiveDumpTree(ostream &out, SCENode *pCurrent, unsigned int iDepth) {
const std::vector<SCENode *> &children = pCurrent->GetChildren();
for (std::vector<SCENode *>::const_iterator it = children.begin(); it!=children.end(); it++) {
SCENode *pCurrent(*it);
for(unsigned int i(0); i < iDepth; ++i)
- std::cout << "-";
- std::cout << " " << pCurrent->pszConversion << std::endl;//" " << pCurrent->IsHeadAndCandNum << " " << pCurrent->CandIndex << " " << pCurrent->IsComplete << " " << pCurrent->AcCharCount << std::endl;
- RecursiveDumpTree(pCurrent, iDepth + 1);
+ out << "-";
+ out << " " << pCurrent->pszConversion << std::endl;//" " << pCurrent->IsHeadAndCandNum << " " << pCurrent->CandIndex << " " << pCurrent->IsComplete << " " << pCurrent->AcCharCount << std::endl;
+ RecursiveDumpTree(out, pCurrent, iDepth + 1);
}
}
diff --git a/Src/DasherCore/ConversionManager.h b/Src/DasherCore/ConversionManager.h
index 7964765..0d910ec 100644
--- a/Src/DasherCore/ConversionManager.h
+++ b/Src/DasherCore/ConversionManager.h
@@ -152,10 +152,10 @@ namespace Dasher {
CDasherScreen *m_pScreen;
///
- /// Dump tree to stdout (debug)
+ /// Dump tree to provided stream (debug)
///
- void RecursiveDumpTree(SCENode *pCurrent, unsigned int iDepth);
+ void RecursiveDumpTree(std::ostream &out, SCENode *pCurrent, unsigned int iDepth);
///
/// Reference count
diff --git a/Src/DasherCore/DashIntfScreenMsgs.cpp b/Src/DasherCore/DashIntfScreenMsgs.cpp
index 1f05f43..ae7fa84 100644
--- a/Src/DasherCore/DashIntfScreenMsgs.cpp
+++ b/Src/DasherCore/DashIntfScreenMsgs.cpp
@@ -2,34 +2,63 @@
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));
+void CDashIntfScreenMsgs::Message(const string &strText, bool bInterrupt) {
+ //Just store the messages for Redraw...
+ CDasherScreen::Label *lab = m_DasherScreen->MakeLabel(strText,GetLongParameter(LP_MESSAGE_FONTSIZE));
+ if (bInterrupt) {
+ m_dqModalMessages.push_back(pair<CDasherScreen::Label*,bool>(lab,false));
+ SetBoolParameter(BP_DASHER_PAUSED, true);
+ }
+ else
+ m_dqAsyncMessages.push_back(pair<CDasherScreen::Label*,unsigned long>(lab, 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
+ //Finally any messages - newest that will fit at bottom, proceeding upwards.
+ // Firstly clear any non-modal messages that have been onscreen for long enough
+ while (!m_dqAsyncMessages.empty() && m_dqAsyncMessages.front().second && ulTime-m_dqAsyncMessages.front().second>GetLongParameter(LP_MESSAGE_TIME)) {
+ delete m_dqAsyncMessages.front().first; //the Label
+ m_dqAsyncMessages.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));
+ if (!m_dqAsyncMessages.empty() || !m_dqModalMessages.empty()) {
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;
+ //still messages to display...first find out longest-ago N that will fit
+ for (deque<pair<CDasherScreen::Label*, unsigned long> >::iterator it = m_dqAsyncMessages.begin(); it!=m_dqAsyncMessages.end() && iY>iMinY; it++) {
+ if (it->second==0) {
+ //reached a not-yet-displayed asynchronous message
+ if (!m_dqModalMessages.empty()) break; //don't start displaying anything while there are modal msgs
+ it->second = ulTime; //display message for first time
+ bMsgsChanged=true;
+ }
+ iY-=m_DasherScreen->TextSize(it->first, GetLongParameter(LP_MESSAGE_FONTSIZE)).second;
+ }
+ if (!m_dqModalMessages.empty()) {
+ bool bDisp(m_dqModalMessages.front().second != 0); //displaying anything atm?
+ for (deque<pair<CDasherScreen::Label*,unsigned long> >::iterator it=m_dqModalMessages.begin(); it!=m_dqModalMessages.end() && iY>iMinY; it++) {
+ if (bDisp) {
+ if (it->second==0) break; //don't start displaying more until previous dismissed
+ } else {
+ DASHER_ASSERT(it->second==0);
+ it->second = ulTime;
+ bMsgsChanged = true;
+ }
+ iY-=m_DasherScreen->TextSize(it->first, GetLongParameter(LP_MESSAGE_FONTSIZE)).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);
+ //Now render messages proceeding downwards - non-modal first, then oldest first
+ bool bModal(false);
+ for (deque<pair<CDasherScreen::Label*, unsigned long> >::iterator it = m_dqAsyncMessages.begin(); ; it++) {
+ if (it==m_dqAsyncMessages.end()) {it=m_dqModalMessages.begin(); bModal=true;}
+ if (it==m_dqModalMessages.end()) break;
+ if (it->second==0) continue;
+ pair<screenint,screenint> textDims = m_DasherScreen->TextSize(it->first, GetLongParameter(LP_MESSAGE_FONTSIZE));
//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);
+ //white (0) text for non-modal, yellow (111) for modal
+ m_DasherScreen->DrawString(it->first, (iSW-textDims.first)/2, iY, GetLongParameter(LP_MESSAGE_FONTSIZE), bModal ? 111 : 0);
iY+=textDims.second;
}
}
@@ -38,9 +67,25 @@ bool CDashIntfScreenMsgs::FinishRender(unsigned long ulTime) {
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++) {
+ for (deque<pair<CDasherScreen::Label*,unsigned long> >::iterator it=m_dqAsyncMessages.begin(); ; it++) {
+ if (it==m_dqAsyncMessages.end()) it = m_dqModalMessages.begin();
+ if (it==m_dqModalMessages.end()) break;
const CDasherScreen::Label *pOldLabel(it->first);
it->first = pNewScreen->MakeLabel(pOldLabel->m_strText, pOldLabel->m_iWrapSize);
delete pOldLabel;
}
}
+
+void CDashIntfScreenMsgs::Unpause(unsigned long lTime) {
+ if (!GetBoolParameter(BP_DASHER_PAUSED)) return;
+ while (!m_dqModalMessages.empty()) {
+ if (m_dqModalMessages.front().second) {
+ //Message has been displayed; delete it
+ delete m_dqModalMessages.front().first; //the label
+ m_dqModalMessages.pop_front();
+ } else return; //there are more, not-yet displayed, modal messages!
+ //These should be after any that were displayed (which have now been erased), so:
+ // do not unpause; next frame will render more messages instead.
+ }
+ CDasherInterfaceBase::Unpause(lTime);
+}
diff --git a/Src/DasherCore/DashIntfScreenMsgs.h b/Src/DasherCore/DashIntfScreenMsgs.h
index 48bde43..6881a39 100644
--- a/Src/DasherCore/DashIntfScreenMsgs.h
+++ b/Src/DasherCore/DashIntfScreenMsgs.h
@@ -27,8 +27,16 @@
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);
+ /// Stores messages for Redraw to render onto the Screen on top of the view.
+ /// For modal messages (bInterrupt=true), pauses Dasher, and keeps the message
+ /// onscreen until the user starts moving again (via normal mechanisms);
+ /// For non-modal or asynchronous messages (bInterrupt=false), we render
+ /// the message over the canvas for LP_MESSAGE_TIME milliseconds without pausing.
+ /// (This method merely stores the messages into m_dqAsyncMessages or m_dqModalMessages
+ /// as appropriate; display, timeout, etc. is handled in Redraw.)
+ /// \param strText text of message to display.
+ /// \param bInterrupt whether to interrupt any text entry in progress.
+ virtual void Message(const std::string &strText, bool bInterrupt);
/// Override to render (on top of nodes+decorations) any messages, for
/// LP_MESSAGE_TIME ms, before removing from queue.
@@ -36,13 +44,19 @@ public:
///Override to re-MakeLabel any messages.
void ChangeScreen(CDasherScreen *pNewScreen);
-
+
+ ///Override to clear any modal messages currently being displayed before resuming.
+ void Unpause(unsigned long lTime);
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;
+ /// Asynchronous (non-modal) 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 - 0 if not yet displayed.
+ std::deque<pair<CDasherScreen::Label*, unsigned long> > m_dqAsyncMessages;
+ /// Modal messages being or waiting to be displayed to the user, longest-ago
+ /// at the front, along with the timestamp when each was first displayed to the
+ /// user (0 if not yet displayed).
+ std::deque<pair<CDasherScreen::Label*, unsigned long> > m_dqModalMessages;
};
}
diff --git a/Src/DasherCore/DasherInterfaceBase.cpp b/Src/DasherCore/DasherInterfaceBase.cpp
index 557abc5..f8de7ca 100644
--- a/Src/DasherCore/DasherInterfaceBase.cpp
+++ b/Src/DasherCore/DasherInterfaceBase.cpp
@@ -137,11 +137,11 @@ void CDasherInterfaceBase::Realize() {
std::vector<std::string> vAlphabetFiles;
ScanAlphabetFiles(vAlphabetFiles);
- m_AlphIO = new CAlphIO(GetStringParameter(SP_SYSTEM_LOC), GetStringParameter(SP_USER_LOC), vAlphabetFiles);
+ m_AlphIO = new CAlphIO(this, GetStringParameter(SP_SYSTEM_LOC), GetStringParameter(SP_USER_LOC), vAlphabetFiles);
std::vector<std::string> vColourFiles;
ScanColourFiles(vColourFiles);
- m_ColourIO = new CColourIO(GetStringParameter(SP_SYSTEM_LOC), GetStringParameter(SP_USER_LOC), vColourFiles);
+ m_ColourIO = new CColourIO(this, GetStringParameter(SP_SYSTEM_LOC), GetStringParameter(SP_USER_LOC), vColourFiles);
ChangeColours();
@@ -483,6 +483,7 @@ void CDasherInterfaceBase::GameMessageIn(int message, void* messagedata) {
void CDasherInterfaceBase::Unpause(unsigned long Time) {
if (!GetBoolParameter(BP_DASHER_PAUSED)) return; //already running, no need to do anything
+
SetBoolParameter(BP_DASHER_PAUSED, false);
if(m_pDasherModel != 0)
@@ -618,6 +619,7 @@ bool CDasherInterfaceBase::Redraw(unsigned long ulTime, bool bRedrawNodes, CExpa
#endif
return bRedrawNodes;
+
}
void CDasherInterfaceBase::ChangeAlphabet() {
diff --git a/Src/DasherCore/DasherInterfaceBase.h b/Src/DasherCore/DasherInterfaceBase.h
index e9d7f03..9fb3df1 100644
--- a/Src/DasherCore/DasherInterfaceBase.h
+++ b/Src/DasherCore/DasherInterfaceBase.h
@@ -270,7 +270,7 @@ public:
/// Unpause Dasher. Clears BP_DASHER_PAUSED.
/// (But does nothing if BP_DASHER_PAUSED is currently set).
/// \param Time Time in ms, used to keep a constant frame rate
- void Unpause(unsigned long Time);
+ virtual void Unpause(unsigned long Time);
///Whether any actions are currently setup to occur when Dasher 'stop's.
/// Default is to return TRUE iff we support speech and BP_SPEAK_ON_STOP is set,
diff --git a/Src/DasherCore/MandarinAlphMgr.cpp b/Src/DasherCore/MandarinAlphMgr.cpp
index e053bbf..ade9e6a 100644
--- a/Src/DasherCore/MandarinAlphMgr.cpp
+++ b/Src/DasherCore/MandarinAlphMgr.cpp
@@ -128,7 +128,7 @@ CMandarinAlphMgr::~CMandarinAlphMgr() {
void CMandarinAlphMgr::CreateLanguageModel(CEventHandler *pEventHandler, CSettingsStore *pSettingsStore) {
//std::cout<<"CHALphabet size "<< pCHAlphabet->GetNumberTextSymbols(); [7603]
- std::cout<<"Setting PPMPY model"<<std::endl;
+ //std::cout<<"Setting PPMPY model"<<std::endl;
m_pLanguageModel = new CPPMPYLanguageModel(pEventHandler, pSettingsStore, m_CHtext.size()-1, m_pAlphabet->GetNumberTextSymbols());
}
@@ -136,7 +136,7 @@ CTrainer *CMandarinAlphMgr::GetTrainer() {
//We pass in the pinyin alphabet to define the context-switch escape character, and the default context.
// Although the default context will be symbolified via the _chinese_ alphabet, this seems reasonable
// as it is the Pinyin alphabet which defines the conversion mapping (i.e. m_strConversionTarget!)
- return new CMandarinTrainer(static_cast<CPPMPYLanguageModel*>(m_pLanguageModel), m_pAlphabet, m_pAlphabetMap, &m_CHAlphabetMap, m_pAlphabet->m_strConversionTrainingDelimiter);
+ return new CMandarinTrainer(m_pInterface, static_cast<CPPMPYLanguageModel*>(m_pLanguageModel), m_pAlphabet, m_pAlphabetMap, &m_CHAlphabetMap, m_pAlphabet->m_strConversionTrainingDelimiter);
}
CAlphabetManager::CAlphNode *CMandarinAlphMgr::GetRoot(CDasherNode *pParent, unsigned int iLower, unsigned int iUpper, bool bEnteredLast, int iOffset) {
diff --git a/Src/DasherCore/Messages.h b/Src/DasherCore/Messages.h
index bef3b69..035fd9a 100644
--- a/Src/DasherCore/Messages.h
+++ b/Src/DasherCore/Messages.h
@@ -32,10 +32,17 @@
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;
+ ///Displays a message to the user - somehow. Two styles
+ /// of message are supported: (1) modal messages, i.e. which interrupt text entry;
+ /// these should be explicitly dismissed (somehow) before text entry resumes; and
+ /// (2) non-modal or asynchronous messages, which should be displayed in the background
+ /// but allow the user to continue text entry as normal.
+ /// NOTE for subclasses: it is best not to popup any modal window here but rather to
+ /// store all messages until the next frame is rendered and then combine them into one.
+ /// \param strText text of message to display.
+ /// \param bInterrupt if true, text entry should be interrupted; if false, user should
+ /// be able to continue writing uninterrupted.
+ virtual void Message(const std::string &strText, bool bInterrupt)=0;
};
/// @}
diff --git a/Src/DasherCore/NodeCreationManager.cpp b/Src/DasherCore/NodeCreationManager.cpp
index d0b50f5..adf227e 100644
--- a/Src/DasherCore/NodeCreationManager.cpp
+++ b/Src/DasherCore/NodeCreationManager.cpp
@@ -6,6 +6,8 @@
#include "ControlManager.h"
#include "EventHandler.h"
+#include <string.h>
+
using namespace Dasher;
class ProgressNotifier : public CTrainer::ProgressIndicator {
@@ -18,11 +20,13 @@ public:
m_pInterface->SetLockStatus(m_strDisplay, m_iPercent = iNewPercent);
}
}
- void run(const string &strDisplay, string strFile) {
+ bool run(const string &strDisplay, string strFile) {
m_pInterface->SetLockStatus(m_strDisplay=strDisplay, m_iPercent=0);
m_iStart = 0;
m_iStop = m_pInterface->GetFileSize(strFile);
- m_pTrainer->LoadFile(strFile,this);
+ if (m_iStop==0) return false;
+ m_pTrainer->LoadFile(strFile,this); //Hmmm. Error-reporting is only via Message()...?
+ return true;
}
private:
CDasherInterfaceBase *m_pInterface;
@@ -80,17 +84,28 @@ CNodeCreationManager::CNodeCreationManager(Dasher::CDasherInterfaceBase *pInterf
if (!pAlphInfo->GetTrainingFile().empty()) {
ProgressNotifier pn(pInterface, m_pTrainer);
-
//1. Look for system training text...
- pn.run("Training on System Text", GetStringParameter(SP_SYSTEM_LOC) + pAlphInfo->GetTrainingFile());
+ bool bFound=pn.run(_("Training on System Text"), GetStringParameter(SP_SYSTEM_LOC) + pAlphInfo->GetTrainingFile());
//2. Now add in any user-provided individual training text...
- pn.run("Training on User Text", GetStringParameter(SP_USER_LOC) + pAlphInfo->GetTrainingFile());
+ if (!pn.run(_("Training on User Text"), GetStringParameter(SP_USER_LOC) + pAlphInfo->GetTrainingFile())) {
+ ///TRANSLATORS: These 3 messages will be displayed when the user has just chosen a new alphabet. The %s parameter will be the name of the alphabet.
+ const char *msg = bFound ? _("No user training text found - if you have written in \"%s\" before, this means Dasher may not be learning from previous sessions")
+ : _("No training text (user or system) found for \"%s\". Dasher will still work but entry will be slower. We suggest downloading a training text file from the Dasher website, or constructing your own.");
+ char *buf(new char[strlen(msg)+pAlphInfo->GetID().length()]);
+ sprintf(buf,msg,pAlphInfo->GetID().c_str());
+ pInterface->Message(buf, true);
+ delete buf;
+ }
//3. Finished, so unlock.
m_pInterface->SetLockStatus("", -1);
}
#ifdef DEBUG
else {
- std::cout << "Alphabet does not specify training file" << std::endl;
+ const char *msg = _("\"%s\" does not specify training file. Dasher will work but entry will be slower. Check you have the latest version of the alphabet definition.");
+ char *buf(new char[strlen(msg) + pAlphInfo->GetID().length()]);
+ sprintf(buf, msg, pAlphInfo->GetID().c_str());
+ pInterface->Message(buf, true);
+ delete buf;
}
#endif
#ifdef DEBUG_LM_READWRITE
diff --git a/Src/DasherCore/SocketInput.cpp b/Src/DasherCore/SocketInput.cpp
index db20dde..3ecee0a 100644
--- a/Src/DasherCore/SocketInput.cpp
+++ b/Src/DasherCore/SocketInput.cpp
@@ -16,8 +16,8 @@
using namespace Dasher;
-CSocketInput::CSocketInput(CEventHandler *pEventHandler, CSettingsStore *pSettingsStore)
-:CSocketInputBase(pEventHandler, pSettingsStore) {
+CSocketInput::CSocketInput(CMessageDisplay *pMsgs, CEventHandler *pEventHandler, CSettingsStore *pSettingsStore)
+:CSocketInputBase(pMsgs, pEventHandler, pSettingsStore) {
}
CSocketInput::~CSocketInput() {
diff --git a/Src/DasherCore/SocketInput.h b/Src/DasherCore/SocketInput.h
index f6c2a7a..9adf5b0 100644
--- a/Src/DasherCore/SocketInput.h
+++ b/Src/DasherCore/SocketInput.h
@@ -45,7 +45,7 @@ class CSocketInput:public CSocketInputBase {
public:
- CSocketInput(CEventHandler * pEventHandler, CSettingsStore * pSettingsStore);
+ CSocketInput(CMessageDisplay *pMsgs, CEventHandler * pEventHandler, CSettingsStore * pSettingsStore);
~CSocketInput();
private:
diff --git a/Src/DasherCore/SocketInputBase.cpp b/Src/DasherCore/SocketInputBase.cpp
index e54f619..d4ff09c 100644
--- a/Src/DasherCore/SocketInputBase.cpp
+++ b/Src/DasherCore/SocketInputBase.cpp
@@ -6,7 +6,7 @@
#include "SocketInputBase.h"
-#include "../DasherCore/Event.h"
+#include "DasherInterfaceBase.h"
#include <string.h>
#include <errno.h>
@@ -34,8 +34,8 @@ static SModuleSettings sSettings[] = {
{BP_SOCKET_DEBUG, T_BOOL, -1, -1, -1, -1, _("Print socket-related debugging information to console:")}
};
-Dasher::CSocketInputBase::CSocketInputBase(CEventHandler * pEventHandler, CSettingsStore * pSettingsStore)
- : CScreenCoordInput(pEventHandler, pSettingsStore, 1, _("Socket Input")) {
+Dasher::CSocketInputBase::CSocketInputBase(CMessageDisplay *pMsgs, CEventHandler * pEventHandler, CSettingsStore * pSettingsStore)
+ : CScreenCoordInput(pEventHandler, pSettingsStore, 1, _("Socket Input")), m_pMsgs(pMsgs) {
port = -1;
debug_socket_input = false;
readerRunning = false;
@@ -107,8 +107,8 @@ bool Dasher::CSocketInputBase::StartListening() {
SocketDebugMsg("Socket input: binding to socket and starting to listen.");
if((sock = socket(PF_INET, SOCK_DGRAM, 0)) == -1) {
- ReportErrnoError("Error creating socket"); //FIXME should use _( (gettext), but need something cross-platform.
- // Could have a member functino, overridden in the platform-specific subclasses, which returns the localised text
+ //TODO This is not a very good error message even in English...???
+ m_pMsgs->Message(_("Error creating socket"),true);
return false;
}
@@ -116,7 +116,7 @@ bool Dasher::CSocketInputBase::StartListening() {
name.sin_port = htons(port);
name.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(sock, (struct sockaddr *)&name, sizeof(name)) < 0) {
- ReportErrnoError("Error binding to socket - already in use?");
+ ReportErrnoError(_("Error binding to socket - already in use?"));
DASHER_SOCKET_CLOSE_FUNCTION(sock);
sock = -1;
return false;
@@ -169,7 +169,11 @@ void CSocketInputBase::SetReaderPort(int _port) {
void CSocketInputBase::SetCoordinateLabel( int iWhichCoordinate, const char *Label) {
DASHER_ASSERT(iWhichCoordinate < DASHER_SOCKET_INPUT_MAX_COORDINATE_COUNT);
if(strlen(Label) > DASHER_SOCKET_INPUT_MAX_COORDINATE_LABEL_LENGTH) {
- cerr << "Warning truncating socket input label '" << Label << "' to " << DASHER_SOCKET_INPUT_MAX_COORDINATE_LABEL_LENGTH << " characters." << endl;
+ const char *msg=_("Warning truncating socket input label '%s' to %i characters.");
+ char *buf(new char[strlen(msg)+strlen(Label)+DASHER_SOCKET_INPUT_MAX_COORDINATE_LABEL_LENGTH]);
+ sprintf(buf,msg,Label,DASHER_SOCKET_INPUT_MAX_COORDINATE_LABEL_LENGTH);
+ m_pMsgs->Message(buf, true);
+ delete buf;
}
strncpy(coordinateNames[iWhichCoordinate], Label, DASHER_SOCKET_INPUT_MAX_COORDINATE_LABEL_LENGTH);
SocketDebugMsg("Socket input: set coordinate %d label to '%s'.", iWhichCoordinate, coordinateNames[iWhichCoordinate]);
@@ -191,7 +195,7 @@ void CSocketInputBase::ReadForever() {
while(sock >= 0) {
SocketDebugMsg("Reading from socket...");
if((numbytes = recv(sock, buffer, sizeof(buffer) - 1, 0)) == -1) {
- ReportError("Socket input: Error reading from socket");
+ m_pMsgs->Message(_("Socket input: Error reading from socket"),false);
continue;
}
buffer[numbytes] = '\0';
@@ -239,10 +243,12 @@ void CSocketInputBase::ParseMessage(char *message) {
double actualMax = (rawMaxValues[i] > rawMinValues[i]) ? rawMaxValues[i] : rawMinValues[i];
double actualMin = (rawMaxValues[i] > rawMinValues[i]) ? rawMinValues[i] : rawMaxValues[i];
if(rawdouble < actualMin) {
+ //TODO: Should these be converted to calls to Message() ? On first occurrence only???
cerr << "Socket input: clipped " << coordinateNames[i] << " value of " << rawdouble << "to configured minimum of " << actualMin << endl;
rawdouble = actualMin;
}
if(rawdouble > actualMax) {
+ //TODO: Should these be converted to calls to Message() ? On first occurrence only???
cerr << "Socket input: clipped " << message << " value of " << rawdouble << "to configured maximum of " << actualMax << endl;
rawdouble = actualMax;
}
@@ -289,15 +295,14 @@ void CSocketInputBase::SetDebug(bool _debug) {
}
}
-void CSocketInputBase::ReportError(std::string s) {
- // override this to pop up a message box etc.
- cerr << s << endl;
-}
-
-void CSocketInputBase::ReportErrnoError(std::string prefix) {
- // override this to pop up a message box
- cerr << "Dasher Socket Input error: ";
- perror(prefix.c_str());
+void CSocketInputBase::ReportErrnoError(const std::string &prefix) {
+ int err = errno; errno=0;
+ const char *msg = _("Dasher Socket Input error: %s: %s");
+ char *e = strerror(err);
+ char *buf(new char[strlen(msg) + prefix.length() + strlen(e)]);
+ sprintf(buf,msg,prefix.c_str(),e);
+ m_pMsgs->Message(buf,true);
+ delete buf;
}
void CSocketInputBase::SocketDebugMsg(const char *pszFormat, ...) {
diff --git a/Src/DasherCore/SocketInputBase.h b/Src/DasherCore/SocketInputBase.h
index 80a023a..2da884f 100644
--- a/Src/DasherCore/SocketInputBase.h
+++ b/Src/DasherCore/SocketInputBase.h
@@ -10,6 +10,7 @@
#include "../DasherCore/DasherInput.h"
#include "../DasherCore/DasherComponent.h"
#include "../DasherCore/EventHandler.h"
+#include "Messages.h"
#include <iostream>
@@ -26,7 +27,7 @@ class CSocketInputBase : public CScreenCoordInput {
public:
- CSocketInputBase(CEventHandler * pEventHandler, CSettingsStore * pSettingsStore);
+ CSocketInputBase(CMessageDisplay *pMsgs, CEventHandler * pEventHandler, CSettingsStore * pSettingsStore);
virtual ~CSocketInputBase();
@@ -120,12 +121,12 @@ protected:
virtual void ParseMessage(char *message);
- virtual void ReportErrnoError(std::string prefix); // override as appropriate for each platform
-
- virtual void ReportError(std::string s); // override as appropriate for each platform
+ //Reports an error by appending an error message obtained from strerror(errno) onto the provided prefix
+ void ReportErrnoError(const std::string &prefix);
virtual void SocketDebugMsg(const char *pszFormat, ...);
+ CMessageDisplay *const m_pMsgs;
};
}
/// \}
diff --git a/Src/DasherCore/Trainer.cpp b/Src/DasherCore/Trainer.cpp
index c8c267d..1815c21 100644
--- a/Src/DasherCore/Trainer.cpp
+++ b/Src/DasherCore/Trainer.cpp
@@ -2,12 +2,14 @@
#include "../Common/Common.h"
#include "Trainer.h"
-#include "DasherInterfaceBase.h"
#include "LanguageModelling/PPMPYLanguageModel.h"
+#include <vector>
#include <cstring>
#include <sstream>
+#include <string>
using namespace Dasher;
+using namespace std;
// Track memory leaks on Windows to the line that new'd the memory
#ifdef _WIN32
@@ -19,16 +21,19 @@ static char THIS_FILE[] = __FILE__;
#endif
#endif
-CTrainer::CTrainer(CLanguageModel *pLanguageModel, const CAlphInfo *pInfo, const CAlphabetMap *pAlphabet)
- : m_pAlphabet(pAlphabet), m_pLanguageModel(pLanguageModel), m_pInfo(pInfo) {
+CTrainer::CTrainer(CMessageDisplay *pMsgs, CLanguageModel *pLanguageModel, const CAlphInfo *pInfo, const CAlphabetMap *pAlphabet)
+ : m_pMsgs(pMsgs), m_pAlphabet(pAlphabet), m_pLanguageModel(pLanguageModel), m_pInfo(pInfo) {
vector<symbol> syms;
pAlphabet->GetSymbols(syms,pInfo->GetContextEscapeChar());
if (syms.size()==1)
m_iCtxEsc = syms[0];
else {
-#ifdef DEBUG
- std::cout << "Warning: escape sequence " << pInfo->GetContextEscapeChar() << " must be a single unicode character; no context-switch commands will be executed." << std::endl;
-#endif
+ //no context switch commands will be executed!
+ const char *msg(_("Warning: faulty alphabet definition, escape sequence %s must be a single unicode character. This may worsen Dasher's text prediction."));
+ char *buf(new char[strlen(msg) + pInfo->GetContextEscapeChar().length() +1]);
+ sprintf(buf,msg,pInfo->GetContextEscapeChar().c_str());
+ pMsgs->Message(string(buf),true);
+ delete buf;
m_iCtxEsc = -1;
}
}
@@ -80,7 +85,7 @@ bool CTrainer::readEscape(CLanguageModel::Context &sContext, CAlphabetMap::Symbo
class ProgressStream : public CAlphabetMap::SymbolStream {
public:
- ProgressStream(std::istream &_in, CTrainer::ProgressIndicator *pProg, off_t iStart=0) : SymbolStream(_in), m_iLastPos(iStart), m_pProg(pProg) {
+ ProgressStream(std::istream &_in, CTrainer::ProgressIndicator *pProg, CMessageDisplay *pMsgs, off_t iStart=0) : SymbolStream(_in,pMsgs), m_iLastPos(iStart), m_pProg(pProg) {
}
void bytesRead(off_t num) {
if (m_pProg) m_pProg->bytesRead(m_iLastPos += num);
@@ -110,14 +115,18 @@ Dasher::CTrainer::LoadFile(const std::string &strFileName, ProgressIndicator *pP
//Invoke AbstractXMLParser method
m_bInSegment = false;
m_iLastBytes=0;
- ParseFile(strFileName);
+ ParseFile(m_pMsgs, strFileName);
} else {
std::ifstream in(strFileName.c_str(), std::ios::binary);
if (in.fail()) {
- std::cerr << "Unable to open file \"" << strFileName << "\" for reading" << std::endl;
+ const char *msg=_("Unable to open file \"%f\" for reading");
+ char *buf(new char[strlen(msg) + strFileName.length()+1]);
+ sprintf(buf, msg, strFileName.c_str());
+ m_pMsgs->Message(buf, true);
+ delete buf;
return;
}
- ProgressStream syms(in,pProg);
+ ProgressStream syms(in,pProg,m_pMsgs);
Train(syms);
in.close();
@@ -134,7 +143,7 @@ void CTrainer::XmlStartHandler(const XML_Char *szName, const XML_Char **pAtts) {
void CTrainer::XmlEndHandler(const XML_Char *szName) {
if(!strcmp(szName, "segment")) {
std::istringstream in(m_strCurrentText);
- ProgressStream syms(in, m_pProg, m_iLastBytes);
+ ProgressStream syms(in, m_pProg, m_pMsgs, m_iLastBytes);
Train(syms);
m_iLastBytes = syms.m_iLastPos; //count that segment, ready for next
m_bInSegment = false;
@@ -146,8 +155,8 @@ void CTrainer::XmlCData(const XML_Char *szS, int iLen) {
m_strCurrentText += std::string(szS, iLen);
}
-CMandarinTrainer::CMandarinTrainer(CPPMPYLanguageModel *pLanguageModel, const CAlphInfo *pInfo, const CAlphabetMap *pPYAlphabet, const CAlphabetMap *pCHAlphabet, const std::string &strDelim)
-: CTrainer(pLanguageModel, pInfo, pCHAlphabet), m_pPYAlphabet(pPYAlphabet), m_strDelim(strDelim) {
+CMandarinTrainer::CMandarinTrainer(CMessageDisplay *pMsgs, CPPMPYLanguageModel *pLanguageModel, const CAlphInfo *pInfo, const CAlphabetMap *pPYAlphabet, const CAlphabetMap *pCHAlphabet, const std::string &strDelim)
+: CTrainer(pMsgs, pLanguageModel, pInfo, pCHAlphabet), m_pPYAlphabet(pPYAlphabet), m_strDelim(strDelim) {
}
void CMandarinTrainer::Train(CAlphabetMap::SymbolStream &syms) {
@@ -160,16 +169,24 @@ void CMandarinTrainer::Train(CAlphabetMap::SymbolStream &syms) {
if (s == m_strDelim) { //found delimiter, so process next two characters
symbol Sympy = syms.next(m_pPYAlphabet);
if (Sympy==-1) break; //EOF
-#ifdef DEBUG
- if (Sympy==0)
- std::cout << "Unknown pinyin character " << syms.peekBack() << std::endl;
-#endif
+ if (Sympy==0) {
+ const char *msg(_("Training file contains unknown source alphabet character %s"));
+ string prev = syms.peekBack();
+ char *buf(new char[strlen(msg) + prev.length()+1]);
+ sprintf(buf, msg, prev.c_str());
+ m_pMsgs->Message(buf,true);
+ delete buf;
+ }
symbol Symchar = syms.next(m_pAlphabet);
if (Symchar==-1) break; //EOF...ignore final Pinyin?
-#ifdef DEBUG
- if (Symchar==0)
- std::cout << "Unknown chinese character " << syms.peekBack() << std::endl;
-#endif
+ if (Symchar==0) {
+ const char *msg=_("Training file contains unknown target alphabet character %s");
+ string prev = syms.peekBack();
+ char *buf(new char[strlen(msg) + prev.length()+1]);
+ sprintf(buf,msg,prev.c_str());
+ m_pMsgs->Message(buf,true);
+ delete buf;
+ }
static_cast<CPPMPYLanguageModel *>(m_pLanguageModel)->LearnPYSymbol(trainContext, Sympy);
m_pLanguageModel->LearnSymbol(trainContext, Symchar);
numberofchar++;
diff --git a/Src/DasherCore/Trainer.h b/Src/DasherCore/Trainer.h
index ca201e7..340a207 100644
--- a/Src/DasherCore/Trainer.h
+++ b/Src/DasherCore/Trainer.h
@@ -6,12 +6,10 @@
#include "AbstractXMLParser.h"
namespace Dasher {
- class CDasherInterfaceBase;
-
class CTrainer : private AbstractXMLParser {
public:
- CTrainer(CLanguageModel *pLanguageModel, const CAlphInfo *pInfo, const CAlphabetMap *pAlphabet);
+ CTrainer(CMessageDisplay *pMsgs, CLanguageModel *pLanguageModel, const CAlphInfo *pInfo, const CAlphabetMap *pAlphabet);
class ProgressIndicator {
public:
@@ -34,10 +32,11 @@ namespace Dasher {
/// \return true if a context-switch command was found (=> sContext reinitialized);
/// false, if instead a double-escape-character (=encoding of that actual symbol) was read
bool readEscape(CLanguageModel::Context &sContext, CAlphabetMap::SymbolStream &syms);
-
- const CAlphabetMap *m_pAlphabet;
- CLanguageModel *m_pLanguageModel;
- const CAlphInfo *m_pInfo;
+
+ CMessageDisplay * const m_pMsgs;
+ const CAlphabetMap * const m_pAlphabet;
+ CLanguageModel * const m_pLanguageModel;
+ const CAlphInfo * const m_pInfo;
// symbol number in alphabet of the context-switch character (maybe 0 if not in alphabet!)
int m_iCtxEsc;
private:
@@ -63,7 +62,7 @@ namespace Dasher {
/// \param pPYAlphabet mapping from text to symbol# in PY alphabet
/// \param pCHAlphabet mapping from text to symbol# (rehashed by MandarinAlphMgr) in CHAlphabet
/// \param strDelim delimiter character (1 unicode, maybe >1 octet; if not, will never be matched)
- CMandarinTrainer(CPPMPYLanguageModel *pLanguageModel, const CAlphInfo *pInfo, const CAlphabetMap *pPYAlphabet, const CAlphabetMap *pCHAlphabet, const std::string &strDelim);
+ CMandarinTrainer(CMessageDisplay *pMsgs, CPPMPYLanguageModel *pLanguageModel, const CAlphInfo *pInfo, const CAlphabetMap *pPYAlphabet, const CAlphabetMap *pCHAlphabet, const std::string &strDelim);
protected:
//override...
diff --git a/Src/Gtk2/DasherControl.cpp b/Src/Gtk2/DasherControl.cpp
index a226681..f58eb6d 100644
--- a/Src/Gtk2/DasherControl.cpp
+++ b/Src/Gtk2/DasherControl.cpp
@@ -95,7 +95,7 @@ void CDasherControl::CreateModules() {
SetDefaultInputDevice(m_pMouseInput);
m_p1DMouseInput =
(CDasher1DMouseInput *)RegisterModule(new CDasher1DMouseInput(m_pEventHandler, m_pSettingsStore));
- RegisterModule(new CSocketInput(m_pEventHandler, m_pSettingsStore));
+ RegisterModule(new CSocketInput(this, m_pEventHandler, m_pSettingsStore));
#ifdef JOYSTICK
RegisterModule(new CDasherJoystickInput(m_pEventHandler, m_pSettingsStore, this));
diff --git a/Src/Win32/Dasher.cpp b/Src/Win32/Dasher.cpp
index 2f8c72b..180b18a 100644
--- a/Src/Win32/Dasher.cpp
+++ b/Src/Win32/Dasher.cpp
@@ -57,7 +57,7 @@ void CDasher::CreateModules() {
//create default set first.
CDasherInterfaceBase::CreateModules();
#ifndef _WIN32_WCE
- RegisterModule(new CSocketInput(m_pEventHandler, m_pSettingsStore));
+ RegisterModule(new CSocketInput(this, m_pEventHandler, m_pSettingsStore));
RegisterModule(new CBTSocketInput(m_pEventHandler, m_pSettingsStore));
#endif
RegisterModule(new CDasherMouseInput(m_pEventHandler, m_pSettingsStore, m_pCanvas->getwindow()));
diff --git a/Src/Win32/Sockets/SocketInput.cpp b/Src/Win32/Sockets/SocketInput.cpp
index 40a7f86..7ef733f 100644
--- a/Src/Win32/Sockets/SocketInput.cpp
+++ b/Src/Win32/Sockets/SocketInput.cpp
@@ -52,9 +52,9 @@ static char THIS_FILE[] = __FILE__;
-CSocketInput::CSocketInput(CEventHandler * pEventHandler, CSettingsStore * pSettingsStore)
+CSocketInput::CSocketInput(CMessageDisplay *pMsgs, CEventHandler * pEventHandler, CSettingsStore * pSettingsStore)
-:CSocketInputBase(pEventHandler, pSettingsStore) {
+:CSocketInputBase(pMsgs, pEventHandler, pSettingsStore) {
diff --git a/Src/Win32/Sockets/SocketInput.h b/Src/Win32/Sockets/SocketInput.h
index 628028d..923bb6b 100644
--- a/Src/Win32/Sockets/SocketInput.h
+++ b/Src/Win32/Sockets/SocketInput.h
@@ -15,7 +15,7 @@ class Dasher::CSocketInput:public CSocketInputBase {
public:
- CSocketInput(CEventHandler * pEventHandler, CSettingsStore * pSettingsStore);
+ CSocketInput(CMessageDisplay *pMsgs, CEventHandler * pEventHandler, CSettingsStore * pSettingsStore);
~CSocketInput();
void SetDebug(bool _debug);
diff --git a/Src/iPhone/Classes/CDasherInterfaceBridge.h b/Src/iPhone/Classes/CDasherInterfaceBridge.h
index f16e4e4..ec04329 100644
--- a/Src/iPhone/Classes/CDasherInterfaceBridge.h
+++ b/Src/iPhone/Classes/CDasherInterfaceBridge.h
@@ -6,7 +6,7 @@
*
*/
-#import "../DasherCore/DasherInterfaceBase.h"
+#import "../DasherCore/DashIntfScreenMsgs.h"
#import "IPhoneInputs.h"
#import "IPhoneFilters.h"
#import "DefaultFilter.h"
@@ -21,8 +21,12 @@
/// Class representing the Dasher UI component (ie the canvas and speed slider).
/// Implements the necessary abstract methods by bridging them into Objective C
/// and sending messages onto the DasherAppDelegate.
-
-class CDasherInterfaceBridge : public Dasher::CDasherInterfaceBase {
+///
+/// We inherit from CDashIntfScreenMsgs but use it for displaying modal messages
+/// only (over the canvas). TODO: we could possibly do better by displaying a modal
+/// View, however we would need some way for users not capable of touching the screen
+/// (who might be using Dasher via tilt control & start-on-circle) to clear the display!
+class CDasherInterfaceBridge : public Dasher::CDashIntfScreenMsgs {
public:
@@ -59,7 +63,8 @@ public:
void editDelete(const string &strText, CDasherNode *pNode);
void editConvert(CDasherNode *pNode);
void editProtect(CDasherNode *pNode);
- void Message(const string &strText);
+ ///Override for asynchronous messages only...TODO?
+ void Message(const string &strText, bool bInterrupt);
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 c927a05..b9af70a 100644
--- a/Src/iPhone/Classes/CDasherInterfaceBridge.mm
+++ b/Src/iPhone/Classes/CDasherInterfaceBridge.mm
@@ -189,8 +189,11 @@ void CDasherInterfaceBridge::editProtect(CDasherNode *pSource) {
CDasherInterfaceBase::editProtect(pSource);
}
-void CDasherInterfaceBridge::Message(const string &strMessage) {
- [dasherApp displayMessage:NSStringFromStdString(strMessage)];
+void CDasherInterfaceBridge::Message(const string &strMessage, bool bInterrupt) {
+ if (bInterrupt)
+ CDashIntfScreenMsgs::Message(strMessage,true);
+ else
+ [dasherApp displayMessage:NSStringFromStdString(strMessage)];
}
void CDasherInterfaceBridge::SetLockStatus(const string &strText, int iPercent) {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]