[dasher] * Removed m_pUserData structs by merging into corresponding CDasherNode



commit 97367e7a6fd27236632ff61fa157d13ad66e9d86
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Mon Nov 16 15:29:06 2009 +0100

    * Removed m_pUserData structs by merging into corresponding CDasherNode
      subclasses.
    * Many covariant overrides, etc., in place of unchecked
      casts --> *type safety*!!

 ChangeLog                                 |    8 ++
 Src/DasherCore/AlphabetManager.cpp        |  120 +++++++++++------------------
 Src/DasherCore/AlphabetManager.h          |   32 ++++----
 Src/DasherCore/ControlManager.cpp         |   20 ++---
 Src/DasherCore/ControlManager.h           |   16 ++--
 Src/DasherCore/ConversionHelper.cpp       |   58 ++++++--------
 Src/DasherCore/ConversionHelper.h         |    4 +-
 Src/DasherCore/ConversionManager.cpp      |   37 +++------
 Src/DasherCore/ConversionManager.h        |   33 +++-----
 Src/DasherCore/DasherNode.h               |    1 -
 Src/DasherCore/MandarinAlphMgr.cpp        |   15 ++--
 Src/DasherCore/MandarinAlphMgr.h          |    6 +-
 Src/DasherCore/PinYinConversionHelper.cpp |   16 ++---
 Src/DasherCore/PinYinConversionHelper.h   |    2 +-
 14 files changed, 157 insertions(+), 211 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 8760e03..6a566af 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,13 @@
 2009-11-16  Alan Lawrence <acl33 inf phy cam ac uk>
 
+	* Removed m_pUserData structs by merging into corresponding
+	  CDasherNode subclasses.
+	* Many covariant overrides, etc., in place of unchecked casts -->
+	  *type safety*!!
+
+2009-11-16  Alan Lawrence <acl33 inf phy cam ac uk>
+
+	Moved all NodeManager methods into subclasses of DasherNode:
 	* NodeManager::Ref() & ClearNode() put into DasherNode subclass
 	  con/destructors
 	* Other calls pNode->m_pNodeManager->Foo(pNode,...) replaced
diff --git a/Src/DasherCore/AlphabetManager.cpp b/Src/DasherCore/AlphabetManager.cpp
index c4aa9d0..9ba3483 100644
--- a/Src/DasherCore/AlphabetManager.cpp
+++ b/Src/DasherCore/AlphabetManager.cpp
@@ -61,9 +61,7 @@ CAlphabetManager::CAlphNode *CAlphabetManager::makeNode(CDasherNode *pParent, in
   return new CAlphNode(pParent, iLbnd, iHbnd, pDisplayInfo, this);
 }
 
