[dasher: 14/27] Moved CAlphInfo::AlphIO out to separate CAlphIO class (friend of CAlphInfo)



commit 926ca8dc4697b773efa182ec1ed66cee6fcf5e31
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Sun Aug 8 19:42:16 2010 +0100

    Moved CAlphInfo::AlphIO out to separate CAlphIO class (friend of CAlphInfo)
    
     => {AlphInfo,AlphIO,AlphabetMap}.{h,cpp}
    
    Also added some general / class header documentation comments

 Src/DasherCore/Alphabet/AlphIO.cpp          |  138 ++++---------------
 Src/DasherCore/Alphabet/AlphIO.h            |  199 ++++++++-------------------
 Src/DasherCore/Alphabet/AlphInfo.cpp        |  121 ++++++++++++++++
 Src/DasherCore/Alphabet/AlphInfo.h          |  155 +++++++++++++++++++++
 Src/DasherCore/Alphabet/AlphabetMap.h       |   16 ++
 Src/DasherCore/DasherInterfaceBase.cpp      |    2 +-
 Src/DasherCore/DasherInterfaceBase.h        |    2 +-
 Src/DasherCore/Makefile.am                  |    2 +
 Src/DasherCore/NodeCreationManager.cpp      |    2 +-
 Src/DasherCore/NodeCreationManager.h        |    2 +-
 Src/MacOSX/Dasher.xcodeproj/project.pbxproj |    8 +
 11 files changed, 389 insertions(+), 258 deletions(-)
---
diff --git a/Src/DasherCore/Alphabet/AlphIO.cpp b/Src/DasherCore/Alphabet/AlphIO.cpp
index b5a568c..b5a8bd0 100644
--- a/Src/DasherCore/Alphabet/AlphIO.cpp
+++ b/Src/DasherCore/Alphabet/AlphIO.cpp
@@ -36,59 +36,7 @@ static char THIS_FILE[] = __FILE__;
 #endif
 #endif
 
-int CAlphInfo::GetTextColour(symbol Symbol) const {
-  const std::string &TextColour(GetForeground(Symbol));
-  if(TextColour != std::string("")) {
-    return atoi(TextColour.c_str());
-  }
-  else {
-    return 4;
-  }
-}
-
-int 
-CAlphInfo::GetColour(symbol i, int iPhase) const {
-  int iColour = m_vCharacters[i-1].Colour;
-  
-  // This is for backwards compatibility with old alphabet files -
-  // ideally make this log a warning (unrelated TODO: automate
-  // validation of alphabet files, plus maintenance of repository
-  // etc.)
-  if(iColour == -1) {
-    if(i == iSpaceCharacter) {
-      iColour = 9;
-    }
-    else {
-      iColour = (i % 3) + 10;
-    }
-  }
-  
-  // Loop on low colours for nodes (TODO: go back to colour namespaces?)
-  if(iPhase == 1 && iColour < 130)
-    iColour += 130;
-  
-  return iColour;
-}
-
-CAlphabetMap *CAlphInfo::MakeMap() const {
-  CAlphabetMap *map = new CAlphabetMap();
-  int i;
-  for(i = 0; i < m_vCharacters.size(); i++) {
-    map->Add(m_vCharacters[i].Text, i+1); //1-indexed
-  }
-  //ACL I'm really not sure where conversion characters should/shouldn't be included.
-  // They seemed to be included in the Alphabet Map, i.e. for reading training text via GetSymbols;
-  // but a TODO comment suggested they should _not_ be included in GetNumberSymbols(),
-  // and I couldn't find any code which would have called e.g. GetText on them....
-  // Hence, not including them in m_vCharacters.
-  if (StartConvertCharacter)
-    map->Add(StartConvertCharacter->Text, ++i);
-  if (EndConvertCharacter)
-    map->Add(EndConvertCharacter->Text, ++i);
-  return map;
-}
-
-CAlphInfo::AlphIO::AlphIO(std::string SystemLocation, std::string UserLocation, std::vector<std::string> &Filenames)
+CAlphIO::CAlphIO(std::string SystemLocation, std::string UserLocation, std::vector<std::string> &Filenames)
 : SystemLocation(SystemLocation), UserLocation(UserLocation), Filenames(Filenames), LoadMutable(false), CData("") {
   Alphabets["Default"]=CreateDefault();
 
@@ -130,39 +78,7 @@ CAlphInfo::AlphIO::AlphIO(std::string SystemLocation, std::string UserLocation,
   }
 }
 
