[dasher] AlphabetManager contexts!



commit b92d45958a925483a0c94fc1446af336fd77ae71
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Tue Nov 24 21:30:16 2009 +0000

    AlphabetManager contexts!
    
    Replaced 'szContext' param to GetAlphRoot with a bool (reflecting its usage!)
    DasherNode::GetContext builds (symbolic) context including not-yet-seen nodes
    This is used to generate contexts for e.g. escaping from Control Mode :-).
    
    Also replaced hardcoded colour 7 for alph root nodes with value from alphabet
       (this is usually a 7 anyway...)

 Src/DasherCore/AlphabetManager.cpp     |  104 +++++++++++++++-----------------
 Src/DasherCore/AlphabetManager.h       |   11 ++--
 Src/DasherCore/ControlManager.cpp      |    2 +-
 Src/DasherCore/ConversionHelper.cpp    |   47 +-------------
 Src/DasherCore/ConversionManager.cpp   |   22 ++++++-
 Src/DasherCore/ConversionManager.h     |    5 +-
 Src/DasherCore/DasherModel.cpp         |   14 +----
 Src/DasherCore/DasherNode.cpp          |   12 ++++-
 Src/DasherCore/DasherNode.h            |   12 +++-
 Src/DasherCore/MandarinAlphMgr.cpp     |   42 ++++++++++----
 Src/DasherCore/MandarinAlphMgr.h       |    2 +-
 Src/DasherCore/NodeCreationManager.cpp |    4 +-
 Src/DasherCore/NodeCreationManager.h   |    2 +-
 13 files changed, 140 insertions(+), 139 deletions(-)
---
diff --git a/Src/DasherCore/AlphabetManager.cpp b/Src/DasherCore/AlphabetManager.cpp
index 924d8a1..5272e13 100644
--- a/Src/DasherCore/AlphabetManager.cpp
+++ b/Src/DasherCore/AlphabetManager.cpp
@@ -61,39 +61,28 @@ CAlphabetManager::CAlphNode *CAlphabetManager::makeNode(CDasherNode *pParent, in
   return new CAlphNode(pParent, iLbnd, iHbnd, pDisplayInfo, this);
 }
 