-CDasherNode *CAlphabetManager::GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset) {
-
-  CDasherNode *pNewNode;
+CAlphabetManager::CAlphNode *CAlphabetManager::GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset) {
 
   int iSymbol;
   int iColour;
@@ -106,18 +104,15 @@ CDasherNode *CAlphabetManager::GetRoot(CDasherNode *pParent, int iLower, int iUp
   pDisplayInfo->bVisible = true;
   pDisplayInfo->strDisplayText = m_pNCManager->GetAlphabet()->GetDisplayText(iSymbol);
 
-  pNewNode = new CAlphNode(pParent, iLower, iUpper, pDisplayInfo, this);
-
-  SAlphabetData *pNodeUserData = new SAlphabetData;
-  pNewNode->m_pUserData = pNodeUserData;
+  CAlphNode *pNewNode = makeNode(pParent, iLower, iUpper, pDisplayInfo);
 
   pNewNode->m_iOffset = iOffset;
-  pNodeUserData->iPhase = 0;
-  pNodeUserData->iSymbol = iSymbol;
+  pNewNode->iPhase = 0;
+  pNewNode->iSymbol = iSymbol;
 
-  pNodeUserData->iContext = iContext;
+  pNewNode->iContext = iContext;
 
-  pNodeUserData->pLanguageModel = m_pLanguageModel;
+  pNewNode->pLanguageModel = m_pLanguageModel;
 
   pNewNode->SetFlag(NF_SEEN, true);
 
@@ -137,7 +132,7 @@ bool CAlphabetManager::CAlphNode::GameSearchNode(string strTargetUtf8Char) {
       SetFlag(NF_GAME, true);
       return true;
     }
-  } else if (m_pMgr->m_pNCManager->GetAlphabet()->GetText(static_cast<SAlphabetData *>(m_pUserData)->iSymbol) == strTargetUtf8Char) {
+  } else if (m_pMgr->m_pNCManager->GetAlphabet()->GetText(iSymbol) == strTargetUtf8Char) {
     SetFlag(NF_GAME, true);
     return true;
   }
@@ -145,20 +140,19 @@ bool CAlphabetManager::CAlphNode::GameSearchNode(string strTargetUtf8Char) {
 }
 
 CLanguageModel::Context CAlphabetManager::CAlphNode::CloneAlphContext(CLanguageModel *pLanguageModel) {
-  SAlphabetData *pData = static_cast<SAlphabetData *>(m_pUserData);      
-  if(pData->iContext) return pLanguageModel->CloneContext(pData->iContext);
+  if (iContext) return pLanguageModel->CloneContext(iContext);
   return CDasherNode::CloneAlphContext(pLanguageModel);
 }
 
 symbol CAlphabetManager::CAlphNode::GetAlphSymbol() {
-  return static_cast<SAlphabetData *>(m_pUserData)->iSymbol;
+  return iSymbol;
 }
 
 void CAlphabetManager::CAlphNode::PopulateChildren() {
   m_pMgr->PopulateChildrenWithSymbol( this, -2, 0 );
 }
 
-CDasherNode *CAlphabetManager::CreateGroupNode(CDasherNode *pParent, SGroupInfo *pInfo, std::vector<unsigned int> *pCProb, unsigned int iStart, unsigned int iEnd, unsigned int iMin, unsigned int iMax) {
+CAlphabetManager::CAlphNode *CAlphabetManager::CreateGroupNode(CAlphNode *pParent, SGroupInfo *pInfo, std::vector<unsigned int> *pCProb, unsigned int iStart, unsigned int iEnd, unsigned int iMin, unsigned int iMax) {
 
 #ifdef WIN32
   unsigned int iLbnd = (((*pCProb)[iStart-1] - (*pCProb)[iMin-1]) *
@@ -176,8 +170,6 @@ CDasherNode *CAlphabetManager::CreateGroupNode(CDasherNode *pParent, SGroupInfo
 	  ((*pCProb)[iMax-1] - (*pCProb)[iMin-1]);
 #endif
 
-  SAlphabetData *pParentData = static_cast<SAlphabetData *>(pParent->m_pUserData);
-
   // TODO: More sensible structure in group data to map directly to this
   CDasherNode::SDisplayInfo *pDisplayInfo = new CDasherNode::SDisplayInfo;
   pDisplayInfo->iColour = pInfo->iColour;
@@ -185,26 +177,23 @@ CDasherNode *CAlphabetManager::CreateGroupNode(CDasherNode *pParent, SGroupInfo
   pDisplayInfo->bVisible = pInfo->bVisible;
   pDisplayInfo->strDisplayText = pInfo->strLabel;
 
-  CDasherNode *pNewNode = new CAlphNode(pParent, iLbnd, iHbnd, pDisplayInfo, this);
+  CAlphNode *pNewNode = makeNode(pParent, iLbnd, iHbnd, pDisplayInfo);
 
   pNewNode->SetFlag(NF_SUBNODE, true);
 
-  SAlphabetData *pNodeUserData = new SAlphabetData;
-  pNewNode->m_pUserData = pNodeUserData;
-
   // When creating a group node...
   pNewNode->m_iOffset = pParent->m_iOffset; // ...the offset is the same as the parent...
-  pNodeUserData->iPhase = pParentData->iPhase;
+  pNewNode->iPhase = pParent->iPhase;
   // TODO: Sort out symbol for groups
-  pNodeUserData->iSymbol = 0; //...but the Symbol is just a 0.
-  pNodeUserData->pLanguageModel = pParentData->pLanguageModel;
-  pNodeUserData->iContext = pParentData->pLanguageModel->CloneContext(pParentData->iContext);
+  pNewNode->iSymbol = 0; //...but the Symbol is just a 0.
+  pNewNode->pLanguageModel = pParent->pLanguageModel;
+  pNewNode->iContext = pParent->pLanguageModel->CloneContext(pParent->iContext);
 
   return pNewNode;
 }
 
 // TODO: use these functions elsewhere in the file
-CDasherNode *CAlphabetManager::CreateSymbolNode(CDasherNode *pParent, symbol iSymbol, std::vector<unsigned int> *pCProb, unsigned int iStart, unsigned int iEnd, unsigned int iMin, unsigned int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild) {
+CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, std::vector<unsigned int> *pCProb, unsigned int iStart, unsigned int iEnd, unsigned int iMin, unsigned int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild) {
   // TODO: Node deletion etc.
   //std::cout << "isymbol: "<<iSymbol << " " << m_pNCManager->GetStartConversionSymbol() << std::endl;
 
@@ -227,16 +216,15 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CDasherNode *pParent, symbol iSy
   return CreateSymbolNode(pParent, iSymbol, iLbnd, iHbnd, iExistingSymbol, pExistingChild);
 }
 
-CLanguageModel::Context CAlphabetManager::CreateSymbolContext(SAlphabetData *pParentData, symbol iSymbol)
+CLanguageModel::Context CAlphabetManager::CreateSymbolContext(CAlphNode *pParent, symbol iSymbol)
 {
-  CLanguageModel::Context iContext = m_pLanguageModel->CloneContext(pParentData->iContext);
+  CLanguageModel::Context iContext = m_pLanguageModel->CloneContext(pParent->iContext);
   m_pLanguageModel->EnterSymbol(iContext, iSymbol); // TODO: Don't use symbols?
   return iContext;
 }
 
-CDasherNode *CAlphabetManager::CreateSymbolNode(CDasherNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild) {
+CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild) {
 
-  SAlphabetData *pParentData = static_cast<SAlphabetData *>(pParent->m_pUserData);
   CDasherNode *pNewNode = NULL;
 
   //Does not invoke conversion node
@@ -248,7 +236,7 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CDasherNode *pParent, symbol iSy
       pNewNode->SetRange(iLbnd, iHbnd);
       pNewNode->SetParent(pParent);
 
-      DASHER_ASSERT(pExistingChild->m_iOffset == pParentData->m_iOffset + 1);
+      DASHER_ASSERT(pExistingChild->m_iOffset == pParent->m_iOffset + 1);
 
     }
     // TODO: Need to fix fact that this is created even when control mode is switched off
@@ -267,7 +255,7 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CDasherNode *pParent, symbol iSy
       pNewNode = m_pNCManager->GetConvRoot(pParent, iLbnd, iHbnd, pParent->m_iOffset);
     }
     else {
-      int iPhase = (pParentData->iPhase + 1) % 2;
+      int iPhase = (pParent->iPhase + 1) % 2;
       int iColour = m_pNCManager->GetColour(iSymbol, iPhase);
 
       // TODO: Exceptions / error handling in general
@@ -278,7 +266,8 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CDasherNode *pParent, symbol iSy
       pDisplayInfo->bVisible = true;
       pDisplayInfo->strDisplayText = m_pNCManager->GetAlphabet()->GetDisplayText(iSymbol);
 
-      pNewNode = new CAlphNode(pParent, iLbnd, iHbnd, pDisplayInfo, this);
+      CAlphNode *pAlphNode;
+      pNewNode = pAlphNode = makeNode(pParent, iLbnd, iHbnd, pDisplayInfo);
 
       //     std::stringstream ssLabel;
 
@@ -289,23 +278,20 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CDasherNode *pParent, symbol iSy
 
       pNewNode->m_iNumSymbols = 1;
 
-      SAlphabetData *pNodeUserData = new SAlphabetData;
-      pNewNode->m_pUserData = pNodeUserData;
-
       pNewNode->m_iOffset = pParent->m_iOffset + 1;
-      pNodeUserData->iPhase = iPhase;
-      pNodeUserData->iSymbol = iSymbol;
+      pAlphNode->iPhase = iPhase;
+      pAlphNode->iSymbol = iSymbol;
 
-      pNodeUserData->iContext = CreateSymbolContext(pParentData, iSymbol);
+      pAlphNode->iContext = CreateSymbolContext(pParent, iSymbol);
 
-      pNodeUserData->pLanguageModel = pParentData->pLanguageModel; // TODO: inconsistent with above?
+    pAlphNode->pLanguageModel = pParent->pLanguageModel; // TODO: inconsistent with above?
   }
 
   return pNewNode;
 }
 
 
-void CAlphabetManager::RecursiveIterateGroup(CDasherNode *pParent, SGroupInfo *pInfo, std::vector<symbol> *pSymbols, std::vector<unsigned int> *pCProb, int iMin, int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild) {
+void CAlphabetManager::RecursiveIterateGroup(CAlphNode *pParent, SGroupInfo *pInfo, std::vector<symbol> *pSymbols, std::vector<unsigned int> *pCProb, int iMin, int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild) {
   // TODO: Think through alphabet file formats etc. to make this class easier.
   // TODO: Throw a warning if parent node already has children
 
@@ -320,7 +306,7 @@ void CAlphabetManager::RecursiveIterateGroup(CDasherNode *pParent, SGroupInfo *p
   // Each SGroupInfo contains a pNext, a pointer to a sibling group info
   SGroupInfo *pCurrentNode(pInfo);
   while(pCurrentNode) {
-    CDasherNode *pNewChild = CreateGroupNode(pParent,
+    CAlphNode *pNewChild = CreateGroupNode(pParent,
 					     pCurrentNode,
 					     pCProb,
 					     pCurrentNode->iStart,
@@ -364,16 +350,14 @@ void CAlphabetManager::RecursiveIterateGroup(CDasherNode *pParent, SGroupInfo *p
   delete[] pChildNodes;
 }
 
-void CAlphabetManager::PopulateChildrenWithSymbol( CDasherNode *pNode, int iExistingSymbol, CDasherNode *pExistingChild ) {
-  SAlphabetData *pParentUserData(static_cast<SAlphabetData *>(pNode->m_pUserData));
-
+void CAlphabetManager::PopulateChildrenWithSymbol( CAlphNode *pNode, int iExistingSymbol, CDasherNode *pExistingChild ) {
   // TODO: generally improve with iterators etc.
   // FIXME: this has to change for history stuff and Japanese dasher
   std::vector < symbol > newchars; // place to put this list of characters
   std::vector < unsigned int >cum; // for the probability list
 
   // TODO: Need to fix up relation to language model here (use one from node, not global).
-  m_pNCManager->GetProbs(pParentUserData->iContext, newchars, cum, m_pNCManager->GetLongParameter(LP_NORMALIZATION));
+  m_pNCManager->GetProbs(pNode->iContext, newchars, cum, m_pNCManager->GetLongParameter(LP_NORMALIZATION));
   int iChildCount = newchars.size();
 
   // work out cumulative probs in place
@@ -386,25 +370,20 @@ void CAlphabetManager::PopulateChildrenWithSymbol( CDasherNode *pNode, int iExis
 }
 
 CAlphabetManager::CAlphNode::~CAlphNode() {
-  SAlphabetData *pUserData(static_cast<SAlphabetData *>(m_pUserData));
-
-  pUserData->pLanguageModel->ReleaseContext(pUserData->iContext);
-  delete pUserData;
+  pLanguageModel->ReleaseContext(iContext);
 }
 
 void CAlphabetManager::CAlphNode::Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, int iNormalization) {
-  symbol t = static_cast<SAlphabetData *>(m_pUserData)->iSymbol;
-
   //std::cout << this << " " << Parent() << ": Output at offset " << m_iOffset << " *" << m_pMgr->m_pNCManager->GetAlphabet()->GetText(t) << "* " << std::endl;
 
-  if(t) { // Ignore symbol 0 (root node)
-    Dasher::CEditEvent oEvent(1, m_pMgr->m_pNCManager->GetAlphabet()->GetText(t), m_iOffset);
+  if(iSymbol) { // Ignore symbol 0 (root node)
+    Dasher::CEditEvent oEvent(1, m_pMgr->m_pNCManager->GetAlphabet()->GetText(iSymbol), m_iOffset);
     m_pMgr->m_pNCManager->InsertEvent(&oEvent);
 
     // Track this symbol and its probability for logging purposes
     if (pAdded != NULL) {
       Dasher::SymbolProb sItem;
-      sItem.sym    = t;
+      sItem.sym    = iSymbol;
       sItem.prob   = GetProb(iNormalization);
 
       pAdded->push_back(sItem);
@@ -413,10 +392,8 @@ void CAlphabetManager::CAlphNode::Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, int
 }
 
 void CAlphabetManager::CAlphNode::Undo() {
-  symbol t = static_cast<SAlphabetData *>(m_pUserData)->iSymbol;
-
-  if(t) { // Ignore symbol 0 (root node)
-    Dasher::CEditEvent oEvent(2, m_pMgr->m_pNCManager->GetAlphabet()->GetText(t), m_iOffset);
+  if(iSymbol) { // Ignore symbol 0 (root node)
+    Dasher::CEditEvent oEvent(2, m_pMgr->m_pNCManager->GetAlphabet()->GetText(iSymbol), m_iOffset);
     m_pMgr->m_pNCManager->InsertEvent(&oEvent);
   }
 }
@@ -425,9 +402,7 @@ void CAlphabetManager::CAlphNode::Undo() {
 CDasherNode *CAlphabetManager::CAlphNode::RebuildParent() {
   int iNewOffset = m_iOffset - 1;
 
-  CDasherNode *pNewNode;
-
-  int iOldPhase(static_cast<SAlphabetData *>(m_pUserData)->iPhase);
+  int iOldPhase(iPhase);
   int iNewPhase;
 
   symbol iNewSymbol;
@@ -435,7 +410,7 @@ CDasherNode *CAlphabetManager::CAlphNode::RebuildParent() {
   std::string strContext;
   CLanguageModel::Context iContext;
 
-  if((m_iOffset == -1) || (static_cast<SAlphabetData *>(m_pUserData)->iSymbol == 0)) {
+  if((m_iOffset == -1) || (iSymbol == 0)) {
     // already a root, or for some other reason has the null
     // symbol (eg because it was generated from a different alphabet)
     return NULL;
@@ -474,23 +449,20 @@ CDasherNode *CAlphabetManager::CAlphNode::RebuildParent() {
     pDisplayInfo->strDisplayText = m_pMgr->m_pNCManager->GetAlphabet()->GetDisplayText(iNewSymbol);
   }
 
-  pNewNode = new CAlphNode(NULL, 0, 0, pDisplayInfo, m_pMgr);
+  CAlphNode *pNewNode = m_pMgr->makeNode(NULL, 0, 0, pDisplayInfo);
   
   // TODO: Some of this context stuff could be consolidated
 
   pNewNode->SetFlag(NF_SEEN, true);
 
-  SAlphabetData *pNodeUserData = new SAlphabetData;
-  pNewNode->m_pUserData = pNodeUserData;
-
   pNewNode->m_iOffset = iNewOffset;
-  pNodeUserData->iPhase = iNewPhase;
-  pNodeUserData->iSymbol = iNewSymbol;
-  pNodeUserData->pLanguageModel = m_pMgr->m_pLanguageModel;
-  pNodeUserData->iContext = iContext;
+  pNewNode->iPhase = iNewPhase;
+  pNewNode->iSymbol = iNewSymbol;
+  pNewNode->pLanguageModel = m_pMgr->m_pLanguageModel;
+  pNewNode->iContext = iContext;
 
 
-  m_pMgr->PopulateChildrenWithSymbol(pNewNode, static_cast<SAlphabetData *>(m_pUserData)->iSymbol, this);
+  m_pMgr->PopulateChildrenWithSymbol(pNewNode, iSymbol, this);
 
   //  std::cout << "**" << std::endl;
 
@@ -504,7 +476,7 @@ void CAlphabetManager::CAlphNode::SetFlag(int iFlag, bool bValue) {
   switch(iFlag) {
   case NF_COMMITTED:
     if(bValue && !GetFlag(NF_GAME) && m_pMgr->m_pInterface->GetBoolParameter(BP_LM_ADAPTIVE))
-      static_cast<SAlphabetData *>(m_pUserData)->pLanguageModel->LearnSymbol(m_pMgr->m_iLearnContext, static_cast<SAlphabetData *>(m_pUserData)->iSymbol);
+      pLanguageModel->LearnSymbol(m_pMgr->m_iLearnContext, iSymbol);
     break;
   }
 }
diff --git a/Src/DasherCore/AlphabetManager.h b/Src/DasherCore/AlphabetManager.h
index 613b3fa..cea602b 100644
--- a/Src/DasherCore/AlphabetManager.h
+++ b/Src/DasherCore/AlphabetManager.h
@@ -45,14 +45,6 @@ namespace Dasher {
 
     CAlphabetManager(CDasherInterfaceBase *pInterface, CNodeCreationManager *pNCManager, CLanguageModel *pLanguageModel, CLanguageModel::Context iLearnContext);
 
-    ///
-    /// Get a new root node owned by this manager
-    ///
-    // ACL note 12/8/09 - if previously passed in an SRootData (containing a char* and int),
-    //   then pass in the same char* and int here (the char* may be null); if previously passed
-    //   in null SRootData, then pass in szContext==null and iOffset==-1.
-    virtual CDasherNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset);
-
   protected:
     class CAlphNode : public CDasherNode {
     public:
@@ -83,9 +75,8 @@ namespace Dasher {
     virtual symbol GetAlphSymbol();
     private:
       CAlphabetManager *m_pMgr;
-    };
+    public: //to AlphabetManager and subclasses only, of course...
     
-    struct SAlphabetData {
       symbol iSymbol;
       int iPhase;
       CLanguageModel *pLanguageModel;
@@ -94,16 +85,25 @@ namespace Dasher {
       int iGameOffset;
     };
 
+  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);
+
+  protected:
     ///
     /// Factory method for CAlphNode construction, so subclasses can override.
     ///
     virtual CAlphNode *makeNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo);    
 
     
-  void PopulateChildrenWithSymbol( CDasherNode *pNode, int iExistingSymbol, CDasherNode *pExistingChild );
+  void PopulateChildrenWithSymbol( CAlphNode *pNode, int iExistingSymbol, CDasherNode *pExistingChild );
 
-	virtual CDasherNode *CreateSymbolNode(CDasherNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild);
-    virtual CLanguageModel::Context CreateSymbolContext(SAlphabetData *pParentData, symbol iSymbol);
+	virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild);
+    virtual CLanguageModel::Context CreateSymbolContext(CAlphNode *pParent, symbol iSymbol);
 
     CLanguageModel *m_pLanguageModel;
 	CNodeCreationManager *m_pNCManager;
@@ -112,10 +112,10 @@ namespace Dasher {
     
     void BuildContext(std::string& strContext, bool bRoot, CLanguageModel::Context &oContext, symbol &iSymbol);
 
-    void RecursiveIterateGroup(CDasherNode *pParent, SGroupInfo *pInfo, std::vector<symbol> *pSymbols, std::vector<unsigned int> *pCProb, int iMin, int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild);
+    void RecursiveIterateGroup(CAlphNode *pParent, SGroupInfo *pInfo, std::vector<symbol> *pSymbols, std::vector<unsigned int> *pCProb, int iMin, int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild);
 
-    CDasherNode *CreateGroupNode(CDasherNode *pParent, SGroupInfo *pInfo, std::vector<unsigned int> *pCProb, unsigned int iStart, unsigned int iEnd, unsigned int iMin, unsigned int iMax);
-    CDasherNode *CreateSymbolNode(CDasherNode *pParent, symbol iSymbol, std::vector<unsigned int> *pCProb, unsigned int iStart, unsigned int iEnd, unsigned int iMin, unsigned int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild);
+    CAlphNode *CreateGroupNode(CAlphNode *pParent, SGroupInfo *pInfo, std::vector<unsigned int> *pCProb, unsigned int iStart, unsigned int iEnd, unsigned int iMin, unsigned int iMax);
+    CDasherNode *CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, std::vector<unsigned int> *pCProb, unsigned int iStart, unsigned int iEnd, unsigned int iMin, unsigned int iMax, symbol iExistingSymbol, CDasherNode *pExistingChild);
 
     CLanguageModel::Context m_iLearnContext;
     CDasherInterfaceBase *m_pInterface;
diff --git a/Src/DasherCore/ControlManager.cpp b/Src/DasherCore/ControlManager.cpp
index eec76e0..be6d408 100644
--- a/Src/DasherCore/ControlManager.cpp
+++ b/Src/DasherCore/ControlManager.cpp
@@ -268,7 +268,6 @@ void CControlManager::DisconnectNode(int iChild, int iParent) {
 
 
 CDasherNode *CControlManager::GetRoot(CDasherNode *pParent, int iLower, int iUpper, int iOffset) {
-  CDasherNode *pNewNode;
 
   // TODO: Tie this structure to info contained in control map
   CDasherNode::SDisplayInfo *pDisplayInfo = new CDasherNode::SDisplayInfo;
@@ -277,13 +276,13 @@ CDasherNode *CControlManager::GetRoot(CDasherNode *pParent, int iLower, int iUpp
   pDisplayInfo->bVisible = true;
   pDisplayInfo->strDisplayText = m_mapControlMap[0]->strLabel;
   
-  pNewNode = new CContNode(pParent, iLower, iUpper, pDisplayInfo, this);
+  CContNode *pNewNode = new CContNode(pParent, iLower, iUpper, pDisplayInfo, this);
  
   // FIXME - handle context properly
 
   //  pNewNode->SetContext(m_pLanguageModel->CreateEmptyContext());
 
-  pNewNode->m_pUserData = m_mapControlMap[0];
+  pNewNode->pControlItem = m_mapControlMap[0];
   pNewNode->m_iOffset = iOffset;
 
   return pNewNode;
@@ -298,13 +297,11 @@ void CControlManager::CContNode::PopulateChildren() {
   
   CDasherNode *pNewNode;
 
-   SControlItem *pControlNode(static_cast<SControlItem *>(m_pUserData));
-
-   int iNChildren( pControlNode->vChildren.size() );
+   int iNChildren( pControlItem->vChildren.size() );
 
    int iIdx(0);
 
-   for(std::vector<SControlItem *>::iterator it(pControlNode->vChildren.begin()); it != pControlNode->vChildren.end(); ++it) {
+   for(std::vector<SControlItem *>::iterator it(pControlItem->vChildren.begin()); it != pControlItem->vChildren.end(); ++it) {
 
      // FIXME - could do this better
 
@@ -331,9 +328,10 @@ void CControlManager::CContNode::PopulateChildren() {
        pDisplayInfo->bVisible = true;
        pDisplayInfo->strDisplayText = (*it)->strLabel;
        
-       pNewNode = new CContNode(this, iLbnd, iHbnd, pDisplayInfo, m_pMgr);
+       CContNode *pContNode;
+       pNewNode = pContNode = new CContNode(this, iLbnd, iHbnd, pDisplayInfo, m_pMgr);
 
-       pNewNode->m_pUserData = *it;
+       pContNode->pControlItem = *it;
 
        pNewNode->m_iOffset = m_iOffset;
      }
@@ -344,9 +342,7 @@ void CControlManager::CContNode::PopulateChildren() {
 
 void CControlManager::CContNode::Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, int iNormalization ) {
 
-  SControlItem *pControlNode(static_cast<SControlItem *>(m_pUserData));
-
-  CControlEvent oEvent(pControlNode->iID);
+  CControlEvent oEvent(pControlItem->iID);
   // TODO: Need to reimplement this
   //  m_pNCManager->m_bContextSensitive=false;
   m_pMgr->m_pNCManager->InsertEvent(&oEvent);
diff --git a/Src/DasherCore/ControlManager.h b/Src/DasherCore/ControlManager.h
index f351007..91d83be 100644
--- a/Src/DasherCore/ControlManager.h
+++ b/Src/DasherCore/ControlManager.h
@@ -79,6 +79,14 @@ namespace Dasher {
     void DisconnectNode(int iChild, int iParent);
     
   private:
+
+    struct SControlItem {
+      std::vector<SControlItem *> vChildren;
+      std::string strLabel;
+      int iID;
+      int iColour;
+    };
+    
     class CContNode : public CDasherNode {
     public:
       int mgrId() {return 1;}
@@ -96,17 +104,11 @@ namespace Dasher {
     virtual void Leave();
 
     void SetControlOffset(int iOffset);
+      SControlItem *pControlItem;
     private:
       CControlManager *m_pMgr;
     };
     
-    struct SControlItem {
-      std::vector<SControlItem *> vChildren;
-      std::string strLabel;
-      int iID;
-      int iColour;
-    };
-    
     static void XmlStartHandler(void *pUserData, const XML_Char *szName, const XML_Char **aszAttr);
     static void XmlEndHandler(void *pUserData, const XML_Char *szName);
     static void XmlCDataHandler(void *pUserData, const XML_Char *szData, int iLength);
diff --git a/Src/DasherCore/ConversionHelper.cpp b/Src/DasherCore/ConversionHelper.cpp
index 1b6c2c0..611a4d6 100644
--- a/Src/DasherCore/ConversionHelper.cpp
+++ b/Src/DasherCore/ConversionHelper.cpp
@@ -52,18 +52,21 @@ CConversionHelper::CConversionHelper(CNodeCreationManager *pNCManager, CAlphabet
 
 }
 
-CDasherNode *CConversionHelper::GetRoot(CDasherNode *pParent, int iLower, int iUpper, int iOffset) {
-  CDasherNode *pNewNode = CConversionManager::GetRoot(pParent, iLower, iUpper, iOffset);
-
-  SConversionData *pNodeUserData = static_cast<SConversionData *>(pNewNode->m_pUserData);
+CConversionManager::CConvNode *CConversionHelper::GetRoot(CDasherNode *pParent, int iLower, int iUpper, int iOffset) {
+  CConvNode *pConvNode = CConversionManager::GetRoot(pParent, iLower, iUpper, iOffset);
+  //note that pConvNode is actually a CConvHNode, created by this CConversionHelper:
+  // the overridden CConversionManager::GetRoot creates the node the node it returns
+  // by calling makeNode(), which we override to create a CConvHNode, and then just
+  // fills in some of the fields; however, short of duplicating the code of
+  // CConversionManager::GetRoot here, we can't get the type to reflect that...
 	
-  pNodeUserData->pLanguageModel = m_pLanguageModel;
+  pConvNode->pLanguageModel = m_pLanguageModel;
 
   // context of a conversion node (e.g. ^) is the context of the
   // letter (e.g. e) before it (as the ^ entails replacing the e with
   // a single accented character e-with-^)
-  pNodeUserData->iContext = pParent->CloneAlphContext(m_pLanguageModel);
-  return pNewNode;
+  pConvNode->iContext = pParent->CloneAlphContext(m_pLanguageModel);
+  return pConvNode;
 }
 
 // TODO: This function needs to be significantly tidied up
@@ -169,24 +172,21 @@ void CConversionHelper::AssignChildSizes(SCENode **pNode, CLanguageModel::Contex
 void CConversionHelper::CConvHNode::PopulateChildren() {
   DASHER_ASSERT(m_pNCManager);
 
-  SConversionData * pCurrentDataNode (static_cast<SConversionData *>(m_pUserData));
-  CDasherNode *pNewNode;
-
   // Do the conversion and build the tree (lattice) if it hasn't been
   // done already.
   //
 
 
-  if(pCurrentDataNode->bisRoot) {
+  if(bisRoot) {
     mgr()->BuildTree(this);
   }
 
   SCENode *pCurrentSCEChild;
 
-  if(pCurrentDataNode->pSCENode){
+  if(pSCENode){
 
-    //    RecursiveDumpTree(pCurrentDataNode->pSCENode, 1);
-    pCurrentSCEChild = pCurrentDataNode->pSCENode->GetChild();
+    //    RecursiveDumpTree(pSCENode, 1);
+    pCurrentSCEChild = pSCENode->GetChild();
 
   }
   else {
@@ -216,7 +216,7 @@ void CConversionHelper::CConvHNode::PopulateChildren() {
 
 
 
-    mgr()->AssignChildSizes(&pCurrentSCEChild, pCurrentDataNode->iContext, pCurrentSCEChild->IsHeadAndCandNum);
+    mgr()->AssignChildSizes(&pCurrentSCEChild, iContext, pCurrentSCEChild->IsHeadAndCandNum);
 
     int iIdx(0);
     int iCum(0);
@@ -249,7 +249,7 @@ void CConversionHelper::CConvHNode::PopulateChildren() {
 
       pDisplayInfo->strDisplayText = pCurrentSCEChild->pszConversion;
 
-      pNewNode = mgr()->makeNode(this, iLbnd, iHbnd, pDisplayInfo);
+      CConvNode *pNewNode = mgr()->makeNode(this, iLbnd, iHbnd, pDisplayInfo);
 
       // TODO: Reimplement ----
 
@@ -257,25 +257,22 @@ void CConversionHelper::CConvHNode::PopulateChildren() {
       //      pNewNode->SetContext(m_pLanguageModel->CreateEmptyContext());
       // -----
 
-      SConversionData *pNodeUserData = new SConversionData;
-      pNodeUserData->bisRoot = false;
-      pNodeUserData->pSCENode = pCurrentSCEChild;
-      pNodeUserData->pLanguageModel = pCurrentDataNode->pLanguageModel;
+      pNewNode->bisRoot = false;
+      pNewNode->pSCENode = pCurrentSCEChild;
+      pNewNode->pLanguageModel = pLanguageModel;
       pNewNode->m_iOffset = m_iOffset + 1;
 
-      if(pCurrentDataNode->pLanguageModel) {
+      if(pLanguageModel) {
 	CLanguageModel::Context iContext;
-	iContext = pCurrentDataNode->pLanguageModel->CloneContext(pCurrentDataNode->iContext);
+	iContext = pLanguageModel->CloneContext(this->iContext);
 	
 	if(pCurrentSCEChild ->Symbol !=-1)
-	  pNodeUserData->pLanguageModel->EnterSymbol(iContext, pCurrentSCEChild->Symbol); // TODO: Don't use symbols?
+	  pNewNode->pLanguageModel->EnterSymbol(iContext, pCurrentSCEChild->Symbol); // TODO: Don't use symbols?
 
 
-	pNodeUserData->iContext = iContext;
+	pNewNode->iContext = iContext;
       }
 
-      pNewNode->m_pUserData = pNodeUserData;
-
       Children().push_back(pNewNode);
 
       pCurrentSCEChild = pCurrentSCEChild->GetNext();
@@ -292,7 +289,7 @@ void CConversionHelper::CConvHNode::PopulateChildren() {
       int iLbnd(0);
       int iHbnd(mgr()->m_pNCManager->GetLongParameter(LP_NORMALIZATION));
 
-      pNewNode = mgr()->m_pNCManager->GetAlphRoot(this, iLbnd, iHbnd, NULL, m_iOffset);
+      CDasherNode *pNewNode = mgr()->m_pNCManager->GetAlphRoot(this, iLbnd, iHbnd, NULL, m_iOffset);
       pNewNode->SetFlag(NF_SEEN, false);
 
       Children().push_back(pNewNode);
@@ -355,7 +352,7 @@ void CConversionHelper::BuildTree(CConvHNode *pRoot) {
   // Store all conversion trees (SCENode trees) in the pUserData->pSCENode
   // of each Conversion Root.
 
-  static_cast<SConversionData *>(pRoot->m_pUserData)->pSCENode = pStartTemp;
+  pRoot->pSCENode = pStartTemp;
 }
 
 CConversionHelper::CConvHNode::CConvHNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, CConversionHelper *pMgr)
@@ -372,9 +369,6 @@ void CConversionHelper::CConvHNode::SetFlag(int iFlag, bool bValue) {
   switch(iFlag) {
   case NF_COMMITTED:
     if(bValue){
-      CLanguageModel * pLan =  static_cast<SConversionData *>(m_pUserData)->pLanguageModel;
-
-      SCENode * pSCENode = static_cast<SConversionData *>(m_pUserData)->pSCENode;
 
       if(!pSCENode)
 	return;
@@ -383,7 +377,7 @@ void CConversionHelper::CConvHNode::SetFlag(int iFlag, bool bValue) {
 
 
       if(s!=-1)
-	pLan->LearnSymbol(mgr()->m_iLearnContext, s);
+	pLanguageModel->LearnSymbol(mgr()->m_iLearnContext, s);
     }
     break;
   }
diff --git a/Src/DasherCore/ConversionHelper.h b/Src/DasherCore/ConversionHelper.h
index ae3a52f..37bb920 100644
--- a/Src/DasherCore/ConversionHelper.h
+++ b/Src/DasherCore/ConversionHelper.h
@@ -101,7 +101,7 @@ namespace Dasher{
     /// Get a new root node owned by this manager
     ///
 	
-    virtual CDasherNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, int iOffset);
+    virtual CConvNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, int iOffset);
 	
     ///
     /// Calculate sizes for each of the children - default
@@ -125,7 +125,7 @@ namespace Dasher{
     	
     virtual void SetFlag(int iFlag, bool bValue);
     protected:
-      CConversionHelper *mgr() {return static_cast<CConversionHelper *>(m_pMgr);}
+      inline CConversionHelper *mgr() {return static_cast<CConversionHelper *>(m_pMgr);}
     };
 	  virtual CConvHNode *makeNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo);
     /// 
diff --git a/Src/DasherCore/ConversionManager.cpp b/Src/DasherCore/ConversionManager.cpp
index 7fc3f11..c562354 100644
--- a/Src/DasherCore/ConversionManager.cpp
+++ b/Src/DasherCore/ConversionManager.cpp
@@ -59,8 +59,7 @@ CConversionManager::CConvNode *CConversionManager::makeNode(CDasherNode *pParent
   return new CConvNode(pParent, iLbnd, iHbnd, pDispInfo, this);
 }
 
-CDasherNode *CConversionManager::GetRoot(CDasherNode *pParent, int iLower, int iUpper, int iOffset) {
-  CDasherNode *pNewNode;
+CConversionManager::CConvNode *CConversionManager::GetRoot(CDasherNode *pParent, int iLower, int iUpper, int iOffset) {
 
   // TODO: Parameters here are placeholders - need to figure out what's right
 
@@ -70,7 +69,7 @@ CDasherNode *CConversionManager::GetRoot(CDasherNode *pParent, int iLower, int i
   pDisplayInfo->bVisible = true;
   pDisplayInfo->strDisplayText = ""; // TODO: Hard coded value, needs i18n
 
-  pNewNode = makeNode(pParent, iLower, iUpper, pDisplayInfo);
+  CConvNode *pNewNode = makeNode(pParent, iLower, iUpper, pDisplayInfo);
 
   // FIXME - handle context properly
   // TODO: Reimplemnt -----
@@ -78,14 +77,12 @@ CDasherNode *CConversionManager::GetRoot(CDasherNode *pParent, int iLower, int i
   // -----
 
 
-  SConversionData *pNodeUserData = new SConversionData;
-  pNewNode->m_pUserData = pNodeUserData;
-  pNodeUserData->bisRoot = true;
+  pNewNode->bisRoot = true;
   pNewNode->m_iOffset = iOffset + 1;
 
-  pNodeUserData->pLanguageModel = NULL;
+  pNewNode->pLanguageModel = NULL;
 
-  pNodeUserData->pSCENode = 0;
+  pNewNode->pSCENode = 0;
 
   return pNewNode;
 }
@@ -98,9 +95,6 @@ CConversionManager::CConvNode::CConvNode(CDasherNode *pParent, int iLbnd, int iH
 void CConversionManager::CConvNode::PopulateChildren() {
   DASHER_ASSERT(m_pMgr->m_pNCManager);
 
-  SConversionData * pCurrentDataNode (static_cast<SConversionData *>(m_pUserData));
-  CDasherNode *pNewNode;
-
   // If no helper class is present then just drop straight back to an
   // alphabet root. This should only happen in error cases, and the
   // user should have been warned here.
@@ -108,21 +102,14 @@ void CConversionManager::CConvNode::PopulateChildren() {
   int iLbnd(0);
   int iHbnd(m_pMgr->m_pNCManager->GetLongParameter(LP_NORMALIZATION));
 
-  pNewNode = m_pMgr->m_pNCManager->GetAlphRoot(this, iLbnd, iHbnd, NULL, m_iOffset + 1);
+  CDasherNode *pNewNode = m_pMgr->m_pNCManager->GetAlphRoot(this, iLbnd, iHbnd, NULL, m_iOffset + 1);
   pNewNode->SetFlag(NF_SEEN, false);
 
   Children().push_back(pNewNode);
-
-  return;
 }
 
 CConversionManager::CConvNode::~CConvNode() {
-  if(m_pUserData){
-    SConversionData *pUserData(static_cast<SConversionData *>(m_pUserData));
-
-    pUserData->pLanguageModel->ReleaseContext(pUserData->iContext);
-    delete (SConversionData *)(m_pUserData);
-  }
+  pLanguageModel->ReleaseContext(iContext);
   m_pMgr->Unref();
 }
 
@@ -152,7 +139,7 @@ void CConversionManager::CConvNode::Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, i
   // TODO: Reimplement this
   //  m_pNCManager->m_bContextSensitive = true;
 
-  SCENode *pCurrentSCENode((static_cast<SConversionData *>(m_pUserData))->pSCENode);
+  SCENode *pCurrentSCENode(pSCENode);
 
   if(pCurrentSCENode){
     Dasher::CEditEvent oEvent(1, pCurrentSCENode->pszConversion, m_iOffset);
@@ -166,7 +153,7 @@ void CConversionManager::CConvNode::Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, i
     }
   }
   else {
-    if(!((static_cast<SConversionData *>(m_pUserData))->bisRoot)) {
+    if(!bisRoot) {
       Dasher::CEditEvent oOPEvent(1, "|", m_iOffset);
       m_pMgr->m_pNCManager->InsertEvent(&oOPEvent);
     }
@@ -180,8 +167,8 @@ void CConversionManager::CConvNode::Output(Dasher::VECTOR_SYMBOL_PROB* pAdded, i
   }
 }
 
-void CConversionManager::CConvNode::Undo() {
-  SCENode *pCurrentSCENode((static_cast<SConversionData *>(m_pUserData))->pSCENode);
+void CConversionManager::CConvNode::Undo() {  
+  SCENode *pCurrentSCENode(pSCENode);
 
   if(pCurrentSCENode) {
     if(pCurrentSCENode->pszConversion && (strlen(pCurrentSCENode->pszConversion) > 0)) {
@@ -190,7 +177,7 @@ void CConversionManager::CConvNode::Undo() {
     }
   }
   else {
-    if(!((static_cast<SConversionData *>(m_pUserData))->bisRoot)) {
+    if(!bisRoot) {
       Dasher::CEditEvent oOPEvent(2, "|", m_iOffset);
       m_pMgr->m_pNCManager->InsertEvent(&oOPEvent);
     }
diff --git a/Src/DasherCore/ConversionManager.h b/Src/DasherCore/ConversionManager.h
index 6eaf217..3256605 100644
--- a/Src/DasherCore/ConversionManager.h
+++ b/Src/DasherCore/ConversionManager.h
@@ -77,12 +77,6 @@ namespace Dasher {
       }
     };
 
-    ///
-    /// Get a new root node owned by this manager
-    ///
-
-    virtual CDasherNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, int iOffset);
-
     protected:
     class CConvNode : public CDasherNode {
     public:
@@ -111,12 +105,9 @@ namespace Dasher {
 
     protected:
       CConversionManager *m_pMgr;
-    };
-    
-    virtual CConvNode *makeNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo);
-    
+    public: //to ConversionManager and subclasses only, of course...
+        
     //TODO: REVISE
-    struct SConversionData {
       symbol iSymbol;
       //     int iPhase;
       CLanguageModel *pLanguageModel;
@@ -125,6 +116,17 @@ namespace Dasher {
       bool bisRoot; // True for root conversion nodes 
       //int iGameOffset;
     };
+
+  public:
+    ///
+    /// Get a new root node owned by this manager
+    ///
+    
+    virtual CConvNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, int iOffset);
+  protected:    
+    
+  virtual CConvNode *makeNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo);
+
 	  
 	CNodeCreationManager *m_pNCManager;
 	CAlphabet *m_pAlphabet;
@@ -141,16 +143,7 @@ namespace Dasher {
 	/// Reference count 
 	///
 	  
-	  
     int m_iRefCount;
-
-    ///
-    /// Unique identifier, used to talk to the conversion helper so
-    /// that it can be shared between multiple conversion nodes
-    /// without state collisions
-    ///
-
-
    
   };
   /// @}
diff --git a/Src/DasherCore/DasherNode.h b/Src/DasherCore/DasherNode.h
index 9fe77cb..e38b94b 100644
--- a/Src/DasherCore/DasherNode.h
+++ b/Src/DasherCore/DasherNode.h
@@ -219,7 +219,6 @@ class Dasher::CDasherNode:private NoClones {
   ///
   bool GameSearchChildren(std::string strTargetUtf8Char);
   
-  void *m_pUserData;
   /// @name Management routines (once accessed via NodeManager)
   /// @{
   virtual int mgrId() = 0;
diff --git a/Src/DasherCore/MandarinAlphMgr.cpp b/Src/DasherCore/MandarinAlphMgr.cpp
index 417fc44..66e8db0 100644
--- a/Src/DasherCore/MandarinAlphMgr.cpp
+++ b/Src/DasherCore/MandarinAlphMgr.cpp
@@ -50,25 +50,24 @@ CMandarinAlphMgr::CMandarinAlphMgr(CDasherInterfaceBase *pInterface, CNodeCreati
   : CAlphabetManager(pInterface, pNCManager, pLanguageModel, iLearnContext) {
 }
 
-CDasherNode *CMandarinAlphMgr::GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset) {
+CAlphabetManager::CAlphNode *CMandarinAlphMgr::GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset) {
 
-  CDasherNode *pNewNode = CAlphabetManager::GetRoot(pParent, iLower, iUpper, szContext, iOffset);
-  SAlphabetData *pNodeUserData = static_cast<SAlphabetData *>(pNewNode->m_pUserData);
+  CAlphNode *pNewNode = CAlphabetManager::GetRoot(pParent, iLower, iUpper, szContext, iOffset);
 
   //Override context for Mandarin Dasher
   if (pParent){
     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!
-    pNodeUserData->iContext = m_pLanguageModel->CloneContext(pPYParent->GetConvContext());
+    pNewNode->iContext = m_pLanguageModel->CloneContext(pPYParent->GetConvContext());
   }
   else
-	pNodeUserData->iContext = m_pLanguageModel->CreateEmptyContext();
+	pNewNode->iContext = m_pLanguageModel->CreateEmptyContext();
 
   return pNewNode;
 }
 
-CDasherNode *CMandarinAlphMgr::CreateSymbolNode(CDasherNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild) {
+CDasherNode *CMandarinAlphMgr::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild) {
 
   if (iSymbol <= 1288) {
     //Modified for Mandarin Dasher
@@ -80,10 +79,10 @@ CDasherNode *CMandarinAlphMgr::CreateSymbolNode(CDasherNode *pParent, symbol iSy
   return CAlphabetManager::CreateSymbolNode(pParent, iSymbol, iLbnd, iHbnd, iExistingSymbol, pExistingChild);
 }
 
-CLanguageModel::Context CMandarinAlphMgr::CreateSymbolContext(SAlphabetData *pParentData, symbol iSymbol)
+CLanguageModel::Context CMandarinAlphMgr::CreateSymbolContext(CAlphNode *pParent, symbol iSymbol)
 {
 	//Context carry-over. This code may worth looking at debug
-	return m_pLanguageModel->CloneContext(pParentData->iContext);
+	return m_pLanguageModel->CloneContext(pParent->iContext);
 }
 
 CMandarinAlphMgr::CMandNode::CMandNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo, CAlphabetManager *pMgr)
diff --git a/Src/DasherCore/MandarinAlphMgr.h b/Src/DasherCore/MandarinAlphMgr.h
index d8a57f8..24ca897 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 CDasherNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset);
+    virtual CAlphNode *GetRoot(CDasherNode *pParent, int iLower, int iUpper, char *szContext, int iOffset);
 
   protected:
     class CMandNode : public CAlphNode {
@@ -50,8 +50,8 @@ namespace Dasher {
       virtual void SetFlag(int iFlag, bool bValue);
     };
     CAlphNode *makeNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo);
-    virtual CDasherNode *CreateSymbolNode(CDasherNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild);
-    virtual CLanguageModel::Context CreateSymbolContext(SAlphabetData *pParentData, symbol iSymbol);
+    virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, symbol iSymbol, unsigned int iLbnd, unsigned int iHbnd, symbol iExistingSymbol, CDasherNode *pExistingChild);
+    virtual CLanguageModel::Context CreateSymbolContext(CAlphNode *pParent, symbol iSymbol);
   };
   /// @}
 
diff --git a/Src/DasherCore/PinYinConversionHelper.cpp b/Src/DasherCore/PinYinConversionHelper.cpp
index 892f37a..205163c 100644
--- a/Src/DasherCore/PinYinConversionHelper.cpp
+++ b/Src/DasherCore/PinYinConversionHelper.cpp
@@ -51,19 +51,15 @@ CPinYinConversionHelper::CPinYinConversionHelper(CNodeCreationManager *pNCManage
 }
 
 void CPinYinConversionHelper::BuildTree(CConvHNode *pRoot) {
-  DASHER_ASSERT(pRoot->m_pNodeManager == this);
+  DASHER_ASSERT(pRoot->bisRoot);
 
   // Find the pinyin (roman) text (stored in Display text) of the
   // previous alphabet node.
 
-  SConversionData *pRootData = static_cast<SConversionData *>(pRoot->m_pUserData);
-
-  DASHER_ASSERT(pRootData->bisRoot);
-
   // Get pinyin string (to translate) from 'Display Text' in the
   // alphabet file (refer to alphabet.spyDict.xml).
 
-  std::string strCurrentString(m_pAlphabet->GetDisplayText(pRootData->iSymbol));
+  std::string strCurrentString(m_pAlphabet->GetDisplayText(pRoot->iSymbol));
 
   SCENode *pStartTemp;
   Convert(strCurrentString, &pStartTemp);
@@ -71,7 +67,7 @@ void CPinYinConversionHelper::BuildTree(CConvHNode *pRoot) {
   // Store all conversion trees (SCENode trees) in the pUserData->pSCENode
   // of each Conversion Root.
 
-  pRootData->pSCENode = pStartTemp;
+  pRoot->pSCENode = pStartTemp;
 }
 
 bool CPinYinConversionHelper::Convert(const std::string &strSource, SCENode ** pRoot) {
@@ -272,9 +268,9 @@ void CPinYinConversionHelper::CPYConvNode::SetFlag(int iFlag, bool bValue)
 }
 
 CLanguageModel::Context CPinYinConversionHelper::CPYConvNode::GetConvContext() {
-  return static_cast<SConversionData *>(m_pUserData)->iContext;
+  return iContext;
 }
 
-void CPinYinConversionHelper::CPYConvNode::SetConvSymbol(int iSymbol) {
-  static_cast<SConversionData *> (m_pUserData)->iSymbol = iSymbol;
+void CPinYinConversionHelper::CPYConvNode::SetConvSymbol(int _iSymbol) {
+  iSymbol = _iSymbol;
 }
diff --git a/Src/DasherCore/PinYinConversionHelper.h b/Src/DasherCore/PinYinConversionHelper.h
index 8afb956..29167ba 100644
--- a/Src/DasherCore/PinYinConversionHelper.h
+++ b/Src/DasherCore/PinYinConversionHelper.h
@@ -48,7 +48,7 @@ protected:
     virtual void SetConvSymbol(int iSymbol);
     
   protected:
-    CPinYinConversionHelper *mgr() {return static_cast<CPinYinConversionHelper *>(m_pMgr);}
+    inline CPinYinConversionHelper *mgr() {return static_cast<CPinYinConversionHelper *>(m_pMgr);}
   };
   CPYConvNode *makeNode(CDasherNode *pParent, int iLbnd, int iHbnd, CDasherNode::SDisplayInfo *pDispInfo);
 	



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