-CAlphInfo::CAlphInfo() {
-  iSpaceCharacter=-1;
-  iParagraphCharacter = -1;
-  ControlCharacter=NULL;
-  StartConvertCharacter=NULL;
-  EndConvertCharacter=NULL;
-  m_pBaseGroup = 0;
-  iNumChildNodes = 0;
-  m_iConversionID = 0;
-  m_strDefaultContext = ". ";
-}
-
-void DeleteGroups(SGroupInfo *Info) {
-  for(SGroupInfo *next; Info; Info=next) {
-    next = Info->pNext;
-    DeleteGroups(Info->pChild);
-    delete Info;
-    Info = next;
-  }
-}
-
-CAlphInfo::~CAlphInfo() {
-  DeleteGroups(m_pBaseGroup);
-}
-
-CAlphInfo::character::character() {
-  Display="";
-  Text="";
-  Colour=-1;
-  Foreground="";
-}
-
-void CAlphInfo::AlphIO::ParseFile(std::string Filename) {
+void CAlphIO::ParseFile(std::string Filename) {
   FILE *Input;
   if((Input = fopen(Filename.c_str(), "r")) == (FILE *) 0) {
     // could not open file
@@ -193,7 +109,7 @@ void CAlphInfo::AlphIO::ParseFile(std::string Filename) {
   fclose(Input);
 }
 
-void CAlphInfo::AlphIO::GetAlphabets(std::vector <std::string >*AlphabetList) const {
+void CAlphIO::GetAlphabets(std::vector <std::string >*AlphabetList) const {
   AlphabetList->clear();
 
   typedef std::map < std::string, const CAlphInfo* >::const_iterator CI;
@@ -203,7 +119,7 @@ void CAlphInfo::AlphIO::GetAlphabets(std::vector <std::string >*AlphabetList) co
     AlphabetList->push_back(Cur->second->AlphID);
 }
 
-std::string CAlphInfo::AlphIO::GetDefault() {
+std::string CAlphIO::GetDefault() {
   if(Alphabets.count("English with limited punctuation") != 0) {
     return "English with limited punctuation";
   }
@@ -212,7 +128,7 @@ std::string CAlphInfo::AlphIO::GetDefault() {
   }
 }
 
-const CAlphInfo *CAlphInfo::AlphIO::GetInfo(const std::string &AlphID) {
+const CAlphInfo *CAlphIO::GetInfo(const std::string &AlphID) {
   if(Alphabets.count(AlphID)!=0) {
     // if we have the alphabet they ask for, return it
     return Alphabets[AlphID];
@@ -223,12 +139,12 @@ const CAlphInfo *CAlphInfo::AlphIO::GetInfo(const std::string &AlphID) {
   }
 }
 
-void CAlphInfo::AlphIO::SetInfo(const CAlphInfo *NewInfo) {
+void CAlphIO::SetInfo(const CAlphInfo *NewInfo) {
   Alphabets[NewInfo->AlphID] = NewInfo;
   Save(NewInfo->AlphID);
 }
 
-void CAlphInfo::AlphIO::Delete(const std::string &AlphID) {
+void CAlphIO::Delete(const std::string &AlphID) {
   map<std::string, const CAlphInfo *>::iterator it = Alphabets.find(AlphID);
   if(it != Alphabets.end()) {
     delete it->second;
@@ -237,7 +153,7 @@ void CAlphInfo::AlphIO::Delete(const std::string &AlphID) {
   }
 }
 
-void CAlphInfo::AlphIO::Save(const std::string &AlphID) {
+void CAlphIO::Save(const std::string &AlphID) {
   // TODO: We cannot reliably output XML at the moment this will have
   // to be re-implemented if we ever decide that we need to do this
   // again
@@ -317,7 +233,7 @@ void CAlphInfo::AlphIO::Save(const std::string &AlphID) {
     
     // Write out the space character
     if (Info.iSpaceCharacter!=0) {
-      character &spC(Info.m_vCharacters[Info.iSpaceCharacter]);
+      CAlphInfo::character &spC(Info.m_vCharacters[Info.iSpaceCharacter]);
       fwrite("<space d=\"", sizeof(char), 10, Output);
       XML_Escape(&spC.Display, true);
       fwrite(spC.Display.c_str(), sizeof(char), spC.Display.size(), Output);
@@ -332,7 +248,7 @@ void CAlphInfo::AlphIO::Save(const std::string &AlphID) {
 
     // Write out the paragraph character
     if (Info.iParagraphCharacter!=-1) {
-      character para(Info.m_vCharacters[Info.iParagraphCharacter]);
+      CAlphInfo::character para(Info.m_vCharacters[Info.iParagraphCharacter]);
       fwrite("<paragraph d=\"", sizeof(char), 14, Output);
       XML_Escape(&para.Display, true);
       fwrite(para.Display.c_str(), sizeof(char), para.Display.size(), Output);
@@ -397,7 +313,7 @@ void CAlphInfo::AlphIO::Save(const std::string &AlphID) {
   fclose(Output);
 }
 
-CAlphInfo *CAlphInfo::AlphIO::CreateDefault() {
+CAlphInfo *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.
@@ -444,7 +360,7 @@ CAlphInfo *CAlphInfo::AlphIO::CreateDefault() {
   Default.m_vCharacters[Default.iSpaceCharacter].Text = " ";
   Default.m_vCharacters[Default.iSpaceCharacter].Colour = 9;
   
-  Default.ControlCharacter = new character();
+  Default.ControlCharacter = new CAlphInfo::character();
   Default.ControlCharacter->Display = "Control";
   Default.ControlCharacter->Text = "";
   Default.ControlCharacter->Colour = 8;
@@ -452,7 +368,7 @@ CAlphInfo *CAlphInfo::AlphIO::CreateDefault() {
   return &Default;
 }
 
-void CAlphInfo::AlphIO::XML_Escape(std::string *Text, bool Attribute) {
+void CAlphIO::XML_Escape(std::string *Text, bool Attribute) {
   // The XML "W3C Recommendation" is here: http://www.w3.org/TR/REC-xml
 
   std::string & Input = *Text;       // Makes syntax less fiddly below
@@ -490,8 +406,8 @@ void CAlphInfo::AlphIO::XML_Escape(std::string *Text, bool Attribute) {
 // Below here handlers for the Expat XML input library
 ////////////////////////////////////////////////////////////////////////////////////
 
-void CAlphInfo::AlphIO::XML_StartElement(void *userData, const XML_Char *name, const XML_Char **atts) {
-  CAlphInfo::AlphIO *Me = (CAlphInfo::AlphIO *) userData;
+void CAlphIO::XML_StartElement(void *userData, const XML_Char *name, const XML_Char **atts) {
+  CAlphIO *Me = (CAlphIO *) userData;
 
   Me->CData = "";
 
@@ -549,12 +465,12 @@ void CAlphInfo::AlphIO::XML_StartElement(void *userData, const XML_Char *name, c
   }
 
   if(strcmp(name, "space") == 0) {
-    if (!Me->SpaceCharacter) Me->SpaceCharacter = new character();
+    if (!Me->SpaceCharacter) Me->SpaceCharacter = new CAlphInfo::character();
     Me->ReadCharAtts(atts,*(Me->SpaceCharacter));
     return;
   }
   if(strcmp(name, "paragraph") == 0) {
-    if (!Me->ParagraphCharacter) Me->ParagraphCharacter=new character();
+    if (!Me->ParagraphCharacter) Me->ParagraphCharacter=new CAlphInfo::character();
     Me->ReadCharAtts(atts,*(Me->ParagraphCharacter));
     if(Me->ParagraphCharacter->Display != "") {
 #ifdef WIN32
@@ -566,7 +482,7 @@ void CAlphInfo::AlphIO::XML_StartElement(void *userData, const XML_Char *name, c
     return;
   }
   if(strcmp(name, "control") == 0) {
-    if (!Me->InputInfo->ControlCharacter) Me->InputInfo->ControlCharacter = new character();
+    if (!Me->InputInfo->ControlCharacter) Me->InputInfo->ControlCharacter = new CAlphInfo::character();
     Me->ReadCharAtts(atts, *(Me->InputInfo->ControlCharacter));
     return;
   }
@@ -649,13 +565,13 @@ void CAlphInfo::AlphIO::XML_StartElement(void *userData, const XML_Char *name, c
 
   // Special characters for character composition
   if(strcmp(name, "convert") == 0) {
-    if (!Me->InputInfo->StartConvertCharacter) Me->InputInfo->StartConvertCharacter = new character();
+    if (!Me->InputInfo->StartConvertCharacter) Me->InputInfo->StartConvertCharacter = new CAlphInfo::character();
     Me->ReadCharAtts(atts, *(Me->InputInfo->StartConvertCharacter));
     return;
   }
 
   if(strcmp(name, "protect") == 0) {
-    if (!Me->InputInfo->EndConvertCharacter) Me->InputInfo->EndConvertCharacter = new character();
+    if (!Me->InputInfo->EndConvertCharacter) Me->InputInfo->EndConvertCharacter = new CAlphInfo::character();
     Me->ReadCharAtts(atts, *(Me->InputInfo->EndConvertCharacter));
     return;
   }
@@ -676,7 +592,7 @@ void CAlphInfo::AlphIO::XML_StartElement(void *userData, const XML_Char *name, c
 
     if (Me->m_vGroups.empty()) Me->InputInfo->iNumChildNodes++; else Me->m_vGroups.back()->iNumChildNodes++;
     Me->InputInfo->m_vCharacters.resize(Me->InputInfo->m_vCharacters.size()+1);
-    character &Ch(Me->InputInfo->m_vCharacters.back());
+    CAlphInfo::character &Ch(Me->InputInfo->m_vCharacters.back());
     
     // FIXME - need to do a more sensible job of ensuring that
     // defaults are correct (plus more generally fixing behaviour when
@@ -686,7 +602,7 @@ void CAlphInfo::AlphIO::XML_StartElement(void *userData, const XML_Char *name, c
   }
 }
 
-void CAlphInfo::AlphIO::ReadCharAtts(const XML_Char **atts, character &ch) {
+void CAlphIO::ReadCharAtts(const XML_Char **atts, CAlphInfo::character &ch) {
   while(*atts != 0) {
     if(strcmp(*atts, "t") == 0) ch.Text = *(atts+1);
     else if(strcmp(*atts, "d") == 0) ch.Display = *(atts+1);
@@ -708,8 +624,8 @@ void Reverse(SGroupInfo *&pList) {
   pList=pPrev;
 }
 
-void CAlphInfo::AlphIO::XML_EndElement(void *userData, const XML_Char *name) {
-  CAlphInfo::AlphIO *Me = (CAlphInfo::AlphIO *) userData;
+void CAlphIO::XML_EndElement(void *userData, const XML_Char *name) {
+  CAlphIO *Me = (CAlphIO *) userData;
 
   if(strcmp(name, "alphabet") == 0) {
     Reverse(Me->InputInfo->m_pBaseGroup);
@@ -757,15 +673,15 @@ void CAlphInfo::AlphIO::XML_EndElement(void *userData, const XML_Char *name) {
   }
 }
 
-void CAlphInfo::AlphIO::XML_CharacterData(void *userData, const XML_Char *s, int len) {
+void CAlphIO::XML_CharacterData(void *userData, const XML_Char *s, int len) {
   // CAREFUL: s points to a string which is NOT null-terminated.
 
-  CAlphInfo::AlphIO *Me = (CAlphInfo::AlphIO *) userData;
+  CAlphIO *Me = (CAlphIO *) userData;
 
   Me->CData.append(s, len);
 }
 
-CAlphInfo::AlphIO::~AlphIO() {
+CAlphIO::~CAlphIO() {
   for (std::map<std::string, const CAlphInfo* >::iterator it = Alphabets.begin(); it != Alphabets.end(); ++it) {
     delete it->second;
   }
diff --git a/Src/DasherCore/Alphabet/AlphIO.h b/Src/DasherCore/Alphabet/AlphIO.h
index b981ebd..709f6bf 100644
--- a/Src/DasherCore/Alphabet/AlphIO.h
+++ b/Src/DasherCore/Alphabet/AlphIO.h
@@ -27,8 +27,7 @@
 #endif
 
 #include "../DasherTypes.h"
-#include "AlphabetMap.h"
-#include "GroupInfo.h"
+#include "AlphInfo.h"
 
 #include <expat.h>
 #include <string>
@@ -38,155 +37,69 @@
 #include <stdio.h>              // for C style file IO
 
 namespace Dasher {
-  class CAlphInfo;
-} 
-
+  class CAlphIO;
+}
 
 /// \ingroup Alphabet
 /// @{
 
-/// This structure completely describes the characters used in alphabet
-class Dasher::CAlphInfo {
-private:
-  struct character {
-    character();
-    std::string Display;
-    std::string Text;
-    int Colour;
-    std::string Foreground;
-  };  
+/// This class is used to read in alphabet definitions from all files
+/// alphabet.*.xml at startup (realization) time; it creates one CAlphInfo
+/// object per alphabet at this time, and stores them in a map from AlphID
+/// string until shutdown/destruction. (CAlphIO is a friend of CAlphInfo,
+/// so can create/manipulate instances.)
+///
+/// Note the alphabet-management functions (SetInfo, Delete, Save, and
+/// hence the mutability of alphabets loaded) don't seem to be fully
+/// implemented...
+class Dasher::CAlphIO {
 public:
-  /// Return number of text symbols - inc space and para, but no control/conversion start/end
-  /// Note symbol numbers are 1-indexed; 0 is reserved (for the root symbol, or for
-  /// element 0 of the probability array to contain a 0)
-  int GetNumberTextSymbols() const {return m_vCharacters.size();}
-  
-  Opts::ScreenOrientations GetOrientation() const {return Orientation;} 
-  
-  Opts::AlphabetTypes GetType() const {return Type;}
-  
-  const std::string & GetTrainingFile() const {return TrainingFile;}
-  
-  const std::string &GetGameModeFile() const {return GameModeFile;}
-  
-  const std::string & GetPalette() const {return PreferredColours;}
-  
-  symbol GetParagraphSymbol() const {return iParagraphCharacter;}
-  
-  symbol GetSpaceSymbol() const {return iSpaceCharacter;}
-  
-  //symbol GetStartConversionSymbol() const;
-  //symbol GetEndConversionSymbol() const;
-  
-  /// return display string for i'th symbol
-  const std::string & GetDisplayText(symbol i) const {return m_vCharacters[i-1].Display;}
-  
-  /// return text for edit box for i'th symbol
-  const std::string & GetText(symbol i) const {return m_vCharacters[i-1].Text;} 
-  
-  // return string for i'th symbol
-  
-  int GetColour(symbol i, int iPhase) const;
-  
-  /// Text foreground colour for i'th symbol; default 4 if unspecified
-  int GetTextColour(symbol i) const;
-  /// Text foreground colour for i'th symbol, as specified in XML
-  const std::string & GetForeground(symbol i) const {return m_vCharacters[i-1].Foreground;}
-    
-  const std::string &GetDefaultContext() const {return m_strDefaultContext;}
-  
-  SGroupInfo *m_pBaseGroup;
-  int iNumChildNodes;
-  int m_iConversionID;
-  
-  CAlphabetMap *MakeMap() const;
-  class AlphIO {
-  public:
-
-    AlphIO(std::string SystemLocation, std::string UserLocation, std::vector < std::string > &Filenames);
-    ~AlphIO();
-    void GetAlphabets(std::vector < std::string > *AlphabetList) const;
-    std::string GetDefault();
-    const CAlphInfo *GetInfo(const std::string & AlphID);
-    void SetInfo(const CAlphInfo *NewInfo);
-    void Delete(const std::string & AlphID);
-  private:
-    character *SpaceCharacter, *ParagraphCharacter;
-    std::vector<SGroupInfo *> m_vGroups;
-    std::string SystemLocation;
-    std::string UserLocation;
-    std::map < std::string, const CAlphInfo* > Alphabets; // map short names (file names) to descriptions. We own all the values but it's easier this way...
-    std::vector < std::string > Filenames;
-
-    void Save(const std::string & AlphID);
-    CAlphInfo *CreateDefault();         // Give the user an English alphabet rather than nothing if anything goes horribly wrong.
-
-    void DeleteAlphabet(CAlphInfo *Alphabet);
-
-    // XML handling:
-    /////////////////////////
-
-    bool LoadMutable;
-    void ParseFile(std::string Filename);
-    void ReadCharAtts(const XML_Char **atts, character &ch);
-    // Alphabet types:
-    std::map < std::string, Opts::AlphabetTypes > StoT;
-    std::map < Opts::AlphabetTypes, std::string > TtoS;
-
-    // & to &amp;  < to &lt; and > to &gt;  and if (Attribute) ' to &apos; and " to &quot;
-    void XML_Escape(std::string * Text, bool Attribute);
-
-    // Data gathered
-    std::string CData;            // Text gathered from when an elemnt starts to when it ends
-    CAlphInfo *InputInfo;
-    bool bFirstGroup;
-    int iGroupIdx;
-
-    // Callback functions. These involve the normal dodgy casting to a pointer
-    // to an instance to get a C++ class to work with a plain C library.
-    static void XML_StartElement(void *userData, const XML_Char * name, const XML_Char ** atts);
-    static void XML_EndElement(void *userData, const XML_Char * name);
-    static void XML_CharacterData(void *userData, const XML_Char * s, int len);
-  };
-  
-  ~CAlphInfo();
   
+  CAlphIO(std::string SystemLocation, std::string UserLocation, std::vector < std::string > &Filenames);
+  ~CAlphIO();
+  void GetAlphabets(std::vector < std::string > *AlphabetList) const;
+  std::string GetDefault();
+  const CAlphInfo *GetInfo(const std::string & AlphID);
+  void SetInfo(const CAlphInfo *NewInfo);
+  void Delete(const std::string & AlphID);
 private:
-  CAlphInfo();
-  // 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;
-  std::string GameModeFile;
-  std::string PreferredColours;
-  Opts::AlphabetTypes Encoding;
-  Opts::AlphabetTypes Type;
-  Opts::ScreenOrientations Orientation;
-    
-  /*     // Obsolete groups stuff */
-  /*     struct group { */
-  /*       std::string Description; */
-  /*       std::vector < character > Characters; */
-  /*       int Colour; */
-  /*       std::string Label; */
-  /*     }; */
-  /*     std::vector < group > Groups; */
-  /*     // --- */
-    
-  std::vector<character> m_vCharacters;
-  
-  int iParagraphCharacter;       // index into m_vCharacters of paragraph char (display and edit text), -1 for none.
-  int iSpaceCharacter;   // index into m_vCharacters of space char (display and edit text), -1 for none.
-  character *ControlCharacter; // display and edit text of Control character. Typically ("", "Control"). Use ("", "") if no control character.
-  character *StartConvertCharacter;
-  character *EndConvertCharacter;
-  
-  std::string m_strDefaultContext;
+  CAlphInfo::character *SpaceCharacter, *ParagraphCharacter;
+  std::vector<SGroupInfo *> m_vGroups;
+  std::string SystemLocation;
+  std::string UserLocation;
+  std::map < std::string, const CAlphInfo* > Alphabets; // map short names (file names) to descriptions. We own all the values but it's easier this way...
+  std::vector < std::string > Filenames;
+  
+  void Save(const std::string & AlphID);
+  CAlphInfo *CreateDefault();         // Give the user an English alphabet rather than nothing if anything goes horribly wrong.
+  
+  void DeleteAlphabet(CAlphInfo *Alphabet);
+  
+  // XML handling:
+  /////////////////////////
+  
+  bool LoadMutable;
+  void ParseFile(std::string Filename);
+  void ReadCharAtts(const XML_Char **atts, CAlphInfo::character &ch);
+  // Alphabet types:
+  std::map < std::string, Opts::AlphabetTypes > StoT;
+  std::map < Opts::AlphabetTypes, std::string > TtoS;
+  
+  // & to &amp;  < to &lt; and > to &gt;  and if (Attribute) ' to &apos; and " to &quot;
+  void XML_Escape(std::string * Text, bool Attribute);
+  
+  // Data gathered
+  std::string CData;            // Text gathered from when an elemnt starts to when it ends
+  CAlphInfo *InputInfo;
+  bool bFirstGroup;
+  int iGroupIdx;
+  
+  // Callback functions. These involve the normal dodgy casting to a pointer
+  // to an instance to get a C++ class to work with a plain C library.
+  static void XML_StartElement(void *userData, const XML_Char * name, const XML_Char ** atts);
+  static void XML_EndElement(void *userData, const XML_Char * name);
+  static void XML_CharacterData(void *userData, const XML_Char * s, int len);
 };
-
-
 /// @}
 
 #endif /* #ifndef __AlphIO_h__ */
diff --git a/Src/DasherCore/Alphabet/AlphInfo.cpp b/Src/DasherCore/Alphabet/AlphInfo.cpp
new file mode 100644
index 0000000..96c04ed
--- /dev/null
+++ b/Src/DasherCore/Alphabet/AlphInfo.cpp
@@ -0,0 +1,121 @@
+// AlphIO.cpp
+//
+// Copyright (c) 2007 The Dasher Team
+//
+// This file is part of Dasher.
+//
+// Dasher is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Dasher is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Dasher; if not, write to the Free Software 
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#include "AlphIO.h"
+
+#include <iostream>
+#include <cstring>
+
+using namespace Dasher;
+using namespace std;
+
+// Track memory leaks on Windows to the line that new'd the memory
+#ifdef _WIN32
+#ifdef _DEBUG_MEMLEAKS
+#define DEBUG_NEW new( _NORMAL_BLOCK, THIS_FILE, __LINE__ )
+#define new DEBUG_NEW
+#undef THIS_FILE
+static char THIS_FILE[] = __FILE__;
+#endif
+#endif
+
+int CAlphInfo::GetTextColour(symbol Symbol) const {
+  const std::string &TextColour(GetForeground(Symbol));
+  if(TextColour != std::string("")) {
+    return atoi(TextColour.c_str());
+  }
+  else {
+    return 4;
+  }
+}
+
+int 
+CAlphInfo::GetColour(symbol i, int iPhase) const {
+  int iColour = m_vCharacters[i-1].Colour;
+  
+  // This is for backwards compatibility with old alphabet files -
+  // ideally make this log a warning (unrelated TODO: automate
+  // validation of alphabet files, plus maintenance of repository
+  // etc.)
+  if(iColour == -1) {
+    if(i == iSpaceCharacter) {
+      iColour = 9;
+    }
+    else {
+      iColour = (i % 3) + 10;
+    }
+  }
+  
+  // Loop on low colours for nodes (TODO: go back to colour namespaces?)
+  if(iPhase == 1 && iColour < 130)
+    iColour += 130;
+  
+  return iColour;
+}
+
+CAlphabetMap *CAlphInfo::MakeMap() const {
+  CAlphabetMap *map = new CAlphabetMap();
+  int i;
+  for(i = 0; i < m_vCharacters.size(); i++) {
+    map->Add(m_vCharacters[i].Text, i+1); //1-indexed
+  }
+  //ACL I'm really not sure where conversion characters should/shouldn't be included.
+  // They seemed to be included in the Alphabet Map, i.e. for reading training text via GetSymbols;
+  // but a TODO comment suggested they should _not_ be included in GetNumberSymbols(),
+  // and I couldn't find any code which would have called e.g. GetText on them....
+  // Hence, not including them in m_vCharacters.
+  if (StartConvertCharacter)
+    map->Add(StartConvertCharacter->Text, ++i);
+  if (EndConvertCharacter)
+    map->Add(EndConvertCharacter->Text, ++i);
+  return map;
+}
+
+CAlphInfo::CAlphInfo() {
+  iSpaceCharacter=-1;
+  iParagraphCharacter = -1;
+  ControlCharacter=NULL;
+  StartConvertCharacter=NULL;
+  EndConvertCharacter=NULL;
+  m_pBaseGroup = 0;
+  iNumChildNodes = 0;
+  m_iConversionID = 0;
+  m_strDefaultContext = ". ";
+}
+
+void DeleteGroups(SGroupInfo *Info) {
+  for(SGroupInfo *next; Info; Info=next) {
+    next = Info->pNext;
+    DeleteGroups(Info->pChild);
+    delete Info;
+    Info = next;
+  }
+}
+
+CAlphInfo::~CAlphInfo() {
+  DeleteGroups(m_pBaseGroup);
+}
+
+CAlphInfo::character::character() {
+  Display="";
+  Text="";
+  Colour=-1;
+  Foreground="";
+}
\ No newline at end of file
diff --git a/Src/DasherCore/Alphabet/AlphInfo.h b/Src/DasherCore/Alphabet/AlphInfo.h
new file mode 100644
index 0000000..2c3a73c
--- /dev/null
+++ b/Src/DasherCore/Alphabet/AlphInfo.h
@@ -0,0 +1,155 @@
+// AlphIO.h
+//
+// Copyright (c) 2007 The Dasher Team
+//
+// This file is part of Dasher.
+//
+// Dasher is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// Dasher is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with Dasher; if not, write to the Free Software 
+// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+#ifndef __ALPHINFO_H__
+#define __ALPHINFO_H__
+
+#include "../../Common/Common.h"
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "../DasherTypes.h"
+#include "AlphabetMap.h"
+#include "GroupInfo.h"
+#include "AlphIO.h"
+
+#include <string>
+#include <vector>
+#include <utility>              // for std::pair
+
+namespace Dasher {
+  class CAlphInfo;
+  class CAlphIO;
+} 
+
+/// \ingroup Alphabet
+/// @{
+
+/// This structure completely describes the characters used in alphabet.
+/// It maps from the "symbol" type (integers, starting at 1 for alphabet
+/// characters, with 0 used for error / "unknown") to display text (that
+/// rendered onto the canvas - e.g. a box or "_" for a space character),
+/// text (that which is written/output, or indeed, read in by CAlphabetMap),
+/// colour (an index into the current colour scheme; note values below 130
+/// are increased by 130 on alternate offsets, this is known as the "phase"),
+/// also foreground colour information (but these does not seem to be used
+/// ATM).
+///
+/// One CAlphInfo object is created per alphabet when the alphabet.*.xml
+/// files are read in by CAlphIO, and a CAlphabetMap object is created for
+/// the alphabet currently in use (and deleted when the alphabet is changed).
+class Dasher::CAlphInfo {
+private:
+  friend class CAlphIO;
+  struct character {
+    character();
+    std::string Display;
+    std::string Text;
+    int Colour;
+    std::string Foreground;
+  };  
+public:
+  /// Return number of text symbols - inc space and para, but no control/conversion start/end
+  /// Note symbol numbers are 1-indexed; 0 is reserved (for the root symbol, or for
+  /// element 0 of the probability array to contain a 0)
+  int GetNumberTextSymbols() const {return m_vCharacters.size();}
+  
+  Opts::ScreenOrientations GetOrientation() const {return Orientation;} 
+  
+  Opts::AlphabetTypes GetType() const {return Type;}
+  
+  const std::string & GetTrainingFile() const {return TrainingFile;}
+  
+  const std::string &GetGameModeFile() const {return GameModeFile;}
+  
+  const std::string & GetPalette() const {return PreferredColours;}
+  
+  symbol GetParagraphSymbol() const {return iParagraphCharacter;}
+  
+  symbol GetSpaceSymbol() const {return iSpaceCharacter;}
+  
+  //symbol GetStartConversionSymbol() const;
+  //symbol GetEndConversionSymbol() const;
+  
+  /// return display string for i'th symbol
+  const std::string & GetDisplayText(symbol i) const {return m_vCharacters[i-1].Display;}
+  
+  /// return text for edit box for i'th symbol
+  const std::string & GetText(symbol i) const {return m_vCharacters[i-1].Text;} 
+  
+  // return string for i'th symbol
+  
+  int GetColour(symbol i, int iPhase) const;
+  
+  /// Text foreground colour for i'th symbol; default 4 if unspecified
+  int GetTextColour(symbol i) const;
+  /// Text foreground colour for i'th symbol, as specified in XML
+  const std::string & GetForeground(symbol i) const {return m_vCharacters[i-1].Foreground;}
+    
+  const std::string &GetDefaultContext() const {return m_strDefaultContext;}
+  
+  SGroupInfo *m_pBaseGroup;
+  int iNumChildNodes;
+  int m_iConversionID;
+  
+  CAlphabetMap *MakeMap() const;
+  
+  ~CAlphInfo();
+  
+private:
+  CAlphInfo();
+  // 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;
+  std::string GameModeFile;
+  std::string PreferredColours;
+  Opts::AlphabetTypes Encoding;
+  Opts::AlphabetTypes Type;
+  Opts::ScreenOrientations Orientation;
+    
+  /*     // Obsolete groups stuff */
+  /*     struct group { */
+  /*       std::string Description; */
+  /*       std::vector < character > Characters; */
+  /*       int Colour; */
+  /*       std::string Label; */
+  /*     }; */
+  /*     std::vector < group > Groups; */
+  /*     // --- */
+    
+  std::vector<character> m_vCharacters;
+  
+  int iParagraphCharacter;       // index into m_vCharacters of paragraph char (display and edit text), -1 for none.
+  int iSpaceCharacter;   // index into m_vCharacters of space char (display and edit text), -1 for none.
+  character *ControlCharacter; // display and edit text of Control character. Typically ("", "Control"). Use ("", "") if no control character.
+  character *StartConvertCharacter;
+  character *EndConvertCharacter;
+  
+  std::string m_strDefaultContext;
+};
+
+
+/// @}
+
+#endif /* #ifndef __AlphIO_h__ */
diff --git a/Src/DasherCore/Alphabet/AlphabetMap.h b/Src/DasherCore/Alphabet/AlphabetMap.h
index c9c46b9..6aa2773 100644
--- a/Src/DasherCore/Alphabet/AlphabetMap.h
+++ b/Src/DasherCore/Alphabet/AlphabetMap.h
@@ -26,6 +26,22 @@ namespace Dasher {
 /// \ingroup Alphabet
 /// \{
 
+/// Class used for fast conversion from training text (i.e. same format as
+/// text output from Dasher...I think, Mandarin / Super-PinYin is probably
+/// an exception and Japanese probably would be too if it worked!) into
+/// Dasher's internal "symbol" indices. One of these is created for the
+/// alphabet (CAlphInfo) currently in use (CAlphInfo is a friend of this
+/// class, to allow creation/setup of the map).
+///
+/// Ian clearly had reservations about this system, as follows; and I'd add
+/// that support for multi-unicode-character symbols (such as the "asdf"
+/// suggested below) is extremely dubious - both here and elsewhere (e.g.
+/// what if "asd" is also a symbol) - but we really need to clarify whether
+/// such symbols are supposed to be supported or not. Most of the fun here
+/// comes from supporting single unicode characters which are multiple
+/// octets,as we use  std::string (which works in octets) for everything...
+/// Anyway, Ian writes:
+///
 /// 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
diff --git a/Src/DasherCore/DasherInterfaceBase.cpp b/Src/DasherCore/DasherInterfaceBase.cpp
index 9b26865..52ef96e 100644
--- a/Src/DasherCore/DasherInterfaceBase.cpp
+++ b/Src/DasherCore/DasherInterfaceBase.cpp
@@ -138,7 +138,7 @@ void CDasherInterfaceBase::Realize() {
 
   std::vector<std::string> vAlphabetFiles;
   ScanAlphabetFiles(vAlphabetFiles);
-  m_AlphIO = new CAlphInfo::AlphIO(GetStringParameter(SP_SYSTEM_LOC), GetStringParameter(SP_USER_LOC), vAlphabetFiles);
+  m_AlphIO = new CAlphIO(GetStringParameter(SP_SYSTEM_LOC), GetStringParameter(SP_USER_LOC), vAlphabetFiles);
 
   std::vector<std::string> vColourFiles;
   ScanColourFiles(vColourFiles);
diff --git a/Src/DasherCore/DasherInterfaceBase.h b/Src/DasherCore/DasherInterfaceBase.h
index 3c9e63e..d621194 100644
--- a/Src/DasherCore/DasherInterfaceBase.h
+++ b/Src/DasherCore/DasherInterfaceBase.h
@@ -585,7 +585,7 @@ protected:
   CDasherInput *m_pInput;
   CInputFilter* m_pInputFilter;
   CModuleManager m_oModuleManager;
-  CAlphInfo::AlphIO *m_AlphIO;
+  CAlphIO *m_AlphIO;
   CColourIO *m_ColourIO;
   CNodeCreationManager *m_pNCManager;
   CUserLogBase *m_pUserLog; 
diff --git a/Src/DasherCore/Makefile.am b/Src/DasherCore/Makefile.am
index 34ca635..f767332 100644
--- a/Src/DasherCore/Makefile.am
+++ b/Src/DasherCore/Makefile.am
@@ -10,6 +10,8 @@ libdasherprefs_a_SOURCES = \
 libdashercore_a_SOURCES = \
 		Alphabet/AlphIO.cpp \
 		Alphabet/AlphIO.h \
+		Alphabet/AlphInfo.cpp \
+		Alphabet/AlphInfo.h \
 		Alphabet/AlphabetMap.cpp \
 		Alphabet/AlphabetMap.h \
 		Alphabet/GroupInfo.h \
diff --git a/Src/DasherCore/NodeCreationManager.cpp b/Src/DasherCore/NodeCreationManager.cpp
index bf5c4b8..fa00ede 100644
--- a/Src/DasherCore/NodeCreationManager.cpp
+++ b/Src/DasherCore/NodeCreationManager.cpp
@@ -17,7 +17,7 @@ using namespace Dasher;
 CNodeCreationManager::CNodeCreationManager(Dasher::CDasherInterfaceBase *pInterface,
                                            Dasher::CEventHandler *pEventHandler, 
                                            CSettingsStore *pSettingsStore,
-                                           Dasher::CAlphInfo::AlphIO *pAlphIO) : CDasherComponent(pEventHandler, pSettingsStore),
+                                           Dasher::CAlphIO *pAlphIO) : CDasherComponent(pEventHandler, pSettingsStore),
   m_pInterface(pInterface), m_pControlManager(NULL) {
 
   const Dasher::CAlphInfo *pAlphInfo(pAlphIO->GetInfo(pSettingsStore->GetStringParameter(SP_ALPHABET_ID)));
diff --git a/Src/DasherCore/NodeCreationManager.h b/Src/DasherCore/NodeCreationManager.h
index ee4ebb2..274f2cc 100644
--- a/Src/DasherCore/NodeCreationManager.h
+++ b/Src/DasherCore/NodeCreationManager.h
@@ -27,7 +27,7 @@ class CNodeCreationManager : public Dasher::CDasherComponent {
   CNodeCreationManager(Dasher::CDasherInterfaceBase *pInterface,
                        Dasher::CEventHandler * pEventHandler,
                        CSettingsStore * pSettingsStore,
-                       Dasher::CAlphInfo::AlphIO *pAlphIO);
+                       Dasher::CAlphIO *pAlphIO);
   ~CNodeCreationManager();
   
   //we watch for changes to BP_CONTROL_MODE and create the Control Manager lazily
diff --git a/Src/MacOSX/Dasher.xcodeproj/project.pbxproj b/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
index fefdb97..d48b771 100755
--- a/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
+++ b/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
@@ -362,6 +362,8 @@
 		335DB101100B3358006DB155 /* training_spyDict.txt in Resources */ = {isa = PBXBuildFile; fileRef = 335DB100100B3358006DB155 /* training_spyDict.txt */; };
 		339055E81195FBD0001BE240 /* Queue.h in Headers */ = {isa = PBXBuildFile; fileRef = 339055E61195FBD0001BE240 /* Queue.h */; };
 		339055E91195FBD0001BE240 /* Queue.m in Sources */ = {isa = PBXBuildFile; fileRef = 339055E71195FBD0001BE240 /* Queue.m */; };
+		339794D4120F2A9600CEA168 /* AlphInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 339794D2120F2A9600CEA168 /* AlphInfo.cpp */; };
+		339794D5120F2A9600CEA168 /* AlphInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 339794D3120F2A9600CEA168 /* AlphInfo.h */; };
 		33ABFEC60FC379EA00EA2BA5 /* ButtonMultiPress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 33ABFEC40FC379EA00EA2BA5 /* ButtonMultiPress.cpp */; };
 		33ABFEC70FC379EA00EA2BA5 /* ButtonMultiPress.h in Headers */ = {isa = PBXBuildFile; fileRef = 33ABFEC50FC379EA00EA2BA5 /* ButtonMultiPress.h */; };
 		33E173C70F3E0B6400D19B38 /* Makefile.am in Resources */ = {isa = PBXBuildFile; fileRef = 33E173A70F3E0B6400D19B38 /* Makefile.am */; };
@@ -777,6 +779,8 @@
 		335DB100100B3358006DB155 /* training_spyDict.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = training_spyDict.txt; sourceTree = "<group>"; };
 		339055E61195FBD0001BE240 /* Queue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Queue.h; sourceTree = "<group>"; };
 		339055E71195FBD0001BE240 /* Queue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Queue.m; sourceTree = "<group>"; };
+		339794D2120F2A9600CEA168 /* AlphInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AlphInfo.cpp; sourceTree = "<group>"; };
+		339794D3120F2A9600CEA168 /* AlphInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AlphInfo.h; sourceTree = "<group>"; };
 		33ABFEC40FC379EA00EA2BA5 /* ButtonMultiPress.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ButtonMultiPress.cpp; sourceTree = "<group>"; };
 		33ABFEC50FC379EA00EA2BA5 /* ButtonMultiPress.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ButtonMultiPress.h; sourceTree = "<group>"; };
 		33E173A70F3E0B6400D19B38 /* Makefile.am */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
@@ -1060,6 +1064,8 @@
 		1948BDF80C226CFC001DFA32 /* Alphabet */ = {
 			isa = PBXGroup;
 			children = (
+				339794D2120F2A9600CEA168 /* AlphInfo.cpp */,
+				339794D3120F2A9600CEA168 /* AlphInfo.h */,
 				1948BDFC0C226CFC001DFA32 /* AlphabetMap.cpp */,
 				1948BDFD0C226CFC001DFA32 /* AlphabetMap.h */,
 				1948BDFE0C226CFC001DFA32 /* AlphIO.cpp */,
@@ -1494,6 +1500,7 @@
 				3300114910A2E9C900D31B1D /* DelayedDraw.h in Headers */,
 				339055E81195FBD0001BE240 /* Queue.h in Headers */,
 				33008360120CB7F900C41FAA /* ConvertingAlphMgr.h in Headers */,
+				339794D5120F2A9600CEA168 /* AlphInfo.h in Headers */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};
@@ -1842,6 +1849,7 @@
 				3300115210A2EA7700D31B1D /* ExpansionPolicy.cpp in Sources */,
 				339055E91195FBD0001BE240 /* Queue.m in Sources */,
 				33008361120CB7F900C41FAA /* ConvertingAlphMgr.cpp in Sources */,
+				339794D4120F2A9600CEA168 /* AlphInfo.cpp in Sources */,
 			);
 			runOnlyForDeploymentPostprocessing = 0;
 		};



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