author | mickeyl <mickeyl> | 2003-09-27 11:29:26 (UTC) |
---|---|---|
committer | mickeyl <mickeyl> | 2003-09-27 11:29:26 (UTC) |
commit | 651b6c612db4e809c506973996f2580c4158ac3a (patch) (side-by-side diff) | |
tree | 8c8edc86e4b206dd4542a6b556ad1a319d6698ab /inputmethods | |
parent | d1a11b45e805fe7771ea05944757d767c3c4c8ea (diff) | |
download | opie-651b6c612db4e809c506973996f2580c4158ac3a.zip opie-651b6c612db4e809c506973996f2580c4158ac3a.tar.gz opie-651b6c612db4e809c506973996f2580c4158ac3a.tar.bz2 |
merge dasher which has been introduced in BRANCH first (wtf?) into HEAD
49 files changed, 5331 insertions, 0 deletions
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()" |