summaryrefslogtreecommitdiff
Side-by-side diff
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--config.in2
-rw-r--r--inputmethods/dasher/AlphIO.cpp83
-rw-r--r--inputmethods/dasher/AlphIO.h80
-rw-r--r--inputmethods/dasher/Alphabet.cpp140
-rw-r--r--inputmethods/dasher/Alphabet.h83
-rw-r--r--inputmethods/dasher/AlphabetMap.cpp86
-rw-r--r--inputmethods/dasher/AlphabetMap.h111
-rw-r--r--inputmethods/dasher/Context.h21
-rw-r--r--inputmethods/dasher/CustomAlphabet.cpp40
-rw-r--r--inputmethods/dasher/CustomAlphabet.h26
-rw-r--r--inputmethods/dasher/DashEdit.h163
-rw-r--r--inputmethods/dasher/DasherAppInterface.h72
-rw-r--r--inputmethods/dasher/DasherInterface.cpp636
-rw-r--r--inputmethods/dasher/DasherInterface.h170
-rw-r--r--inputmethods/dasher/DasherModel.cpp322
-rw-r--r--inputmethods/dasher/DasherModel.h111
-rw-r--r--inputmethods/dasher/DasherNode.cpp167
-rw-r--r--inputmethods/dasher/DasherNode.h127
-rw-r--r--inputmethods/dasher/DasherScreen.h102
-rw-r--r--inputmethods/dasher/DasherSettingsInterface.cpp126
-rw-r--r--inputmethods/dasher/DasherSettingsInterface.h149
-rw-r--r--inputmethods/dasher/DasherTypes.h66
-rw-r--r--inputmethods/dasher/DasherView.cpp93
-rw-r--r--inputmethods/dasher/DasherView.h99
-rw-r--r--inputmethods/dasher/DasherView.inl75
-rw-r--r--inputmethods/dasher/DasherViewSquare.cpp229
-rw-r--r--inputmethods/dasher/DasherViewSquare.h58
-rw-r--r--inputmethods/dasher/DasherViewSquare.inl142
-rw-r--r--inputmethods/dasher/DasherWidgetInterface.h93
-rw-r--r--inputmethods/dasher/FrameRate.h112
-rw-r--r--inputmethods/dasher/LanguageModel.cpp77
-rw-r--r--inputmethods/dasher/LanguageModel.h123
-rw-r--r--inputmethods/dasher/MSVC_Unannoy.h17
-rw-r--r--inputmethods/dasher/NoClones.h39
-rw-r--r--inputmethods/dasher/PPMLanguageModel.cpp309
-rw-r--r--inputmethods/dasher/PPMLanguageModel.h122
-rw-r--r--inputmethods/dasher/QtDasherImpl.cc85
-rw-r--r--inputmethods/dasher/QtDasherImpl.h38
-rw-r--r--inputmethods/dasher/QtDasherPlugin.cc79
-rw-r--r--inputmethods/dasher/QtDasherPlugin.h42
-rw-r--r--inputmethods/dasher/QtDasherScreen.cc180
-rw-r--r--inputmethods/dasher/QtDasherScreen.h117
-rw-r--r--inputmethods/dasher/SettingsStore.cpp135
-rw-r--r--inputmethods/dasher/SettingsStore.h92
-rw-r--r--inputmethods/dasher/config.in5
-rw-r--r--inputmethods/dasher/dasher.pro57
-rw-r--r--inputmethods/dasher/opie-dasher-english.control12
-rw-r--r--inputmethods/dasher/opie-dasher.control11
-rw-r--r--inputmethods/dasher/opie-dasher.postinst7
-rw-r--r--inputmethods/dasher/opie-dasher.postrm2
-rw-r--r--packages1
51 files changed, 5333 insertions, 1 deletions
diff --git a/config.in b/config.in
index a89724b..dac9024 100644
--- a/config.in
+++ b/config.in
@@ -149,3 +149,3 @@ menu "Development"
source development/keyview/config.in
- source development/debugviewer/config.in
+ #source development/debugviewer/config.in
endmenu
diff --git a/inputmethods/dasher/AlphIO.cpp b/inputmethods/dasher/AlphIO.cpp
new file mode 100644
index 0000000..41b1b23
--- a/dev/null
+++ b/inputmethods/dasher/AlphIO.cpp
@@ -0,0 +1,83 @@
+// AlphIO.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#include "AlphIO.h"
+
+using namespace Dasher;
+using namespace std;
+
+CAlphIO::CAlphIO(string SystemLocation, string UserLocation)
+ : SystemLocation(SystemLocation), UserLocation(UserLocation),
+ BlankInfo(), CData("")
+{
+ CreateDefault();
+}
+
+
+void CAlphIO::GetAlphabets(std::vector< std::string > * AlphabetList) const
+{
+ AlphabetList->clear();
+
+ typedef std::map<std::string, AlphInfo>::const_iterator CI;
+ CI End = Alphabets.end();
+
+ for (CI Cur=Alphabets.begin(); Cur!=End; Cur++)
+ AlphabetList->push_back( (*Cur).second.AlphID);
+}
+
+
+const CAlphIO::AlphInfo& CAlphIO::GetInfo(const std::string& AlphID)
+{
+ if (AlphID=="")
+ return Alphabets["Default"];
+ else {
+ AlphInfo& CurInfo = Alphabets[AlphID];
+ Alphabets[AlphID].AlphID = AlphID; // Ensure consistency
+ return Alphabets[AlphID];
+ }
+}
+
+
+void CAlphIO::SetInfo(const AlphInfo& NewInfo)
+{
+ Alphabets[NewInfo.AlphID] = NewInfo;
+}
+
+
+void CAlphIO::Delete(const std::string& AlphID)
+{
+ if (Alphabets.find(AlphID)!=Alphabets.end()) {
+ Alphabets.erase(AlphID);
+ }
+}
+
+
+void CAlphIO::CreateDefault()
+{
+ // TODO I appreciate these strings should probably be in a resource file.
+ // Not urgent though as this is not intended to be used. It's just a
+ // last ditch effort in case file I/O totally fails.
+ AlphInfo& Default = Alphabets["Default"];
+ Default.AlphID = "Default";
+ Default.Type = Opts::Western;
+ Default.Mutable = false;
+ Default.Orientation = Opts::LeftToRight;
+ Default.SpaceCharacter.Display = "_";
+ Default.SpaceCharacter.Text = " ";
+ Default.TrainingFile = "training_english_GB.txt";
+ string Chars = "abcdefghijklmnopqrstuvwxyz";
+ Default.Groups.resize(1);
+ Default.Groups[0].Description = "Lower case Latin letters";
+ Default.Groups[0].Characters.resize(Chars.size());
+ for (unsigned int i=0; i<Chars.size(); i++) {
+ Default.Groups[0].Characters[i].Text = Chars[i];
+ Default.Groups[0].Characters[i].Display = Chars[i];
+ }
+}
diff --git a/inputmethods/dasher/AlphIO.h b/inputmethods/dasher/AlphIO.h
new file mode 100644
index 0000000..ad31554
--- a/dev/null
+++ b/inputmethods/dasher/AlphIO.h
@@ -0,0 +1,80 @@
+// AlphIO.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef __AlphIO_h__
+#define __AlphIO_h__
+
+
+#include "DasherTypes.h"
+
+#include "MSVC_Unannoy.h"
+#include <string>
+#include <map>
+#include <vector>
+#include <utility> // for std::pair
+#include <stdio.h> // for C style file IO
+
+namespace Dasher {class CAlphIO;}
+class Dasher::CAlphIO
+{
+public:
+ // This structure completely describes the characters used in alphabet
+ struct AlphInfo
+ {
+ // Basic information
+ std::string AlphID;
+ bool Mutable; // If from user we may play. If from system defaults this is immutable. User should take a copy.
+
+ // Complete description of the alphabet:
+ std::string TrainingFile;
+ Opts::AlphabetTypes Encoding;
+ Opts::AlphabetTypes Type;
+ Opts::ScreenOrientations Orientation;
+ struct character
+ {
+ std::string Display;
+ std::string Text;
+ std::string Colour;
+ std::string Foreground;
+ };
+ struct group
+ {
+ std::string Description;
+ std::vector< character > Characters;
+ };
+ std::vector< group > Groups;
+ character SpaceCharacter; // display and edit text of Space character. Typically (" ", "_"). Use ("", "") if no space character.
+ };
+
+ CAlphIO(std::string SystemLocation, std::string UserLocation);
+ void GetAlphabets(std::vector< std::string >* AlphabetList) const;
+ const AlphInfo& GetInfo(const std::string& AlphID);
+ void SetInfo(const AlphInfo& NewInfo);
+ void Delete(const std::string& AlphID);
+private:
+ AlphInfo BlankInfo;
+ std::string SystemLocation;
+ std::string UserLocation;
+ std::map<std::string, AlphInfo> Alphabets; // map short names (file names) to descriptions
+
+ void CreateDefault(); // Give the user an English alphabet rather than nothing if anything goes horribly wrong.
+
+
+ // Alphabet types:
+ std::map<std::string, Opts::AlphabetTypes> StoT;
+ std::map<Opts::AlphabetTypes, std::string> TtoS;
+
+ // Data gathered
+ std::string CData; // Text gathered from when an elemnt starts to when it ends
+ AlphInfo InputInfo;
+
+};
+
+
+#endif /* #ifndef __AlphIO_h__ */
diff --git a/inputmethods/dasher/Alphabet.cpp b/inputmethods/dasher/Alphabet.cpp
new file mode 100644
index 0000000..dc58b35
--- a/dev/null
+++ b/inputmethods/dasher/Alphabet.cpp
@@ -0,0 +1,140 @@
+// Alphabet.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "Alphabet.h"
+#include "AlphabetMap.h"
+
+//#include <iostream>
+//WinCE doesn't have iostream!
+
+using namespace Dasher;
+using namespace std;
+
+
+CAlphabet::CAlphabet() : m_Groups(0), m_DefaultEncoding(Opts::Western), m_Orientation(Opts::LeftToRight)
+{
+ m_Characters.push_back("");
+ m_Display.push_back("");
+ m_Colours.push_back("");
+ m_Foreground.push_back("");
+ m_Group.push_back(0);
+}
+
+
+void CAlphabet::GetSymbols(vector<symbol>* Symbols, string* Input, bool IsMore)
+{
+ string Tmp;
+ symbol CurSymbol=0, TmpSymbol=0;
+ bool KeyIsPrefix;
+ int z= Input->size();
+ int extras;
+ unsigned int bit;
+
+ for (unsigned int i=0; i<Input->size(); i++) {
+
+ Tmp = (*Input)[i];
+
+ /* The string we've been given is in UTF-8. The symbols are
+ also in UTF-8, so we need to pass the entire UTF-8 character
+ which may be several bytes long. RFC 2279 describes this
+ encoding */
+
+ if ((*Input)[i] & 0x80) { // Character is more than 1 byte long
+ extras = 1;
+ for (bit = 0x20; ((*Input)[i] & bit) != 0; bit >>= 1)
+ extras++;
+ if (extras > 5) {
+ } // Malformed character
+ while (extras-->0) {
+ Tmp += (*Input)[++i];
+ }
+ }
+
+ CurSymbol = TextMap.Get(Tmp, &KeyIsPrefix);
+
+ if (KeyIsPrefix) {
+ CurSymbol = 0;
+ for (; i<Input->size(); i++) {
+
+ Tmp += (*Input)[i];
+
+ TmpSymbol = TextMap.Get(Tmp, &KeyIsPrefix);
+ if (TmpSymbol>0) {
+ CurSymbol = TmpSymbol;
+ }
+ if (!KeyIsPrefix) {
+ if (CurSymbol!=0) {
+ Symbols->push_back(CurSymbol);
+ } else {
+ i -= Tmp.size()-1;
+ //Tmp.erase(Tmp.begin(), Tmp.end());
+ Tmp = "";
+ }
+ break;
+ }
+ }
+ } else {
+ if (CurSymbol!=0)
+ Symbols->push_back(CurSymbol);
+ }
+ }
+
+ if (IsMore)
+ if (KeyIsPrefix)
+ *Input = Tmp;
+ else
+ *Input = "";
+ else
+ if (KeyIsPrefix)
+ Symbols->push_back(CurSymbol);
+}
+
+
+// add single char to the character set
+void CAlphabet::AddChar(const string NewCharacter, const string Display, const string Colour, const string Foreground)
+{
+ m_Characters.push_back(NewCharacter);
+ m_Display.push_back(Display);
+ m_Colours.push_back(Colour);
+ m_Foreground.push_back(Foreground);
+ m_Group.push_back(m_Groups);
+
+ symbol ThisSymbol = m_Characters.size()-1;
+ TextMap.Add(NewCharacter, ThisSymbol);
+}
+
+
+void CAlphabet::StartNewGroup()
+{
+ m_Groups++;
+}
+
+
+// diagnostic dump of character set
+void CAlphabet::dump() const {
+// TODO
+/*
+ dchar deb[256];
+ unsigned int i;
+ for (i=1;i<m_vtCharacters.size();i++) {
+ //wsprintf(deb,TEXT("%d %c %d\n"),i,m_vtCharacters[i],m_viGroup[i]); // Windows specific
+ Usprintf(deb,TEXT("%d %c %d\n"),i,m_vtCharacters[i],m_viGroup[i]);
+ DebugOutput(deb);
+ }
+*/
+}
+
+int CAlphabet::GetTextColour(symbol Symbol)
+{
+ std::string TextColour=m_Foreground[Symbol];
+ if (TextColour != "") {
+ return atoi(TextColour.c_str());
+ } else {
+ return 0;
+ }
+}
diff --git a/inputmethods/dasher/Alphabet.h b/inputmethods/dasher/Alphabet.h
new file mode 100644
index 0000000..5f0f9a5
--- a/dev/null
+++ b/inputmethods/dasher/Alphabet.h
@@ -0,0 +1,83 @@
+// Alphabet.h
+//
+/////////////////////////////////////////////////////////////////////////////
+// Alphabet.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __DASHER_ALPHABET_H__
+#define __DASHER_ALPHABET_H__
+
+
+#include "DasherTypes.h"
+
+#include "MSVC_Unannoy.h"
+#include <map>
+#include <vector>
+#include "AlphabetMap.h"
+
+
+namespace Dasher {class CAlphabet;}
+class Dasher::CAlphabet
+{
+public:
+ CAlphabet();
+ ~CAlphabet() {}
+
+ int GetNumberSymbols() const { return m_Characters.size();} // return size of alphabet
+
+ Opts::ScreenOrientations GetOrientation() {return m_Orientation;}
+ Opts::AlphabetTypes GetType() {return m_DefaultEncoding;}
+ std::string& GetTrainingFile() {return m_TrainingFile;}
+
+ symbol GetSpaceSymbol() {return m_SpaceSymbol;}
+ const std::string& GetDisplayText(symbol i) const {return m_Display[i];} // return display string for i'th symbol
+ const std::string& GetText(symbol i) const {return m_Characters[i];} // return string for i'th symbol
+ const std::string& GetColour(symbol i) const {return m_Colours[i];} // return the colour for i'th symbol
+ int GetTextColour(symbol i); // return the foreground colour for i'th symbol
+ const std::string& GetForeground(symbol i) const {return m_Foreground[i];} // return the foreground colour for i'th symbol
+ int get_group(symbol i) const {return m_Group[i];} // return group membership of i'th symbol
+
+ // Fills Symbols with the symbols corresponding to Input. {{{ Note that this
+ // is not necessarily reversible by repeated use of GetText. Some text
+ // may not be recognised and so discarded. If IsMore is true then Input
+ // is truncated to any final characters that were not used due to ambiguous
+ // continuation. If IsMore is false Input is assumed to be all the available
+ // text and so a symbol will be returned for a final "a" even if "ae" is
+ // defined as its own symbol. }}}
+ void GetSymbols(std::vector<symbol>* Symbols, std::string* Input, bool IsMore);
+
+ void dump() const; // diagnostic
+
+protected:
+ // Add the characters that can appear in Nodes
+ void AddChar(const std::string NewCharacter, const std::string Display, const std::string Colour, const std::string Foreground); // add single char to the alphabet
+ void StartNewGroup();
+
+ // Alphabet language parameters
+ void SetSpaceSymbol() {m_SpaceSymbol=m_Characters.size()-1;} // We can set the space symbol to be the last character added
+ void SetSpaceSymbol(symbol SpaceSymbol) {m_SpaceSymbol=SpaceSymbol;} // ...or any desired symbol.
+ void SetOrientation(Opts::ScreenOrientations Orientation) {m_Orientation=Orientation;}
+ void SetLanguage(Opts::AlphabetTypes Group) {m_DefaultEncoding=Group;}
+ void SetTrainingFile(std::string TrainingFile) {m_TrainingFile=TrainingFile;}
+private:
+ Opts::AlphabetTypes m_DefaultEncoding;
+ Opts::ScreenOrientations m_Orientation;
+ symbol m_SpaceSymbol;
+ std::string m_TrainingFile;
+
+ std::vector<std::string> m_Characters; // stores the characters
+ std::vector<std::string> m_Display; // stores how the characters are visually represented in the Dasher nodes
+ std::vector<std::string> m_Colours; // stores the colour of the characters
+ std::vector<std::string> m_Foreground; // stores the colour of the character foreground
+ std::vector<int> m_Group; // stores the group indicators - e.g. caps, numbers, punctuation
+ int m_Groups; // number of groups
+ alphabet_map TextMap;
+};
+
+
+#endif // ifndef __DASHER_ALPHABET_H__
diff --git a/inputmethods/dasher/AlphabetMap.cpp b/inputmethods/dasher/AlphabetMap.cpp
new file mode 100644
index 0000000..09e2c72
--- a/dev/null
+++ b/inputmethods/dasher/AlphabetMap.cpp
@@ -0,0 +1,86 @@
+// AlphabetMap.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "AlphabetMap.h"
+
+using namespace Dasher;
+using namespace std;
+
+alphabet_map::alphabet_map(unsigned int InitialTableSize)
+ : Undefined(0), HashTable(InitialTableSize<<1)
+{
+ Entries.reserve(InitialTableSize);
+}
+
+
+void alphabet_map::Add(const string& Key, symbol Value)
+{
+ RecursiveAdd(Key, Value, false);
+}
+
+
+void alphabet_map::RecursiveAdd(const string& Key, symbol Value, bool PrefixFlag)
+{
+ Entry*& HashEntry = HashTable[Hash(Key)];
+
+ // Loop through Entries with the correct Hash value.
+ for (Entry* i = HashEntry; i; i=i->Next) {
+ if (i->Key==Key) {
+ if (PrefixFlag) {
+ // Just tagging - don't change symbol. Recurse if necessary
+ i->KeyIsPrefix = true;
+ if (Key.size()>1)
+ RecursiveAdd(Key.substr(Key.size()-1), Undefined, true);
+ } else {
+ // Add symbol and leave
+ i->Symbol = Value;
+ }
+ return;
+ }
+ }
+
+ // When hash table gets 1/2 full...
+ // (no I haven't optimised when to resize)
+ if (Entries.size()<<1 >= HashTable.size()) {
+ // Double up all the storage
+ HashTable.clear();
+ HashTable.resize(Entries.size()<<2);
+ Entries.reserve(Entries.size()<<1);
+
+ // Rehash as the pointers will all be mangled.
+ for (uint j=0; j<Entries.size(); j++) {
+ Entry*& HashEntry2 = HashTable[Hash(Entries[j].Key)];
+ Entries[j].Next = HashEntry2;
+ HashEntry2 = &Entries[j];
+ }
+
+ // Have to recall this function as the key's hash needs recalculating
+ RecursiveAdd(Key, Value, PrefixFlag);
+ return;
+ }
+
+ Entries.push_back(Entry(Key, Value, HashEntry));
+ HashEntry = &Entries.back();
+}
+
+
+symbol alphabet_map::Get(const string& Key, bool* KeyIsPrefix) const
+{
+ // Loop through Entries with the correct Hash value.
+ for (Entry* i = HashTable[Hash(Key)]; i; i=i->Next) {
+ if (i->Key==Key) {
+ if (KeyIsPrefix!=0)
+ *KeyIsPrefix = i->KeyIsPrefix;
+ return i->Symbol;
+ }
+ }
+
+ if (KeyIsPrefix!=0)
+ *KeyIsPrefix = false;
+ return Undefined;
+}
diff --git a/inputmethods/dasher/AlphabetMap.h b/inputmethods/dasher/AlphabetMap.h
new file mode 100644
index 0000000..3aac1f5
--- a/dev/null
+++ b/inputmethods/dasher/AlphabetMap.h
@@ -0,0 +1,111 @@
+// AlphabetMap.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+/*
+If I were just using GCC, which comes with the CGI "STL" implementation, I would
+use hash_map (which isn't part of the ANSI/ISO standard C++ STL, but hey it's nice).
+Using a plain map is just too slow for training on large files (or it is with certain
+STL implementations). I'm sure training could be made much faster still, but that's
+another matter...
+
+While I could (and probably should) get a hash_map for VC++ from
+http://www.stlport.org I thought it would be nicer if people didn't have
+to download extra stuff and then have to get it working alongside the STL
+with VC++, especially for just one small part of Dasher.
+
+The result is this:
+***************************************************
+very much thrown together to get Dasher out ASAP.
+***************************************************
+It is deliberately not like an STL container.
+However, as it has a tiny interface, it should still be easy to replace.
+Sorry if this seems really unprofressional.
+
+Replacing it might be a good idea. On the other hand it could be customised
+to the needs of the alphabet, so that it works faster. For example,
+currently if I have a string "asdf", it might be that "a" is checked
+then "as" is checked then "asd" is checked. I shouldn't need to keep
+rehashing the leading characters. I plan to fix that here. Doing so with
+a standard hash_map would be hard.
+
+
+Usage:
+alphabet_map MyMap(NumberOfEntriesWeExpect); // Can omit NumberOfEntriesWeExpect
+MyMap.add("asdf", 15);
+symbol i = MyMap.get("asdf") // i=15
+symbol j = MyMap.get("fdsa") // j=0
+
+You can't remove items once they are added as Dasher has no need for that.
+
+IAM 08/2002
+*/
+
+#ifndef __AlphabetMap_h__
+#define __AlphabetMap_h__
+
+#include "MSVC_Unannoy.h"
+#include <vector>
+#include <string>
+
+#include "DasherTypes.h"
+
+namespace Dasher {class alphabet_map;}
+class Dasher::alphabet_map
+{
+public:
+ alphabet_map(uint InitialTableSize=255);
+ void Add(const std::string& Key, symbol Value);
+ symbol Get(const std::string& Key, bool* KeyIsPrefix=0) const;
+
+private:
+ class Entry
+ {
+ public:
+ Entry(std::string Key, symbol Symbol, Entry* Next)
+ : Key(Key), Symbol(Symbol), Next(Next), KeyIsPrefix(false) {}
+
+ std::string Key;
+ bool KeyIsPrefix;
+ symbol Symbol;
+ Entry* Next;
+ };
+
+ void RecursiveAdd(const std::string& Key, symbol Value, bool PrefixFlag);
+
+ // A standard hash -- could try and research something specific.
+ inline uint Hash(const std::string& Input) const {
+ uint Result = 0;
+
+ typedef std::string::const_iterator CI;
+ CI Cur = Input.begin();
+ CI end = Input.end();
+
+ while (Cur!=end) Result = (Result<<1)^*Cur++;
+ Result %= HashTable.size();
+
+ return Result;
+ /*
+ if (Input.size()==1) // Speedup for ASCII text
+ return Input[0];
+
+ for (int i=0; i<Input.size(); i++)
+ Result = (Result<<1)^Input[i];
+
+
+ return Result%HashTable.size();
+ */
+ }
+
+ std::vector<Entry> Entries;
+ std::vector<Entry*> HashTable;
+ const symbol Undefined;
+};
+
+
+#endif /* #ifndef __AlphabetMap_h__ */
diff --git a/inputmethods/dasher/Context.h b/inputmethods/dasher/Context.h
new file mode 100644
index 0000000..ff31cee
--- a/dev/null
+++ b/inputmethods/dasher/Context.h
@@ -0,0 +1,21 @@
+// Context.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef Context_h
+#define Context_h
+
+namespace Dasher {class CContext;}
+class Dasher::CContext
+{
+public:
+ CContext() {};
+ virtual ~CContext() {};
+};
+
+
+#endif /* #ifndef Context_h */
diff --git a/inputmethods/dasher/CustomAlphabet.cpp b/inputmethods/dasher/CustomAlphabet.cpp
new file mode 100644
index 0000000..deb0f6d
--- a/dev/null
+++ b/inputmethods/dasher/CustomAlphabet.cpp
@@ -0,0 +1,40 @@
+// CustomAlphabet.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+#include "CustomAlphabet.h"
+
+using namespace Dasher;
+using namespace std;
+
+
+CCustomAlphabet::CCustomAlphabet(const CAlphIO::AlphInfo& AlphInfo)
+{
+ // Set miscellaneous options
+ SetOrientation(AlphInfo.Orientation);
+ SetLanguage(AlphInfo.Type);
+ SetTrainingFile(AlphInfo.TrainingFile);
+
+ // Add all the characters.
+ for (unsigned int i=0; i<AlphInfo.Groups.size(); i++) { // loop groups
+ for (unsigned int j=0; j<AlphInfo.Groups[i].Characters.size(); j++) { // loop characters
+ AddChar(AlphInfo.Groups[i].Characters[j].Text, AlphInfo.Groups[i].Characters[j].Display, AlphInfo.Groups[i].Characters[j].Colour, AlphInfo.Groups[i].Characters[j].Foreground);
+ }
+ StartNewGroup();
+ }
+
+ // Set Space character if requested
+
+ // This line makes it a bit easier for our WindowsCE compiler
+ std::string empty="";
+
+ if (AlphInfo.SpaceCharacter.Text != empty ) {
+ AddChar(AlphInfo.SpaceCharacter.Text, AlphInfo.SpaceCharacter.Display, AlphInfo.SpaceCharacter.Colour, AlphInfo.SpaceCharacter.Foreground);
+ SetSpaceSymbol();
+ }
+}
diff --git a/inputmethods/dasher/CustomAlphabet.h b/inputmethods/dasher/CustomAlphabet.h
new file mode 100644
index 0000000..4cd7880
--- a/dev/null
+++ b/inputmethods/dasher/CustomAlphabet.h
@@ -0,0 +1,26 @@
+// CustomAlphabet.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef __CustomAlphabet_h__
+#define __CustomAlphabet_h__
+
+
+#include "Alphabet.h"
+#include "AlphIO.h"
+
+
+namespace Dasher {class CCustomAlphabet;}
+class Dasher::CCustomAlphabet : public Dasher::CAlphabet
+{
+public:
+ CCustomAlphabet(const CAlphIO::AlphInfo& AlphInfo);
+};
+
+
+#endif /* #ifndef __CustomAlphabet_h__ */
diff --git a/inputmethods/dasher/DashEdit.h b/inputmethods/dasher/DashEdit.h
new file mode 100644
index 0000000..dc14d15
--- a/dev/null
+++ b/inputmethods/dasher/DashEdit.h
@@ -0,0 +1,163 @@
+//! Class definition for an edit box
+// DashEdit.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+/*
+An abstract DashEditbox class is described here.
+An implementation will handle interaction between Dasher and an actual Edit control.
+e.g. - output characters to the edit control
+ - tapping on the edit box updates the Dasher display
+*/
+
+#ifndef __DashEdit_h__
+#define __DashEdit_h__
+
+#include "DasherWidgetInterface.h"
+
+namespace Dasher {class CDashEditbox;}
+class Dasher::CDashEditbox
+{
+public:
+ CDashEditbox() : m_iFlushed(0), m_DasherInterface(0), m_dirty(false) {}
+
+ //! Provide the Editbox with a widget interface
+ virtual void SetInterface(CDasherWidgetInterface* DasherInterface) {m_DasherInterface = DasherInterface;}
+
+ //! Write some buffered output to a file
+ virtual void write_to_file()=0;
+
+ //! Set the number of flushed characters
+ //
+ //! Set the number of flushed characters to an arbitrary number.
+ //! Usually used to reset it to 0 after unflushing
+ void set_flushed(int i) {m_iFlushed=i;}
+
+ //! Provide context from the editbox for the core
+ //
+ //! Provide the context at the current position within the editbox to
+ //! the core. Set str to up to max characters before
+ //! the cursor position within the editbox.
+ virtual void get_new_context(std::string& str, int max)=0;
+
+ //! Delete flushed text from the editbox
+ virtual inline void unflush()=0;
+
+ //! Enter a the character Symbol into the text box
+ virtual void output(symbol Symbol)=0;
+
+ //! Delete the previous symbol from the text box
+ virtual void deletetext()=0;
+
+ //! Enter a character into the text box and remember that it is flushed
+ //
+ //! Output the character and increment m_iFlushed. When unflush is
+ //! called, remove the previous m_iFlushed characters
+ virtual void flush(symbol Symbol)=0;
+
+ // File I/O (optional)
+
+ //! If Value is true, timestamp all new files (optional)
+ //
+ //! If switched on, all new files should be timestamped, either in the
+ //! filename or in file metadata
+ virtual void TimeStampNewFiles(bool Value) {}
+
+ //! Return true if any text has been modified since the last save (optional)
+ bool IsDirty() {return m_dirty;}
+
+ //! Generate a new file (optional)
+ //
+ //! New file - provide a file save dialogue and return the filename in
+ //! filename, or provide a blank filename and present a file
+ //! save dialogue when Save() is called
+ virtual void New(const std::string& filename) {}; // filename can be "", but you cannot call Save() without having set a filename.
+
+ //! Open a file (optional)
+ //
+ //! Provide a file open dialogue and set filename to the
+ //! filename. Return true if a file is chosen and opened successfully,
+ //! false otherwise
+ virtual bool Open(const std::string& filename) {return false;};
+
+ //! Open a file and append to it (optional)
+ //
+ //! Provide a file open dialogue and set filename to the
+ //! filename. The file will then have any new text appended to it.
+ //! Return true if a file is chosen and opened successfully, false
+ //! otherwise
+ virtual bool OpenAppendMode(const std::string& filename) {return false;};
+ //! Save a file as a provided filename (optional)
+ //
+ //! Provide a file save dialogue and set filename to the
+ //! filename. Return true if a file is chosen and saved successfully,
+ //! false otherwise
+ virtual bool SaveAs(const std::string& filename) {return false;};
+
+ //! Save the current file (optional)
+ //
+ //! Save file to the current filename. If there is no current filename,
+ //! or if saving fails, return false
+ virtual bool Save() {return false;}; // returns false if there is no filename set, or if saving fails
+
+ // Clipboard (optional)
+ //! Cut selected text (optional)
+ //
+ //! Copy the selected text to the clipboard and remove it from the
+ //! editbox
+ virtual void Cut() {};
+
+ //! Copy selected text (optional)
+ //
+ //! Copy the selected text to the clipboard
+ virtual void Copy() {};
+
+ //! Copy all text (optional)
+ //
+ //! Copy all text in the editbox to the clipboard
+ virtual void CopyAll() {};
+
+ //! Paste text from clipboard (optional)
+ //
+ //! Paste text from the clipboard into the editbox at the current
+ //! position
+ virtual void Paste() {};
+
+ //! Select all text in the editbox (optional)
+ virtual void SelectAll() {};
+
+ //! Clear all text from the editbox (REQUIRED)
+ virtual void Clear()=0; // Must at least be able to clear edit box
+
+ //! Set the file encoding
+ //
+ //! Set the file encoding to the provided encoding Encoding.
+ //! The editbox is responsible for saving the file in the encoding
+ //! desired by the user. As Dasher is internally UTF8, it may well be
+ //! necessary to save in an alternative format based on locale and OS.
+ virtual void SetEncoding(Opts::FileEncodingFormats Encoding)=0;
+
+ //! Set the font used in the editbox
+ //
+ //! Set the font used in the editbox to Name and size
+ //! Size (in points)
+ virtual void SetFont(std::string Name, long Size)=0;
+
+// TODO sort relationship between CDashEditbox and derived classes
+protected:
+ //! Have the contents of the editbox been altered since the last save?
+ bool m_dirty;
+
+ //! Record the number of characters that have been flushed
+ int m_iFlushed; // how many characters have been flushed
+
+ //! Pointer to a DasherWidgetInterface for communication with the core
+ CDasherWidgetInterface* m_DasherInterface;
+};
+
+
+#endif /* #ifndef __DashEdit_h__ */
diff --git a/inputmethods/dasher/DasherAppInterface.h b/inputmethods/dasher/DasherAppInterface.h
new file mode 100644
index 0000000..c4f011c
--- a/dev/null
+++ b/inputmethods/dasher/DasherAppInterface.h
@@ -0,0 +1,72 @@
+// DasherAppInterface.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __DasherAppInterface_h__
+#define __DasherAppInterface_h__
+
+#include "DasherScreen.h"
+#include "DashEdit.h"
+#include "AlphIO.h"
+#include <string>
+#include <vector>
+
+namespace Dasher {class CDasherAppInterface;}
+class Dasher::CDasherAppInterface
+{
+public:
+ // We may change the widgets Dasher uses at run time
+
+ //! Change the screen being used by the core to NewScreen
+ virtual void ChangeScreen(CDasherScreen* NewScreen)=0;
+
+ //! Change the editbox being used by the core to NewEdit
+ virtual void ChangeEdit(CDashEditbox* NewEdit)=0;
+
+ // Training by string segments or file all training data must be in UTF-8.
+ //! Train the core on Trainstring
+ //
+ //! \param TrainString UTF-8 encoded string to train the core on
+ //! \param IsMore True if more text is to follow as part of the same
+ //! logical sequence, false otherwise (this allows the model to make
+ //! assumptions regarding whether the final character provided is in
+ //! the middle of a word or not)
+ virtual void Train(std::string* TrainString, bool IsMore)=0;
+
+ //! Train the core on the file in Filename.
+ //
+ //! The file should contain UTF-8 encoded text
+ virtual void TrainFile(std::string Filename)=0;
+
+ // App may want to display characters per minute or frames per second.
+
+ //! Tell the interface how many font sizes there are and what they are
+
+ virtual void GetFontSizes(std::vector<int> *FontSizes)=0;
+
+ //! Provides the number of characters per minute input. (Not implemented)
+ virtual double GetCurCPM()=0;
+
+ //! Provides the framerate that Dasher is runnin at. (Not implemented)
+ virtual double GetCurFPS()=0;
+
+ // Customize alphabet
+ //! Get a vector containing a list of alphabet names available to Dasher
+ virtual void GetAlphabets(std::vector< std::string >* AlphabetList)=0;
+
+ //! Return an AlphInfo object containing the alphabet with name AlphID
+ virtual const CAlphIO::AlphInfo& GetInfo(const std::string& AlphID)=0;
+
+ //! Save a new or modified AlphInfo object
+ virtual void SetInfo(const CAlphIO::AlphInfo& NewInfo)=0;
+
+ //! Delete the alphabet with name AlphID
+ virtual void DeleteAlphabet(const std::string& AlphID)=0;
+};
+
+
+#endif /* #ifndef __DasherAppInterface_h__ */
diff --git a/inputmethods/dasher/DasherInterface.cpp b/inputmethods/dasher/DasherInterface.cpp
new file mode 100644
index 0000000..bb5b85e
--- a/dev/null
+++ b/inputmethods/dasher/DasherInterface.cpp
@@ -0,0 +1,636 @@
+// DasherInterface.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#include "DasherInterface.h"
+//#include "EnglishAlphabet.h"
+#include "CustomAlphabet.h"
+#include "DasherViewSquare.h"
+#include "PPMLanguageModel.h"
+#include <iostream>
+namespace {
+ #include "stdio.h"
+}
+using namespace Dasher;
+using namespace std;
+
+
+const string CDasherInterface::EmptyString = "";
+
+
+CDasherInterface::CDasherInterface()
+ : m_DashEditbox(0), m_DasherScreen(0), m_LanguageModel(0), TrainContext(0), m_Alphabet(0),
+ m_DasherModel(0), m_DasherView(0), AlphabetID(""), LanguageModelID(-1), ViewID(-1),
+ m_MaxBitRate(-1), m_Orientation(Opts::LeftToRight), m_SettingsStore(0), m_SettingsUI(0),
+ m_UserLocation("usr_"), m_SystemLocation("sys_"), m_AlphIO(0), m_TrainFile(""),
+ m_DasherFont(""), m_EditFont(""), m_EditFontSize(0), m_DrawKeyboard(false)
+{
+}
+
+
+CDasherInterface::~CDasherInterface()
+{
+ if (m_LanguageModel)
+ m_LanguageModel->ReleaseNodeContext(TrainContext);
+ delete m_DasherModel; // The order of some of these deletions matters
+ delete m_LanguageModel; // eg DasherModel has a pointer to LanguageModel.
+ delete m_Alphabet; // DM baulks if LM is deleted before it is.
+ delete m_DasherView;
+ // Do NOT delete Edit box or Screen. This class did not create them.
+}
+
+
+void CDasherInterface::SetSettingsStore(CSettingsStore* SettingsStore)
+{
+ delete m_SettingsStore;
+ m_SettingsStore = SettingsStore;
+ this->SettingsDefaults(m_SettingsStore);
+}
+
+
+void CDasherInterface::SetSettingsUI(CDasherSettingsInterface* SettingsUI)
+{
+ delete m_SettingsUI;
+ m_SettingsUI = SettingsUI;
+ //this->SettingsDefaults(m_SettingsStore);
+ m_SettingsUI->SettingsDefaults(m_SettingsStore);
+}
+
+
+void CDasherInterface::SetUserLocation(std::string UserLocation)
+{
+ // Nothing clever updates. (At the moment) it is assumed that
+ // this is set before anything much happens and that it does
+ // not require changing.
+ m_UserLocation = UserLocation;
+ if (m_Alphabet!=0)
+ m_TrainFile = m_UserLocation + m_Alphabet->GetTrainingFile();
+}
+
+
+void CDasherInterface::SetSystemLocation(std::string SystemLocation)
+{
+ // Nothing clever updates. (At the moment) it is assumed that
+ // this is set before anything much happens and that it does
+ // not require changing.
+ m_SystemLocation = SystemLocation;
+}
+
+
+void CDasherInterface::CreateDasherModel()
+{
+
+ if (m_DashEditbox!=0 && m_LanguageModel!=0) {
+ delete m_DasherModel;
+ m_DasherModel = new CDasherModel(m_DashEditbox, m_LanguageModel, m_Dimensions);
+ if (m_MaxBitRate>=0)
+ m_DasherModel->SetMaxBitrate(m_MaxBitRate);
+ if (ViewID!=-1)
+ ChangeView(ViewID);
+ }
+
+
+}
+
+
+void CDasherInterface::Start()
+{
+ if (m_DasherModel!=0)
+ m_DasherModel->Start();
+}
+
+
+void CDasherInterface::PauseAt(int MouseX, int MouseY)
+{
+ if (m_DasherView!=0)
+ m_DasherView->FlushAt(MouseX, MouseY);
+ if (m_DashEditbox!=0) {
+ m_DashEditbox->write_to_file();
+ if (m_CopyAllOnStop)
+ m_DashEditbox->CopyAll();
+ }
+}
+
+
+void CDasherInterface::Unpause(unsigned long Time)
+{
+ if (m_DashEditbox!=0)
+ m_DashEditbox->unflush();
+ if (m_DasherModel!=0)
+ m_DasherModel->Reset_framerate(Time);
+}
+
+
+void CDasherInterface::Redraw()
+{
+
+ if (m_DasherView!=0) {
+ m_DasherView->Render();
+ m_DasherView->Display();
+ }
+
+}
+
+
+void CDasherInterface::TapOn(int MouseX, int MouseY, unsigned long Time)
+{
+ if (m_DasherView!=0) {
+ m_DasherView->TapOnDisplay(MouseX, MouseY, Time);
+ m_DasherView->Render();
+ if (m_DrawMouse==true) {
+ m_DasherView->DrawMouse(MouseX, MouseY);
+ }
+ if (m_DrawKeyboard==true) {
+ m_DasherView->DrawKeyboard();
+ }
+ m_DasherView->Display();
+ }
+ if (m_DasherModel!=0)
+ m_DasherModel->NewFrame(Time);
+}
+
+
+void CDasherInterface::ChangeAlphabet(const std::string& NewAlphabetID)
+{
+ if (m_SettingsUI!=0)
+ m_SettingsUI->ChangeAlphabet(NewAlphabetID);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetStringOption(Keys::ALPHABET_ID, NewAlphabetID);
+
+ AlphabetID = NewAlphabetID;
+ if (!m_AlphIO)
+ m_AlphIO = new CAlphIO(m_SystemLocation, m_UserLocation);
+ CAlphIO::AlphInfo Info = m_AlphIO->GetInfo(NewAlphabetID);
+
+ CAlphabet* old = m_Alphabet;
+ m_Alphabet = new CCustomAlphabet(Info);
+
+ // Apply options from alphabet
+
+ m_TrainFile = m_UserLocation + m_Alphabet->GetTrainingFile();
+
+ // Recreate widgets and language model
+ if (m_DashEditbox!=0)
+ m_DashEditbox->SetInterface(this);
+ if (m_DasherScreen!=0)
+ m_DasherScreen->SetInterface(this);
+ if (LanguageModelID!=-1 || m_LanguageModel)
+ ChangeLanguageModel(LanguageModelID);
+
+ delete old; // only delete old alphabet after telling all other objects not to use it
+
+ Start();
+
+ // We can only change the orientation after we have called
+ // Start, as this will prompt a redraw, which will fail if the
+ // model hasn't been updated for the new alphabet
+
+ if (m_Orientation==Opts::Alphabet)
+ ChangeOrientation(Opts::Alphabet);
+
+ Redraw();
+}
+
+
+void CDasherInterface::ChangeMaxBitRate(double NewMaxBitRate)
+{
+ m_MaxBitRate = NewMaxBitRate;
+
+ if (m_DasherModel!=0)
+ m_DasherModel->SetMaxBitrate(m_MaxBitRate);
+ if (m_SettingsUI!=0)
+ m_SettingsUI->ChangeMaxBitRate(m_MaxBitRate);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetLongOption(Keys::MAX_BITRATE_TIMES100, long(m_MaxBitRate*100) );
+
+ if (m_DrawKeyboard==true && m_DasherView!=NULL) {
+ m_DasherView->DrawKeyboard();
+ }
+}
+
+
+void CDasherInterface::ChangeLanguageModel(unsigned int NewLanguageModelID)
+{
+ LanguageModelID = NewLanguageModelID;
+ if (m_Alphabet!=0) {
+ if (m_LanguageModel)
+ m_LanguageModel->ReleaseNodeContext(TrainContext);
+ TrainContext = 0;
+ delete m_DasherModel; // Have to delete DasherModel, or removing its LanguageModel will confuse it
+ m_DasherModel = 0;
+ delete m_LanguageModel;
+ // TODO Use LanguageModelID to decide which model to use
+ m_LanguageModel = new CPPMLanguageModel(m_Alphabet,1<<10);
+ TrainContext = m_LanguageModel->GetRootNodeContext();
+ string T = m_Alphabet->GetTrainingFile();
+ TrainFile(m_SystemLocation+T);
+ TrainFile(m_UserLocation+T);
+ CreateDasherModel();
+ }
+}
+
+
+void CDasherInterface::ChangeScreen()
+{
+ if (m_DasherView!=0) {
+ m_DasherView->ChangeScreen(m_DasherScreen);
+ } else {
+ if (ViewID!=-1)
+ ChangeView(ViewID);
+ }
+}
+
+
+void CDasherInterface::ChangeScreen(CDasherScreen* NewScreen)
+{
+ m_DasherScreen = NewScreen;
+ m_DasherScreen->SetFont(m_DasherFont);
+ m_DasherScreen->SetInterface(this);
+ ChangeScreen();
+ Redraw();
+}
+
+
+void CDasherInterface::ChangeView(unsigned int NewViewID)
+{
+ //TODO Use DasherViewID
+ ViewID = NewViewID;
+ if (m_DasherScreen!=0 && m_DasherModel!=0) {
+ delete m_DasherView;
+ if (m_Orientation==Opts::Alphabet)
+ m_DasherView = new CDasherViewSquare(m_DasherScreen, *m_DasherModel, GetAlphabetOrientation());
+ else
+ m_DasherView = new CDasherViewSquare(m_DasherScreen, *m_DasherModel, m_Orientation);
+ }
+}
+
+
+void CDasherInterface::ChangeOrientation(Opts::ScreenOrientations Orientation)
+{
+ m_Orientation = Orientation;
+ if (m_DasherView!=0) {
+ if (Orientation==Opts::Alphabet)
+ m_DasherView->ChangeOrientation(GetAlphabetOrientation());
+ else
+ m_DasherView->ChangeOrientation(Orientation);
+ }
+ if (m_SettingsUI!=0)
+ m_SettingsUI->ChangeOrientation(Orientation);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetLongOption(Keys::SCREEN_ORIENTATION, Orientation);
+}
+
+
+void CDasherInterface::SetFileEncoding(Opts::FileEncodingFormats Encoding)
+{
+ if (m_SettingsUI!=0)
+ m_SettingsUI->SetFileEncoding(Encoding);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetLongOption(Keys::FILE_ENCODING, Encoding);
+ if (m_DashEditbox)
+ m_DashEditbox->SetEncoding(Encoding);
+}
+
+
+void CDasherInterface::ShowToolbar(bool Value)
+{
+ if (m_SettingsUI!=0)
+ m_SettingsUI->ShowToolbar(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::SHOW_TOOLBAR, Value);
+}
+
+
+void CDasherInterface::ShowToolbarText(bool Value)
+{
+ if (m_SettingsUI!=0)
+ m_SettingsUI->ShowToolbarText(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::SHOW_TOOLBAR_TEXT, Value);
+}
+
+
+void CDasherInterface::ShowToolbarLargeIcons(bool Value)
+{
+ if (m_SettingsUI!=0)
+ m_SettingsUI->ShowToolbarLargeIcons(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::SHOW_LARGE_ICONS, Value);
+}
+
+
+void CDasherInterface::ShowSpeedSlider(bool Value)
+{
+ if (m_SettingsUI!=0)
+ m_SettingsUI->ShowSpeedSlider(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::SHOW_SLIDER, Value);
+}
+
+
+void CDasherInterface::FixLayout(bool Value)
+{
+ if (m_SettingsUI!=0)
+ m_SettingsUI->FixLayout(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::FIX_LAYOUT, Value);
+}
+
+
+void CDasherInterface::TimeStampNewFiles(bool Value)
+{
+ if (m_SettingsUI!=0)
+ m_SettingsUI->TimeStampNewFiles(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::TIME_STAMP, Value);
+ if (m_DashEditbox!=0)
+ m_DashEditbox->TimeStampNewFiles(Value);
+}
+
+
+void CDasherInterface::CopyAllOnStop(bool Value)
+{
+ m_CopyAllOnStop = Value;
+ if (m_SettingsUI!=0)
+ m_SettingsUI->CopyAllOnStop(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::COPY_ALL_ON_STOP, Value);
+}
+
+void CDasherInterface::DrawMouse(bool Value)
+{
+ m_DrawMouse = Value;
+ if (m_SettingsUI!=0)
+ m_SettingsUI->DrawMouse(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::DRAW_MOUSE, Value);
+}
+
+void CDasherInterface::StartOnSpace(bool Value)
+{
+ m_StartSpace = Value;
+ if (m_SettingsUI!=0)
+ m_SettingsUI->StartOnSpace(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::START_SPACE, Value);
+}
+
+void CDasherInterface::StartOnLeft(bool Value)
+{
+ m_StartLeft = Value;
+ if (m_SettingsUI!=0)
+ m_SettingsUI->StartOnLeft(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::START_MOUSE, Value);
+}
+
+void CDasherInterface::KeyControl(bool Value)
+{
+ m_KeyControl = Value;
+ if (m_SettingsUI!=0)
+ m_SettingsUI->KeyControl(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::KEY_CONTROL, Value);
+}
+
+void CDasherInterface::WindowPause(bool Value)
+{
+ m_KeyControl = Value;
+ if (m_SettingsUI!=0)
+ m_SettingsUI->WindowPause(Value);
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::WINDOW_PAUSE, Value);
+}
+
+void CDasherInterface::SetEditFont(string Name, long Size)
+{
+ m_EditFont = Name;
+ m_EditFontSize = Size;
+ if (m_DashEditbox)
+ m_DashEditbox->SetFont(Name, Size);
+ if (m_SettingsUI!=0)
+ m_SettingsUI->SetEditFont(Name, Size);
+ if (m_SettingsStore!=0) {
+ m_SettingsStore->SetStringOption(Keys::EDIT_FONT, Name);
+ m_SettingsStore->SetLongOption(Keys::EDIT_FONT_SIZE, Size);
+ }
+}
+
+
+void CDasherInterface::SetDasherFont(string Name)
+{
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetStringOption(Keys::DASHER_FONT, Name);
+ m_DasherFont = Name;
+ if (m_DasherScreen!=0)
+ m_DasherScreen->SetFont(Name);
+ Redraw();
+}
+
+void CDasherInterface::SetDasherFontSize(FontSize fontsize)
+{
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetLongOption(Keys::DASHER_FONTSIZE, fontsize);
+ if (m_DasherScreen!=0) {
+ m_DasherScreen->SetFontSize(fontsize);
+ }
+ Redraw();
+}
+
+void CDasherInterface::SetDasherDimensions(bool Value)
+{
+ m_Dimensions=Value;
+ if (m_SettingsStore!=0)
+ m_SettingsStore->SetBoolOption(Keys::DASHER_DIMENSIONS, Value);
+ if (m_DasherModel!=0) {
+ m_DasherModel->Set_dimensions(Value);
+ }
+ if (m_SettingsUI!=0) {
+ m_SettingsUI->SetDasherDimensions(Value);
+ }
+}
+
+
+unsigned int CDasherInterface::GetNumberSymbols()
+{
+ if (m_Alphabet!=0)
+ return m_Alphabet->GetNumberSymbols();
+ else
+ return 0;
+}
+
+
+const string& CDasherInterface::GetDisplayText(symbol Symbol)
+{
+ if (m_Alphabet!=0)
+ return m_Alphabet->GetDisplayText(Symbol);
+ else
+ return EmptyString;
+}
+
+
+const string& CDasherInterface::GetEditText(symbol Symbol)
+{
+ if (m_Alphabet!=0)
+ return m_Alphabet->GetText(Symbol);
+ else
+ return EmptyString;
+}
+
+int CDasherInterface::GetTextColour(symbol Symbol)
+{
+ if (m_Alphabet!=0)
+ return m_Alphabet->GetTextColour(Symbol);
+ else
+ return 0;
+}
+
+
+Opts::ScreenOrientations CDasherInterface::GetAlphabetOrientation()
+{
+ return m_Alphabet->GetOrientation();
+}
+
+
+Opts::AlphabetTypes CDasherInterface::GetAlphabetType()
+{
+ return m_Alphabet->GetType();
+}
+
+
+const std::string& CDasherInterface::GetTrainFile()
+{
+ return m_TrainFile;
+}
+
+
+void CDasherInterface::GetAlphabets(std::vector< std::string >* AlphabetList)
+{
+ if (!m_AlphIO)
+ m_AlphIO = new CAlphIO(m_SystemLocation, m_UserLocation);
+ m_AlphIO->GetAlphabets(AlphabetList);
+}
+
+
+const CAlphIO::AlphInfo& CDasherInterface::GetInfo(const std::string& AlphID)
+{
+ if (!m_AlphIO)
+ m_AlphIO = new CAlphIO(m_SystemLocation, m_UserLocation);
+
+ return m_AlphIO->GetInfo(AlphID);
+}
+
+
+void CDasherInterface::SetInfo(const CAlphIO::AlphInfo& NewInfo)
+{
+ if (!m_AlphIO)
+ m_AlphIO = new CAlphIO(m_SystemLocation, m_UserLocation);
+
+ m_AlphIO->SetInfo(NewInfo);
+}
+
+
+void CDasherInterface::DeleteAlphabet(const std::string& AlphID)
+{
+ if (!m_AlphIO)
+ m_AlphIO = new CAlphIO(m_SystemLocation, m_UserLocation);
+
+ m_AlphIO->Delete(AlphID);
+}
+
+
+void CDasherInterface::ChangeEdit()
+{
+ CreateDasherModel();
+ if (m_DasherModel!=0)
+ m_DasherModel->Start();
+ if (m_DasherView!=0)
+ m_DasherView->Render();
+}
+
+
+void CDasherInterface::ChangeEdit(CDashEditbox* NewEdit)
+{
+ m_DashEditbox = NewEdit;
+ m_DashEditbox->SetFont(m_EditFont, m_EditFontSize);
+ m_DashEditbox->SetInterface(this);
+ if (m_SettingsStore!=0)
+ m_DashEditbox->TimeStampNewFiles(m_SettingsStore->GetBoolOption(Keys::TIME_STAMP));
+ m_DashEditbox->New("");
+ ChangeEdit();
+}
+
+
+void CDasherInterface::Train(string* TrainString, bool IsMore)
+{
+ m_LanguageModel->LearnText(TrainContext, TrainString, IsMore);
+ return;
+}
+
+
+/*
+ I've used C style I/O because I found that C++ style I/O bloated
+ the Win32 code enormously. The overhead of loading the buffer into
+ the string instead of reading straight into a string seems to be
+ negligible compared to huge requirements elsewhere.
+*/
+void CDasherInterface::TrainFile(string Filename)
+{
+ if (Filename=="")
+ return;
+
+ FILE* InputFile;
+ if ( (InputFile = fopen(Filename.c_str(), "r")) == (FILE*)0)
+ return;
+
+ const int BufferSize = 1024;
+ char InputBuffer[BufferSize];
+ string StringBuffer;
+ int NumberRead;
+
+ do {
+ NumberRead = fread(InputBuffer, 1, BufferSize-1, InputFile);
+ InputBuffer[NumberRead] = '\0';
+ StringBuffer += InputBuffer;
+ if (NumberRead == (BufferSize-1)) {
+ m_LanguageModel->LearnText(TrainContext, &StringBuffer, true);
+ } else {
+ m_LanguageModel->LearnText(TrainContext, &StringBuffer, false);
+ }
+ } while (NumberRead==BufferSize-1);
+
+ fclose(InputFile);
+}
+
+void CDasherInterface::GetFontSizes(std::vector<int> *FontSizes)
+{
+ FontSizes->push_back(20);
+ FontSizes->push_back(14);
+ FontSizes->push_back(11);
+ FontSizes->push_back(40);
+ FontSizes->push_back(28);
+ FontSizes->push_back(22);
+ FontSizes->push_back(80);
+ FontSizes->push_back(56);
+ FontSizes->push_back(44);
+}
+
+
+double CDasherInterface::GetCurCPM()
+{
+ //
+ return 0;
+}
+
+
+double CDasherInterface::GetCurFPS()
+{
+ //
+ return 0;
+}
diff --git a/inputmethods/dasher/DasherInterface.h b/inputmethods/dasher/DasherInterface.h
new file mode 100644
index 0000000..6338801
--- a/dev/null
+++ b/inputmethods/dasher/DasherInterface.h
@@ -0,0 +1,170 @@
+// DasherInterface.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef __DasherInterface_h__
+#define __DasherInterface_h__
+
+// 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 "MSVC_Unannoy.h"
+#include "NoClones.h"
+
+#include "DasherWidgetInterface.h"
+#include "DasherAppInterface.h"
+#include "DasherSettingsInterface.h"
+
+#include "DasherScreen.h"
+#include "Alphabet.h"
+#include "AlphIO.h"
+#include "LanguageModel.h"
+#include "DasherModel.h"
+#include "DashEdit.h"
+#include "DasherView.h"
+
+#include "MSVC_Unannoy.h"
+#include <map>
+
+namespace Dasher {class CDasherInterface;}
+class Dasher::CDasherInterface : private NoClones,
+ public CDasherWidgetInterface, public CDasherAppInterface, public CDasherSettingsInterface
+{
+public:
+ CDasherInterface();
+ ~CDasherInterface();
+
+ //! Tell the core which CSettingsStore should be used
+ void SetSettingsStore(CSettingsStore* SettingsStore);
+
+ //! Tell the core which CDasherSettingsInterface should be used
+ //
+ //! Provide a pointer to an instance of CDasherSettingsInterface in
+ //! order to allow for platform dependent configuration of certain
+ //! options
+ void SetSettingsUI(CDasherSettingsInterface* SettingsUI);
+
+ //! Set the path for user specific configuration and files
+ void SetUserLocation(std::string UserLocation);
+
+ //! Set the path for system-wide configuration and files
+ void SetSystemLocation(std::string SystemLocation);
+
+ // Widget Interface
+ // -----------------------------------------------------
+ void Start();
+
+ void TapOn(int MouseX, int MouseY, unsigned long Time); // Times in milliseconds
+ void PauseAt(int MouseX, int MouseY); // are required to make
+ void Unpause(unsigned long Time); // Dasher run at the
+ void Redraw(); // correct speed.
+
+ void ChangeScreen(); // The widgets need to tell the engine when they have been
+ void ChangeEdit(); // affected by external interaction
+
+ unsigned int GetNumberSymbols(); // These are needed so widgets know
+ const std::string& GetDisplayText(symbol Symbol); // how to render the alphabet. All
+ const std::string& GetEditText(symbol Symbol); // strings are encoded in UTF-8
+ int GetTextColour(symbol Symbol); // the foreground colour of the text
+ Opts::ScreenOrientations GetAlphabetOrientation();
+ Opts::AlphabetTypes GetAlphabetType();
+ const std::string& GetTrainFile();
+
+ // App Interface
+ // -----------------------------------------------------
+
+ // std::map<int, std::string>& GetAlphabets(); // map<key, value> int is a UID string can change. Store UID in preferences. Display string to user.
+ // std::vector<std::string>& GetAlphabets();
+ // std::vector<std::string>& GetLangModels();
+ // std::vector<std::string>& GetViews();
+
+ void ChangeScreen(CDasherScreen* NewScreen); // We may change the widgets Dasher uses
+ void ChangeEdit(CDashEditbox* NewEdit); // at run time.
+
+ void Train(std::string* TrainString, bool IsMore); // Training by string segments or file
+ void TrainFile(std::string Filename); // all training data must be in UTF-8.
+
+ void GetFontSizes(std::vector<int> *FontSizes);
+
+ double GetCurCPM(); // App may want to display characters per minute
+ double GetCurFPS(); // or frames per second.
+
+ // Customize alphabet
+ void GetAlphabets(std::vector< std::string >* AlphabetList);
+ const CAlphIO::AlphInfo& GetInfo(const std::string& AlphID);
+ void SetInfo(const CAlphIO::AlphInfo& NewInfo);
+ void DeleteAlphabet(const std::string& AlphID);
+
+ // Settings Interface (options saved between sessions)
+ // -----------------------------------------------------
+
+ void ChangeAlphabet(const std::string& NewAlphabetID);
+ void ChangeMaxBitRate(double NewMaxBitRate);
+ void ChangeLanguageModel(unsigned int NewLanguageModelID);
+ void ChangeView(unsigned int NewViewID);
+ void ChangeOrientation(Opts::ScreenOrientations Orientation);
+ void SetFileEncoding(Opts::FileEncodingFormats Encoding);
+ // TODO Color customization.
+
+ void ShowToolbar(bool Value);
+ void ShowToolbarText(bool Value);
+ void ShowToolbarLargeIcons(bool Value);
+ void ShowSpeedSlider(bool Value);
+ void FixLayout(bool Value);
+ void TimeStampNewFiles(bool Value);
+ void CopyAllOnStop(bool Value);
+ void DrawMouse(bool Value);
+ void StartOnSpace(bool Value);
+ void StartOnLeft(bool Value);
+ void KeyControl(bool Value);
+ void WindowPause(bool Value);
+ void SetEditFont(std::string Name, long Size);
+ void SetDasherFont(std::string Name);
+ void SetDasherFontSize(FontSize fontsize);
+ void SetDasherDimensions(bool Value);
+
+private:
+ CAlphabet* m_Alphabet;
+ CLanguageModel* m_LanguageModel;
+ CDasherModel* m_DasherModel;
+ CDashEditbox* m_DashEditbox;
+ CDasherScreen* m_DasherScreen;
+ CDasherView* m_DasherView;
+ CSettingsStore* m_SettingsStore;
+ CDasherSettingsInterface* m_SettingsUI;
+ CAlphIO* m_AlphIO;
+
+ CLanguageModel::CNodeContext* TrainContext;
+
+ std::string AlphabetID;
+ int LanguageModelID;
+ int ViewID;
+ double m_MaxBitRate;
+ bool m_CopyAllOnStop;
+ bool m_DrawMouse;
+ bool m_DrawKeyboard;
+ bool m_StartSpace;
+ bool m_StartLeft;
+ bool m_KeyControl;
+ bool m_Dimensions;
+ bool m_WindowPause;
+ Opts::ScreenOrientations m_Orientation;
+ std::string m_UserLocation;
+ std::string m_SystemLocation;
+ std::string m_TrainFile;
+ std::string m_DasherFont;
+ std::string m_EditFont;
+ int m_EditFontSize;
+ static const std::string EmptyString;
+
+ void CreateDasherModel();
+};
+
+
+#endif /* #ifndef __DasherInterface_h__ */
diff --git a/inputmethods/dasher/DasherModel.cpp b/inputmethods/dasher/DasherModel.cpp
new file mode 100644
index 0000000..0450d66
--- a/dev/null
+++ b/inputmethods/dasher/DasherModel.cpp
@@ -0,0 +1,322 @@
+// DasherModel.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include <iostream>
+#include "DasherModel.h"
+
+using namespace Dasher;
+using namespace std;
+
+//////////////////////////////////////////////////////////////////////
+// CDasherModel
+//////////////////////////////////////////////////////////////////////
+
+CDasherModel::CDasherModel(CDashEditbox* Editbox, CLanguageModel* LanguageModel, bool Dimensions)
+ : m_editbox(Editbox), m_languagemodel(LanguageModel), m_Root(0), m_Dimensions(Dimensions)
+{
+ LearnContext = m_languagemodel->GetRootNodeContext();
+
+ // various settings
+ int iShift = 12;
+ m_DasherY = 1<<iShift;
+ m_DasherOY = m_DasherY/2;
+ m_DasherOX = m_DasherY/2;
+ m_dAddProb = 0.003;
+}
+
+
+CDasherModel::~CDasherModel()
+{
+ m_languagemodel->ReleaseNodeContext(LearnContext);
+ delete m_Root; // which will also delete all the whole structure
+}
+
+
+void CDasherModel::Make_root(int whichchild)
+ // find a new root node
+{
+ symbol t=m_Root->Symbol();
+ if (t) {
+ m_editbox->output(t);
+ m_languagemodel->LearnNodeSymbol(LearnContext, t);
+ }
+
+ CDasherNode * oldroot=m_Root;
+
+ CDasherNode **children=m_Root->Children();
+ m_Root=children[whichchild];
+ // oldroot->Children()[whichchild]=0; // null the pointer so we don't delete the whole tree
+ // delete oldroot;
+
+ oldroots.push_back(oldroot);
+
+ myint range=m_Rootmax-m_Rootmin;
+ m_Rootmax=m_Rootmin+(range*m_Root->Hbnd())/Normalization();
+ m_Rootmin+=(range*m_Root->Lbnd())/Normalization();
+}
+
+void CDasherModel::Reparent_root(int lower, int upper)
+{
+ /* Change the root node to the parent of the existing node
+ We need to recalculate the coordinates for the "new" root as the
+ user may have moved around within the current root */
+
+ /* Determine how zoomed in we are */
+ float scalefactor=(m_Rootmax-m_Rootmin)/(upper-lower);
+
+ m_Rootmax=int(m_Rootmax+((1024-upper)*scalefactor));
+ m_Rootmin=int(m_Rootmin-(lower*scalefactor));
+
+ m_editbox->deletetext();
+
+ m_Root=oldroots.back();
+ oldroots.pop_back();
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+CDasherNode * CDasherModel::Get_node_under_crosshair()
+{
+ return m_Root->Get_node_under(Normalization(),m_Rootmin,m_Rootmax,m_DasherOX,m_DasherOY);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+CDasherNode * CDasherModel::Get_node_under_mouse(myint Mousex,myint Mousey)
+{
+ return m_Root->Get_node_under(Normalization(),m_Rootmin,m_Rootmax,Mousex,Mousey);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+void CDasherModel::Get_string_under_mouse(const myint Mousex,const myint Mousey, vector<symbol> &str)
+{
+ m_Root->Get_string_under(Normalization(),m_Rootmin,m_Rootmax,Mousex,Mousey,str);
+ return;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+
+void CDasherModel::Flush(const myint Mousex,const myint Mousey)
+{
+ vector<symbol> vtUnder;
+ Get_string_under_mouse(m_DasherOX,m_DasherOY,vtUnder);
+ unsigned int i;
+ for (i=0;i<vtUnder.size();i++) {
+ if (vtUnder[i]==0)
+ continue;
+ m_editbox->flush(vtUnder[i]);
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherModel::Update(CDasherNode *node,CDasherNode *under_mouse,int iSafe)
+// go through the Dasher nodes, delete ones who have expired
+// decrease the time left for nodes which arent safe
+// safe nodes are those which are under the mouse or offspring of this node
+{
+// if (node->pushme )
+// node->push_node();
+ if (node==under_mouse)
+ iSafe=1;
+ if (!iSafe)
+ node->Age();
+// dchar debug[256];
+// wsprintf(debug,TEXT("node->Age %d %f\n"),node->Age, fr.framerate());
+// OutputDebugString(debug);
+
+
+ if (node->Age() > Framerate())
+ node->Kill();
+
+
+ if (node->Alive()) {
+ CDasherNode **children=node->Children();
+ if (children) {
+ unsigned int i;
+ for (i=1;i<node->Chars();i++)
+ Update(children[i],under_mouse,iSafe);
+ }
+ }
+ return;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherModel::Start()
+{
+ m_Rootmin=0;
+ m_Rootmax=m_DasherY;
+
+ delete m_Root;
+ CLanguageModel::CNodeContext* therootcontext=m_languagemodel->GetRootNodeContext();
+
+ //Rootparent=new DasherNode(0,0,0,therootcontext,0,0,0,Normalization(),languagemodel);
+ if (m_editbox) {
+ m_editbox->set_flushed(0);
+ string ContextString;
+ m_editbox->get_new_context(ContextString,5);
+ if (ContextString.size() != 0) {
+ m_languagemodel->EnterText(therootcontext, ContextString);
+ }
+ m_languagemodel->ReleaseNodeContext(LearnContext);
+ LearnContext = m_languagemodel->CloneNodeContext(therootcontext);
+ }
+ m_Root=new CDasherNode(0,0,0,0,Opts::Nodes1,0,Normalization(),m_languagemodel);
+ m_Root->Push_Node(therootcontext);
+
+ m_languagemodel->ReleaseNodeContext(therootcontext);
+// ppmmodel->dump();
+// dump();
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherModel::Get_new_root_coords(myint Mousex,myint Mousey)
+{
+ int cappedrate=0;
+ double dRx=1.0,dRxnew=1.0;
+ double dRxnew2;
+
+ int iSteps=m_fr.Steps();
+
+ if (Mousex<m_DasherOX) {
+ // rx=1.0001*Ixmap[mx]/Ixmap[cx];
+ if (Mousex<=0)
+ Mousex=1;
+ dRx=1.0*m_DasherOX/Mousex;
+ dRxnew=pow(dRx,1.0/iSteps); // or exp(log(rx)/steps) - i think the replacement is faster
+
+ dRxnew2=1+(dRx-1)/iSteps;
+ //+(rx-1)*(rx-1)*(1.0/fr.steps()-1.0)/2/fr.steps();
+
+
+ const double dRxmax=m_fr.Rxmax();
+ if (dRxnew>dRxmax)
+ dRxnew=dRxmax;
+ // cappedrate=1;
+ } else {
+ if (Mousex==m_DasherOX)
+ Mousex++;
+ // OutputDebugString(TEXT("zoom out\n"));
+ dRx=1.0001*m_DasherOX/Mousex;
+ dRxnew=exp(log(dRx)/iSteps);
+ // get_coords(root->lbnd,root->hbnd,&x1,&y1,&y2);
+ //if (x1>0 || y1>0 || y2<CanvasY)
+ //go_back_a_char();
+ if (m_Rootmax<m_DasherY && m_Rootmin>0)
+ return;
+ }
+// dchar debug[256];
+// _stprintf(debug,TEXT("rx %f rxnew %f approx %f\n"),rx,rxnew,rxnew2);
+// OutputDebugString(debug);
+ //wsprintf(debug,TEXT("rx %f rxnew %f\n"),rx,rxnew);
+ //OutputDebugString(debug);
+ myint above=(Mousey-m_Rootmin);//*(1-rxnew)/(1-rx);
+ myint below=(m_Rootmax-Mousey);//*(1-rxnew)/(1-rx);
+
+// wsprintf(debug,TEXT("above %I64d below %I64d \n"),above,below);
+// OutputDebugString(debug);
+
+ myint miDistance=m_DasherY/2-Mousey;
+ miDistance=myint(miDistance*(dRxnew-1)/(dRx-1));
+ myint miNewrootzoom=Mousey+miDistance;
+
+ myint newRootmax=miNewrootzoom+myint(below*dRxnew);
+ myint newRootmin=miNewrootzoom-myint(above*dRxnew);
+ if (newRootmin<m_DasherY/2 && newRootmax>m_DasherY/2 && newRootmax<LLONG_MAX && newRootmin>LLONG_MIN) {
+ m_Rootmax=newRootmax;
+ m_Rootmin=newRootmin;
+ }
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherModel::Tap_on_display(myint miMousex,myint miMousey, unsigned long Time)
+ // work out the next viewpoint, opens some new nodes
+{
+ // works out next viewpoint
+ Get_new_root_coords(miMousex,miMousey);
+
+ // opens up new nodes
+
+ // push node under mouse
+ CDasherNode *under_mouse=Get_node_under_mouse(miMousex,miMousey);
+ under_mouse->Push_Node();
+
+
+ if (Framerate() > 4) {
+ // push node under mouse but with x coord on RHS
+ CDasherNode *right=Get_node_under_mouse(50,miMousey);
+ right->Push_Node();
+ }
+
+ if (Framerate() > 8) {
+ // push node under the crosshair
+ CDasherNode *under_cross=Get_node_under_crosshair();
+ under_cross->Push_Node();
+ }
+
+ unsigned int iRandom;
+#if defined(_WIN32_WCE)
+ iRandom=Random();
+#else
+ iRandom=rand();
+#endif
+ if (Framerate() > 8) {
+ // add some noise and push another node
+ CDasherNode *right=Get_node_under_mouse(50,miMousey+iRandom%500-250);
+ right->Push_Node();
+ }
+#if defined(_WIN32_WCE)
+ iRandom=Random();
+#else
+ iRandom=rand();
+#endif
+ if (Framerate() > 15) {
+ // add some noise and push another node
+ CDasherNode *right=Get_node_under_mouse(50,miMousey+iRandom%500-250);
+ right->Push_Node();
+ }
+
+ // only do this is Dasher is flying
+ if (Framerate() > 30) {
+ for (int i=1;i<int(Framerate()-30)/3;i++) {
+#if defined(_WIN32_WCE)
+ iRandom=Random();
+#else
+ iRandom=rand();
+#endif
+ // push at a random node on the RHS
+ CDasherNode *right=Get_node_under_mouse(50,miMousey+iRandom%1000-500);
+ right->Push_Node();
+
+ }
+ }
+ Update(m_Root,under_mouse,0);
+
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherModel::Dump() const
+ // diagnostic dump
+{
+ // OutputDebugString(TEXT(" ptr symbol context Next Child pushme pushed cscheme lbnd hbnd \n"));
+ m_Root->Dump_node();
+}
+
+
+
diff --git a/inputmethods/dasher/DasherModel.h b/inputmethods/dasher/DasherModel.h
new file mode 100644
index 0000000..348900f
--- a/dev/null
+++ b/inputmethods/dasher/DasherModel.h
@@ -0,0 +1,111 @@
+// DasherModel.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __DasherModel_h__
+#define __DasherModel_h__
+
+#include <iostream>
+#include "MSVC_Unannoy.h"
+#include "DashEdit.h"
+#include "DasherNode.h"
+#include "LanguageModel.h"
+#include "NoClones.h"
+#include <math.h>
+#include "DasherTypes.h"
+#include "FrameRate.h"
+#include <vector>
+
+// The CDasherModel represents the current state of Dasher
+// It contains a pointer to a structure of DasherNodes
+// The knows the current viewpoint
+// It also knows how to evolve the viewpoint
+
+namespace Dasher {class CDasherModel;}
+class Dasher::CDasherModel : private NoClones
+{
+public:
+
+ CDasherModel(CDashEditbox* Editbox, CLanguageModel* LanguageModel, bool Dimensions);
+ ~CDasherModel();
+
+ // framerate functions
+ void NewFrame(unsigned long Time) {m_fr.NewFrame(Time);} // called everytime we render a new frame
+ const double Framerate () {return m_fr.Framerate();} // return the framerate
+
+ // User control of speed
+ void SetBitrate(double TargetRate) {m_fr.SetBitrate(TargetRate);} // Use or start at this bitrate
+ void SetMaxBitrate(double MaxRate) {m_fr.SetMaxBitrate(MaxRate);} // Cap any adaption at this rate
+
+ // functions returning private data (read only access)
+ const myint Rootmin() const {return m_Rootmin;}
+ const myint Rootmax() const {return m_Rootmax;}
+ const myint DasherOX() const {return m_DasherOX;}
+ CDasherNode* Root() const {return m_Root;}
+ int Normalization() const {return m_languagemodel->normalization();}
+ myint DasherY() const {return m_DasherY;}
+ bool Dimensions() const {return m_Dimensions;}
+
+ void Dump() const; // diagnostics
+ void Flush(const myint smousex,const myint smousey); // flush to the edit control
+ //void Learn_symbol(symbol Symbol) {m_languagemodel->learn_symbol(Symbol);} // feed character to language model
+
+ void Set_dimensions(bool dimensions) {m_Dimensions=dimensions;}
+
+ void Tap_on_display(myint,myint, unsigned long Time); // evolves the current viewpoint
+ void Start(); // initializes the data structure
+ void Make_root(int whichchild); // find a new root node
+ void Reparent_root(int lower, int upper); // change back to the previous root
+ void Reset_framerate(unsigned long Time) {m_fr.Reset(Time);}
+
+ CAlphabet* m_alphabet; // pointer to the alphabet
+
+ CAlphabet* GetAlphabet() { return m_alphabet; }
+private:
+
+ // Old root notes
+ std::vector<CDasherNode*> oldroots;
+
+ // Rootmin and Rootmax specify the position of the root node in Dasher coords
+ myint m_Rootmin,m_Rootmax;
+
+ // Size of Dasher's arithmetic coding interval - it defines the Dasher coordinate system
+ myint m_DasherY;
+
+ // x position of crosshair in Dasher coords - distance from RHS is square Dasher
+ myint m_DasherOX;
+
+ // y position of crosshair in Dasher coords - distance from top in square Dasher
+ myint m_DasherOY;
+
+ // Number of input dimensions
+ bool m_Dimensions;
+
+ CDashEditbox* m_editbox; // pointer to the editbox
+ CLanguageModel* m_languagemodel; // pointer to the language model
+ CLanguageModel::CNodeContext* LearnContext; // Used to add data to model as it is entered
+ CFrameRate m_fr; // keep track of framerate
+
+ // TODO - move somewhere
+ // the probability that gets added to every symbol
+ double m_dAddProb;
+
+ CDasherNode* Get_node_under_mouse(myint smousex,myint smousey);
+ CDasherNode* Get_node_under_crosshair();
+ CDasherNode* m_Root;
+ void Get_new_root_coords(myint mousex,myint mousey);
+ void Get_string_under_mouse(const myint smousex,const myint smousey,std::vector<symbol> &str);
+ void Update(CDasherNode* node,CDasherNode* under,int safe);
+
+
+
+
+
+};
+
+
+#endif /* #ifndef __DasherModel_h__ */
diff --git a/inputmethods/dasher/DasherNode.cpp b/inputmethods/dasher/DasherNode.cpp
new file mode 100644
index 0000000..26af10f
--- a/dev/null
+++ b/inputmethods/dasher/DasherNode.cpp
@@ -0,0 +1,167 @@
+// DasherNode.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "DasherNode.h"
+using namespace Dasher;
+using namespace Opts;
+using namespace std;
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherNode::Dump_node () const
+{
+ /* TODO sort out
+ dchar out[256];
+ if (m_Symbol)
+ wsprintf(out,TEXT("%7x %3c %7x %5d %7x %5d %8x %8x \n"),this,m_Symbol,m_iGroup,m_context,m_Children,m_Cscheme,m_iLbnd,m_iHbnd);
+ else
+ wsprintf(out,TEXT("%7x %7x %5d %7x %5d %8x %8x \n"),this,m_iGroup,m_context,m_Children,m_Cscheme,m_iLbnd,m_iHbnd);
+
+ OutputDebugString(out);
+
+ if (m_Children) {
+ unsigned int i;
+ for (i=1;i<m_iChars;i++)
+ m_Children[i]->Dump_node();
+ }
+ */
+}
+
+void CDasherNode::Generic_Push_Node(CLanguageModel::CNodeContext *context) {
+
+ m_iAge=0;
+ m_bAlive=true;
+ if (m_Symbol && !m_iChars) // make sure it's a valid symbol and don't enter if already done
+ m_languagemodel->EnterNodeSymbol(m_context,m_Symbol);
+
+
+ vector<symbol> newchars; // place to put this list of characters
+ vector<unsigned int> cum,groups; // for the probability list
+ m_languagemodel->GetNodeProbs(m_context,newchars,groups,cum,0.003);
+ m_iChars=newchars.size();
+ // work out cumulative probs
+ unsigned int i;
+ for (i=1;i<m_iChars;i++)
+ cum[i]+=cum[i-1];
+
+ m_Children =new CDasherNode *[m_iChars];
+
+ // create the children
+ ColorSchemes NormalScheme, SpecialScheme;
+ if ((m_ColorScheme==Nodes1) || (m_ColorScheme==Special1)) {
+ NormalScheme = Nodes2;
+ SpecialScheme = Special2;
+ } else {
+ NormalScheme = Nodes1;
+ SpecialScheme = Special1;
+ }
+
+ ColorSchemes ChildScheme;
+ for (i=1;i<m_iChars;i++) {
+ if (newchars[i]==this->m_languagemodel->GetSpaceSymbol())
+ ChildScheme = SpecialScheme;
+ else
+ ChildScheme = NormalScheme;
+ m_Children[i]=new CDasherNode(this,newchars[i],groups[i],i,ChildScheme,cum[i-1],cum[i],m_languagemodel,m_languagemodel->GetColour(i));
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherNode::Push_Node(CLanguageModel::CNodeContext *context)
+// push a node copying the specified context
+{
+
+ if (m_Children) {
+ // if there are children just give them a poke
+ unsigned int i;
+ for (i=1;i<m_iChars;i++) {
+ m_Children[i]->m_iAge=0;
+ m_Children[i]->m_bAlive=1;
+ }
+ return;
+ }
+
+ // if we haven't got a context then try to get a new one
+ m_context=m_languagemodel->CloneNodeContext(context);
+ // if it fails, be patient
+ if (!m_context)
+ return;
+ Generic_Push_Node(m_context);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherNode::Push_Node()
+{
+
+ if (m_Children) {
+ // if there are children just give them a poke
+ unsigned int i;
+ for (i=1;i<m_iChars;i++) {
+ m_Children[i]->m_iAge=0;
+ m_Children[i]->m_bAlive=1;
+ }
+ return;
+ }
+
+ // if we haven't got a context then try to get a new one
+ if (m_parent)
+ m_context=m_languagemodel->CloneNodeContext(m_parent->m_context);
+ else
+ m_context=m_languagemodel->GetRootNodeContext();
+
+ // if it fails, be patient
+ if (!m_context)
+ return;
+ Generic_Push_Node(m_context);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherNode::Get_string_under(const int iNormalization,const myint miY1,const myint miY2,const myint miMousex,const myint miMousey, vector<symbol> &vString) const
+{
+ // we are over (*this) node so add it to the string
+ vString.push_back(m_Symbol);
+
+ // look for children who might also be under the coords
+ if (m_Children) {
+ myint miRange=miY2-miY1;
+ unsigned int i;
+ for (i=1;i<m_iChars;i++) {
+ myint miNewy1=miY1+(miRange*m_Children[i]->m_iLbnd)/iNormalization;
+ myint miNewy2=miY1+(miRange*m_Children[i]->m_iHbnd)/iNormalization;
+ if (miMousey<miNewy2 && miMousey>miNewy1 && miMousex<miNewy2-miNewy1) {
+ m_Children[i]->Get_string_under(iNormalization,miNewy1,miNewy2,miMousex,miMousey,vString);
+ return;
+ }
+ }
+ }
+ return;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+CDasherNode * const CDasherNode::Get_node_under(int iNormalization,myint miY1,myint miY2,myint miMousex,myint miMousey)
+{
+ if (m_Children) {
+ myint miRange=miY2-miY1;
+ m_iAge=0;
+ m_bAlive=true;
+ unsigned int i;
+ for (i=1;i<m_iChars;i++) {
+ myint miNewy1=miY1+(miRange*m_Children[i]->m_iLbnd)/iNormalization;
+ myint miNewy2=miY1+(miRange*m_Children[i]->m_iHbnd)/iNormalization;
+ if (miMousey<miNewy2 && miMousey>miNewy1 && miMousex<miNewy2-miNewy1)
+ return m_Children[i]->Get_node_under(iNormalization,miNewy1,miNewy2,miMousex,miMousey);
+ }
+ }
+ return this;
+}
+
+/////////////////////////////////////////////////////////////////////////////
diff --git a/inputmethods/dasher/DasherNode.h b/inputmethods/dasher/DasherNode.h
new file mode 100644
index 0000000..705a9d4
--- a/dev/null
+++ b/inputmethods/dasher/DasherNode.h
@@ -0,0 +1,127 @@
+// DasherNode.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __DasherNode_h__
+#define __DasherNode_h__
+
+#include "NoClones.h"
+#include "DasherTypes.h"
+#include "LanguageModel.h"
+
+namespace Dasher {class CDasherNode;}
+class Dasher::CDasherNode : private NoClones
+{
+ // CDasherNode represents a rectangle and character
+ // nodes have children, siblings and parents
+private:
+ const unsigned int m_iLbnd,m_iHbnd;// the cumulative lower and upper bound prob relative to parent
+ const unsigned int m_iGroup; // group membership - e.g. 0=nothing 1=caps 2=punc
+ unsigned int m_iChars, m_iAge;
+ bool m_bAlive; // if true, then display node, else dont bother
+ bool m_bControlNode; // if true, node is a control node
+ bool m_bControlChild; // if true, node is offspring of a control node
+ //bool m_Cscheme; // color scheme for the node - alternates through relatives
+ Opts::ColorSchemes m_ColorScheme;
+ int m_iPhase; // index for coloring
+ int m_iColour; // for the advanced colour mode
+
+ const symbol m_Symbol; // the character to display
+ CLanguageModel *m_languagemodel; // pointer to the language model - in future, could be different for each node
+ CDasherNode **m_Children; // pointer to array of children
+ CDasherNode *m_parent; // pointer to parent - only needed to grab parent context
+ CLanguageModel::CNodeContext *m_context;
+public:
+
+ CDasherNode(CDasherNode *parent,symbol Symbol, unsigned int igroup, int iphase, Opts::ColorSchemes ColorScheme,int ilbnd,int ihbnd,CLanguageModel *lm, int Colour);
+ ~CDasherNode();
+ bool m_bForce; // flag to force a node to be drawn - shouldn't be public
+
+ // return private data members - read only
+ CDasherNode ** const Children() const {return m_Children;}
+ unsigned int Lbnd() const {return m_iLbnd;}
+ bool Alive() {return m_bAlive;}
+ bool Control() {return m_bControlChild;}
+ void Kill() {m_bAlive=0;m_iAge=0;}
+ unsigned int Hbnd() const {return m_iHbnd;}
+ unsigned int Group() const {return m_iGroup;}
+ unsigned int Age() const {return m_iAge;}
+ symbol Symbol() const {return m_Symbol;}
+ unsigned int Chars() const {return m_iChars;}
+ int Phase() const {return m_iPhase;}
+ Opts::ColorSchemes Cscheme() const {return m_ColorScheme;}
+ int Colour() const {return m_iColour;}
+
+ CDasherNode* const Get_node_under(int,myint y1,myint y2,myint smousex,myint smousey); // find node under given co-ords
+ void Get_string_under(const int,const myint y1,const myint y2,const myint smousex,const myint smousey,std::vector<symbol>&) const; // get string under given co-ords
+ void Generic_Push_Node(CLanguageModel::CNodeContext *context);
+ void Push_Node(); // give birth to children
+ void Push_Node(CLanguageModel::CNodeContext *context); // give birth to children with this context
+ void Delete_children();
+ void Dump_node() const; // diagnostic
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Inline functions
+/////////////////////////////////////////////////////////////////////////////
+
+using namespace Dasher;
+using namespace Opts;
+
+/////////////////////////////////////////////////////////////////////////////
+
+inline CDasherNode::CDasherNode(CDasherNode *parent,symbol Symbol, unsigned int igroup, int iphase, ColorSchemes ColorScheme,int ilbnd,int ihbnd,CLanguageModel *lm, int Colour=0)
+ : m_parent(parent),m_Symbol(Symbol),m_iGroup(igroup),m_iLbnd(ilbnd),m_iHbnd(ihbnd),m_languagemodel(lm),m_iPhase(iphase),
+ m_context(0), m_iAge(0), m_bAlive(1), m_Children(0), m_bForce(false), m_iChars(0), m_ColorScheme(ColorScheme), m_bControlChild(false), m_iColour(Colour)
+{
+ /*
+ switch (ColorScheme) {
+ case Nodes1:
+ m_ColorScheme = Nodes2;
+ break;
+ case Nodes2:
+ m_ColorScheme = Nodes1;
+ break;
+ case Special1:
+ m_ColorScheme = Special2;
+ break;
+ case Special2:
+ m_ColorScheme = Special1;
+ break;
+ case default:
+ m_ColorScheme = ColorScheme;
+ break;
+ }
+ */
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+inline void CDasherNode::Delete_children()
+{
+ if (m_Children) {
+ unsigned int i;
+ for (i=1;i<m_iChars;i++)
+ delete m_Children[i];
+ delete [] m_Children;
+ }
+ m_Children=0;
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+inline CDasherNode::~CDasherNode()
+{
+ Delete_children();
+ if (m_context)
+ m_languagemodel->ReleaseNodeContext(m_context);
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+#endif /* #ifndef __DasherNode_h__ */
diff --git a/inputmethods/dasher/DasherScreen.h b/inputmethods/dasher/DasherScreen.h
new file mode 100644
index 0000000..36ca780
--- a/dev/null
+++ b/inputmethods/dasher/DasherScreen.h
@@ -0,0 +1,102 @@
+//! Class definition for the Dasher screen
+// DasherScreen.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __DasherScreen_h_
+#define __DasherScreen_h_
+
+#include "DasherWidgetInterface.h"
+#include "DasherTypes.h"
+
+namespace Dasher {class CDasherScreen;}
+class Dasher::CDasherScreen
+{
+public:
+ //! \param width Width of the screen
+ //! \param height Height of the screen
+ CDasherScreen(int width,int height)
+ : m_iWidth(width), m_iHeight(height) {}
+
+ //! Set the widget interface used for communication with the core
+ virtual void SetInterface(CDasherWidgetInterface* DasherInterface) {m_DasherInterface = DasherInterface;}
+
+ //! Return the width of the screen
+ int GetWidth() const { return m_iWidth; }
+
+ //! Return the height of the screen
+ int GetHeight() const { return m_iHeight; }
+
+ //! Structure defining a point on the screen
+ typedef struct tagpoint { int x; int y; } point;
+
+ //! Set the Dasher font (ie, the screen font) to Name
+ //!
+ //! This is the font used to render letters in the main screen
+ virtual void SetFont(std::string Name)=0;
+
+ //! Set the Dasher font to Normal, Big or VBig
+ virtual void SetFontSize(Dasher::Opts::FontSize fontsize)=0;
+
+ //! Return the Dasher font size
+ virtual Dasher::Opts::FontSize GetFontSize()=0;
+
+ // DasherView asks for the width and height of the given symbol at a requested height,
+ // then it is able to sensibly specify the upper left corner in DrawText.
+ //! Set Width and Height to those of the character Character at size Size
+ virtual void TextSize(symbol Character, int* Width, int* Height, int Size) const=0;
+ //! Draw character Character of size Size positioned at x1 and y1
+ virtual void DrawText(symbol Character, int x1, int y1, int Size) const=0;
+
+
+ // Draw a filled rectangle - given position and color id
+ //! Draw a filled rectangle
+ //
+ //! Draw a coloured rectangle on the screen
+ //! \param x1 top left of rectangle (x coordinate)
+ //! \param y1 top left corner of rectangle (y coordinate)
+ //! \param x2 bottom right of rectangle (x coordinate)
+ //! \param y2 bottom right of rectangle (y coordinate)
+ //! \param Color the colour to be used (numeric)
+ //! \param ColorScheme Which colourscheme is to be used
+ virtual void DrawRectangle(int x1, int y1, int x2, int y2, int Color, Opts::ColorSchemes ColorScheme) const=0;
+
+ // Draw a line of fixed colour (usually black). Intended for static UI elements such as a cross-hair
+ //! Draw a line between each of the points in the array
+ //
+ //! \param Number the number of points in the array
+ virtual void Polyline(point* Points, int Number) const=0;
+
+ // Draw a filled polygon - given vertices and color id
+ // This is not (currently) used in standard Dasher. However, it could be very
+ // useful in the future. Please implement unless it will be very difficult,
+ // in which case make this function call Polyline.
+ //! Draw a filled polygon
+ //
+ //! \param Points array of points defining the edge of the polygon
+ //! \param Number number of points in the array
+ //! \param Color colour of the polygon (numeric)
+ //! \param Colorscheme Which colourscheme is to be used
+ virtual void DrawPolygon(point* Points, int Number, int Color, Opts::ColorSchemes ColorScheme) const=0;
+
+ // Signal the screen when a frame is started and finished
+ //! Signal that a frame is being started
+ virtual void Blank() const=0;
+
+ //! Signal that a frame is finished - the screen should be updated
+ virtual void Display()=0;
+
+protected:
+ //! Width and height of the screen
+ const int m_iWidth, m_iHeight;
+
+ //! Pointer to a widget interface for communication with the core
+ CDasherWidgetInterface* m_DasherInterface;
+};
+
+
+#endif /* #ifndef __DasherScreen_h_ */
diff --git a/inputmethods/dasher/DasherSettingsInterface.cpp b/inputmethods/dasher/DasherSettingsInterface.cpp
new file mode 100644
index 0000000..6e7f7da
--- a/dev/null
+++ b/inputmethods/dasher/DasherSettingsInterface.cpp
@@ -0,0 +1,126 @@
+// DasherSettingsInterface.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include <iostream>
+
+#include "DasherSettingsInterface.h"
+
+namespace Dasher{
+namespace Keys {
+ // Standard Option strings. You are encouraged to use these constants.
+ // -------------------------------------------------------------------
+
+ // bool options
+ const std::string TIME_STAMP = "TimeStampNewFiles";
+ const std::string SHOW_TOOLBAR = "ViewToolbar";
+ const std::string SHOW_TOOLBAR_TEXT = "ShowToolbarText";
+ const std::string SHOW_LARGE_ICONS = "ShowLargeIcons";
+ const std::string FIX_LAYOUT = "FixLayout";
+ const std::string SHOW_SLIDER = "ShowSpeedSlider";
+ const std::string COPY_ALL_ON_STOP = "CopyAllOnStop";
+ const std::string DRAW_MOUSE = "DrawMouse";
+ const std::string START_MOUSE = "StartOnLeft";
+ const std::string START_SPACE = "StartOnSpace";
+ const std::string KEY_CONTROL = "KeyControl";
+ const std::string WINDOW_PAUSE = "PauseOutsideWindow";
+
+ // long options
+ const std::string FILE_ENCODING = "FileEncodingFormat";
+ const std::string MAX_BITRATE_TIMES100 = "MaxBitRateTimes100";
+ const std::string SCREEN_ORIENTATION = "ScreenOrientation";
+ const std::string VIEW_ID = "ViewID";
+ const std::string LANGUAGE_MODEL_ID = "LanguageModelID";
+ const std::string EDIT_FONT_SIZE = "EditFontSize";
+ const std::string EDIT_HEIGHT = "EditHeight";
+ const std::string SCREEN_WIDTH = "ScreenWidth";
+ const std::string SCREEN_HEIGHT = "ScreenHeight";
+ const std::string DASHER_FONTSIZE = "DasherFontSize";
+ const std::string DASHER_DIMENSIONS = "NumberDimensions";
+
+ // string options
+ const std::string ALPHABET_ID = "AlphabetID";
+ const std::string DASHER_FONT = "DasherFont";
+ const std::string EDIT_FONT = "EditFont";
+}
+}
+
+
+void Dasher::CDasherSettingsInterface::SettingsDefaults(CSettingsStore* Store)
+{
+ using namespace Dasher;
+ using namespace Keys;
+ using namespace Opts;
+
+ Store->SetLongDefault(MAX_BITRATE_TIMES100, 150);
+ this->ChangeMaxBitRate(Store->GetLongOption(MAX_BITRATE_TIMES100)/100.0);
+
+ Store->SetBoolDefault(TIME_STAMP, true);
+ this->TimeStampNewFiles(Store->GetBoolOption(TIME_STAMP));
+ Store->SetBoolDefault(COPY_ALL_ON_STOP, false);
+ this->CopyAllOnStop(Store->GetBoolOption(COPY_ALL_ON_STOP));
+
+ Store->SetBoolDefault(DRAW_MOUSE, false);
+ this->DrawMouse(Store->GetBoolOption(DRAW_MOUSE));
+
+ Store->SetLongDefault(FILE_ENCODING, AlphabetDefault);
+ this->SetFileEncoding((FileEncodingFormats) Store->GetLongOption(FILE_ENCODING));
+
+ Store->SetBoolDefault(SHOW_SLIDER, true);
+ this->ShowSpeedSlider(Store->GetBoolOption(SHOW_SLIDER));
+ Store->SetBoolDefault(FIX_LAYOUT, false);
+ this->FixLayout(Store->GetBoolOption(FIX_LAYOUT));
+
+ // Toolbar defaults
+ Store->SetBoolDefault(SHOW_TOOLBAR_TEXT, true);
+ this->ShowToolbarText(Store->GetBoolOption(SHOW_TOOLBAR_TEXT));
+ Store->SetBoolDefault(SHOW_LARGE_ICONS, true);
+ this->ShowToolbarLargeIcons(Store->GetBoolOption(SHOW_LARGE_ICONS));
+
+ Store->SetBoolDefault(SHOW_TOOLBAR, true);
+ this->ShowToolbar(Store->GetBoolOption(SHOW_TOOLBAR));
+
+ Store->SetLongDefault(SCREEN_ORIENTATION, Opts::LeftToRight);
+ this->ChangeOrientation((ScreenOrientations) Store->GetLongOption(SCREEN_ORIENTATION));
+
+ Store->SetBoolDefault(START_MOUSE, true);
+ this->StartOnLeft(Store->GetBoolOption(START_MOUSE));
+
+ Store->SetBoolDefault(START_SPACE, false);
+ this->StartOnSpace(Store->GetBoolOption(START_SPACE));
+
+ Store->SetBoolDefault(KEY_CONTROL, false);
+ this->KeyControl(Store->GetBoolOption(KEY_CONTROL));
+
+ Store->SetBoolDefault(DASHER_DIMENSIONS, false);
+ this->SetDasherDimensions(Store->GetBoolOption(DASHER_DIMENSIONS));
+
+ Store->SetBoolDefault(WINDOW_PAUSE, false);
+ this->WindowPause(Store->GetBoolOption(WINDOW_PAUSE));
+
+ // The following standard options don't have sensible cross-platform or cross-language defaults.
+ // "" or 0 will have to mean "do something sensible for this user and platform"
+ // The user may have saved a preference for some of these options though:
+
+ this->ChangeAlphabet(Store->GetStringOption(ALPHABET_ID));
+
+ // FIXME - need to work out why this breaks stuff
+ // this->ChangeLanguageModel(Store->GetLongOption(LANGUAGE_MODEL_ID));
+ this->ChangeView(Store->GetLongOption(VIEW_ID));
+
+ // Fonts
+ this->SetEditFont(Store->GetStringOption(EDIT_FONT), Store->GetLongOption(EDIT_FONT_SIZE));
+ this->SetDasherFont(Store->GetStringOption(DASHER_FONT));
+ this->SetDasherFontSize(Dasher::Opts::FontSize(Store->GetLongOption(DASHER_FONTSIZE)));
+
+ // Window Geometry
+ this->SetEditHeight(Store->GetLongOption(EDIT_HEIGHT));
+ this->SetScreenSize(Store->GetLongOption(SCREEN_WIDTH), Store->GetLongOption(SCREEN_HEIGHT));
+}
+
+
+
diff --git a/inputmethods/dasher/DasherSettingsInterface.h b/inputmethods/dasher/DasherSettingsInterface.h
new file mode 100644
index 0000000..9d03eba
--- a/dev/null
+++ b/inputmethods/dasher/DasherSettingsInterface.h
@@ -0,0 +1,149 @@
+// DasherSettingsInterface.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef __DasherSettingsInterface_h__
+#define __DasherSettingsInterface_h__
+
+#include "DasherTypes.h"
+#include "SettingsStore.h"
+
+namespace Dasher {class CDasherSettingsInterface;}
+class Dasher::CDasherSettingsInterface
+{
+public:
+ void SettingsDefaults(CSettingsStore* Store);
+
+ // These actually affect the way Dasher works
+ //! Change the alphabet in use to NewAlphabetID
+ virtual void ChangeAlphabet(const std::string& NewAlphabetID) {};
+
+ //! Change the maximum bitrate (effectively the speed) of Dasher
+ virtual void ChangeMaxBitRate(double NewMaxBitRate) {};
+
+ //! Generate a new langage model. Not usually needed
+ virtual void ChangeLanguageModel(unsigned int NewLanguageModelID) {};
+
+ //! Generate a new view of the model. Call it with 0 when starting up
+ virtual void ChangeView(unsigned int NewViewID) {};
+
+ //! Change the orientation (l->r, r->l, so on) of the model
+ virtual void ChangeOrientation(Opts::ScreenOrientations Orientation) {};
+
+ //! Set the file encoding of output files to Encoding
+ virtual void SetFileEncoding(Opts::FileEncodingFormats Encoding) {};
+
+ //! Inform the core that the screen has this size
+ virtual void SetScreenSize(long Width, long Height) {};
+
+ //! Set the size of the font used in the Dasher canvas
+ virtual void SetDasherFontSize(Dasher::Opts::FontSize fontsize) {};
+
+ //! Set the number of dimensions of input (either 1 or 2)
+ virtual void SetDasherDimensions(bool Value) {};
+
+ // These are recommended options for the Dasher GUI. {{{ They don't actually
+ // change the way Dasher works. They are part of the Dasher interface
+ // anyway so that it can handle option saving for you, and to make it
+ // easy for the Dasher engine to control the GUI later on. }}}
+
+ //! True if toolbar should be shown, false otherwise
+ virtual void ShowToolbar(bool Value) {};
+
+ //! True if toolbar should show text, false otherwse
+ virtual void ShowToolbarText(bool Value) {};
+
+ //! True if toolbar should have large icons, false otherwise
+ virtual void ShowToolbarLargeIcons(bool Value) {};
+
+ //! True if the speed slider should be shown, false otherwise
+ virtual void ShowSpeedSlider(bool Value) {};
+
+ //! True if the window layout should be fixed, false otherwise
+ virtual void FixLayout(bool Value) {};
+
+ //! True if new files should be timestamped, false otherwise
+ virtual void TimeStampNewFiles(bool Value) {};
+
+ //! True if all text should be copied to clipboard when Dasher is stopped, false otherwise
+ virtual void CopyAllOnStop(bool Value) {};
+
+ //! True if a box should be drawn to represent the logical position of the mouse
+ virtual void DrawMouse(bool Value) {};
+
+ //! Set the editbox font
+ virtual void SetEditFont(std::string Name, long Size) {};
+
+ //! Set the canvas font
+ virtual void SetDasherFont(std::string Name) {};
+
+ //! Set the height of the edit box
+ virtual void SetEditHeight(long Value) {};
+
+ //! Should Dasher start and stop on space bar?
+ virtual void StartOnSpace(bool Value) {};
+
+ //! Should Dasher start and stop on left mouse button?
+ virtual void StartOnLeft(bool Value) {};
+
+ //! Should Dasher be keyboard controlled?
+ virtual void KeyControl(bool Value) {};
+
+ //! Should Dasher pause when the pointer leaves the window?
+ virtual void WindowPause(bool Value) {};
+};
+
+
+#include <string>
+
+namespace Dasher
+{
+namespace Keys
+{
+ // Standard Option strings. You are encouraged to use these constants.
+ // -------------------------------------------------------------------
+
+ // bool options
+ extern const std::string TIME_STAMP;
+ extern const std::string SHOW_TOOLBAR;
+ extern const std::string SHOW_TOOLBAR_TEXT;
+ extern const std::string SHOW_LARGE_ICONS;
+ extern const std::string FIX_LAYOUT;
+ extern const std::string SHOW_SLIDER;
+ extern const std::string COPY_ALL_ON_STOP;
+ extern const std::string DRAW_MOUSE;
+ extern const std::string START_SPACE;
+ extern const std::string START_MOUSE;
+ extern const std::string KEY_CONTROL;
+ extern const std::string WINDOW_PAUSE;
+ // long options
+ extern const std::string FILE_ENCODING;
+ extern const std::string MAX_BITRATE_TIMES100;
+ extern const std::string SCREEN_ORIENTATION;
+ extern const std::string VIEW_ID;
+ extern const std::string LANGUAGE_MODEL_ID;
+ extern const std::string EDIT_FONT_SIZE;
+ extern const std::string EDIT_HEIGHT;
+ extern const std::string SCREEN_WIDTH;
+ extern const std::string SCREEN_HEIGHT;
+ extern const std::string DASHER_FONTSIZE;
+ extern const std::string DASHER_DIMENSIONS;
+
+ // string options
+ extern const std::string ALPHABET_ID;
+ extern const std::string DASHER_FONT;
+ extern const std::string EDIT_FONT;
+}
+} // namespace Dasher
+
+
+#endif /* #ifndef __DasherSettingsInterface_h__ */
+
+
+
+
diff --git a/inputmethods/dasher/DasherTypes.h b/inputmethods/dasher/DasherTypes.h
new file mode 100644
index 0000000..8885052
--- a/dev/null
+++ b/inputmethods/dasher/DasherTypes.h
@@ -0,0 +1,66 @@
+// DasherTypes.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+#ifndef __DasherTypes_h__
+#define __DasherTypes_h__
+
+namespace Dasher
+{
+ /* TODO: note by IAM 08/2002 {{{
+
+ MS docs tell us the __int64 type has no ANSI equivalent
+ I've checked and currently a 32bit long leads to problems.
+ The code could probably be altered to get around this 64bit
+ precision requirement. If not a custom class could be found
+ (or implemented fairly easily). However, as GCC supports
+ "long long int" I'm giving this low priority until someone
+ complains...
+
+ "ISO C99 supports data types for integers that are at least 64 bits wide,
+ and as an extension GCC supports them in C89 mode and in C++."
+
+ I've heard some compilers have a "quad int". If "long long int" does not
+ work, try that.
+ }}} */
+ #ifdef _MSC_VER
+ typedef __int64 myint;
+ #define LLONG_MAX 9223372036854775807
+ #define LLONG_MIN (-LLONG_MAX - 1)
+ #else
+ typedef long long int myint;
+ #define LLONG_MAX 9223372036854775807LL
+ #define LLONG_MIN (-LLONG_MAX - 1LL)
+ #endif
+
+ // Using a signed symbol type allows "Out of band" ie negative {{{
+ // values to be used to flag non-symbol data. For example commands
+ // in dasher nodes.
+ //typedef unsigned int symbol; // }}}
+ typedef int symbol;
+
+// typedef unsigned int uint;
+ // typedef unsigned short ushort;
+
+ namespace Opts
+ {
+ // Numbers should be applied to elements of the following two enumerations as these preferences may be stored to file. Constancy between
+ // versions is a good idea. It should *not* be assumed that the numbers map onto anything useful. Different codepages may be appropriate on different systems for different character sets.
+ enum FileEncodingFormats {UserDefault=-1, AlphabetDefault=-2, UTF8=65001, UTF16LE=1200, UTF16BE=1201};
+ enum AlphabetTypes {MyNone=0, Arabic=1256, Baltic=1257, CentralEurope=1250, ChineseSimplified=936, ChineseTraditional=950, Cyrillic=1251, Greek=1253, Hebrew=1255, Japanese=932, Korean=949, Thai=874, Turkish=1254, VietNam=1258, Western=1252};
+ enum ScreenOrientations {Alphabet=-2, LeftToRight=0, RightToLeft=1, TopToBottom=2, BottomToTop=3};
+ // TODO: Possibly make colors long and add an RGB item to this {{{
+ // Would allow literal as well as semantic colors for
+ // greater flexibility. }}}
+ enum ColorSchemes {Nodes1=0, Nodes2=1, Special1=2, Special2=3, Groups=4, Objects=5};
+ enum FontSize {Normal=1, Big=2, VBig=4};
+ }
+
+}
+
+#endif /* #ifndef __DasherTypes_h__ */
diff --git a/inputmethods/dasher/DasherView.cpp b/inputmethods/dasher/DasherView.cpp
new file mode 100644
index 0000000..3b8cb64
--- a/dev/null
+++ b/inputmethods/dasher/DasherView.cpp
@@ -0,0 +1,93 @@
+// DasherView.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "DasherView.h"
+using namespace Dasher;
+
+
+CDasherView::CDasherView(CDasherScreen* DasherScreen, CDasherModel& DasherModel, Opts::ScreenOrientations Orientation)
+ : m_Screen(DasherScreen), m_DasherModel(DasherModel), ScreenOrientation(Orientation), ColourMode(false)
+{
+// XYScale = (double)m_Screen->GetHeight() / m_Screen->GetWidth();
+}
+
+
+void CDasherView::ChangeOrientation(Dasher::Opts::ScreenOrientations Orientation)
+{
+ ScreenOrientation = Orientation;
+ Render();
+}
+
+
+void CDasherView::FlushAt(int mousex,int mousey)
+{
+ m_DasherModel.Flush(0,0);
+}
+
+int CDasherView::RecursiveRender(CDasherNode* Render, myint y1,myint y2,int mostleft, bool text)
+{
+ symbol CurChar = Render->Symbol();
+ int Color;
+
+ if (ColourMode==true) {
+ Color = Render->Colour();
+ } else {
+ Color = Render->Phase()%3;
+ }
+
+ if (RenderNode(Render->Symbol(), Color, Render->Cscheme(), y1, y2, mostleft, Render->m_bForce, text))
+ RenderGroups(Render, y1, y2, text);
+ else
+ Render->Kill();
+
+ CDasherNode** const Children=Render->Children();
+ if (!Children)
+ return 0;
+ int norm=DasherModel().Normalization();
+ for (unsigned int i=1; i<Render->Chars(); i++) {
+ if (Children[i]->Alive()) {
+ myint Range=y2-y1;
+ myint newy1=y1+(Range*Children[i]->Lbnd())/norm;
+ myint newy2=y1+(Range*Children[i]->Hbnd())/norm;
+ RecursiveRender(Children[i], newy1, newy2, mostleft, text);
+ }
+ }
+ return 1;
+
+
+}
+
+
+void CDasherView::RenderGroups(CDasherNode* Render, myint y1, myint y2, bool text)
+{
+ CDasherNode** Children = Render->Children();
+ if (!Children)
+ return;
+ int current=0;
+ int lower=0;
+ int upper=0;
+ myint range=y2-y1;
+ for (unsigned int i=1; i<Render->Chars(); i++) {
+ int g=Children[i]->Group();
+ if (g!=current) {
+ lower=upper;
+ upper=i;
+
+ if (current!=0) {
+ myint lbnd=Children[lower]->Lbnd();
+ myint hbnd=Children[upper]->Lbnd();
+ myint newy1=y1+(range*lbnd)/m_DasherModel.Normalization();
+ myint newy2=y1+(range*hbnd)/m_DasherModel.Normalization();
+ int mostleft;
+ bool force;
+ RenderNode(0,current-1,Opts::Groups,newy1,newy2,mostleft,force,text);
+ }
+ current=g;
+ }
+ }
+}
diff --git a/inputmethods/dasher/DasherView.h b/inputmethods/dasher/DasherView.h
new file mode 100644
index 0000000..81cc24e
--- a/dev/null
+++ b/inputmethods/dasher/DasherView.h
@@ -0,0 +1,99 @@
+// DasherView.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////
+// DasherView.h: interface for the DasherView class.
+// Copyright 2002 David Ward
+//////////////////////////////////////////////////////////////////////
+
+#ifndef __DasherView_h_
+#define __DasherView_h_
+
+#include "MSVC_Unannoy.h"
+#include "DasherScreen.h"
+#include "DasherModel.h"
+
+// CDasherView is an abstract view class
+// The implentation must provide several functions - defined here as pure virtual functions
+// See the CDasherViewSquare class for an example
+
+namespace Dasher {class CDasherView;}
+class Dasher::CDasherView
+{
+public:
+ CDasherView(CDasherScreen* DasherScreen, CDasherModel& DasherModel, Dasher::Opts::ScreenOrientations Orientation=Dasher::Opts::LeftToRight);
+ ~CDasherView() {}
+
+ void ChangeOrientation(Dasher::Opts::ScreenOrientations Orientation);
+
+ // TODO Sort this out
+ void FlushAt(int mousex,int mousey);
+
+ // renders Dasher
+ inline void Render();
+
+ // translates the screen coordinates to Dasher coordinates and calls
+ // dashermodel.TapOnDisplay
+ virtual void TapOnDisplay(int mousex, int mousey, unsigned long Time)=0;
+
+ virtual void ChangeScreen(CDasherScreen* NewScreen)
+ {
+ m_Screen=NewScreen;
+
+ // DJW - removed floating point stuff
+ //XYScale = (double)m_Screen->GetHeight() / m_Screen->GetWidth();
+ }
+
+ virtual void DrawMouse(int mousex, int mousey)=0;
+ virtual void DrawKeyboard()=0;
+
+ // Return references to the model and the screen:
+ CDasherModel& DasherModel() {return m_DasherModel;}
+ CDasherScreen& Screen() {return *m_Screen;}
+
+ void Display() {m_Screen->Display();}
+
+ // Toggle advanced colour mode
+ void SetColourMode(bool colourmode) {ColourMode=colourmode;}
+
+protected:
+ // Orientation of Dasher Screen
+ inline void MapScreen(int* DrawX, int* DrawY);
+ inline void UnMapScreen(int* DrawX, int* DrawY);
+
+private:
+ CDasherScreen* m_Screen; // provides the graphics (text, lines, rectangles):
+ CDasherModel& m_DasherModel; // Model view represents
+
+ // Pure virtuals to implement
+ virtual void Crosshair(myint sx)=0; // Tells m_Screen to draw a crosshair - or other static decoration
+ virtual int RenderNode(const symbol Character, const int Color, Opts::ColorSchemes ColorScheme,
+ myint y1, myint y2, int& mostleft, bool& force, bool text)=0;
+
+ // Responsible for all the Render_node calls
+ int RecursiveRender(CDasherNode* Render, myint y1,myint y2,int mostleft, bool text);
+
+ // Displays some nodes inside one parent node. Used to group capital letters, accents, punctuation etc.
+ void RenderGroups(CDasherNode* Render, myint y1, myint y2, bool text);
+
+ // Orientation of Dasher Screen
+ Dasher::Opts::ScreenOrientations ScreenOrientation;
+
+ // Advanced colour mode
+ bool ColourMode;
+
+ // DJW - removed floating point stuff
+ //double XYScale;
+};
+
+
+#include "DasherView.inl"
+
+
+#endif /* #ifndef __DasherView_h_ */
diff --git a/inputmethods/dasher/DasherView.inl b/inputmethods/dasher/DasherView.inl
new file mode 100644
index 0000000..fbb0c16
--- a/dev/null
+++ b/inputmethods/dasher/DasherView.inl
@@ -0,0 +1,75 @@
+// DasherView.inl
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+inline void Dasher::CDasherView::Render()
+{
+ m_Screen->Blank();
+
+ // Render nodes to screen object (should use off screen buffer)
+ RecursiveRender(m_DasherModel.Root(), m_DasherModel.Rootmin(), m_DasherModel.Rootmax(), 2, false);
+ RecursiveRender(m_DasherModel.Root(), m_DasherModel.Rootmin(), m_DasherModel.Rootmax(), 2, true);
+ Crosshair(m_DasherModel.DasherOX()); // add crosshair
+// m_Screen->Display(); // copy from buffer to screen
+}
+
+inline void Dasher::CDasherView::MapScreen(int* DrawX, int* DrawY)
+{
+ using namespace Dasher::Opts;
+
+ switch (ScreenOrientation) {
+ case (LeftToRight):
+ break;
+ case (RightToLeft):
+ *DrawX = m_Screen->GetWidth() - *DrawX;
+ break;
+ case (TopToBottom): {
+ int Swapper = ( *DrawX * m_Screen->GetHeight()) / m_Screen->GetWidth();
+ *DrawX = (*DrawY * m_Screen->GetWidth()) / m_Screen->GetHeight();
+ *DrawY = Swapper;
+ break;
+ }
+ case (BottomToTop): {
+ // Note rotation by 90 degrees not reversible like others
+ int Swapper = m_Screen->GetHeight() - ( *DrawX * m_Screen->GetHeight()) / m_Screen->GetWidth();
+ *DrawX = (*DrawY * m_Screen->GetWidth()) / m_Screen->GetHeight();
+ *DrawY = Swapper;
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+
+inline void Dasher::CDasherView::UnMapScreen(int* MouseX, int* MouseY)
+{
+ using namespace Dasher::Opts;
+
+ switch (ScreenOrientation) {
+ case (LeftToRight):
+ break;
+ case (RightToLeft):
+ *MouseX = m_Screen->GetWidth() - *MouseX;
+ break;
+ case (TopToBottom): {
+ int Swapper = (*MouseX * m_Screen->GetHeight()) / m_Screen->GetWidth();
+ *MouseX = (*MouseY *m_Screen->GetWidth()) / m_Screen->GetHeight();;
+ *MouseY = Swapper;
+ break;
+ }
+ case (BottomToTop): {
+ int Swapper = (*MouseX * m_Screen->GetHeight()) / m_Screen->GetWidth();
+ *MouseX = ((m_Screen->GetHeight() - *MouseY) * m_Screen->GetWidth()) / m_Screen->GetHeight();
+ *MouseY = Swapper;
+ break;
+ }
+ default:
+ break;
+ }
+}
diff --git a/inputmethods/dasher/DasherViewSquare.cpp b/inputmethods/dasher/DasherViewSquare.cpp
new file mode 100644
index 0000000..1b12a58
--- a/dev/null
+++ b/inputmethods/dasher/DasherViewSquare.cpp
@@ -0,0 +1,229 @@
+// DasherViewSquare.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////
+// DasherViewSquare.cpp: implementation of the DasherViewSquare class.
+// Copyright 2002 David Ward
+//////////////////////////////////////////////////////////////////////
+
+#include "DasherModel.h"
+#include "DasherViewSquare.h"
+#include <iostream>
+
+using namespace Dasher;
+
+// ARG! MSVC++ V6 doesn't seem to come with min and max in <algorithm>
+#ifdef _MSC_VER
+#ifndef max
+#define max(a,b) (((a) > (b)) ? (a) : (b))
+#endif
+#ifndef min
+#define min(a,b) (((a) < (b)) ? (a) : (b))
+#endif
+#else
+#include <algorithm>
+using std::min;
+using std::max;
+#endif
+
+
+CDasherViewSquare::CDasherViewSquare(CDasherScreen* DasherScreen, CDasherModel& DasherModel, Dasher::Opts::ScreenOrientations Orientation)
+ : CDasherView(DasherScreen, DasherModel, Orientation)
+{
+ ChangeScreen(DasherScreen);
+
+ // tweak these if you know what you are doing
+ m_dXmpa=0.2; // these are for the x non-linearity
+ m_dXmpb=0.5;
+ m_dXmpc=0.9;
+ m_dXmpd=0.5; // slow X movement when accelerating Y
+
+ double dY1=0.25; // Amount of acceleration
+ double dY2=0.95; // Accelerate Y movement below this point
+ double dY3=0.05; // Accelerate Y movement above this point
+
+ m_Y2=int (dY2 * (CDasherView::DasherModel().DasherY()) );
+ m_Y3=int (dY3 * (CDasherView::DasherModel().DasherY()) );
+ m_Y1=int(1.0/dY1);
+
+}
+
+
+int CDasherViewSquare::RenderNode(const symbol Character, const int Color, Opts::ColorSchemes ColorScheme,
+ myint y1, myint y2, int& mostleft, bool& force, bool text)
+{
+ int top = dashery2screen(y1);
+ if (top>CanvasY)
+ return 0;
+ if (top<0)
+ top=0;
+
+ int bottom = dashery2screen(y2);
+ if (bottom<0)
+ return 0;
+ if (bottom>CanvasY)
+ bottom=CanvasY;
+
+ int height=bottom-top;
+
+ if (height==0 && text==true)
+ force=false;
+
+ if (force || height>1) {
+ force=true;
+
+ int left=dasherx2screen(y2-y1);
+
+ int right=CanvasX;
+
+ int newleft=left, newtop=top, newright=right, newbottom=bottom;
+ MapScreen(&newleft, &newtop);
+ MapScreen(&newright, &newbottom);
+ if( !text )
+ Screen().DrawRectangle(newleft, newtop, newright, newbottom, Color, ColorScheme);
+ else
+ {
+ if (left<mostleft)
+ left=mostleft;
+
+ int Size;
+ if (left*Screen().GetFontSize()<CanvasX*19/20) {
+ Size = 20*Screen().GetFontSize();
+ } else if (left*Screen().GetFontSize()<CanvasX*159/160) {
+ Size = 14*Screen().GetFontSize();
+ } else {
+ Size = 11*Screen().GetFontSize();
+ }
+
+ int TextWidth, TextHeight, OriginX=0, OriginY=0;
+ Screen().TextSize(Character, &TextWidth, &TextHeight, Size);
+ UnMapScreen(&TextWidth, &TextHeight);
+ UnMapScreen(&OriginX, &OriginY);
+ int FontHeight = abs(TextHeight-OriginY);
+ int FontWidth = abs(TextWidth-OriginX);
+ mostleft = left + FontWidth;
+
+ int newleft2 = left;
+ int newtop2 = (height-FontHeight)/2 + top;
+ int newright2 = left + FontWidth;
+ int newbottom2 = (height+FontHeight)/2 + top;
+ MapScreen(&newleft2, &newtop2);
+ MapScreen(&newright2, &newbottom2);
+ newleft = min(newleft2, newright2);
+ newtop = min(newtop2, newbottom2);
+
+ Screen().DrawText(Character, newleft, newtop, Size);
+ }
+
+ return 1;
+ } else
+ return 0;
+}
+
+
+void CDasherViewSquare::CheckForNewRoot()
+{
+ CDasherNode * const root=DasherModel().Root();
+ CDasherNode ** const children=root->Children();
+
+
+ myint y1=DasherModel().Rootmin();
+ myint y2=DasherModel().Rootmax();
+
+ if ((y1>0 || y2 < DasherModel().DasherY() || dasherx2screen(y2-y1)>0) && root->Symbol()!=0) {
+ DasherModel().Reparent_root(root->Lbnd(),root->Hbnd());
+ }
+
+ if (children==0)
+ return;
+
+ int alive=0;
+ int theone=0;
+ unsigned int i;
+ for (i=1;i<root->Chars();i++) {
+ if (children[i]->Alive()) {
+ alive++;
+ theone=i;
+ }
+ }
+
+ if (alive==1) {
+ y1=DasherModel().Rootmin();
+ y2=DasherModel().Rootmax();
+ myint range=y2-y1;
+ myint newy1=y1+(range*children[theone]->Lbnd())/DasherModel().Normalization();
+ myint newy2=y1+(range*children[theone]->Hbnd())/DasherModel().Normalization();
+ if (newy1<0 && newy2> DasherModel().DasherY()) {
+ myint left=dasherx2screen(newy2-newy1);
+ if (left<0) {
+ DasherModel().Make_root(theone);
+ return;
+ }
+ }
+ }
+}
+
+
+// work out the next viewpoint
+// move the rectangles accordingly
+void CDasherViewSquare::TapOnDisplay(int mousex,int mousey, unsigned long Time)
+{
+ // convert mouse (screen) coords into dasher coords
+ if (mousex>CanvasX)
+ mousex=CanvasX;
+
+ UnMapScreen(&mousex, &mousey);
+ screen2dasher(&mousex,&mousey);
+ DasherModel().Tap_on_display(mousex,mousey, Time);
+ CheckForNewRoot();
+}
+
+void CDasherViewSquare::DrawMouse(int mousex, int mousey)
+{
+ screen2dasher(&mousex,&mousey);
+ mousex=dasherx2screen(mousex);
+ mousey=dashery2screen(mousey);
+ Screen().DrawRectangle(mousex-5, mousey-5, mousex+5, mousey+5, 0, Opts::ColorSchemes(Objects));
+}
+
+void CDasherViewSquare::DrawKeyboard()
+{
+ CDasherScreen::point line[2];
+ line[0].x = 200;
+ line[0].y = 0;
+ line[1].x = 200;
+ line[1].y = CanvasY/2;
+
+ Screen().Polyline(line,2);
+
+ line[0].x = 200;
+ line[0].y = CanvasY/2;
+ line[1].x = 0;
+ line[1].y = CanvasY/2;
+
+ Screen().Polyline(line,2);
+
+ line[0].x = 200;
+ line[0].y = CanvasY/2;
+ line[1].x = 200;
+ line[1].y = CanvasY;
+
+ Screen().Polyline(line,2);
+}
+
+void CDasherViewSquare::ChangeScreen(CDasherScreen* NewScreen)
+{
+ CDasherView::ChangeScreen(NewScreen);
+ int Width = Screen().GetWidth();
+ int Height = Screen().GetHeight();
+ CanvasX=9*Width/10;
+ CanvasBorder=Width-CanvasX;
+ CanvasY=Height;
+}
+
diff --git a/inputmethods/dasher/DasherViewSquare.h b/inputmethods/dasher/DasherViewSquare.h
new file mode 100644
index 0000000..5d689d0
--- a/dev/null
+++ b/inputmethods/dasher/DasherViewSquare.h
@@ -0,0 +1,58 @@
+// DasherViewSquare.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __DasherViewSquare_h__
+#define __DasherViewSquare_h__
+
+#include "MSVC_Unannoy.h"
+#include "DasherScreen.h"
+#include "DasherModel.h"
+#include "DasherView.h"
+
+
+// An implementation of the DasherView class
+//
+// This class renders Dasher in the vanilla style,
+// but with horizontal and vertical mappings
+//
+// Horizontal mapping - linear and log
+// Vertical mapping - linear with different gradient
+
+namespace Dasher {class CDasherViewSquare;}
+class Dasher::CDasherViewSquare : public Dasher::CDasherView
+{
+public:
+ CDasherViewSquare(CDasherScreen* DasherScreen, CDasherModel& DasherModel, Dasher::Opts::ScreenOrientations Orientation=Dasher::Opts::LeftToRight);
+ void TapOnDisplay(int mousex,int mousey, unsigned long Time);
+
+ void ChangeScreen(CDasherScreen* NewScreen);
+ void DrawMouse(int mousex, int mousey);
+ void DrawKeyboard();
+private:
+ // the x and y non-linearities
+ inline const void screen2dasher(int *mousex, int *mousey);
+ inline const int dasherx2screen(const myint sx);
+ inline const int dashery2screen(myint sy);
+
+ int RenderNode(const symbol Character, const int Color, Opts::ColorSchemes ColorScheme,
+ myint y1, myint y2, int& mostleft, bool& force, bool text);
+
+ void CheckForNewRoot();
+ inline void Crosshair(myint sx);
+ double m_dXmpa,m_dXmpb,m_dXmpc,m_dXmpd;
+ myint m_Y1,m_Y2,m_Y3;
+ myint s_Y1,s_Y2,s_Y3;
+ int CanvasX,CanvasY,CanvasBorder;
+ double xmap(double x);
+ double ixmap(double x);
+};
+
+#include "DasherViewSquare.inl"
+
+
+#endif /* #ifndef __DasherViewSquare_h__ */
diff --git a/inputmethods/dasher/DasherViewSquare.inl b/inputmethods/dasher/DasherViewSquare.inl
new file mode 100644
index 0000000..c22c32c
--- a/dev/null
+++ b/inputmethods/dasher/DasherViewSquare.inl
@@ -0,0 +1,142 @@
+// DasherViewSquare.inl
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+namespace Dasher {
+
+inline const void CDasherViewSquare::screen2dasher(int *mousex, int *mousey)
+{
+ int dashery=*mousey;
+
+ double x=1.0*(CanvasX-*mousex)/CanvasX;
+ dashery*=DasherModel().DasherY();
+ dashery/=CanvasY;
+
+ if (DasherModel().Dimensions()==false) {
+ if (dashery>m_Y2)
+ dashery= (dashery-m_Y2)*m_Y1 + m_Y2;
+ else if (dashery<m_Y3)
+ dashery= (dashery-m_Y3)*m_Y1+m_Y3;
+ }
+
+ x=ixmap(x)*DasherModel().DasherY();
+
+ if (DasherModel().Dimensions()==true) {
+ double distx, disty;
+
+ distx=2048-x;
+ disty=DasherModel().DasherY()/2-dashery;
+
+ if (disty>1500) {
+ dashery=548+(548-dashery);
+ disty=1298-dashery;
+ if(disty<-750) {
+ x=2048;
+ dashery=2048;
+ } else {
+ x=2048+pow(pow(750,2)-pow(disty,2),0.5)*10;
+ }
+ *mousex=int(x);
+ *mousey=dashery;
+ return;
+ }
+ else if (disty <-1500) {
+ dashery=3548+(3548-dashery);
+ disty=2798-dashery;
+ if(disty>750) {
+ x=2048;
+ dashery=2048;
+ } else {
+ x=2048+pow(pow(750,2)-pow(disty,2),0.5)*10;
+ }
+ *mousex=int(x);
+ *mousey=dashery;
+ return;
+ } else {
+ x=pow(pow(1500,2)-pow(disty,2),0.5);
+ }
+ x=2048-x;
+ }
+ *mousex=int(x);
+ *mousey=dashery;
+}
+
+inline const int CDasherViewSquare::dasherx2screen(const myint sx)
+{
+ double x=1.0*sx/(DasherModel().DasherY());
+ x=xmap(x);
+// return CanvasX-int(x*CanvasY);
+ return CanvasX-int(x*CanvasX);
+
+}
+
+
+inline const int CDasherViewSquare::dashery2screen(myint y)
+{
+ if (y > m_Y2 )
+ y= m_Y2 + (y-m_Y2)/m_Y1;
+ else if (y<m_Y3)
+ y= m_Y3+ (y-m_Y3 )/m_Y1;
+
+// y*=CanvasY*Screen().GetFontSize();
+ y*=CanvasY;
+ y/=DasherModel().DasherY();
+// y-=(CanvasY*Screen().GetFontSize()-CanvasY)/2;
+ return int(y);
+}
+
+
+inline void CDasherViewSquare::Crosshair(myint sx)
+{
+ CDasherScreen::point crosshair[2];
+
+ crosshair[0].x = dasherx2screen(sx);
+ crosshair[0].y = 0;
+ crosshair[1].x = crosshair[0].x;
+ crosshair[1].y = CanvasY;
+
+ MapScreen(&crosshair[0].x, &crosshair[0].y);
+ MapScreen(&crosshair[1].x, &crosshair[1].y);
+ Screen().Polyline(crosshair,2);
+
+ crosshair[0].x = dasherx2screen(12*sx/14);
+ crosshair[0].y = CanvasY/2;
+ crosshair[1].x = dasherx2screen(17*sx/14);
+ crosshair[1].y = CanvasY/2;
+
+ MapScreen(&crosshair[0].x, &crosshair[0].y);
+ MapScreen(&crosshair[1].x, &crosshair[1].y);
+ Screen().Polyline(crosshair,2);
+}
+
+
+
+
+
+inline double CDasherViewSquare::ixmap(double x)
+// invert x non-linearity
+{
+ if (x<m_dXmpb*m_dXmpc)
+ return x/m_dXmpc;
+ else
+ return m_dXmpb-m_dXmpa + m_dXmpa * exp( (x/m_dXmpc - m_dXmpb) / m_dXmpa);
+
+}
+
+
+inline double CDasherViewSquare::xmap(double x)
+// x non-linearity
+{
+ if (x<m_dXmpb)
+ return m_dXmpc*x;
+ else
+ return m_dXmpc*(m_dXmpa*log((x+m_dXmpa-m_dXmpb)/m_dXmpa) +m_dXmpb);
+}
+
+
+
+} // namespace Dasher
diff --git a/inputmethods/dasher/DasherWidgetInterface.h b/inputmethods/dasher/DasherWidgetInterface.h
new file mode 100644
index 0000000..5a1387e
--- a/dev/null
+++ b/inputmethods/dasher/DasherWidgetInterface.h
@@ -0,0 +1,93 @@
+// DasherWidgetInterface.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __DasherWidgetInterface_h__
+#define __DasherWidgetInterface_h__
+
+
+#include "DasherTypes.h"
+#include <string>
+
+namespace Dasher {class CDasherWidgetInterface;}
+class Dasher::CDasherWidgetInterface
+{
+public:
+ //! Signal to the core that the model should be started
+ //
+ //! Call this function before providing input coordinates and whenever
+ //! reinitialising Dasher
+ virtual void Start()=0;
+
+ // Times in milliseconds are required so Dasher runs at the correct speed.
+ //! Signal an input location
+ //
+ //! Signal an input event. This may be the current location of the
+ //! mouse or a stylus tap, for example
+ //! \param MouseX The mouse X coordinate, in screen coordinates
+ //! \param MouseY The mouse Y coordinate, in screen coordinates
+ //! \param Time Time in milliseconds, required to keep Dasher running
+ //! at the correct speed
+ virtual void TapOn(int MouseX, int MouseY, unsigned long Time)=0;
+
+ //! Signal an input event and pause the simulation
+ virtual void PauseAt(int MouseX, int MouseY)=0;
+
+ //! Unpause the simulation.
+ //
+ //! \param Time should be in milliscones and should be consistent with
+ //! previous time values
+ virtual void Unpause(unsigned long Time)=0;
+
+ //! Signal that the core should redraw the screen
+ virtual void Redraw()=0;
+
+ // The widgets need to tell the engine when they have been affected
+ // by external interaction
+
+ //! Signal the core that a change has occured to the screen. (Unneeded)
+ virtual void ChangeScreen()=0;
+
+ //! Signal the core that a change has occued to the editbox. (Unneeded)
+ virtual void ChangeEdit()=0;
+
+ // These are needed so widgets know how to render the alphabet.
+ // All strings are encoded in UTF-8.
+
+ //! Request the number of symbols in the current alphabet
+ virtual unsigned int GetNumberSymbols()=0;
+
+ //! Request the text that should be displayed on the Dasher canvas
+ //
+ //! Note - the returned string is in UTF-8 encoding.
+ //! \param Symbol the symbol that is to be displayed
+ virtual const std::string& GetDisplayText(Dasher::symbol Symbol)=0;
+
+ //! Request the text that should be entered into the edit box
+ //
+ //! Note - the returned string is in UTF-8 encoding.
+ //! \param Symbol the symbol that is to be displayed
+ virtual const std::string& GetEditText(Dasher::symbol Symbol)=0;
+
+ //! Request the foreground colour for the text to be drawn on the canvas
+ //! \param Symbol the symbol that is to be displayed
+ virtual int GetTextColour(Dasher::symbol Symbol)=0;
+
+ //! Request the default screen orientation for the current alphabet
+ //
+ //! (Eg, left to right for English, right to left for Hebrew)
+ virtual Opts::ScreenOrientations GetAlphabetOrientation()=0;
+
+ //! Returns the codepage for the current alphabet
+ virtual Opts::AlphabetTypes GetAlphabetType()=0;
+
+ //! Provides a fully qualified path to the training file for the alphabet
+ virtual const std::string& GetTrainFile()=0; // Returns a fully-qualified path to file:
+ // UserLocation + TrainFile
+};
+
+#endif /* #ifndef __DasherWidgetInterface_h__ */
diff --git a/inputmethods/dasher/FrameRate.h b/inputmethods/dasher/FrameRate.h
new file mode 100644
index 0000000..2f86b03
--- a/dev/null
+++ b/inputmethods/dasher/FrameRate.h
@@ -0,0 +1,112 @@
+// FrameRate.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __FrameRate_h__
+#define __FrameRate_h__
+
+#include "MSVC_Unannoy.h"
+
+// keeps track of framerate
+// computes the Steps parameter
+// computes RXmax - which controls the maximum rate of zooming in
+
+const double LN2= log(2);
+
+class CFrameRate {
+ public:
+ CFrameRate() ;
+ ~CFrameRate() {};
+ const double Rxmax() const {return m_dRXmax;}
+ const int Steps() const {return m_iSteps;}
+ const double Framerate() const {return m_dFr;}
+ void Reset(unsigned long Time);
+ void NewFrame(unsigned long Time);
+
+ // TODO: These two shouldn't be the same thing:
+ void SetBitrate(double TargetRate);
+ void SetMaxBitrate(double MaxRate);
+ private:
+ double m_dFr;
+ double m_dMaxbitrate; // the maximum rate of entering information
+ double m_dRXmax; // the maximum zoomin per frame
+ int m_iFrames,m_iTime,m_iTime2,m_iSamples;
+ int m_iSteps; // the 'Steps' parameter. See djw thesis.
+};
+
+inline CFrameRate::CFrameRate() {
+
+ // maxbitrate should be user-defined and/or adaptive. Currently it is not.
+#if defined(_WIN32_WCE)
+ m_dMaxbitrate=5;
+#else
+ m_dMaxbitrate=5.5;
+#endif
+
+ m_dRXmax=2; // only a transient effect
+ m_iFrames=0;
+ m_iSamples=1;
+
+ // we dont know the framerate yet - play it safe by setting it high
+ m_dFr=1<<5;
+
+ // start off very slow until we have sampled framerate adequately
+ m_iSteps=2000;
+ m_iTime=0; // Hmmm, User must reset framerate before starting.
+}
+
+inline void CFrameRate::NewFrame(unsigned long Time)
+ // compute framerate if we have sampled enough frames
+{
+
+ m_iFrames++;
+
+ if (m_iFrames==m_iSamples) {
+ m_iTime2=Time;
+ if (m_iTime2-m_iTime < 50)
+ m_iSamples++; // increase sample size
+ else if (m_iTime2-m_iTime > 80) {
+ m_iSamples--;
+ if (m_iSamples <2)
+ m_iSamples=2;
+ }
+ if (m_iTime2-m_iTime) {
+ m_dFr=m_iFrames*1000.0/(m_iTime2-m_iTime);
+ m_iTime=m_iTime2;
+ m_iFrames=0;
+
+ }
+ m_dRXmax=exp(m_dMaxbitrate*LN2/m_dFr);
+ m_iSteps=m_iSteps/2+(int)(-log(0.2)*m_dFr/LN2/m_dMaxbitrate)/2;
+ // dchar debug[256];
+ // _stprintf(debug,TEXT("fr %f Steps %d samples %d time2 %d rxmax %f\n"),fr,Steps,samples,time2,RXmax);
+ // OutputDebugString(debug);
+
+ }
+}
+
+inline void CFrameRate::Reset(unsigned long Time)
+{
+ m_iFrames=0;
+ m_iTime=Time;
+}
+
+
+inline void CFrameRate::SetBitrate(double TargetRate)
+{
+ m_dMaxbitrate = TargetRate;
+}
+
+
+inline void CFrameRate::SetMaxBitrate(double MaxRate)
+{
+ m_dMaxbitrate = MaxRate;
+}
+
+
+
+#endif /* #ifndef __FrameRate_h__ */
diff --git a/inputmethods/dasher/LanguageModel.cpp b/inputmethods/dasher/LanguageModel.cpp
new file mode 100644
index 0000000..9635273
--- a/dev/null
+++ b/inputmethods/dasher/LanguageModel.cpp
@@ -0,0 +1,77 @@
+// LanguageModel.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include "LanguageModel.h"
+
+using namespace Dasher;
+using namespace std;
+
+// I have removed the following as it doesn't seem to compile in gcc:
+
+// using CLanguageModel::CNodeContext;
+
+///////////////////////////////////////////////////////////////////
+
+CLanguageModel::CLanguageModel(CAlphabet* Alphabet, int Normalization)
+ : m_Alphabet(Alphabet), m_iNorm(Normalization)
+{
+ m_iModelChars = m_Alphabet->GetNumberSymbols();
+}
+
+
+///////////////////////////////////////////////////////////////////
+
+void CLanguageModel::EnterText(CNodeContext* NodeContext, string TheText)
+{
+ vector<symbol> Symbols;
+ m_Alphabet->GetSymbols(&Symbols, &TheText, false);
+ for (unsigned int i=0; i<Symbols.size(); i++)
+ EnterSymbol((CContext*) NodeContext, (modelchar) Symbols[i]);
+}
+
+///////////////////////////////////////////////////////////////////
+
+void CLanguageModel::LearnText(CNodeContext* NodeContext, string* TheText, bool IsMore)
+{
+ vector<symbol> Symbols;
+
+ m_Alphabet->GetSymbols(&Symbols, TheText, IsMore);
+
+ for (unsigned int i=0; i<Symbols.size(); i++)
+ LearnSymbol((CContext*) NodeContext, (modelchar) Symbols[i]);
+}
+
+///////////////////////////////////////////////////////////////////
+
+bool CLanguageModel::GetNodeProbs(CNodeContext* Context, vector<symbol> &NewSymbols,
+ vector<unsigned int> &Groups, vector<unsigned int> &Probs, double AddProb)
+{
+ // make sure it is a valid context
+ if (Context) {
+ int s = m_Alphabet->GetNumberSymbols();
+ NewSymbols.resize(s);
+ Groups.resize(s);
+ for (int i=0;i<s;i++) {
+ NewSymbols[i]=i; // This will be replaced by something that works out valid nodes for this context
+ Groups[i]=m_Alphabet->get_group(i);
+ }
+ GetProbs((CContext*) Context,Probs,AddProb);
+ return true;
+ }
+ return false;
+}
+
+int CLanguageModel::GetColour(int character)
+{
+ std::string colour=m_Alphabet->GetColour(character);
+ if (colour!="") {
+ return atoi(colour.c_str());
+ } else {
+ return 0;
+ }
+}
diff --git a/inputmethods/dasher/LanguageModel.h b/inputmethods/dasher/LanguageModel.h
new file mode 100644
index 0000000..8ffe100
--- a/dev/null
+++ b/inputmethods/dasher/LanguageModel.h
@@ -0,0 +1,123 @@
+// LanguageModel.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2001-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+// Abstract language model class
+// See PPMModel for an example implementation
+
+// Contexts are indentified by a unique unsigned integer
+
+#ifndef __LanguageModel_h__
+#define __LanguageModel_h__
+
+#include "MSVC_Unannoy.h"
+#include <vector>
+#include <string>
+
+#include "Alphabet.h"
+#include "Context.h"
+
+namespace Dasher {class CLanguageModel;}
+class Dasher::CLanguageModel
+{
+public:
+ CLanguageModel(CAlphabet* Alphabet, int Normalization);
+
+ // Interface for the Dasher code
+ // --------------------------------------------------------------------------
+ class CNodeContext {
+ public:
+ CNodeContext() {};
+ virtual ~CNodeContext() {};
+ };
+
+ // return the model's normalization - what the probabilities sum to
+ const int normalization() const { return m_iNorm;}
+
+ CNodeContext* GetRootNodeContext();
+ CNodeContext* CloneNodeContext(CNodeContext* NodeContext);
+ void ReleaseNodeContext(CNodeContext* NodeContext);
+ void EnterNodeSymbol(CNodeContext* NodeContext, symbol Symbol);
+ void LearnNodeSymbol(CNodeContext* NodeContext, symbol Symbol);
+ void EnterText(CNodeContext* NodeContext, std::string TheText);
+ void LearnText(CNodeContext* NodeContext, std::string* TheText, bool IsMore);
+ bool GetNodeProbs(CNodeContext* Context, std::vector<symbol> &NewSymbols,
+ std::vector<unsigned int> &Groups, std::vector<unsigned int> &Probs, double AddProb);
+
+ // Alphabet pass-through functions for widely needed information
+ symbol GetSpaceSymbol() {return m_Alphabet->GetSpaceSymbol();}
+
+ int GetColour(int character);
+
+protected:
+ int GetNumberModelChars() {return m_Alphabet->GetNumberSymbols();}
+
+ // Generic language model functions to be implemented
+ // --------------------------------------------------------------------------
+ typedef unsigned int modelchar;
+
+ // return the id for the root context:
+ virtual CContext* GetRootContext()=0;
+ // clone a context and return the new id:
+ virtual CContext* CloneContext(CContext*)=0;
+ // delete a context:
+ virtual void ReleaseContext(CContext*)=0;
+ // diagnostic info:
+ virtual void dump()=0;
+ // add character to the language model:
+ virtual void LearnSymbol(CContext* Context, modelchar Symbol)=0;
+ // update context with a character:
+ virtual void EnterSymbol(CContext* context, modelchar Symbol)=0;
+ // get the probability distrubution at the given context:
+ virtual bool GetProbs(CContext* Context, std::vector<unsigned int> &Probs, double AddProb)=0;
+
+private:
+ CAlphabet *m_Alphabet;
+ int m_iModelChars; // number of charater in the model 1...ModelChars
+ int m_iNorm; // normalization of probabilities
+};
+
+using namespace Dasher;
+
+///////////////////////////////////////////////////////////////////
+
+inline CLanguageModel::CNodeContext* CLanguageModel::GetRootNodeContext()
+{
+ return (CNodeContext*) GetRootContext();
+}
+
+///////////////////////////////////////////////////////////////////
+
+inline CLanguageModel::CNodeContext* CLanguageModel::CloneNodeContext(CNodeContext* NodeContext)
+{
+ return (CNodeContext*) CloneContext((CContext*) NodeContext);
+}
+
+///////////////////////////////////////////////////////////////////
+
+inline void CLanguageModel::ReleaseNodeContext(CNodeContext* NodeContext)
+{
+ ReleaseContext((CContext*) NodeContext);
+}
+
+///////////////////////////////////////////////////////////////////
+
+inline void CLanguageModel::EnterNodeSymbol(CNodeContext* NodeContext, symbol Symbol)
+{
+ EnterSymbol((CContext*) NodeContext, (modelchar) Symbol);
+}
+
+///////////////////////////////////////////////////////////////////
+
+inline void CLanguageModel::LearnNodeSymbol(CNodeContext* NodeContext, symbol Symbol)
+{
+ LearnSymbol((CContext*) NodeContext, (modelchar) Symbol);
+}
+
+
+
+#endif /* #ifndef __LanguageModel_h__ */
diff --git a/inputmethods/dasher/MSVC_Unannoy.h b/inputmethods/dasher/MSVC_Unannoy.h
new file mode 100644
index 0000000..2167eec
--- a/dev/null
+++ b/inputmethods/dasher/MSVC_Unannoy.h
@@ -0,0 +1,17 @@
+#ifndef __MSVC_Unannoy_h__
+#define __MSVC_Unannoy_h__
+
+// Sorry about this frequently included header non-VC++ users.
+// It shouldn't do any harm.
+
+// Warning 4786 is so annoying if you have VC++ 6.
+// It produces *pages* of complaints if you use certain STL headers.
+// The warning just means that VC++ is unable to produce certain debug
+// information - there is nothing wrong with the code. IAM 08/2002
+#ifdef _MSC_VER
+#pragma warning(disable:4786)
+#pragma warning(disable:4018)
+#endif
+
+
+#endif /* #ifndef __MSVC_Unannoy_h__ */
diff --git a/inputmethods/dasher/NoClones.h b/inputmethods/dasher/NoClones.h
new file mode 100644
index 0000000..11cdabb
--- a/dev/null
+++ b/inputmethods/dasher/NoClones.h
@@ -0,0 +1,39 @@
+#ifndef __NoClones_h__
+#define __NoClones_h__
+
+/* Explanation of NoClones {{{
+
+C++ defines default copy constructors and assignment operators, which clone
+every member of a class. Stroustrup describes this behaviour as the result of
+"historical accident". For many non-trivial classes, especially those
+containing pointers, this default behaviour is too naive. In fact it often leads
+to heap corruption.
+
+Sometimes it does not make any sense to copy an instance of a class. For
+example if it contains a unique file handle, or other lock on a system resource.
+Sometimes it is too much effort to write reliable replacement copy operations[1].
+In either case a private copy constructor and a private assignment operator
+prevent accidental copying. [2]
+
+Deriving a class from this class has the same preventative effect. It is also a
+bit neater and means that all the above explanation is centralised here.
+
+IAM 09/2002
+
+[1] An example of how it is very easy to make mistakes:
+http://www.mistybeach.com/articles/WhyIDontLikeCPlusPlusForLargeProjects.html
+If we don't need a copy feature it really isn't worth the hassle.
+[2] The C++ Programming Language. Stroustrup. 3rd edition. Section 10.4.6.3
+
+}}} */
+
+class NoClones
+{
+protected: // Default constructor doesn't need to be public, but can't be private.
+ NoClones() {}; // Lots of compiler complaints without default constructor.
+private:
+ NoClones(const NoClones&);
+ NoClones& operator=(const NoClones&);
+};
+
+#endif /* #ifndef __NoClones_h__ */
diff --git a/inputmethods/dasher/PPMLanguageModel.cpp b/inputmethods/dasher/PPMLanguageModel.cpp
new file mode 100644
index 0000000..b725a2b
--- a/dev/null
+++ b/inputmethods/dasher/PPMLanguageModel.cpp
@@ -0,0 +1,309 @@
+// PPMLanguageModel.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 1999-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#include <math.h>
+#include "PPMLanguageModel.h"
+
+using namespace Dasher;
+using namespace std;
+
+// static TCHAR debug[256];
+typedef unsigned long ulong;
+
+////////////////////////////////////////////////////////////////////////
+/// PPMnode definitions
+////////////////////////////////////////////////////////////////////////
+
+CPPMLanguageModel::CPPMnode *CPPMLanguageModel::CPPMnode::find_symbol(int sym)
+// see if symbol is a child of node
+{
+ // printf("finding symbol %d at node %d\n",sym,node->id);
+ CPPMnode *found=child;
+ while (found) {
+ if (found->symbol==sym)
+ return found;
+ found=found->next;
+ }
+ return 0;
+}
+
+
+CPPMLanguageModel::CPPMnode * CPPMLanguageModel::CPPMnode::add_symbol_to_node(int sym,int *update)
+{
+ CPPMnode *born,*search;
+ search=find_symbol(sym);
+ if (!search) {
+ born = new CPPMnode(sym);
+ born->next=child;
+ child=born;
+ // node->count=1;
+ return born;
+ } else {
+ if (*update) { // perform update exclusions
+ search->count++;
+ *update=0;
+ }
+ return search;
+ }
+
+}
+
+
+/////////////////////////////////////////////////////////////////////
+// CPPMLanguageModel defs
+/////////////////////////////////////////////////////////////////////
+
+CPPMLanguageModel::CPPMLanguageModel(CAlphabet *_alphabet,int _normalization)
+ : CLanguageModel(_alphabet,_normalization)
+{
+ root=new CPPMnode(-1);
+ m_rootcontext=new CPPMContext(root,0);
+}
+
+
+CPPMLanguageModel::~CPPMLanguageModel()
+{
+ delete root;
+}
+
+
+bool CPPMLanguageModel::GetProbs(CContext *context,vector<unsigned int> &probs,double addprob)
+ // get the probability distribution at the context
+{
+ // seems like we have to have this hack for VC++
+ CPPMContext *ppmcontext=static_cast<CPPMContext *> (context);
+
+
+ int modelchars=GetNumberModelChars();
+ int norm=CLanguageModel::normalization();
+ probs.resize(modelchars);
+ CPPMnode *temp,*s;
+ int loop,total;
+ int sym;
+ ulong spent=0;
+ ulong size_of_slice;
+ bool *exclusions=new bool [modelchars];
+ ulong uniform=modelchars;
+ ulong tospend=norm-uniform;
+ temp=ppmcontext->head;
+ for (loop=0; loop <modelchars; loop++) { /* set up the exclusions array */
+ probs[loop]=0;
+ exclusions[loop]=0;
+ }
+ while (temp!=0) {
+ // Usprintf(debug,TEXT("tospend %u\n"),tospend);
+ // DebugOutput(TEXT("round\n"));
+ total=0;
+ s=temp->child;
+ while (s) {
+ sym=s->symbol;
+ if (!exclusions[s->symbol])
+ total=total+s->count;
+ s=s->next;
+ }
+ if (total) {
+ // Usprintf(debug,TEXT"escape %u\n"),tospend*
+ size_of_slice=tospend;
+ s=temp->child;
+ while (s) {
+ if (!exclusions[s->symbol]) {
+ exclusions[s->symbol]=1;
+ ulong p=size_of_slice*(2*s->count-1)/2/ulong(total);
+ probs[s->symbol]+=p;
+ tospend-=p;
+ }
+ // Usprintf(debug,TEXT("sym %u counts %d p %u tospend %u \n"),sym,s->count,p,tospend);
+ // DebugOutput(debug);
+ s=s->next;
+ }
+ }
+ temp = temp->vine;
+ }
+ // Usprintf(debug,TEXT("Norm %u tospend %u\n"),Norm,tospend);
+ // DebugOutput(debug);
+
+ size_of_slice=tospend;
+ int symbolsleft=0;
+ for (sym=1;sym<modelchars;sym++)
+ if (!probs[sym])
+ symbolsleft++;
+ for (sym=1;sym<modelchars;sym++)
+ if (!probs[sym]) {
+ ulong p=size_of_slice/symbolsleft;
+ probs[sym]+=p;
+ tospend-=p;
+ }
+
+ // distribute what's left evenly
+ tospend+=uniform;
+ for (sym=1;sym<modelchars;sym++) {
+ ulong p=tospend/(modelchars-sym);
+ probs[sym]+=p;
+ tospend-=p;
+ }
+ // Usprintf(debug,TEXT("finaltospend %u\n"),tospend);
+ // DebugOutput(debug);
+
+ // free(exclusions); // !!!
+ // !!! NB by IAM: p577 Stroustrup 3rd Edition: "Allocating an object using new and deleting it using free() is asking for trouble"
+ delete[] exclusions;
+ return true;
+}
+
+
+void CPPMLanguageModel::AddSymbol(CPPMLanguageModel::CPPMContext &context,int symbol)
+ // add symbol to the context
+ // creates new nodes, updates counts
+ // and leaves 'context' at the new context
+{
+ // sanity check
+ if (symbol==0 || symbol>=GetNumberModelChars())
+ return;
+
+ CPPMnode *vineptr,*temp;
+ int updatecnt=1;
+
+ temp=context.head->vine;
+ context.head=context.head->add_symbol_to_node(symbol,&updatecnt);
+ vineptr=context.head;
+ context.order++;
+
+ while (temp!=0) {
+ vineptr->vine=temp->add_symbol_to_node(symbol,&updatecnt);
+ vineptr=vineptr->vine;
+ temp=temp->vine;
+ }
+ vineptr->vine=root;
+ if (context.order>MAX_ORDER){
+ context.head=context.head->vine;
+ context.order--;
+ }
+}
+
+
+// update context with symbol 'Symbol'
+void CPPMLanguageModel::EnterSymbol(CContext* Context, modelchar Symbol)
+{
+ CPPMLanguageModel::CPPMContext& context = * static_cast<CPPMContext *> (Context);
+
+ CPPMnode *find;
+ CPPMnode *temp=context.head;
+
+ while (context.head) {
+ find =context.head->find_symbol(Symbol);
+ if (find) {
+ context.order++;
+ context.head=find;
+ // Usprintf(debug,TEXT("found context %x order %d\n"),head,order);
+ // DebugOutput(debug);
+ return;
+ }
+ context.order--;
+ context.head=context.head->vine;
+ }
+
+ if (context.head==0) {
+ context.head=root;
+ context.order=0;
+ }
+
+}
+
+
+void CPPMLanguageModel::LearnSymbol(CContext* Context, modelchar Symbol)
+{
+ CPPMLanguageModel::CPPMContext& context = * static_cast<CPPMContext *> (Context);
+ AddSymbol(context, Symbol);
+}
+
+
+void CPPMLanguageModel::dumpSymbol(int symbol)
+{
+ if ((symbol <= 32) || (symbol >= 127))
+ printf( "<%d>", symbol );
+ else
+ printf( "%c", symbol );
+}
+
+
+void CPPMLanguageModel::dumpString( char *str, int pos, int len )
+ // Dump the string STR starting at position POS
+{
+ char cc;
+ int p;
+ for (p = pos; p<pos+len; p++) {
+ cc = str [p];
+ if ((cc <= 31) || (cc >= 127))
+ printf( "<%d>", cc );
+ else
+ printf( "%c", cc );
+ }
+}
+
+
+void CPPMLanguageModel::dumpTrie( CPPMLanguageModel::CPPMnode *t, int d )
+ // diagnostic display of the PPM trie from node t and deeper
+{
+//TODO
+/*
+ dchar debug[256];
+ int sym;
+ CPPMnode *s;
+ Usprintf( debug,TEXT("%5d %7x "), d, t );
+ //TODO: Uncomment this when headers sort out
+ //DebugOutput(debug);
+ if (t < 0) // pointer to input
+ printf( " <" );
+ else {
+ Usprintf(debug,TEXT( " %3d %5d %7x %7x %7x <"), t->symbol,t->count, t->vine, t->child, t->next );
+ //TODO: Uncomment this when headers sort out
+ //DebugOutput(debug);
+ }
+
+ dumpString( dumpTrieStr, 0, d );
+ Usprintf( debug,TEXT(">\n") );
+ //TODO: Uncomment this when headers sort out
+ //DebugOutput(debug);
+ if (t != 0) {
+ s = t->child;
+ while (s != 0) {
+ sym =s->symbol;
+
+ dumpTrieStr [d] = sym;
+ dumpTrie( s, d+1 );
+ s = s->next;
+ }
+ }
+*/
+}
+
+
+void CPPMLanguageModel::dump()
+ // diagnostic display of the whole PPM trie
+{
+// TODO:
+/*
+ dchar debug[256];
+ Usprintf(debug,TEXT( "Dump of Trie : \n" ));
+ //TODO: Uncomment this when headers sort out
+ //DebugOutput(debug);
+ Usprintf(debug,TEXT( "---------------\n" ));
+ //TODO: Uncomment this when headers sort out
+ //DebugOutput(debug);
+ Usprintf( debug,TEXT( "depth node symbol count vine child next context\n") );
+ //TODO: Uncomment this when headers sort out
+ //DebugOutput(debug);
+ dumpTrie( root, 0 );
+ Usprintf( debug,TEXT( "---------------\n" ));
+ //TODO: Uncomment this when headers sort out
+ //DebugOutput(debug);
+ Usprintf(debug,TEXT( "\n" ));
+ //TODO: Uncomment this when headers sort out
+ //DebugOutput(debug);
+*/
+}
diff --git a/inputmethods/dasher/PPMLanguageModel.h b/inputmethods/dasher/PPMLanguageModel.h
new file mode 100644
index 0000000..bd860b8
--- a/dev/null
+++ b/inputmethods/dasher/PPMLanguageModel.h
@@ -0,0 +1,122 @@
+// PPMLanguageModel.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 1999-2002 David Ward
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#ifndef __PPMLanguageModel_h__
+#define __PPMLanguageModel_h__
+
+#include "NoClones.h"
+#include "MSVC_Unannoy.h"
+#include <vector>
+#include <stdio.h>
+
+#include "LanguageModel.h"
+
+static char dumpTrieStr[40000];
+const int MAX_ORDER = 5;
+const int maxcont =200;
+
+namespace Dasher {class CPPMLanguageModel;}
+class Dasher::CPPMLanguageModel : public Dasher::CLanguageModel, private NoClones
+{
+public:
+ CPPMLanguageModel(CAlphabet *_alphabet, int _normalization);
+ ~CPPMLanguageModel();
+
+ class CPPMnode {
+ public:
+ CPPMnode* find_symbol(int sym);
+ CPPMnode* add_symbol_to_node(int sym,int *update);
+ CPPMnode* child;
+ CPPMnode* next;
+ CPPMnode* vine;
+ short int count;
+ const short int symbol;
+ CPPMnode(int sym);
+ };
+
+ class CPPMContext : public CContext {
+ public:
+ CPPMContext(CPPMContext const &input) {head = input.head; order= input.order;}
+ CPPMContext(CPPMnode* _head=0, int _order=0) : head(_head),order(_order) {};
+ ~CPPMContext() {};
+ void dump();
+ CPPMnode* head;
+ int order;
+ };
+
+ void ReleaseContext(CContext*);
+ CContext* GetRootContext();
+ inline CContext* CloneContext(CContext*);
+ void EnterSymbol(CContext* context, modelchar Symbol);
+ //inline bool GetProbs(CContext*,std::vector<symbol> &newchars,std::vector<unsigned int> &groups,std::vector<unsigned int> &probs,double addprob);
+ bool GetProbs(CContext*, std::vector<unsigned int> &Probs, double AddProb);
+
+ void LearnSymbol(CContext* Context, modelchar Symbol);
+ void dump();
+
+private:
+ CPPMContext *m_rootcontext;
+ CPPMnode *root;
+ void AddSymbol(CPPMContext& context,int symbol);
+ void dumpSymbol(int symbol);
+ void dumpString( char *str, int pos, int len );
+ void dumpTrie( CPPMnode *t, int d );
+
+
+
+};
+
+////////////////////////////////////////////////////////////////////////
+// Inline functions
+////////////////////////////////////////////////////////////////////////
+
+////////////////////////////////////////////////////////////////////////
+
+inline CPPMLanguageModel::CPPMnode::CPPMnode(int sym) : symbol(sym)
+{
+ child=next=vine=0;
+ count=1;
+}
+
+///////////////////////////////////////////////////////////////////
+
+inline void CPPMLanguageModel::CPPMContext::dump()
+ // diagnostic output
+{
+ // TODO uncomment this when headers sorted out
+ //dchar debug[128];
+ //Usprintf(debug,TEXT("head %x order %d\n"),head,order);
+ //DebugOutput(debug);
+}
+
+///////////////////////////////////////////////////////////////////
+
+inline CContext* CPPMLanguageModel::GetRootContext()
+{
+ CPPMContext * nc = new CPPMLanguageModel::CPPMContext(*m_rootcontext);
+ CContext *cont=static_cast<CContext *> (nc);
+ return cont;
+}
+
+///////////////////////////////////////////////////////////////////
+
+inline CContext* CPPMLanguageModel::CloneContext(CContext *copythis)
+{
+ CPPMContext *ppmcontext=static_cast<CPPMContext *> (copythis);
+ CPPMContext * nc = new CPPMLanguageModel::CPPMContext(*ppmcontext);
+ return static_cast<CContext *> (nc);
+}
+
+///////////////////////////////////////////////////////////////////
+
+inline void CPPMLanguageModel::ReleaseContext(CContext *release)
+{
+ delete release;
+}
+
+#endif /* #ifndef __PPMLanguageModel_H__ */
diff --git a/inputmethods/dasher/QtDasherImpl.cc b/inputmethods/dasher/QtDasherImpl.cc
new file mode 100644
index 0000000..55c21b1
--- a/dev/null
+++ b/inputmethods/dasher/QtDasherImpl.cc
@@ -0,0 +1,85 @@
+#include <iostream>
+#include <qapplication.h>
+#include <qobject.h>
+#include <qpixmap.h>
+#include "DasherInterface.h"
+#include "QtDasherScreen.h"
+#include "QtDasherImpl.h"
+
+/* XPM */
+static const char * qtdasher_xpm[]={
+"28 7 2 1",
+"# c #303030",
+" c None",
+" ########################## ",
+" ",
+" # # ",
+" # # # # ",
+" # # # # ",
+" # # # ",
+" ########################## "};
+
+
+QtDasherImpl::QtDasherImpl()
+ : qtdasherwidget(0), icn(0), ref(0), qtdasherinterface(0)
+{
+}
+
+QtDasherImpl::~QtDasherImpl()
+{
+ delete qtdasherwidget;
+ delete icn;
+}
+
+QWidget *QtDasherImpl::inputMethod( QWidget *parent, Qt::WFlags f )
+{
+ if ( !qtdasherwidget ) {
+ qtdasherwidget = new QtDasherPlugin( parent, "Dasher", f );
+ }
+ return qtdasherwidget;
+}
+
+void QtDasherImpl::resetState()
+{
+ if ( qtdasherwidget )
+ qtdasherwidget->resetState();
+}
+
+QPixmap *QtDasherImpl::icon()
+{
+ if ( !icn )
+ icn = new QPixmap( (const char **)qtdasher_xpm );
+ return icn;
+}
+
+QString QtDasherImpl::name()
+{
+ return qApp->translate( "InputMethods", "Dasher" );
+}
+
+void QtDasherImpl::onKeyPress( QObject *receiver, const char *slot )
+{
+ if ( qtdasherwidget )
+ QObject::connect( qtdasherwidget, SIGNAL(key(ushort,ushort,ushort,bool,bool)), receiver, slot );
+}
+
+#ifndef QT_NO_COMPONENT
+QRESULT QtDasherImpl::queryInterface( const QUuid &uuid, QUnknownInterface **iface )
+{
+ *iface = 0;
+ if ( uuid == IID_QUnknown )
+ *iface = this;
+ else if ( uuid == IID_InputMethod )
+ *iface = this;
+
+ if ( *iface )
+ (*iface)->addRef();
+ return QS_OK;
+}
+
+Q_EXPORT_INTERFACE()
+{
+ Q_CREATE_INSTANCE( QtDasherImpl )
+}
+#endif
+
diff --git a/inputmethods/dasher/QtDasherImpl.h b/inputmethods/dasher/QtDasherImpl.h
new file mode 100644
index 0000000..c143dc3
--- a/dev/null
+++ b/inputmethods/dasher/QtDasherImpl.h
@@ -0,0 +1,38 @@
+#ifndef QTDASHERIMPL_H
+#define QTDASHERIMPL_H
+
+#include <qpe/inputmethodinterface.h>
+#include "QtDasherPlugin.h"
+
+class QtDasher;
+class QPixmap;
+
+class QtDasherImpl : public InputMethodInterface
+{
+public:
+ QtDasherImpl();
+ virtual ~QtDasherImpl();
+
+#ifndef QT_NO_COMPONENT
+ QRESULT queryInterface( const QUuid&, QUnknownInterface** );
+ Q_REFCOUNT
+#endif
+
+ virtual QWidget *inputMethod( QWidget *parent, Qt::WFlags f );
+ virtual void resetState();
+ virtual QPixmap *icon();
+ virtual QString name();
+ virtual void onKeyPress( QObject *receiver, const char *slot );
+
+private:
+ CDasherInterface *qtdasherinterface;
+ QtDasherPlugin *qtdasherwidget;
+ QPixmap *icn;
+ ulong ref;
+};
+
+#endif
+
+
+
+
diff --git a/inputmethods/dasher/QtDasherPlugin.cc b/inputmethods/dasher/QtDasherPlugin.cc
new file mode 100644
index 0000000..fe1712e
--- a/dev/null
+++ b/inputmethods/dasher/QtDasherPlugin.cc
@@ -0,0 +1,79 @@
+#include "QtDasherPlugin.h"
+
+#include <qpe/global.h>
+
+#include <qpainter.h>
+#include <qlist.h>
+#include <qbitmap.h>
+#include <qlayout.h>
+#include <qvbox.h>
+#include <qdialog.h>
+#include <qscrollview.h>
+#include <qpopupmenu.h>
+#include <qhbuttongroup.h>
+#include <qpushbutton.h>
+#include <qmessagebox.h>
+#include <qwindowsystem_qws.h>
+
+QtDasherPlugin::QtDasherPlugin(QWidget* parent, const char* name, WFlags f) : QFrame(parent,name,f)
+{
+ (new QHBoxLayout(this))->setAutoAdd(TRUE);
+ interface = new CDasherInterface;
+ interface->SetSystemLocation("/opt/QtPalmtop/share/dasher");
+ interface->Unpause(0);
+ interface->Start();
+ d = new QtDasherScreen(240,100,interface,this,this);
+ interface->ChangeMaxBitRate(2.5);
+ d->show();
+ utf8_codec = new QUtf8Codec;
+}
+
+QSize QtDasherPlugin::sizeHint() const
+{
+ return QSize(240,100);
+}
+
+QtDasherPlugin::~QtDasherPlugin()
+{
+ delete d;
+}
+
+void QtDasherPlugin::resetState()
+{
+ flushcount=0;
+ interface->Start();
+ interface->Redraw();
+}
+
+void QtDasherPlugin::unflush()
+{
+ if (flushcount==0)
+ return;
+ for (flushcount; flushcount>0; flushcount--) {
+ deletetext();
+ }
+}
+
+void QtDasherPlugin::output(int Symbol)
+{
+ std::string label = interface->GetEditText(Symbol);
+ QString unicodestring = utf8_codec->toUnicode(label.c_str());
+ for (int i=0; i<int(unicodestring.length()); i++) {
+ emit key( unicodestring[i].unicode(), 0, 0, true, false );
+ emit key( unicodestring[i].unicode(), 0, 0, false, false );
+ }
+}
+
+void QtDasherPlugin::deletetext()
+{
+ emit key( 0, Qt::Key_Backspace, 0, true, false);
+ emit key( 0, Qt::Key_Backspace, 0, false, false);
+}
+
+void QtDasherPlugin::flush(int Symbol)
+{
+ if (Symbol==0)
+ return;
+ output(Symbol);
+ flushcount++;
+}
diff --git a/inputmethods/dasher/QtDasherPlugin.h b/inputmethods/dasher/QtDasherPlugin.h
new file mode 100644
index 0000000..5f70acf
--- a/dev/null
+++ b/inputmethods/dasher/QtDasherPlugin.h
@@ -0,0 +1,42 @@
+#include <qutfcodec.h>
+#include <qframe.h>
+#include "QtDasherScreen.h"
+#include "DasherInterface.h"
+#include "DashEdit.h"
+
+class QtDasherPlugin : public QFrame, public CDashEditbox
+{
+ Q_OBJECT
+public:
+ QtDasherPlugin(QWidget* parent=0, const char* name=0, WFlags f=0);
+ ~QtDasherPlugin();
+
+ void resetState();
+ QSize sizeHint() const;
+
+ void write_to_file() {};
+ void get_new_context(std::string&, int) {};
+ void unflush();
+ void output(int);
+ void deletetext();
+ void flush(int);
+ void Clear() {};
+ void SetEncoding(Dasher::Opts::FileEncodingFormats) {};
+ void SetFont(std::string Name, long Size) {};
+
+ signals:
+ void key( ushort, ushort, ushort, bool, bool);
+
+ private:
+ QtDasherScreen *d;
+ CDasherInterface *interface;
+ int flushcount;
+ QUtf8Codec *utf8_codec;
+};
+
+
+
+
+
+
+
diff --git a/inputmethods/dasher/QtDasherScreen.cc b/inputmethods/dasher/QtDasherScreen.cc
new file mode 100644
index 0000000..6820105
--- a/dev/null
+++ b/inputmethods/dasher/QtDasherScreen.cc
@@ -0,0 +1,180 @@
+// QtDasherScreen.cc
+// (c) 2003 Yann Dirson
+// Derived from GtkDasherCanvas.cc
+// (c) 2002 Philip Cowans
+
+#include <iostream>
+#include <string>
+
+#include <qpointarray.h>
+#include <qpoint.h>
+
+#include "QtDasherScreen.h"
+#include "DasherScreen.h"
+#include "SettingsStore.h"
+
+#define MAXFONTSIZE 25
+#define MINFONTSIZE 8
+
+#include <iconv.h>
+#include <iostream>
+
+QtDasherScreen::QtDasherScreen (int _width, int _height,
+ CDasherInterface *_interface,
+ QWidget * _parent, Dasher::CDashEditbox *edit):
+ QWidget(_parent), interface( _interface ),
+ fontname( "fixed" ), // fontsize(12),
+ Dasher::CDasherScreen(_width, _height)
+{
+ // font = new QFont (fontname, fontsize);
+ painter = new QPainter ();
+
+ pixmap = new QPixmap (_width, _height);
+ pixmap->setOptimization(QPixmap::BestOptim);
+ interface->SetSettingsStore(new CSettingsStore);
+
+ interface->ChangeLanguageModel(0);
+ interface->ChangeView(0);
+ interface->ChangeEdit(edit);
+
+ interface->GetFontSizes(&FontSizes);
+
+ for (int i=0; i<FontSizes.size(); i++) {
+ if (FontSizes[i]>Fonts.size())
+ Fonts.resize((FontSizes[i])+1);
+ Fonts[FontSizes[i]]= QFont (fontname.c_str(), FontSizes[i]);
+ Fonts[FontSizes[i]].setPixelSize(FontSizes[i]);
+ }
+
+ interface->ChangeScreen(this);
+
+ paused=true;
+
+ QTimer *tmr = new QTimer(this);
+ connect (tmr, SIGNAL(timeout()), SLOT(timer()));
+ tmr->start(200);
+
+}
+
+long QtDasherScreen::get_time()
+{
+ long s_now;
+ long ms_now;
+
+ struct timeval tv;
+ struct timezone tz;
+
+ gettimeofday( &tv, &tz );
+
+ s_now = tv.tv_sec-1054487600;
+
+ ms_now = tv.tv_usec / 1000;
+
+ return( long(s_now*1000 + ms_now) );
+
+}
+
+QtDasherScreen::~QtDasherScreen()
+{
+ delete painter;
+ delete interface;
+ delete edit;
+}
+
+QColor QtDasherScreen::getColor(int Color, const Opts::ColorSchemes ColorScheme) const
+{
+ switch (ColorScheme) {
+ case Dasher::Opts::Nodes1:
+ switch (Color) {
+ case 0: return QColor (180, 245, 180);
+ case 1: return QColor (160, 200, 160);
+ case 2: return QColor (0, 255, 255);
+ default: abort ();
+ }
+ case Dasher::Opts::Nodes2:
+ switch (Color) {
+ case 0: return QColor (255, 185, 255);
+ case 1: return QColor (140, 200, 255);
+ case 2: return QColor (255, 175, 175);
+ default: abort ();
+ }
+ case Dasher::Opts::Special1: return QColor (240, 240, 240);
+ case Dasher::Opts::Special2: return QColor (255, 255, 255);
+ case Dasher::Opts::Groups:
+ switch (Color) {
+ case 0: return QColor (255, 255, 0);
+ case 1: return QColor (255, 100, 100);
+ case 2: return QColor (0, 255, 0);
+ default: abort ();
+ }
+ case Dasher::Opts::Objects: return QColor (0, 0, 0);
+ default: abort();
+ }
+}
+
+void QtDasherScreen::DrawRectangle(int x1, int y1, int x2, int y2,
+ int Color, Opts::ColorSchemes ColorScheme) const
+{
+ painter->setBrush (getColor (Color, ColorScheme));
+ painter->drawRect (x1, y1, x2-x1, y2-y1);
+}
+
+static void Points_to_QPointArray(const Dasher::CDasherScreen::point* const points,
+ int number,
+ QPointArray &qpa)
+{
+ for (int i = 0; i < number; i++) {
+ qpa.setPoint (i, points[i].x, points[i].y);
+ }
+}
+
+void QtDasherScreen::Polyline(point* Points, int Number) const
+{
+ QPointArray qpa(Number);
+ Points_to_QPointArray (Points, Number, qpa);
+ painter->setPen (SolidLine);
+ painter->drawPolyline (qpa);
+ painter->setPen (NoPen);
+}
+
+void QtDasherScreen::DrawPolygon(point* Points, int Number, int Color,
+ Opts::ColorSchemes ColorScheme) const
+{
+ painter->setBrush (getColor (Color, ColorScheme));
+ QPointArray qpa(Number);
+ Points_to_QPointArray (Points, Number, qpa);
+ painter->drawPolygon (qpa);
+}
+
+void QtDasherScreen::mousePressEvent (QMouseEvent *e)
+{
+ paused=false;
+ interface->Unpause(get_time());
+}
+
+void QtDasherScreen::mouseReleaseEvent(QMouseEvent *e)
+{
+ QPoint p = e->pos();
+ interface->PauseAt(p.x(), p.y());
+ paused=true;
+}
+
+void QtDasherScreen::timer()
+{
+ if (paused==false) {
+ QPoint cursorpos;
+ cursorpos=this->cursor().pos();
+ cursorpos=mapFromGlobal(cursorpos);
+
+ interface->TapOn(cursorpos.x(), cursorpos.y(), get_time());
+ }
+}
+
+
+
+
+
+
+
+
+
diff --git a/inputmethods/dasher/QtDasherScreen.h b/inputmethods/dasher/QtDasherScreen.h
new file mode 100644
index 0000000..f359113
--- a/dev/null
+++ b/inputmethods/dasher/QtDasherScreen.h
@@ -0,0 +1,117 @@
+// QtDasherScreen.h
+// (c) 2003 Yann Dirson
+// Derived from GtkDasherCanvas.h
+// (c) 2002 Philip Cowans
+
+#ifndef QT_DASHER_SCREEN_H
+#define QT_DASHER_SCREEN_H
+
+#include <string>
+#include <sys/time.h>
+
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qfont.h>
+#include <qstring.h>
+#include <qpixmap.h>
+#include <qtimer.h>
+#include <qcursor.h>
+
+#include "DasherScreen.h"
+#include "DashEdit.h"
+#include "DasherInterface.h"
+
+#include <iconv.h>
+
+using namespace Dasher;
+
+class QtDasherScreen : public QWidget, public Dasher::CDasherScreen
+
+{
+ Q_OBJECT
+ public:
+ QtDasherScreen (int _width, int _height,
+ CDasherInterface *_interface,
+ QWidget * _parent=0, Dasher::CDashEditbox* edit=0);
+ QtDasherScreen::~QtDasherScreen();
+
+ void SetFont(std::string Name)
+ { fontname = Name; /* set_the_font(); */ }
+
+ void SetFontSize(Dasher::Opts::FontSize fontsize)
+ {
+#warning QtDasherScreen::SetFontSize() not implemented
+ }
+ Dasher::Opts::FontSize GetFontSize()
+ {
+#warning QtDasherScreen::GetFontSize() not implemented
+ return (Dasher::Opts::Normal);
+ }
+
+ void TextSize(symbol Character, int* Width, int* Height, int Size) const
+ {
+ // should probably use QPainter::boundingRect()
+ *Width = *Height = Fonts[Size].pixelSize();
+
+ }
+ void DrawText(symbol Character, int x1, int y1, int Size) const
+ {
+ // QFont font = QFont (fontname.c_str(), Size);
+ // font.setPixelSize(Size);
+ QPoint point = QPoint(x1, y1+Size/2);
+
+ painter->setFont (Fonts[Size]);
+ painter->drawText (point,
+ QString(interface->GetDisplayText(Character).c_str()));
+ }
+
+ void DrawRectangle(int x1, int y1, int x2, int y2,
+ int Color, Opts::ColorSchemes ColorScheme) const;
+ void Polyline(point* Points, int Number) const;
+ void DrawPolygon(point* Points, int Number, int Color,
+ Opts::ColorSchemes ColorScheme) const;
+
+ std::vector<int> FontSizes;
+ std::vector<QFont> Fonts;
+
+ void Blank() const {
+ painter->begin(pixmap);
+ painter->setPen (NoPen);
+ painter->fillRect(0, 0, m_iWidth, m_iHeight,
+ QColor(255,255,255));
+ }
+ void Display() {
+ painter->end();
+ repaint();
+ }
+
+ void paintEvent( QPaintEvent * )
+ {
+ bitBlt(this, 0, 0, pixmap);
+ }
+
+ void mousePressEvent (QMouseEvent *e);
+ void mouseReleaseEvent (QMouseEvent *e);
+
+ protected:
+ QColor getColor(int Color, const Opts::ColorSchemes ColorScheme) const;
+
+ long QtDasherScreen::get_time();
+
+ CDasherInterface* interface;
+ Dasher::CDashEditbox* edit;
+
+ bool paused;
+
+ QPainter* painter;
+
+ QPixmap* pixmap;
+
+ std::string fontname;
+
+ protected slots:
+ void timer();
+
+};
+
+#endif
diff --git a/inputmethods/dasher/SettingsStore.cpp b/inputmethods/dasher/SettingsStore.cpp
new file mode 100644
index 0000000..c5bbfea
--- a/dev/null
+++ b/inputmethods/dasher/SettingsStore.cpp
@@ -0,0 +1,135 @@
+// SettingsStore.cpp
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+
+#include "SettingsStore.h"
+
+using namespace std;
+
+/* TODO: Consider using Template functions to make this neater. */
+
+
+bool CSettingsStore::GetBoolOption(const string& Key)
+{
+ if (BoolMap.find(Key)==BoolMap.end()) {
+ bool Value = false;
+ LoadSetting(Key, &Value);
+ BoolMap[Key] = Value;
+ }
+
+ return BoolMap[Key];
+}
+
+
+long CSettingsStore::GetLongOption(const string& Key)
+{
+ if (LongMap.find(Key)==LongMap.end()) {
+ long Value = 0l;
+ LoadSetting(Key, &Value);
+ LongMap[Key] = Value;
+ }
+
+ return LongMap[Key];
+}
+
+
+string& CSettingsStore::GetStringOption(const string& Key)
+{
+ if (StringMap.find(Key)==StringMap.end()) {
+ string Value = "";
+ LoadSetting(Key, &Value);
+ StringMap[Key] = Value;
+ }
+
+ return StringMap[Key];
+}
+
+
+void CSettingsStore::SetBoolOption(const string& Key, bool Value)
+{
+ BoolMap[Key] = Value;
+ SaveSetting(Key, Value);
+}
+
+
+void CSettingsStore::SetLongOption(const string& Key, long Value)
+{
+ LongMap[Key] = Value;
+ SaveSetting(Key, Value);
+}
+
+
+void CSettingsStore::SetStringOption(const string& Key, const string& Value)
+{
+ StringMap[Key] = Value;
+ SaveSetting(Key, Value);
+}
+
+
+void CSettingsStore::SetBoolDefault(const string& Key, bool Value)
+{
+ bool TmpValue;
+ if ( (BoolMap.find(Key)==BoolMap.end()) && (!LoadSetting(Key, &TmpValue)) )
+ SetBoolOption(Key, Value);
+}
+
+
+void CSettingsStore::SetLongDefault(const string& Key, long Value)
+{
+ long TmpValue;
+ if ( (LongMap.find(Key)==LongMap.end()) && (!LoadSetting(Key, &TmpValue)) )
+ SetLongOption(Key, Value);
+}
+
+
+void CSettingsStore::SetStringDefault(const string& Key, const string& Value)
+{
+ string TmpValue;
+ if ( (StringMap.find(Key)==StringMap.end()) && (!LoadSetting(Key, &TmpValue)) )
+ SetStringOption(Key, Value);
+}
+
+
+/* Private functions -- Settings are not saved between sessions unless these
+functions are over-ridden.
+--------------------------------------------------------------------------*/
+
+
+bool CSettingsStore::LoadSetting(const string& Key, bool* Value)
+{
+ return false;
+}
+
+
+bool CSettingsStore::LoadSetting(const string& Key, long* Value)
+{
+ return false;
+}
+
+
+bool CSettingsStore::LoadSetting(const string& Key, string* Value)
+{
+ return false;
+}
+
+
+void CSettingsStore::SaveSetting(const string& Key, bool Value)
+{
+}
+
+
+void CSettingsStore::SaveSetting(const string& Key, long Value)
+{
+}
+
+
+void CSettingsStore::SaveSetting(const string& Key, const string& Value)
+{
+}
diff --git a/inputmethods/dasher/SettingsStore.h b/inputmethods/dasher/SettingsStore.h
new file mode 100644
index 0000000..8ef9fcf
--- a/dev/null
+++ b/inputmethods/dasher/SettingsStore.h
@@ -0,0 +1,92 @@
+// SettingsStore.h
+//
+/////////////////////////////////////////////////////////////////////////////
+//
+// Copyright (c) 2002 Iain Murray
+//
+/////////////////////////////////////////////////////////////////////////////
+
+
+
+#ifndef __SettingsStore_h__
+#define __SettingsStore_h__
+
+
+#include "MSVC_Unannoy.h"
+#include <string>
+#include <map>
+
+
+/*
+ The public interface uses UTF-8 strings. All Keys should be
+ in American English and encodable in ASCII. However,
+ string Values may contain special characters where appropriate.
+*/
+
+
+class CSettingsStore
+{
+public:
+ bool GetBoolOption(const std::string& Key);
+ long GetLongOption(const std::string& Key);
+ std::string& GetStringOption(const std::string& Key);
+
+ void SetBoolOption(const std::string& Key, bool Value);
+ void SetLongOption(const std::string& Key, long Value);
+ void SetStringOption(const std::string& Key, const std::string& Value);
+
+ void SetBoolDefault(const std::string& Key, bool Value);
+ void SetLongDefault(const std::string& Key, long Value);
+ void SetStringDefault(const std::string& Key, const std::string& Value);
+private:
+ // Platform Specific settings file management
+
+ // LoadSetting changes Value only if it succeeds in loading the setting,
+ // in which case it also returns true. Failure is indicated by returning false.
+ //! Load a setting with a boolean value
+ //
+ //! Load a setting with a boolean value. Return true if successful
+ //! \param Key Name of the setting
+ //! \param Value Value of the setting
+ virtual bool LoadSetting(const std::string& Key, bool* Value);
+
+ //! Load a setting with a long value
+ //
+ //! Load a setting with a long value. Return true if successful
+ //! \param Key Name of the setting
+ //! \param Value Value of the setting
+ virtual bool LoadSetting(const std::string& Key, long* Value);
+
+ //! Load a setting with a string value
+ //
+ //! Load a setting with a string value. Return true if successful
+ //! \param Key Name of the setting
+ //! \param Value Value of the setting, UTF8 encoded
+ virtual bool LoadSetting(const std::string& Key, std::string* Value);
+
+ //! Save a setting with a boolean value
+ //
+ //! \param Key Name of the setting
+ //! \param Value Value of the setting
+ virtual void SaveSetting(const std::string& Key, bool Value);
+
+ //! Save a setting with a long value
+ //
+ //! \param Key Name of the setting
+ //! \param Value Value of the setting
+ virtual void SaveSetting(const std::string& Key, long Value);
+
+ //! Save a setting with a string value
+ //
+ //! \param Key Name of the setting
+ //! \param Value Value of the setting, UTF8 encoded
+ virtual void SaveSetting(const std::string& Key, const std::string& Value);
+
+ // Used to store settings in memory
+ std::map<std::string, bool> BoolMap;
+ std::map<std::string, long> LongMap;
+ std::map<std::string, std::string> StringMap;
+};
+
+
+#endif /* #ifndef __SettingsStore_h__ */
diff --git a/inputmethods/dasher/config.in b/inputmethods/dasher/config.in
new file mode 100644
index 0000000..44232dd
--- a/dev/null
+++ b/inputmethods/dasher/config.in
@@ -0,0 +1,5 @@
+ config DASHER
+ boolean "opie-dasher (zooming predictive text input)"
+ default "y"
+ depends ( LIBQPE || LIBQPE-X11 )
+
diff --git a/inputmethods/dasher/dasher.pro b/inputmethods/dasher/dasher.pro
new file mode 100644
index 0000000..7b6def9
--- a/dev/null
+++ b/inputmethods/dasher/dasher.pro
@@ -0,0 +1,57 @@
+TEMPLATE = lib
+CONFIG += qt warn_on release
+
+HEADERS = Alphabet.h \
+ DasherModel.h \
+ FrameRate.h \
+ AlphabetMap.h \
+ DasherNode.h \
+ LanguageModel.h \
+ AlphIO.h \
+ DasherScreen.h \
+ PPMLanguageModel.h \
+ Context.h \
+ DasherSettingsInterface.h \
+ QtDasherImpl.h \
+ CustomAlphabet.h \
+ DasherTypes.h \
+ QtDasherPlugin.h \
+ DashEdit.h \
+ DasherView.h \
+ QtDasherScreen.h \
+ DasherAppInterface.h \
+ DasherViewSquare.h \
+ SettingsStore.h \
+ DasherInterface.h \
+ DasherWidgetInterface.h
+SOURCES = Alphabet.cpp \
+ DasherModel.cpp \
+ LanguageModel.cpp \
+ AlphabetMap.cpp \
+ DasherNode.cpp \
+ PPMLanguageModel.cpp \
+ AlphIO.cpp \
+ DasherSettingsInterface.cpp \
+ SettingsStore.cpp \
+ CustomAlphabet.cpp \
+ DasherView.cpp \
+ DasherInterface.cpp \
+ DasherViewSquare.cpp \
+ QtDasherImpl.cc \
+ QtDasherPlugin.cc \
+ QtDasherScreen.cc
+TARGET = qdasher
+DESTDIR = ../../plugins/inputmethods
+INCLUDEPATH += $(OPIEDIR)/include
+DEPENDPATH += ../$(OPIEDIR)/include ../../launcher
+LIBS += -lqpe
+QMAKE_LFLAGS += -Wl,-rpath,/opt/QtPalmtop/plugins/inputmethods
+VERSION = 1.0.0
+SUBDIRS = DasherCore
+
+
+include ( $(OPIEDIR)/include.pro )
+target.path = $$prefix/plugins/inputmethods
+
+
+
diff --git a/inputmethods/dasher/opie-dasher-english.control b/inputmethods/dasher/opie-dasher-english.control
new file mode 100644
index 0000000..c2cee2e
--- a/dev/null
+++ b/inputmethods/dasher/opie-dasher-english.control
@@ -0,0 +1,12 @@
+Package: opie-dasher-english
+Files: share/dasher/training_english_GB.txt
+Priority: optional
+Section: opie/inputmethods
+Maintainer: Matthew Garrett <mjg59@srcf.ucam.org>
+Architecture: arm
+Version: $QPE_VERSION-1
+Depends: opie-dasher
+Description: Dasher text input method
+ Dasher is a novel zooming text entry method that allows significantly faster
+ text entry than traditional methods. This package provides the necessary
+ data file to allow it to make predictions in English.
diff --git a/inputmethods/dasher/opie-dasher.control b/inputmethods/dasher/opie-dasher.control
new file mode 100644
index 0000000..586b88a
--- a/dev/null
+++ b/inputmethods/dasher/opie-dasher.control
@@ -0,0 +1,11 @@
+Package: opie-dasher
+Files: plugins/inputmethods/libqdasher.so* share/dasher/alphabet.xml
+Priority: optional
+Section: opie/inputmethods
+Maintainer: Matthew Garrett <mjg59@srcf.ucam.org>
+Architecture: arm
+Version: $QPE_VERSION-1
+Depends: task-opie-minimal
+Description: Dasher text input method
+ Dasher is a novel zooming text entry method that allows significantly faster
+ text entry than traditional methods.
diff --git a/inputmethods/dasher/opie-dasher.postinst b/inputmethods/dasher/opie-dasher.postinst
new file mode 100644
index 0000000..b9ac6f0
--- a/dev/null
+++ b/inputmethods/dasher/opie-dasher.postinst
@@ -0,0 +1,7 @@
+#!/bin/sh
+if pidof -s qpe >/dev/null; then
+ /opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadInputMethods()"
+else
+ exit 0
+fi
+
diff --git a/inputmethods/dasher/opie-dasher.postrm b/inputmethods/dasher/opie-dasher.postrm
new file mode 100644
index 0000000..c254b01
--- a/dev/null
+++ b/inputmethods/dasher/opie-dasher.postrm
@@ -0,0 +1,2 @@
+#!/bin/sh
+/opt/QtPalmtop/bin/qcop QPE/TaskBar "reloadInputMethods()"
diff --git a/packages b/packages
index 74a6111..7fac4f0 100644
--- a/packages
+++ b/packages
@@ -25,2 +25,3 @@ CONFIG_CLOCKAPPLET core/applets/clockapplet clockapplet.pro
CONFIG_CONFEDIT noncore/apps/confedit confedit.pro
+CONFIG_DASHER inputmethods/dasher dasher.pro
CONFIG_DATEBOOK core/pim/datebook datebook.pro