-CAlphabetManager::CAlphNode *CAlphabetManager::GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset) {
-
-  int iSymbol;
-  int iColour;
-
-  std::string strContext;
-
-  CLanguageModel::Context iContext;
-
-  if(szContext) {
-    int iMaxContextLength = m_pLanguageModel->GetContextLength() + 1;
+CAlphabetManager::CAlphNode *CAlphabetManager::GetRoot(CDasherNode *pParent, int iLower, int iUpper, bool bEnteredLast, int iOffset) {
+  
+  std::vector<symbol> vContextSymbols;
 
-    // TODO: No need to explicitly pass context
+  if(iOffset>0) {
     // TODO: Utility function for looking up symbolic context
+    // also TODO: make the LM get the context, rather than force it to fix max context length as an int
+    int iStart = max(0, iOffset - (m_pLanguageModel->GetContextLength() + 1));
 
-    int iStart = iOffset - iMaxContextLength;
-    if(iStart < 0)
-      iStart = 0;
-
-    strContext = m_pInterface->GetContext(iStart, iOffset - iStart);
-    BuildContext(strContext, false, iContext, iSymbol);
-
+    pParent->GetContext(m_pInterface, vContextSymbols, iStart, iOffset - iStart);
+    //take one off offset: the children (leaf) nodes (symbols) should have the specified offset;
+    //the containing groups therefore have offset 1 less.
     iOffset = iOffset - 1;
-    iColour = m_pNCManager->GetColour(iSymbol, 0);
-  }
-  else {
-    // Create a root node
-
-    iColour = 7;
-
-    strContext = m_pNCManager->GetAlphabet()->GetDefaultContext();
-    BuildContext(strContext, true, iContext, iSymbol);
+  } else {
+    iOffset = -1;
+    std::string strContext = m_pNCManager->GetAlphabet()->GetDefaultContext();
+    m_pNCManager->GetAlphabet()->GetSymbols(vContextSymbols, strContext);
   }
+  CLanguageModel::Context iContext;
+  int iSymbol;
+  BuildContext(vContextSymbols, !bEnteredLast, iContext, iSymbol);
+  int iColour = m_pNCManager->GetAlphabet()->GetColour(iSymbol, 0);
 
   // FIXME - Make this a CDasherComponent
 
@@ -144,6 +133,15 @@ CLanguageModel::Context CAlphabetManager::CAlphNode::CloneAlphContext(CLanguageM
   return CDasherNode::CloneAlphContext(pLanguageModel);
 }
 
+void CAlphabetManager::CAlphNode::GetContext(CDasherInterfaceBase *pInterface, vector<symbol> &vContextSymbols, int iOffset, int iLength) {
+  if (!GetFlag(NF_SEEN) && iOffset+iLength-1 == m_iOffset && iSymbol) {
+    if (iLength > 1) Parent()->GetContext(pInterface, vContextSymbols, iOffset, iLength-1);
+    vContextSymbols.push_back(iSymbol);
+  } else {
+    CDasherNode::GetContext(pInterface, vContextSymbols, iOffset, iLength);
+  }
+}
+
 symbol CAlphabetManager::CAlphNode::GetAlphSymbol() {
   return iSymbol;
 }
@@ -201,18 +199,23 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, symbol iSymb
     }
     // TODO: Need to fix fact that this is created even when control mode is switched off
     else if(iSymbol == m_pNCManager->GetControlSymbol()) {
-      pNewNode = m_pNCManager->GetCtrlRoot(pParent, iLbnd, iHbnd, pParent->m_iOffset); 
+      //ACL setting offset as one more than parent for consistency with "proper" symbol nodes...
+      pNewNode = m_pNCManager->GetCtrlRoot(pParent, iLbnd, iHbnd, pParent->m_iOffset+1); 
 
+#ifdef _WIN32_WCE
+      //no control manager - but (TODO!) we still try to create (0-size!) control node...
+      DASHER_ASSERT(!pNewNode);
       // For now, just hack it so we get a normal root node here
-      if(!pNewNode) {
-	pNewNode = m_pNCManager->GetAlphRoot(pParent, iLbnd, iHbnd, NULL, -1);
-      }
+      pNewNode = m_pNCManager->GetAlphRoot(pParent, iLbnd, iHbnd, false, pParent->m_iOffset+1);
+#else
+      DASHER_ASSERT(pNewNode);
+#endif
     }
     else if(iSymbol == m_pNCManager->GetStartConversionSymbol()) {
       //  else if(iSymbol == m_pNCManager->GetSpaceSymbol()) {
 
-      // TODO: Need to consider the case where there is no compile-time support for this
-      pNewNode = m_pNCManager->GetConvRoot(pParent, iLbnd, iHbnd, pParent->m_iOffset);
+      //ACL setting m_iOffset+1 for consistency with "proper" symbol nodes...
+      pNewNode = m_pNCManager->GetConvRoot(pParent, iLbnd, iHbnd, pParent->m_iOffset+1);
     }
     else {
       int iPhase = (pParent->iPhase + 1) % 2;
@@ -360,7 +363,7 @@ CDasherNode *CAlphabetManager::CAlphNode::RebuildParent() {
 
   symbol iNewSymbol;
 
-  std::string strContext;
+  std::vector<symbol> vContextSymbols;
   CLanguageModel::Context iContext;
 
   if((m_iOffset == -1) || (iSymbol == 0)) {
@@ -375,32 +378,24 @@ CDasherNode *CAlphabetManager::CAlphNode::RebuildParent() {
   
   if(m_iOffset == 0) {
     // TODO: Creating a root node, Shouldn't be a special case
+    std::string strContext = m_pMgr->m_pNCManager->GetAlphabet()->GetDefaultContext();
+    m_pMgr->m_pNCManager->GetAlphabet()->GetSymbols(vContextSymbols, strContext);
+    m_pMgr->BuildContext(vContextSymbols, true, iContext, iNewSymbol); //sets iNewSymbol to 0
+
     iNewPhase = 0;
-    iNewSymbol = 0;
-    strContext = m_pMgr->m_pNCManager->GetAlphabet()->GetDefaultContext();
-    m_pMgr->BuildContext(strContext, true, iContext, iNewSymbol);
 
-    pDisplayInfo->iColour = 7; // TODO: Hard coded value
     pDisplayInfo->strDisplayText = "";
   }
   else {
-    int iMaxContextLength = m_pMgr->m_pLanguageModel->GetContextLength() + 1;
-
-    int iStart = m_iOffset - iMaxContextLength;
-    if(iStart < 0)
-      iStart = 0;
-
-    strContext = m_pMgr->m_pInterface->GetContext(iStart, m_iOffset - iStart);
-
-    m_pMgr->BuildContext(strContext, false, iContext, iNewSymbol);
+    int iStart = max(0, m_iOffset - (m_pMgr->m_pLanguageModel->GetContextLength() + 1));
+    GetContext(m_pMgr->m_pInterface, vContextSymbols, iStart, m_iOffset - iStart);
+    m_pMgr->BuildContext(vContextSymbols, false, iContext, iNewSymbol);
 
     iNewPhase = ((iOldPhase + 2 - 1) % 2);
 
-    int iColour(m_pMgr->m_pNCManager->GetColour(iNewSymbol, iNewPhase));
-            
-    pDisplayInfo->iColour = iColour;
     pDisplayInfo->strDisplayText = m_pMgr->m_pNCManager->GetAlphabet()->GetDisplayText(iNewSymbol);
   }
+  pDisplayInfo->iColour = m_pMgr->m_pNCManager->GetColour(iNewSymbol, iNewPhase);
 
   CAlphNode *pNewNode = m_pMgr->makeNode(NULL, 0, 0, pDisplayInfo);
   
@@ -434,17 +429,14 @@ void CAlphabetManager::CAlphNode::SetFlag(int iFlag, bool bValue) {
   }
 }
 
-void CAlphabetManager::BuildContext(std::string &strContext, bool bRoot, CLanguageModel::Context &oContext, symbol &iSymbol) {
+void CAlphabetManager::BuildContext(const std::vector<symbol> &vContextSymbols, bool bRoot, CLanguageModel::Context &oContext, symbol &iSymbol) {
   // Hopefully this will obsolete any need to handle contexts outside
   // of the alphabet manager - check this and remove resulting
   // redundant code
 
-  std::vector<symbol> vContextSymbols;
-  m_pNCManager->GetAlphabet()->GetSymbols(vContextSymbols, strContext);
-
   oContext = m_pLanguageModel->CreateEmptyContext();
 
-  for(std::vector<symbol>::iterator it(vContextSymbols.begin()); it != vContextSymbols.end(); ++it)
+  for(std::vector<symbol>::const_iterator it(vContextSymbols.begin()); it != vContextSymbols.end(); ++it)
     if(*it != 0)
       m_pLanguageModel->EnterSymbol(oContext, *it);
 
diff --git a/Src/DasherCore/AlphabetManager.h b/Src/DasherCore/AlphabetManager.h
index 3412d0a..0031011 100644
--- a/Src/DasherCore/AlphabetManager.h
+++ b/Src/DasherCore/AlphabetManager.h
@@ -72,6 +72,7 @@ namespace Dasher {
     virtual bool GameSearchNode(std::string strTargetUtf8Char);
     
     virtual CLanguageModel::Context CloneAlphContext(CLanguageModel *pLanguageModel);
+    virtual void GetContext(CDasherInterfaceBase *pInterface, std::vector<symbol> &vContextSymbols, int iOffset, int iLength);
     virtual symbol GetAlphSymbol();
     private:
       CAlphabetManager *m_pMgr;
@@ -88,10 +89,10 @@ namespace Dasher {
   public:
     ///
     /// Get a new root node owned by this manager
-    ///
-    // Note that iOffset may be -1, to indicate no root data; in which case,
-    // szContext should be null. (szContext may be null in other cases too!)
-    virtual CAlphNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset);
+    /// bEnteredLast - true if this "root" node should be considered as entering the preceding symbol
+    /// Offset is the index of the character which _child_ nodes (i.e. between which this root allows selection)
+    /// will enter. (Also used to build context for preceding characters.)
+    virtual CAlphNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, bool bEnteredLast, int iOffset);
 
   protected:
     ///
@@ -110,7 +111,7 @@ namespace Dasher {
 
   private:
     
-    void BuildContext(std::string& strContext, bool bRoot, CLanguageModel::Context &oContext, symbol &iSymbol);
+    void BuildContext(const std::vector<symbol> &vContextSymbols, bool bRoot, CLanguageModel::Context &oContext, symbol &iSymbol);
 
     void RecursiveIterateGroup(CAlphNode *pParent, SGroupInfo *pInfo, std::vector<symbol> *pSymbols, std::vector<unsigned int> *pCProb, int iMin, int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild);
 
diff --git a/Src/DasherCore/ControlManager.cpp b/Src/DasherCore/ControlManager.cpp
index 96cb26f..3b4d217 100644
--- a/Src/DasherCore/ControlManager.cpp
+++ b/Src/DasherCore/ControlManager.cpp
@@ -311,7 +311,7 @@ void CControlManager::CContNode::PopulateChildren() {
      if( *it == NULL ) {
        // Escape back to alphabet
 
-       pNewNode = m_pMgr->m_pNCManager->GetAlphRoot(this, iLbnd, iHbnd, NULL/*TODO fix this*/, m_iOffset);
+       pNewNode = m_pMgr->m_pNCManager->GetAlphRoot(this, iLbnd, iHbnd, false, m_iOffset);
        pNewNode->SetFlag(NF_SEEN, false);
      }
      else {
diff --git a/Src/DasherCore/ConversionHelper.cpp b/Src/DasherCore/ConversionHelper.cpp
index aa21d08..03c1ac3 100644
--- a/Src/DasherCore/ConversionHelper.cpp
+++ b/Src/DasherCore/ConversionHelper.cpp
@@ -286,49 +286,10 @@ void CConversionHelper::CConvHNode::PopulateChildren() {
       //Phil//
       // TODO: Placeholder algorithm here
       // TODO: Add an 'end of conversion' node?
-      int iLbnd(0);
-      int iHbnd(mgr()->m_pNCManager->GetLongParameter(LP_NORMALIZATION));
-
-      CDasherNode *pNewNode = mgr()->m_pNCManager->GetAlphRoot(this, iLbnd, iHbnd, NULL, m_iOffset);
-      pNewNode->SetFlag(NF_SEEN, false);
-
-      DASHER_ASSERT(GetChildren().back()==pNewNode);
-      //    pNode->SetHasAllChildren(false);
-      //}
-    /* What do the following code do?
-    else {
-
-      std::cout<<"DOES IT EVER COME TO HERE?"<<std::endl;
-      int iLbnd(0);
-      int iHbnd(m_pNCManager->GetLongParameter(LP_NORMALIZATION));
-
-      CDasherNode::SDisplayInfo *pDisplayInfo = new CDasherNode::SDisplayInfo;
-      pDisplayInfo->iColour = AssignColour(0, pCurrentSCEChild, 0);
-      pDisplayInfo->bShove = true;
-      pDisplayInfo->bVisible = true;
-      pDisplayInfo->strDisplayText = "";
-
-      pNewNode = m_pMgr->makeNode(this, iLbnd, iHbnd, pDisplayInfo);
-
-      // TODO: Reimplement ----
-
-      // FIXME - handle context properly
-      //      pNewNode->SetContext(m_pLanguageModel->CreateEmptyContext());
-      // -----
-
-      SConversionData *pNodeUserData = new SConversionData;
-      pNodeUserData->bType = true;
-      pNodeUserData->pSCENode = NULL;
-      pNodeUserData->pLanguageModel = pCurrentDataNode->pLanguageModel;
-      pNewNode->m_iOffset = pNode->m_iOffset + 1;
-
-      pNewNode->m_pUserData = pNodeUserData;
-
-      pNewNode->SetFlag(NF_SEEN, false);
-
-      pNode->Children().push_back(pNewNode);
-    }
-    */
+    //ACL 1/12/09 Note that this adds one to the m_iOffset of the created node
+    // (whereas code that was here did not, but was otherwise identical to
+    // superclass method...?)
+    CConvNode::PopulateChildren();
   }
 }
 
diff --git a/Src/DasherCore/ConversionManager.cpp b/Src/DasherCore/ConversionManager.cpp
index 13c5f8a..9b89b55 100644
--- a/Src/DasherCore/ConversionManager.cpp
+++ b/Src/DasherCore/ConversionManager.cpp
@@ -78,7 +78,7 @@ CConversionManager::CConvNode *CConversionManager::GetRoot(CDasherNode *pParent,
 
 
   pNewNode->bisRoot = true;
-  pNewNode->m_iOffset = iOffset + 1;
+  pNewNode->m_iOffset = iOffset;
 
   pNewNode->pLanguageModel = NULL;
 
@@ -102,7 +102,7 @@ void CConversionManager::CConvNode::PopulateChildren() {
   int iLbnd(0);
   int iHbnd(m_pMgr->m_pNCManager->GetLongParameter(LP_NORMALIZATION));
 
-  CDasherNode *pNewNode = m_pMgr->m_pNCManager->GetAlphRoot(this, iLbnd, iHbnd, NULL, m_iOffset + 1);
+  CDasherNode *pNewNode = m_pMgr->m_pNCManager->GetAlphRoot(this, iLbnd, iHbnd, false, m_iOffset + 1);
   pNewNode->SetFlag(NF_SEEN, false);
 
   DASHER_ASSERT(GetChildren().back()==pNewNode);
@@ -135,6 +135,24 @@ void CConversionManager::RecursiveDumpTree(SCENode *pCurrent, unsigned int iDept
   */
 }
 
+void CConversionManager::CConvNode::GetContext(CDasherInterfaceBase *pInterface, std::vector<symbol> &vContextSymbols, int iOffset, int iLength) {
+  if (!GetFlag(NF_SEEN) && iOffset+iLength-1 == m_iOffset) {
+    //ACL I'm extrapolating from PinYinConversionHelper (in which root nodes have their
+    // Symbol set by SetConvSymbol, and child nodes are created in PopulateChildren
+    // from SCENode's with Symbols having been set in in AssignSizes); not really sure
+    // whether this is applicable in the general case(! - but although I think it's right
+    // for PinYin, it wouldn't actually be used there, as MandarinDasher overrides contexts
+    // everywhere!)
+    DASHER_ASSERT(bisRoot || pSCENode);
+    if (bisRoot || pSCENode->Symbol!=-1) {
+      if (iLength>1) Parent()->GetContext(pInterface, vContextSymbols, iOffset, iLength-1);
+      vContextSymbols.push_back(bisRoot ? iSymbol : pSCENode->Symbol);
+      return;
+    } //else, non-root with pSCENode->Symbol==-1 => fallthrough back to superclass code
+  }
+  CDasherNode::GetContext(pInterface, vContextSymbols, iOffset, iLength);
+}
+
 void CConversionManager::CConvNode::Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, int iNormalization) {
   // TODO: Reimplement this
   //  m_pNCManager->m_bContextSensitive = true;
diff --git a/Src/DasherCore/ConversionManager.h b/Src/DasherCore/ConversionManager.h
index 3256605..de88c91 100644
--- a/Src/DasherCore/ConversionManager.h
+++ b/Src/DasherCore/ConversionManager.h
@@ -89,7 +89,10 @@ namespace Dasher {
     virtual void PopulateChildren();
     
     ~CConvNode();
-      
+
+    ///Attempts to fill vContextSymbols with the context that would exist _after_ this node has been entered
+    void GetContext(CDasherInterfaceBase *pInterface, std::vector<symbol> &vContextSymbols, int iOffset, int iLength);
+
     ///
     /// Called whenever a node belonging to this manager first 
     /// moves under the crosshair
diff --git a/Src/DasherCore/DasherModel.cpp b/Src/DasherCore/DasherModel.cpp
index 3887838..94d929e 100644
--- a/Src/DasherCore/DasherModel.cpp
+++ b/Src/DasherCore/DasherModel.cpp
@@ -318,19 +318,7 @@ void CDasherModel::DeleteTree() {
 void CDasherModel::InitialiseAtOffset(int iOffset, CDasherView *pView) {
   DeleteTree();
 
-  if(iOffset == 0)
-    m_Root = m_pNodeCreationManager->GetAlphRoot(NULL, 0,GetLongParameter(LP_NORMALIZATION), NULL, -1);
-  else {
-    // Get the most recent character
-    std::string strContext = m_pDasherInterface->GetContext(iOffset - 1, 1);
-
-    char *szContext = new char[strContext.size() + 1];
-    strcpy(szContext, strContext.c_str());
-
-    m_Root = m_pNodeCreationManager->GetAlphRoot(NULL, 0, GetLongParameter(LP_NORMALIZATION), szContext, iOffset);
-
-    delete[] szContext;
-  }
+  m_Root = m_pNodeCreationManager->GetAlphRoot(NULL, 0,GetLongParameter(LP_NORMALIZATION), iOffset!=0, iOffset);
 
   m_pLastOutput = m_Root;
 
diff --git a/Src/DasherCore/DasherNode.cpp b/Src/DasherCore/DasherNode.cpp
index 57535bb..07d85c2 100644
--- a/Src/DasherCore/DasherNode.cpp
+++ b/Src/DasherCore/DasherNode.cpp
@@ -22,7 +22,7 @@
 
 // #include "AlphabetManager.h" - doesnt seem to be required - pconlon
 
-#include "DasherNode.h"
+#include "DasherInterfaceBase.h"
 
 using namespace Dasher;
 using namespace Opts;
@@ -106,6 +106,16 @@ bool CDasherNode::NodeIsParent(CDasherNode *oldnode) const {
 
 }
 
+void CDasherNode::GetContext(CDasherInterfaceBase *pInterface, vector<symbol> &vContextSymbols, int iOffset, int iLength) {
+  if (!GetFlag(NF_SEEN)) {
+    DASHER_ASSERT(m_pParent);
+    if (m_pParent) m_pParent->GetContext(pInterface, vContextSymbols, iOffset,iLength);
+  } else {
+    std::string strContext = pInterface->GetContext(iOffset, iLength);
+    pInterface->GetAlphabet()->GetSymbols(vContextSymbols, strContext);
+  }
+}
+
 CDasherNode *const CDasherNode::Get_node_under(int iNormalization, myint miY1, myint miY2, myint miMousex, myint miMousey) {
   myint miRange = miY2 - miY1;
 
diff --git a/Src/DasherCore/DasherNode.h b/Src/DasherCore/DasherNode.h
index af0e591..1692aec 100644
--- a/Src/DasherCore/DasherNode.h
+++ b/Src/DasherCore/DasherNode.h
@@ -27,9 +27,11 @@
 #include "DasherTypes.h"
 namespace Dasher {
   class CDasherNode;
+  class CDasherInterfaceBase;
 };
 #include <deque>
 #include <iostream>
+#include <vector>
 
 // Node flag constants
 #define NF_COMMITTED 1
@@ -240,8 +242,14 @@ class Dasher::CDasherNode:private NoClones {
   
   virtual CDasherNode *RebuildParent() {
     return 0;
-  }
-    
+  };
+  
+  ///
+  /// Get as many symbols of context, up to the _end_ of the specified range,
+  /// as possible from this node and its uncommitted ancestors
+  ///
+  virtual void GetContext(CDasherInterfaceBase *pInterface, std::vector<symbol> &vContextSymbols, int iOffset, int iLength);
+  
   virtual void SetControlOffset(int iOffset) {};
   
   ///
diff --git a/Src/DasherCore/MandarinAlphMgr.cpp b/Src/DasherCore/MandarinAlphMgr.cpp
index 88ae976..ada6b56 100644
--- a/Src/DasherCore/MandarinAlphMgr.cpp
+++ b/Src/DasherCore/MandarinAlphMgr.cpp
@@ -50,29 +50,49 @@ CMandarinAlphMgr::CMandarinAlphMgr(CDasherInterfaceBase *pInterface, CNodeCreati
   : CAlphabetManager(pInterface, pNCManager, pLanguageModel) {
 }
 
-CAlphabetManager::CAlphNode *CMandarinAlphMgr::GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset) {
-
-  CAlphNode *pNewNode = CAlphabetManager::GetRoot(pParent, iLower, iUpper, szContext, iOffset);
+CAlphabetManager::CAlphNode *CMandarinAlphMgr::GetRoot(CDasherNode *pParent, int iLower, int iUpper, bool bEnteredLast, int iOffset) {
+  CAlphNode *pNewNode;
+  if (!bEnteredLast) {
+    //(probably) escaping back to alphabet after conversion. At any rate, we'll duplicate a lot of
+    // superclass node-construction code, to avoid building a context - as we're going to throw that away
+    // (and the context-building code often doesn't work with conversion!)...
+    CDasherNode::SDisplayInfo *pDispInfo = new CDasherNode::SDisplayInfo;
+    pDispInfo->bShove = true;
+    pDispInfo->bVisible = true;
+    pDispInfo->strDisplayText = "";
+    pDispInfo->iColour = m_pNCManager->GetAlphabet()->GetColour(0, 0);
+    pNewNode = makeNode(pParent, iLower, iUpper, pDispInfo);
+    pNewNode->m_iOffset=max(0,iOffset)-1;
+    pNewNode->iPhase=0;
+    pNewNode->iSymbol=0;
+    pNewNode->pLanguageModel = m_pLanguageModel;    
+  } else {
+    //probably rebuilding parent; call standard GetRoot, which'll extract the most recent symbol
+    // (entered by the node (equivalent to that) which we are rebuilding)
+    pNewNode = CAlphabetManager::GetRoot(pParent, iLower, iUpper, bEnteredLast, iOffset);
+  }
 
   //Override context for Mandarin Dasher
-  if (pParent){
+  if (pParent && pParent->mgrId() == 2) {
+    //ACL MandarinAlphMgr should always be used with a PinYinConversionHelper,
+    //so this cast really should be ok :-)....but I still wish for a guarantee!
     CPinYinConversionHelper::CPYConvNode *pPYParent = static_cast<CPinYinConversionHelper::CPYConvNode *>(pParent);
-    //ACL think this is how this Mandarin thing works here...
-    // but would be nice if I could ASSERT that that cast is ok!
     pNewNode->iContext = m_pLanguageModel->CloneContext(pPYParent->GetConvContext());
-  }
-  else
-	pNewNode->iContext = m_pLanguageModel->CreateEmptyContext();
+  } else
+    pNewNode->iContext = m_pLanguageModel->CreateEmptyContext();
 
   return pNewNode;
 }
 
 CDasherNode *CMandarinAlphMgr::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild) {
 
-  if (iSymbol <= 1288) {
+  if (iSymbol <= 1288 && iSymbol != iExistingSymbol) {
+    //Will wrote:
     //Modified for Mandarin Dasher
     //The following logic switch allows punctuation nodes in Mandarin to be treated in the same way as English (i.e. display and populate next round) instead of invoking a conversion node
-	  CDasherNode *pNewNode = m_pNCManager->GetConvRoot(pParent, iLbnd, iHbnd, pParent->m_iOffset);
+    //ACL I think by "the following logic switch" he meant that symbols <= 1288 are "normal" nodes, NOT punctuation nodes,
+    // whereas punctuation is handled by the fallthrough case (standard AlphabetManager CreateSymbolNode)
+	  CDasherNode *pNewNode = m_pNCManager->GetConvRoot(pParent, iLbnd, iHbnd, pParent->m_iOffset+1);
 	  static_cast<CPinYinConversionHelper::CPYConvNode *>(pNewNode)->SetConvSymbol(iSymbol);
 	  return pNewNode;
   }
diff --git a/Src/DasherCore/MandarinAlphMgr.h b/Src/DasherCore/MandarinAlphMgr.h
index 61c8d49..a54c5a9 100644
--- a/Src/DasherCore/MandarinAlphMgr.h
+++ b/Src/DasherCore/MandarinAlphMgr.h
@@ -41,7 +41,7 @@ namespace Dasher {
     /// Get a new root node owned by this manager
     ///
 
-    virtual CAlphNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset);
+    virtual CAlphNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, bool bEnteredLast, int iOffset);
 
   protected:
     class CMandNode : public CAlphNode {
diff --git a/Src/DasherCore/NodeCreationManager.cpp b/Src/DasherCore/NodeCreationManager.cpp
index 1c9228e..8a417ba 100644
--- a/Src/DasherCore/NodeCreationManager.cpp
+++ b/Src/DasherCore/NodeCreationManager.cpp
@@ -179,8 +179,8 @@ void CNodeCreationManager::DisconnectNode(int iChild, int iParent) {
     m_pControlManager->DisconnectNode(iChild, iParent);
 }
 
-CDasherNode *CNodeCreationManager::GetAlphRoot(Dasher::CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset) { 
- return m_pAlphabetManager->GetRoot(pParent, iLower, iUpper, szContext, iOffset);
+CDasherNode *CNodeCreationManager::GetAlphRoot(Dasher::CDasherNode *pParent, int iLower, int iUpper, bool bEnteredLast, int iOffset) { 
+ return m_pAlphabetManager->GetRoot(pParent, iLower, iUpper, bEnteredLast, iOffset);
 }
 
 CDasherNode *CNodeCreationManager::GetCtrlRoot(Dasher::CDasherNode *pParent, int iLower, int iUpper, int iOffset) { 
diff --git a/Src/DasherCore/NodeCreationManager.h b/Src/DasherCore/NodeCreationManager.h
index 7588838..5524272 100644
--- a/Src/DasherCore/NodeCreationManager.h
+++ b/Src/DasherCore/NodeCreationManager.h
@@ -32,7 +32,7 @@ class CNodeCreationManager : public Dasher::CDasherComponent {
   /// Get a root node of a particular type
   ///
 
-  Dasher::CDasherNode *GetAlphRoot(Dasher::CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset);
+  Dasher::CDasherNode *GetAlphRoot(Dasher::CDasherNode *pParent, int iLower, int iUpper, bool bEnteredLast, int iOffset);
   Dasher::CDasherNode *GetCtrlRoot(Dasher::CDasherNode *pParent, int iLower, int iUpper, int iOffset);
   Dasher::CDasherNode *GetConvRoot(Dasher::CDasherNode *pParent, int iLower, int iUpper, int iOffset);
 



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