[dasher: 14/28] Refactor: Combine SetRange+SetParent -> Reparent + call on newly-c'ted nodes.



commit ab62c1ca5c6ced09b35aa32760e5407ebc63febd
Author: Alan Lawrence <acl33 inf phy cam ac uk>
Date:   Fri Sep 23 15:18:20 2011 +0100

    Refactor: Combine SetRange+SetParent -> Reparent + call on newly-c'ted nodes.
    
    Saves a huge amount of passing around iLbnd / iHbnd.
    
    Also (belatedly) move ConversionHelper into ConversionManager. Still a mess...

 Src/DasherCore/AlphabetManager.cpp          |   72 ++++-----
 Src/DasherCore/AlphabetManager.h            |   27 ++--
 Src/DasherCore/CannaConversionHelper.cpp    |    2 +-
 Src/DasherCore/CannaConversionHelper.h      |    4 +-
 Src/DasherCore/ControlManager.cpp           |   21 ++-
 Src/DasherCore/ControlManager.h             |    6 +-
 Src/DasherCore/ConversionHelper.cpp         |  220 ---------------------------
 Src/DasherCore/ConversionHelper.h           |  147 ------------------
 Src/DasherCore/ConversionManager.cpp        |  189 ++++++++++++++++++-----
 Src/DasherCore/ConversionManager.h          |  124 +++++++++++-----
 Src/DasherCore/ConvertingAlphMgr.cpp        |   19 ++-
 Src/DasherCore/ConvertingAlphMgr.h          |    2 +-
 Src/DasherCore/DasherCore_vc80.vcproj       |    8 -
 Src/DasherCore/DasherModel.cpp              |   24 +---
 Src/DasherCore/DasherNode.cpp               |   32 +---
 Src/DasherCore/DasherNode.h                 |   34 ++---
 Src/DasherCore/IMEConversionHelper.cpp      |    2 +-
 Src/DasherCore/IMEConversionHelper.h        |    4 +-
 Src/DasherCore/Makefile.am                  |    2 -
 Src/DasherCore/MandarinAlphMgr.cpp          |   63 +++-----
 Src/DasherCore/MandarinAlphMgr.h            |   16 +-
 Src/DasherCore/NodeCreationManager.cpp      |    3 +-
 Src/MacOSX/Dasher.xcodeproj/project.pbxproj |    8 -
 Src/iPhone/Dasher.xcodeproj/project.pbxproj |    6 -
 24 files changed, 384 insertions(+), 651 deletions(-)
---
diff --git a/Src/DasherCore/AlphabetManager.cpp b/Src/DasherCore/AlphabetManager.cpp
index 9f8d5e4..64a12d1 100644
--- a/Src/DasherCore/AlphabetManager.cpp
+++ b/Src/DasherCore/AlphabetManager.cpp
@@ -229,8 +229,8 @@ int CAlphabetManager::GetColour(symbol sym, int iOffset) const {
 }
 
 
-CAlphabetManager::CAlphBase::CAlphBase(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr)
-: CDasherNode(pParent, iOffset, iLbnd, iHbnd, iColour, pLabel), m_pMgr(pMgr) {
+CAlphabetManager::CAlphBase::CAlphBase(int iOffset, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr)
+: CDasherNode(iOffset, iColour, pLabel), m_pMgr(pMgr) {
 }
 
 void CAlphabetManager::CAlphBase::Output() {
@@ -244,28 +244,28 @@ void CAlphabetManager::CAlphBase::Output() {
 void CAlphabetManager::CAlphBase::Undo() {
   if (m_pMgr->m_pLastOutput==this) m_pMgr->m_pLastOutput = Parent();
 }
-CAlphabetManager::CAlphNode::CAlphNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr)
-: CAlphBase(pParent, iOffset, iLbnd, iHbnd, iColour, pLabel, pMgr), m_pProbInfo(NULL) {
+CAlphabetManager::CAlphNode::CAlphNode(int iOffset, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr)
+: CAlphBase(iOffset, iColour, pLabel, pMgr), m_pProbInfo(NULL) {
 }
 
-CAlphabetManager::CSymbolNode::CSymbolNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr, symbol _iSymbol)
-: CAlphNode(pParent, iOffset, iLbnd, iHbnd, pMgr->GetColour(_iSymbol, iOffset), pLabel, pMgr), iSymbol(_iSymbol) {
+CAlphabetManager::CSymbolNode::CSymbolNode(int iOffset, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr, symbol _iSymbol)
+: CAlphNode(iOffset, pMgr->GetColour(_iSymbol, iOffset), pLabel, pMgr), iSymbol(_iSymbol) {
 }
 
-CAlphabetManager::CSymbolNode::CSymbolNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr, symbol _iSymbol)
-: CAlphNode(pParent, iOffset, iLbnd, iHbnd, iColour, pLabel, pMgr), iSymbol(_iSymbol) {
+CAlphabetManager::CSymbolNode::CSymbolNode(int iOffset, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr, symbol _iSymbol)
+: CAlphNode(iOffset, iColour, pLabel, pMgr), iSymbol(_iSymbol) {
 }
 
-CAlphabetManager::CGroupNode::CGroupNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, CDasherScreen::Label *pLabel, int iBkgCol, CAlphabetManager *pMgr, const SGroupInfo *pGroup)
-: CAlphNode(pParent, iOffset, iLbnd, iHbnd,
+CAlphabetManager::CGroupNode::CGroupNode(int iOffset, CDasherScreen::Label *pLabel, int iBkgCol, CAlphabetManager *pMgr, const SGroupInfo *pGroup)
+: CAlphNode(iOffset,
             pGroup ? (pGroup->bVisible ? pGroup->iColour : iBkgCol)
             : (iOffset&1) ? 7 : 137, //special case for root nodes
             pLabel, pMgr), m_pGroup(pGroup) {
   if (m_pGroup && !m_pGroup->bVisible) SetFlag(NF_VISIBLE, false);
 }
 
-CAlphabetManager::CAlphNode *CAlphabetManager::GetRoot(CDasherNode *pParent, unsigned int iLower, unsigned int iUpper, bool bEnteredLast, int iOffset) {
-
+CAlphabetManager::CAlphNode *CAlphabetManager::GetRoot(CDasherNode *pParent, bool bEnteredLast, int iOffset) {
+  //pParent is not a parent, just for document/context.
   int iNewOffset(max(-1,iOffset-1));
 
   pair<symbol, CLanguageModel::Context> p = GetContextSymbols(pParent, iNewOffset, m_pAlphabetMap);
@@ -273,12 +273,14 @@ CAlphabetManager::CAlphNode *CAlphabetManager::GetRoot(CDasherNode *pParent, uns
   CAlphNode *pNewNode;
   if(p.first==0 || !bEnteredLast) {
     //couldn't extract last symbol (so probably using default context), or shouldn't
-    pNewNode = new CGroupNode(pParent, iNewOffset, iLower, iUpper, NULL, 0, this, NULL); //default background colour
+    pNewNode = new CGroupNode(iNewOffset, NULL, 0, this, NULL); //default background colour
   } else {
     //new node represents a symbol that's already happened - i.e. user has already steered through it;
     // so either we're rebuilding, or else creating a new root from existing text (in edit box)
     DASHER_ASSERT(!pParent);
-    pNewNode = new CSymbolNode(pParent, iNewOffset, iLower, iUpper, m_vLabels[p.first], this, p.first);
+    pNewNode = new CSymbolNode(iNewOffset, m_vLabels[p.first], this, p.first);
+    pNewNode->SetFlag(NF_SEEN, true);
+    pNewNode->CDasherNode::SetFlag(NF_COMMITTED, true); //do NOT commit!
   }
 
   pNewNode->iContext = p.second;
@@ -336,11 +338,6 @@ bool CAlphabetManager::CGroupNode::GameSearchNode(symbol sym) {
 return false;
 }
 
-CLanguageModel::Context CAlphabetManager::CAlphNode::CloneAlphContext(CLanguageModel *pLanguageModel) {
-  if (iContext) return pLanguageModel->CloneContext(iContext);
-  return CDasherNode::CloneAlphContext(pLanguageModel);
-}
-
 void CAlphabetManager::CSymbolNode::GetContext(CDasherInterfaceBase *pInterface, const CAlphabetMap *pAlphabetMap, vector<symbol> &vContextSymbols, int iOffset, int iLength) {
   if (!GetFlag(NF_SEEN) && iOffset+iLength-1 == offset()) {
     if (iLength > 1) Parent()->GetContext(pInterface, pAlphabetMap, vContextSymbols, iOffset, iLength-numChars());
@@ -425,12 +422,12 @@ int CAlphabetManager::CGroupNode::ExpectedNumChildren() {
   return (m_pGroup) ? m_pGroup->iNumChildNodes : CAlphNode::ExpectedNumChildren();
 }
 
-CAlphabetManager::CGroupNode *CAlphabetManager::CreateGroupNode(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, int iBkgCol, const SGroupInfo *pInfo) {
+CAlphabetManager::CGroupNode *CAlphabetManager::CreateGroupNode(CAlphNode *pParent, int iBkgCol, const SGroupInfo *pInfo) {
 
   // When creating a group node...
   // ...the offset is the same as the parent...
 
-  CGroupNode *pNewNode = new CGroupNode(pParent, pParent->offset(), iLbnd, iHbnd, pInfo->pLabel, iBkgCol, this, pInfo);
+  CGroupNode *pNewNode = new CGroupNode(pParent->offset(), pInfo->pLabel, iBkgCol, this, pInfo);
 
   //...as is the context!
   pNewNode->iContext = m_pLanguageModel->CloneContext(pParent->iContext);
@@ -438,8 +435,8 @@ CAlphabetManager::CGroupNode *CAlphabetManager::CreateGroupNode(CAlphNode *pPare
   return pNewNode;
 }
 
-CDasherNode *CAlphabetManager::CAlphBase::RebuildGroup(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, int iBkgCol, const SGroupInfo *pInfo) {
-  CGroupNode *pRet=m_pMgr->CreateGroupNode(pParent, iLbnd, iHbnd, iBkgCol, pInfo);
+CDasherNode *CAlphabetManager::CAlphBase::RebuildGroup(CAlphNode *pParent, int iBkgCol, const SGroupInfo *pInfo) {
+  CGroupNode *pRet=m_pMgr->CreateGroupNode(pParent, iBkgCol, pInfo);
   if (isInGroup(pInfo)) {
     //created group node should contain this one
     m_pMgr->IterateChildGroups(pRet,pInfo,this);
@@ -447,15 +444,13 @@ CDasherNode *CAlphabetManager::CAlphBase::RebuildGroup(CAlphNode *pParent, unsig
   return pRet;
 }
 
-CDasherNode *CAlphabetManager::CGroupNode::RebuildGroup(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, int iBkgCol, const SGroupInfo *pInfo) {
+CDasherNode *CAlphabetManager::CGroupNode::RebuildGroup(CAlphNode *pParent, int iBkgCol, const SGroupInfo *pInfo) {
   if (pInfo == m_pGroup) {
-    SetRange(iLbnd, iHbnd);
-    SetParent(pParent);
     //offset doesn't increase for groups...
     DASHER_ASSERT (offset() == pParent->offset());
     return this;
   }
-  return CAlphBase::RebuildGroup(pParent, iLbnd, iHbnd, iBkgCol, pInfo);
+  return CAlphBase::RebuildGroup(pParent, iBkgCol, pInfo);
 }
 
 bool CAlphabetManager::CGroupNode::isInGroup(const SGroupInfo *pInfo) {
@@ -466,7 +461,7 @@ bool CAlphabetManager::CSymbolNode::isInGroup(const SGroupInfo *pInfo) {
   return (pInfo->iStart <= iSymbol && pInfo->iEnd > iSymbol);
 }
 
-CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol) {
+CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol) {
 
     // TODO: Exceptions / error handling in general
 
@@ -474,8 +469,7 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, unsigned int
     // (and we can't call numChars() on the symbol before we've constructed it!)
     int iNewOffset = pParent->offset()+1;
     if (m_pAlphabet->GetText(iSymbol)=="\r\n") iNewOffset++;
-    CSymbolNode *pAlphNode = new CSymbolNode(pParent, iNewOffset, iLbnd, iHbnd, m_vLabels[iSymbol], this, iSymbol);
-
+    CSymbolNode *pAlphNode = new CSymbolNode(iNewOffset, m_vLabels[iSymbol], this, iSymbol);
     //     std::stringstream ssLabel;
 
     //     ssLabel << m_pAlphabet->GetDisplayText(iSymbol) << ": " << pNewNode;
@@ -488,18 +482,16 @@ CDasherNode *CAlphabetManager::CreateSymbolNode(CAlphNode *pParent, unsigned int
   return pAlphNode;
 }
 
-CDasherNode *CAlphabetManager::CAlphBase::RebuildSymbol(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol) {
-  return m_pMgr->CreateSymbolNode(pParent, iLbnd, iHbnd, iSymbol);
+CDasherNode *CAlphabetManager::CAlphBase::RebuildSymbol(CAlphNode *pParent, symbol iSymbol) {
+  return m_pMgr->CreateSymbolNode(pParent, iSymbol);
 }
 
-CDasherNode *CAlphabetManager::CSymbolNode::RebuildSymbol(CAlphNode *pParent,  unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol) {
+CDasherNode *CAlphabetManager::CSymbolNode::RebuildSymbol(CAlphNode *pParent, symbol iSymbol) {
   if(iSymbol == this->iSymbol) {
-    SetRange(iLbnd, iHbnd);
-    SetParent(pParent);
     DASHER_ASSERT(offset() == pParent->offset() + numChars());
     return this;
   }
-  return CAlphBase::RebuildSymbol(pParent, iLbnd, iHbnd, iSymbol);
+  return CAlphBase::RebuildSymbol(pParent, iSymbol);
 }
 
 void CAlphabetManager::IterateChildGroups(CAlphNode *pParent, const SGroupInfo *pParentGroup, CAlphBase *buildAround) {
@@ -531,17 +523,17 @@ void CAlphabetManager::IterateChildGroups(CAlphNode *pParent, const SGroupInfo *
                           static_cast<uint64>(CDasherModel::NORMALIZATION)) /
                          iRange;
     if (bSymbol) {
-      pNewChild = (buildAround) ? buildAround->RebuildSymbol(pParent, iLbnd, iHbnd, i) : CreateSymbolNode(pParent, iLbnd, iHbnd, i);
+      pNewChild = (buildAround) ? buildAround->RebuildSymbol(pParent, i) : CreateSymbolNode(pParent, i);
       i++; //make one symbol at a time - move onto next symbol in next iteration of (outer) loop
     } else {
       DASHER_ASSERT(pCurrentNode->iNumChildNodes > 1);
-      pNewChild= (buildAround) ? buildAround->RebuildGroup(pParent, iLbnd, iHbnd, pParent->getColour(), pCurrentNode) : CreateGroupNode(pParent, iLbnd, iHbnd, pParent->getColour(), pCurrentNode);
+      pNewChild= (buildAround) ? buildAround->RebuildGroup(pParent, pParent->getColour(), pCurrentNode) : CreateGroupNode(pParent, pParent->getColour(), pCurrentNode);
       i = pCurrentNode->iEnd; //make one group at a time - so move past entire group...
       pCurrentNode = pCurrentNode->pNext; //next sibling of _original_ pCurrentNode (above)
       // (maybe not of pCurrentNode now, which might be a subgroup filling the original)
     }
     //created a new node - symbol or (group which will have >1 child).
-    DASHER_ASSERT(pParent->GetChildren().back()==pNewChild);
+    pNewChild->Reparent(pParent, iLbnd, iHbnd);
   }
 
   if (!pParentGroup) m_pNCManager->AddExtras(pParent);
@@ -638,7 +630,7 @@ CDasherNode *CAlphabetManager::CAlphBase::RebuildParent() {
     //Parent's offset usually one less than this, but can be two for the paragraph symbol.
     int iNewOffset = offset()-numChars();
 
-    CAlphNode *pNewNode = m_pMgr->GetRoot(NULL, 0, 0, iNewOffset!=-1, iNewOffset+1);
+    CAlphNode *pNewNode = m_pMgr->GetRoot(NULL, iNewOffset!=-1, iNewOffset+1);
 
     RebuildForwardsFromAncestor(pNewNode);
 
diff --git a/Src/DasherCore/AlphabetManager.h b/Src/DasherCore/AlphabetManager.h
index 9b277a8..c37d423 100644
--- a/Src/DasherCore/AlphabetManager.h
+++ b/Src/DasherCore/AlphabetManager.h
@@ -100,13 +100,13 @@ namespace Dasher {
       /// \param pParent parent of the symbol node to create; could be the previous root, or an intervening node (e.g. group)
       /// \param iBkgCol background colour to show through any new transparent node created;
       /// if the existing node is grafted in, again this will already have been taken into account.
-      virtual CDasherNode *RebuildSymbol(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol);
+      virtual CDasherNode *RebuildSymbol(CAlphNode *pParent, symbol iSymbol);
       ///Called to build a group node which is a descendant of the symbol or root node preceding this.
       /// Default implementation calls the manager's CreateGroupNode method to create a new node,
       /// but then populates that group (i.e. further descends the hierarchy) _if_ that group
       /// would contain this node (see IsInGroup). Subclasses can override to graft themselves into the hierarchy, if appropriate.
       /// \param pParent parent of the symbol node to create; could be the previous root, or an intervening node (e.g. group)
-      virtual CDasherNode *RebuildGroup(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, int iBkgCol, const SGroupInfo *pInfo);
+      virtual CDasherNode *RebuildGroup(CAlphNode *pParent, int iBkgCol, const SGroupInfo *pInfo);
       ///Just keep track of the last node output (for training file purposes)
       void Undo();
       ///Just keep track of the last node output (for training file purposes)
@@ -118,7 +118,7 @@ namespace Dasher {
       /// at which point RebuildSymbol/Group should graft it in.
       /// \param pNewNode newly-created root node beneath which this node should fit
       virtual void RebuildForwardsFromAncestor(CAlphNode *pNewNode);
-      CAlphBase(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr);
+      CAlphBase(int iOffset, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr);
       CAlphabetManager *m_pMgr;
       ///Number of unicode characters entered by this node; i.e., the number
       /// to take off this node's offset, to get the offset of the most-recent
@@ -131,13 +131,12 @@ namespace Dasher {
     ///Additionally stores LM contexts and probabilities calculated therefrom
     class CAlphNode : public CAlphBase {
     public:
-      CAlphNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr);
+      CAlphNode(int iOffset, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr);
       CLanguageModel::Context iContext;
       ///
       /// Delete any storage alocated for this node
       ///
       virtual ~CAlphNode();
-      virtual CLanguageModel::Context CloneAlphContext(CLanguageModel *pLanguageModel);
       ///Have to call this from CAlphabetManager, and from CGroupNode on a _different_ CAlphNode, hence public...
       virtual std::vector<unsigned int> *GetProbInfo();
       virtual int ExpectedNumChildren();
@@ -148,7 +147,7 @@ namespace Dasher {
     public:
       ///Standard constructor, gets colour from GetColour(symbol,offset) and label from current alphabet
       /// Note we treat GetColour() as always returning an opaque color.
-      CSymbolNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr, symbol iSymbol);
+      CSymbolNode(int iOffset, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr, symbol iSymbol);
 
       ///Create the children of this node, by starting traversal of the alphabet from the top
       virtual void PopulateChildren();
@@ -163,7 +162,7 @@ namespace Dasher {
       virtual void GetContext(CDasherInterfaceBase *pInterface, const CAlphabetMap *pAlphabetMap, std::vector<symbol> &vContextSymbols, int iOffset, int iLength);
       virtual symbol GetAlphSymbol();
       ///Override: if the symbol to create is the same as this node's symbol, return this node instead of creating a new one
-      virtual CDasherNode *RebuildSymbol(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol);
+      virtual CDasherNode *RebuildSymbol(CAlphNode *pParent, symbol iSymbol);
     protected:
       virtual const std::string &outputText();
       ///Text to write to user training file/buffer when this symbol output.
@@ -175,7 +174,7 @@ namespace Dasher {
       /// unicode char, even if that might take >1 octet.
       int numChars();
       ///Compatibility constructor, so that subclasses can specify their own colour & label
-      CSymbolNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr, symbol _iSymbol);
+      CSymbolNode(int iOffset, int iColour, CDasherScreen::Label *pLabel, CAlphabetManager *pMgr, symbol _iSymbol);
       ///Override: true iff pGroup encloses this symbol (according to its start/end symbol#)
       bool isInGroup(const SGroupInfo *pGroup);
       const symbol iSymbol;
@@ -183,7 +182,7 @@ namespace Dasher {
 
     class CGroupNode : public CAlphNode {
     public:
-      CGroupNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, CDasherScreen::Label *pLabel, int iBkgCol, CAlphabetManager *pMgr, const SGroupInfo *pGroup);
+      CGroupNode(int iOffset, CDasherScreen::Label *pLabel, int iBkgCol, CAlphabetManager *pMgr, const SGroupInfo *pGroup);
 
       ///Override: if m_pGroup==NULL, i.e. whole/root-of alphabet, cannot rebuild.
       virtual CDasherNode *RebuildParent();
@@ -195,7 +194,7 @@ namespace Dasher {
       virtual bool GameSearchNode(symbol sym);
       std::vector<unsigned int> *GetProbInfo();
       ///Override: if the group to create is the same as this node's group, return this node instead of creating a new one
-      virtual CDasherNode *RebuildGroup(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, int iBkgCol, const SGroupInfo *pInfo);
+      virtual CDasherNode *RebuildGroup(CAlphNode *pParent, int iBkgCol, const SGroupInfo *pInfo);
     protected:
       ///Override: true if pGroup encloses this one (by start/end symbol#)
       bool isInGroup(const SGroupInfo *pGroup);
@@ -206,11 +205,13 @@ namespace Dasher {
   public:
     ///
     /// Get a new root node owned by this manager
+    /// pContext - node from which to extract context (e.g. perhaps an un-seen node);
+    /// the new root is NOT made  a child, and initially has no parent.
     /// 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.)
     /// Note, the new node will _not_ be NF_SEEN
-    virtual CAlphNode *GetRoot(CDasherNode *pParent, unsigned int iLower, unsigned int iUpper, bool bEnteredLast, int iOffset);
+    virtual CAlphNode *GetRoot(CDasherNode *pContext, bool bEnteredLast, int iOffset);
 
     const CAlphInfo *GetAlphabet() const;
 
@@ -228,8 +229,8 @@ namespace Dasher {
 
     ///Called to create a node for a given symbol (leaf), as a child of a specified parent node
     /// \param iBkgCol colour behind the new node, i.e. that should show through if the (group) node is transparent
-    virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol);
-    virtual CGroupNode *CreateGroupNode(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, int iBkgCol, const SGroupInfo *pInfo);
+    virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, symbol iSymbol);
+    virtual CGroupNode *CreateGroupNode(CAlphNode *pParent, int iBkgCol, const SGroupInfo *pInfo);
 
     ///Called to compute colour for a symbol at a specified offset.
     /// Wraps CAlphabet::GetColour(sym), but (a) implements a default
diff --git a/Src/DasherCore/CannaConversionHelper.cpp b/Src/DasherCore/CannaConversionHelper.cpp
index e012564..5a55a08 100644
--- a/Src/DasherCore/CannaConversionHelper.cpp
+++ b/Src/DasherCore/CannaConversionHelper.cpp
@@ -15,7 +15,7 @@
 using namespace Dasher;
 
 CCannaConversionHelper::CCannaConversionHelper(CNodeCreationManager *pNCManager, const CAlphInfo *pAlphabet, int Type, int Order)
-: CConversionHelper(pNCManager, pAlphabet) {
+: CConversionManager(pNCManager, pAlphabet) {
 
   int ret;
   char *buf;
diff --git a/Src/DasherCore/CannaConversionHelper.h b/Src/DasherCore/CannaConversionHelper.h
index 7b28f58..53daa5c 100644
--- a/Src/DasherCore/CannaConversionHelper.h
+++ b/Src/DasherCore/CannaConversionHelper.h
@@ -3,13 +3,13 @@
 
 #define BUFSIZE 10240
 
-#include "ConversionHelper.h"
+#include "ConversionManager.h"
 #include <iconv.h>
 
 #include <iostream> 
 /// \ingroup Model
 /// @{
-class CCannaConversionHelper : public Dasher::CConversionHelper {
+class CCannaConversionHelper : public Dasher::CConversionManager {
  public:
   CCannaConversionHelper(CNodeCreationManager *pNCManager, Dasher::const CAlphInfo *pAlphabet, int Type, int Order);
   ~CCannaConversionHelper();
diff --git a/Src/DasherCore/ControlManager.cpp b/Src/DasherCore/ControlManager.cpp
index 9483bdb..48cc5ae 100644
--- a/Src/DasherCore/ControlManager.cpp
+++ b/Src/DasherCore/ControlManager.cpp
@@ -49,10 +49,16 @@ void CControlBase::SetRootTemplate(NodeTemplate *pRoot) {
   m_pRoot = pRoot;
 }
 
-CDasherNode *CControlBase::GetRoot(CDasherNode *pParent, unsigned int iLower, unsigned int iUpper, int iOffset) {
-  if (!m_pRoot) return m_pNCManager->GetAlphabetManager()->GetRoot(pParent, iLower, iUpper, false, iOffset);
+int CControlBase::getColour(NodeTemplate *pTemplate, CDasherNode *pParent) {
+  if (pTemplate->m_iColour!=-1) return  pTemplate->m_iColour;
+  if (pParent) return (pParent->ChildCount()%99)+11;
+  return 11;
+}
+
+CDasherNode *CControlBase::GetRoot(CDasherNode *pContext, int iOffset) {
+  if (!m_pRoot) return m_pNCManager->GetAlphabetManager()->GetRoot(pContext, false, iOffset);
 
-  CContNode *pNewNode = new CContNode(pParent, iOffset, iLower, iUpper, m_pRoot, this);
+  CContNode *pNewNode = new CContNode(iOffset, getColour(m_pRoot, pContext), m_pRoot, this);
 
   // FIXME - handle context properly
 
@@ -87,8 +93,8 @@ CControlBase::NodeTemplate::~NodeTemplate() {
   delete m_pLabel;
 }
 
-CControlBase::CContNode::CContNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, NodeTemplate *pTemplate, CControlBase *pMgr)
-: CDasherNode(pParent, iOffset, iLbnd, iHbnd, (pTemplate->m_iColour != -1) ? pTemplate->m_iColour : (pParent->ChildCount()%99)+11, pTemplate->m_pLabel), m_pTemplate(pTemplate), m_pMgr(pMgr) {
+CControlBase::CContNode::CContNode(int iOffset, int iColour, NodeTemplate *pTemplate, CControlBase *pMgr)
+: CDasherNode(iOffset, iColour, pTemplate->m_pLabel), m_pTemplate(pTemplate), m_pMgr(pMgr) {
 }
 
 void CControlBase::CContNode::PopulateChildren() {
@@ -105,12 +111,13 @@ void CControlBase::CContNode::PopulateChildren() {
     if( *it == NULL ) {
       // Escape back to alphabet
 
-      pNewNode = m_pMgr->m_pNCManager->GetAlphabetManager()->GetRoot(this, iLbnd, iHbnd, false, offset()+1);
+      pNewNode = m_pMgr->m_pNCManager->GetAlphabetManager()->GetRoot(this, false, offset()+1);
     }
     else {
 
-      pNewNode = new CContNode(this, offset(), iLbnd, iHbnd, *it, m_pMgr);
+      pNewNode = new CContNode(offset(), m_pMgr->getColour(*it, this), *it, m_pMgr);
     }
+    pNewNode->Reparent(this, iLbnd, iHbnd);
     iLbnd=iHbnd;
     DASHER_ASSERT(GetChildren().back()==pNewNode);
   }
diff --git a/Src/DasherCore/ControlManager.h b/Src/DasherCore/ControlManager.h
index 37c9beb..c3bcae9 100644
--- a/Src/DasherCore/ControlManager.h
+++ b/Src/DasherCore/ControlManager.h
@@ -60,7 +60,7 @@ namespace Dasher {
     class CContNode : public CDasherNode {
     public:
       CControlBase *mgr() {return m_pMgr;}
-      CContNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, NodeTemplate *pTemplate, CControlBase *pMgr);
+      CContNode(int iOffset, int iColour, NodeTemplate *pTemplate, CControlBase *pMgr);
 
       bool bShove() {return false;}
       ///
@@ -128,7 +128,7 @@ namespace Dasher {
     /// Get a new root node owned by this manager
     ///
 
-    virtual CDasherNode *GetRoot(CDasherNode *pParent, unsigned int iLower, unsigned int iUpper, int iOffset);
+    virtual CDasherNode *GetRoot(CDasherNode *pContext, int iOffset);
 
   protected:
     ///Sets the root - should be called by subclass constructor to make
@@ -138,6 +138,8 @@ namespace Dasher {
 
     CDasherInterfaceBase *m_pInterface;
     CNodeCreationManager *m_pNCManager;
+    
+    int getColour(NodeTemplate *pTemplate, CDasherNode *pParent);
 
   private:
     NodeTemplate *m_pRoot;
diff --git a/Src/DasherCore/ConversionManager.cpp b/Src/DasherCore/ConversionManager.cpp
index 01578ed..95ae78a 100644
--- a/Src/DasherCore/ConversionManager.cpp
+++ b/Src/DasherCore/ConversionManager.cpp
@@ -41,12 +41,8 @@
 using namespace Dasher;
 using namespace std;
 
-CConversionManager::CConversionManager(CDasherInterfaceBase *pInterface, CNodeCreationManager *pNCManager, const CAlphInfo *pAlphabet) {
-  m_pInterface = pInterface;
-  m_pNCManager = pNCManager;
-  m_pAlphabet = pAlphabet;
-
-  m_iRefCount = 1;
+CConversionManager::CConversionManager(CSettingsUser *pCreateFrom, CDasherInterfaceBase *pInterface, CNodeCreationManager *pNCManager, const CAlphInfo *pAlphabet, CLanguageModel *pLanguageModel)
+: CSettingsUser(pCreateFrom), m_pInterface(pInterface), m_pNCManager(pNCManager), m_pAlphabet(pAlphabet), m_pLanguageModel(pLanguageModel) {
 
   //Testing for alphabet details, delete if needed:
   /*
@@ -55,10 +51,19 @@ CConversionManager::CConversionManager(CDasherInterfaceBase *pInterface, CNodeCr
   for(int i =0; i<alphSize; i++)
     std::cout<<"symbol: "<<i<<"    display text:"<<pNCManager->GetAlphabet()->GetDisplayText(i)<<std::endl;
   */
+  colourStore[0][0]=66;//light blue
+  colourStore[0][1]=64;//very light green
+  colourStore[0][2]=62;//light yellow
+  colourStore[1][0]=78;//light purple
+  colourStore[1][1]=81;//brownish
+  colourStore[1][2]=60;//red
+  
+  m_iLearnContext = m_pLanguageModel->CreateEmptyContext();
+
 }
 
-CConversionManager::CConvNode *CConversionManager::makeNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel) {
-  return new CConvNode(pParent, iOffset, iLbnd, iHbnd, iColour, pLabel, this);
+CConversionManager::CConvNode *CConversionManager::makeNode(int iOffset, int iColour, CDasherScreen::Label *pLabel) {
+  return new CConvNode(iOffset, iColour, pLabel, this);
 }
 
 void CConversionManager::ChangeScreen(CDasherScreen *pScreen) {
@@ -76,51 +81,28 @@ CDasherScreen::Label *CConversionManager::GetLabel(const char *pszConversion) {
   return m_vLabels[strConv] = m_pScreen->MakeLabel(strConv);
 }
 
-CConversionManager::CConvNode *CConversionManager::GetRoot(CDasherNode *pParent, unsigned int iLower, unsigned int iUpper, int iOffset) {
+CConversionManager::CConvNode *CConversionManager::GetRoot(int iOffset, CLanguageModel::Context newCtx) {
 
   // TODO: Parameters here are placeholders - need to figure out what's right
 
   //TODO: hard-coded colour, and hard-coded displaytext... (ACL: read from Alphabet -> startConversionSymbol ?)
-  CConvNode *pNewNode = makeNode(pParent, iOffset, iLower, iUpper, 9, NULL);
-
-  // FIXME - handle context properly
-  // TODO: Reimplemnt -----
-  //  pNewNode->SetContext(m_pLanguageModel->CreateEmptyContext());
-  // -----
+  CConvNode *pNewNode = makeNode(iOffset, 9, NULL);
 
+  pNewNode->iContext = newCtx;
 
   pNewNode->bisRoot = true;
 
-  pNewNode->pLanguageModel = NULL;
-
   pNewNode->pSCENode = 0;
 
   return pNewNode;
 }
 
-CConversionManager::CConvNode::CConvNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel, CConversionManager *pMgr)
- : CDasherNode(pParent, iOffset, iLbnd, iHbnd, iColour, pLabel), m_pMgr(pMgr) {
-  pMgr->m_iRefCount++;
-}
-
-void CConversionManager::CConvNode::PopulateChildren() {
-  DASHER_ASSERT(m_pMgr->m_pNCManager);
-
-  // 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.
-  //
-  CDasherNode *pNewNode = m_pMgr->m_pNCManager->GetAlphabetManager()->GetRoot(this, 0, CDasherModel::NORMALIZATION, false, offset() + 1);
-
-  DASHER_ASSERT(GetChildren().back()==pNewNode);
-}
-int CConversionManager::CConvNode::ExpectedNumChildren() {
-  return 1; //the alphabet root
+CConversionManager::CConvNode::CConvNode(int iOffset, int iColour, CDasherScreen::Label *pLabel, CConversionManager *pMgr)
+ : CDasherNode(iOffset, iColour, pLabel), m_pMgr(pMgr) {
 }
 
 CConversionManager::CConvNode::~CConvNode() {
-  pLanguageModel->ReleaseContext(iContext);
-  m_pMgr->Unref();
+  m_pMgr->m_pLanguageModel->ReleaseContext(iContext);
 }
 
 void CConversionManager::RecursiveDumpTree(ostream &out, SCENode *pCurrent, unsigned int iDepth) {
@@ -186,3 +168,136 @@ void CConversionManager::CConvNode::Undo() {
     m_pMgr->m_pInterface->editDelete(bisRoot ? ">" : "|", this);
   }
 }
+
+// TODO: This function needs to be significantly tidied up
+// TODO: get rid of pSizes
+
+void CConversionManager::AssignChildSizes(const std::vector<SCENode *> &nodes, CLanguageModel::Context context) {
+  
+  AssignSizes(nodes, context, CDasherModel::NORMALIZATION, GetLongParameter(LP_UNIFORM));
+  
+}
+
+void CConversionManager::CConvNode::PopulateChildren() {
+  DASHER_ASSERT(mgr()->m_pNCManager);
+  
+  // Do the conversion and build the tree (lattice) if it hasn't been
+  // done already.
+  //
+  
+  
+  if(bisRoot && !pSCENode) {
+    mgr()->BuildTree(this);
+  }
+  
+  
+  if(pSCENode && !pSCENode->GetChildren().empty()) {
+    const std::vector<SCENode *> &vChildren = pSCENode->GetChildren();
+    //    RecursiveDumpTree(pSCENode, 1);
+    mgr()->AssignChildSizes(vChildren, iContext);
+    
+    int iIdx(0);
+    int iCum(0);
+    
+    //    int parentClr = pNode->Colour();
+    // TODO: Fixme
+    int parentClr = 0;
+    
+    // Finally loop through and create the children
+    
+    for (std::vector<SCENode *>::const_iterator it = vChildren.begin(); it!=vChildren.end(); it++) {
+      //      std::cout << "Current scec: " << pCurrentSCEChild << std::endl;
+      SCENode *pCurrentSCEChild(*it);
+      DASHER_ASSERT(pCurrentSCEChild != NULL);
+      unsigned int iLbnd(iCum);
+      unsigned int iHbnd(iCum + pCurrentSCEChild->NodeSize);
+      //CDasherModel::NORMALIZATION);//
+      
+      iCum = iHbnd;
+      
+      // TODO: Parameters here are placeholders - need to figure out
+      // what's right
+      
+      //  std::cout << "#" << pCurrentSCEChild->pszConversion << "#" << std::endl;
+      
+      CConvNode *pNewNode = mgr()->makeNode(offset()+1, mgr()->AssignColour(parentClr, pCurrentSCEChild, iIdx), mgr()->GetLabel(pCurrentSCEChild->pszConversion));
+
+      // TODO: Reimplement ----
+
+      // FIXME - handle context properly
+      //      pNewNode->SetContext(m_pLanguageModel->CreateEmptyContext());
+      // -----
+
+      pNewNode->bisRoot = false;
+      pNewNode->pSCENode = pCurrentSCEChild;
+
+      pNewNode->iContext = mgr()->m_pLanguageModel->CloneContext(this->iContext);
+
+      if(pCurrentSCEChild ->Symbol !=-1)
+        mgr()->m_pLanguageModel->EnterSymbol(pNewNode->iContext, pCurrentSCEChild->Symbol); // TODO: Don't use symbols?
+
+      pNewNode->Reparent(this, iLbnd, iHbnd);
+
+      ++iIdx;
+    }
+    
+  }
+  else {//End of conversion -> default to alphabet
+    
+    //Phil//
+    // TODO: Placeholder algorithm here
+    // TODO: Add an 'end of conversion' node?
+    //ACL 1/12/09 Note that this adds one to the m_iOffset of the created node
+    // (whereas code that was once here did not, but was otherwise identical...)
+    CDasherNode *pNewNode = m_pMgr->m_pNCManager->GetAlphabetManager()->GetRoot(this, false, offset() + 1);
+    pNewNode->Reparent(this, 0, CDasherModel::NORMALIZATION);
+  }
+}
+
+int CConversionManager::CConvNode::ExpectedNumChildren() {
+  if(bisRoot && !pSCENode) mgr()->BuildTree(this);
+  if (pSCENode && !pSCENode->GetChildren().empty()) return pSCENode->GetChildren().size();
+  return 1;//Alphabet root
+}
+
+void CConversionManager::BuildTree(CConvNode *pRoot) {
+  // Build the string to convert.
+  std::string strCurrentString;
+  // Search backwards but stop at any conversion node.
+  for (CDasherNode *pNode = pRoot->Parent();
+       pNode && pNode->mgr() == this;
+       pNode = pNode->Parent()) {
+    
+    // TODO: Need to make this the edit text rather than the display text
+    strCurrentString =
+    m_pAlphabet->GetText(pNode->GetAlphSymbol())
+    + strCurrentString;
+  }
+  // Handle/store the result.
+  SCENode *pStartTemp;
+  Convert(strCurrentString, &pStartTemp);
+  
+  // Store all conversion trees (SCENode trees) in the pUserData->pSCENode
+  // of each Conversion Root.
+  
+  pRoot->pSCENode = pStartTemp;
+}
+
+void CConversionManager::CConvNode::SetFlag(int iFlag, bool bValue) {
+  CDasherNode::SetFlag(iFlag, bValue);
+  switch(iFlag) {
+    case NF_COMMITTED:
+      if(bValue){
+        
+        if(!pSCENode)
+          return;
+        
+        symbol s =pSCENode ->Symbol;
+        
+        
+        if(s!=-1)
+          mgr()->m_pLanguageModel->LearnSymbol(mgr()->m_iLearnContext, s);
+      }
+      break;
+  }
+}
diff --git a/Src/DasherCore/ConversionManager.h b/Src/DasherCore/ConversionManager.h
index 8758cb6..ccd3e4f 100644
--- a/Src/DasherCore/ConversionManager.h
+++ b/Src/DasherCore/ConversionManager.h
@@ -60,41 +60,35 @@ namespace Dasher {
   /// aspects of conversion, and CNodeManager for details of the node
   /// management process.
   ///
-  class CConversionManager : public CNodeManager {
+  class CConversionManager : protected CSettingsUser, public CNodeManager {
+    friend class CConvertingAlphMgr;
+  protected:  class CConvNode; //fwd decl
   public:
-    CConversionManager(CDasherInterfaceBase *pInterface, CNodeCreationManager *pNCManager, const CAlphInfo *pAlphabet);
+    CConversionManager(CSettingsUser *pCreateFrom, CDasherInterfaceBase *pInterface, CNodeCreationManager *pNCManager, const CAlphInfo *pAlphabet, CLanguageModel *pLanguageModel);
+
+    ///
+    /// Get a new root node owned by this manager
+    ///
+    
+    virtual CConvNode *GetRoot(int iOffset, CLanguageModel::Context newCtx);
 
     ///Tells us to use the specified screen to create node labels.
     /// (note we cache the screen and create labels lazily)
     void ChangeScreen(CDasherScreen *pScreen);
     
-    ///
-    /// Decrement reference count
-    ///
-
-    virtual void Unref() {
-      --m_iRefCount;
-
-
-      //      std::cout << "Unref, new count = " << m_iRefCount << std::endl;
-
-      if(m_iRefCount == 0) {
-	//	std::cout << "Deleting " << this << std::endl;
-	delete this;
-      }
-    };
-
-    protected:
+  protected:
+    
     class CConvNode : public CDasherNode {
     public:
       CConversionManager *mgr() {return m_pMgr;}
-      CConvNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel, CConversionManager *pMgr);
+      CConvNode(int iOffset, int iColour, CDasherScreen::Label *pLabel, CConversionManager *pMgr);
     ///
     /// Provide children for the supplied node
     ///
 
     virtual void PopulateChildren();
     virtual int ExpectedNumChildren();
+      virtual void SetFlag(int iFlag, bool bValue);
 
     ~CConvNode();
 
@@ -121,24 +115,15 @@ namespace Dasher {
     //TODO: REVISE
       symbol iSymbol;
       //     int iPhase;
-      CLanguageModel *pLanguageModel;
       CLanguageModel::Context iContext;
       SCENode * pSCENode;
       bool bisRoot; // True for root conversion nodes
       //int iGameOffset;
     };
 
-  public:
-    ///
-    /// Get a new root node owned by this manager
-    ///
-
-    virtual CConvNode *GetRoot(CDasherNode *pParent, unsigned int iLower, unsigned int iUpper, int iOffset);
-  protected:
-
-    virtual CConvNode *makeNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel);
+    virtual CConvNode *makeNode(int iOffset, int iColour, CDasherScreen::Label *pLabel);
 
-  CDasherInterfaceBase *m_pInterface;
+    CDasherInterfaceBase *m_pInterface;
 	CNodeCreationManager *m_pNCManager;
 	const CAlphInfo *m_pAlphabet;
 	
@@ -146,6 +131,73 @@ namespace Dasher {
     /// \return a node label displaying the specified string
     CDasherScreen::Label *GetLabel(const char *pszConversion);
     
+    /// Convert a given string to a lattice of candidates. Sizes for
+	/// candidates aren't assigned at this point. The input string
+	/// should be UTF-8 encoded.
+	///
+	/// @param strSource UTF-8 encoded input string.
+	/// @param pRoot Used to return the root of the conversion lattice.
+	/// @param childCount Unsure - document this.
+	/// @param CMid A unique identifier for the conversion helper 'context'.
+	///
+	/// @return True if conversion succeeded, false otherwise
+	virtual bool Convert(const std::string &strSource, SCENode ** pRoot) = 0;
+    
+	/// Assign sizes to the children of a given conversion node. This
+	/// happens when the conversion manager populates the children of
+	/// the Dasher node so as to avoid unnecessary computation.
+	///
+	/// @param pStart The parent of the nodes to be sized.
+	/// @param context Unsure - document this, shouldn't be in general class (include userdata pointer).
+	/// @param normalization Normalisation constant for the child sizes (TODO: check that this is a sensible value, ie the same as Dasher normalisation).
+	/// @param uniform Unsure - document this.
+	///
+    virtual void AssignSizes(const std::vector<SCENode *> &vChildren, Dasher::CLanguageModel::Context context, long normalization, int uniform)=0;
+    
+	/// Assign colours to the children of a given conversion node.
+	/// This function needs a rethink.
+	///
+	/// @param parentClr
+	/// @param pNode
+	/// @param childIndex
+	///
+	/// @return
+	///
+	virtual int AssignColour(int parentClr, SCENode * pNode, int childIndex) {
+      int which = -1;
+      
+      for (int i=0; i<2; i++)
+        for(int j=0; j<3; j++)
+          if (parentClr == colourStore[i][j])
+            which = i;
+      
+      if(which == -1)
+        return colourStore[0][childIndex%3];
+      else if(which == 0)
+        return colourStore[1][childIndex%3];
+      else
+        return colourStore[0][childIndex%3];
+	};
+    
+    ///
+    /// Calculate sizes for each of the children - default
+    /// implementation assigns decending probabilities in a power law
+    /// fashion (so assumes ordering), but specific subclasses are
+    /// free to implement their own behaviour. The only restriction is
+    /// that sizes should be positive and sum to the appropriate
+    /// normalisation constant
+    ///
+    
+    virtual void AssignChildSizes(const std::vector<SCENode *> &vChildren, CLanguageModel::Context context);
+    
+    ///
+    /// Build the conversion tree (lattice) for the given string -
+    /// evaluated late to prevent unnecessary conversions when the
+    /// children of the root node are never instantiated
+    ///
+    
+    virtual void BuildTree(CConvNode *pRoot);
+
   private:
 
     std::map<std::string, CDasherScreen::Label *> m_vLabels;
@@ -157,11 +209,11 @@ namespace Dasher {
 
     void RecursiveDumpTree(std::ostream &out, SCENode *pCurrent, unsigned int iDepth);
 
-	///
-	/// Reference count
-	///
-
-    int m_iRefCount;
+    CLanguageModel *m_pLanguageModel;
+    
+    CLanguageModel::Context m_iLearnContext;
+    
+	int colourStore[2][3];
 
   };
   /// @}
diff --git a/Src/DasherCore/ConvertingAlphMgr.cpp b/Src/DasherCore/ConvertingAlphMgr.cpp
index 4838ba5..8574bca 100644
--- a/Src/DasherCore/ConvertingAlphMgr.cpp
+++ b/Src/DasherCore/ConvertingAlphMgr.cpp
@@ -21,19 +21,28 @@ void CConvertingAlphMgr::MakeLabels(CDasherScreen *pScreen) {
   m_pConvMgr->ChangeScreen(pScreen);
 }
 
-
 CConvertingAlphMgr::~CConvertingAlphMgr() {
-  m_pConvMgr->Unref();
 }
 
-CDasherNode *CConvertingAlphMgr::CreateSymbolNode(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol) {
+CDasherNode *CConvertingAlphMgr::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol) {
   int i=m_pAlphabet->GetNumberTextSymbols()+1;
   if (iSymbol == i) {
     vector<unsigned int> *pCProb(pParent->GetProbInfo());
     DASHER_ASSERT(pCProb->size() == m_pAlphabet->GetNumberTextSymbols()+2);//initial 0, final conversion prob
+
+    //this used to be the "CloneAlphContext" method. Why it uses the
+    // ConversionManager's LM to clone a context from an Alphabet Node,
+    // I don't know - not sure how LanguageModelling WRT conversion
+    // is supposed to work...
+    CLanguageModel::Context iContext = (pParent->iContext)
+      ? m_pConvMgr->m_pLanguageModel->CloneContext(pParent->iContext)
+      : m_pConvMgr->m_pLanguageModel->CreateEmptyContext(); 
+
     //ACL setting m_iOffset+1 for consistency with "proper" symbol nodes...
-    return m_pConvMgr->GetRoot(pParent, (*pCProb)[i-1], (*pCProb)[i], pParent->offset()+1);
+    return m_pConvMgr->GetRoot(pParent->offset()+1, iContext);
+    //Note: previous code used (*pCProb)[i-1] and (*pCProb)[i] instead of
+    // iLbnd and iHbnd passed in; presumably these must have been the same?
   } else {
-    return CAlphabetManager::CreateSymbolNode(pParent, iLbnd, iHbnd, iSymbol);
+    return CAlphabetManager::CreateSymbolNode(pParent, iSymbol);
   }
 }
diff --git a/Src/DasherCore/ConvertingAlphMgr.h b/Src/DasherCore/ConvertingAlphMgr.h
index e3a9a68..c1760ce 100644
--- a/Src/DasherCore/ConvertingAlphMgr.h
+++ b/Src/DasherCore/ConvertingAlphMgr.h
@@ -28,7 +28,7 @@ namespace Dasher {
     virtual ~CConvertingAlphMgr();
   protected:
     ///Override to return a conversion root for iSymbol==(one beyond last alphabet symbol)
-    virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol);
+    virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, symbol iSymbol);
   private:
     CConversionManager *m_pConvMgr;
     
diff --git a/Src/DasherCore/DasherCore_vc80.vcproj b/Src/DasherCore/DasherCore_vc80.vcproj
index 7bb6e87..d55e5e9 100644
--- a/Src/DasherCore/DasherCore_vc80.vcproj
+++ b/Src/DasherCore/DasherCore_vc80.vcproj
@@ -1759,14 +1759,6 @@
 			>
 		</File>
 		<File
-			RelativePath=".\ConversionHelper.cpp"
-			>
-		</File>
-		<File
-			RelativePath=".\ConversionHelper.h"
-			>
-		</File>
-		<File
 			RelativePath=".\ConversionManager.cpp"
 			>
 		</File>
diff --git a/Src/DasherCore/DasherModel.cpp b/Src/DasherCore/DasherModel.cpp
index b3ed700..4282f56 100644
--- a/Src/DasherCore/DasherModel.cpp
+++ b/Src/DasherCore/DasherModel.cpp
@@ -204,26 +204,11 @@ void CDasherModel::SetOffset(int iOffset, CAlphabetManager *pMgr, CDasherView *p
   if (m_Root && iOffset == GetOffset() && !bForce) return;
 
   if (m_pLastOutput) m_pLastOutput->Leave();
-
+  AbortOffset();
   ClearRootQueue();
   delete m_Root;
 
-  m_Root = pMgr->GetRoot(NULL, 0, NORMALIZATION, iOffset!=0, iOffset);
-  if (iOffset) {
-    //there were preceding characters. It's nonetheless possible that they weren't
-    // part of the current alphabet, and so we may have got a simple group node as root,
-    // rather than a character node (responsible for the last said preceding character),
-    // but even so, it seems fair enough to say we've "seen" the root:
-    m_Root->SetFlag(NF_SEEN, true);
-    m_Root->Enter();
-    // (of course, we don't do Output() - the context contains it already!)
-    m_pLastOutput = m_Root;
-
-    //We also want to avoid training the LM on nodes representing already-written context
-    m_Root->SetFlag(NF_COMMITTED, true);
-
-  } else
-    m_pLastOutput = NULL;
+  m_Root = pMgr->GetRoot(NULL, iOffset!=0, iOffset);
   if (GetBoolParameter(BP_GAME_MODE)) m_Root->SetFlag(NF_GAME, true);
 
   // Create children of the root...
@@ -231,6 +216,9 @@ void CDasherModel::SetOffset(int iOffset, CAlphabetManager *pMgr, CDasherView *p
 
   // Set the root coordinates so that the root node is an appropriate
   // size and we're not in any of the children
+  m_Root->Enter(); //(but we are in the node itself)
+  m_Root->SetFlag(NF_SEEN, true);
+  m_pLastOutput = m_Root;
 
   double dFraction( 1 - (1 - m_Root->MostProbableChild() / static_cast<double>(NORMALIZATION)) / 2.0 );
 
@@ -242,8 +230,6 @@ void CDasherModel::SetOffset(int iOffset, CAlphabetManager *pMgr, CDasherView *p
 
   m_Rootmin = MAX_Y / 2 - iWidth / 2;
   m_Rootmax = MAX_Y / 2 + iWidth / 2;
-
-  m_iDisplayOffset = 0;
 }
 
 int CDasherModel::GetOffset() {
diff --git a/Src/DasherCore/DasherNode.cpp b/Src/DasherCore/DasherNode.cpp
index b0bd452..28023c5 100644
--- a/Src/DasherCore/DasherNode.cpp
+++ b/Src/DasherCore/DasherNode.cpp
@@ -42,15 +42,8 @@ static int iNumNodes = 0;
 int Dasher::currentNumNodeObjects() {return iNumNodes;}
 
 //TODO this used to be inline - should we make it so again?
-CDasherNode::CDasherNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel)
-: m_pParent(pParent), m_iFlags(DEFAULT_FLAGS), onlyChildRendered(NULL), m_iLbnd(iLbnd), m_iHbnd(iHbnd), m_iOffset(iOffset), m_iColour(iColour), m_pLabel(pLabel) {
-  DASHER_ASSERT(iHbnd >= iLbnd);
-
-  if (pParent) {
-    DASHER_ASSERT(!pParent->GetFlag(NF_ALLCHILDREN));
-    pParent->Children().push_back(this);
-  }
-
+CDasherNode::CDasherNode(int iOffset, int iColour, CDasherScreen::Label *pLabel)
+: m_pParent(NULL), m_iFlags(DEFAULT_FLAGS), onlyChildRendered(NULL), m_iLbnd(0), m_iHbnd(CDasherModel::NORMALIZATION), m_iOffset(iOffset), m_iColour(iColour), m_pLabel(pLabel) {
   iNumNodes++;
 }
 
@@ -94,21 +87,6 @@ void CDasherNode::GetContext(CDasherInterfaceBase *pInterface, const CAlphabetMa
   }
 }
 
-CDasherNode *const CDasherNode::Get_node_under(int iNormalization, myint miY1, myint miY2, myint miMousex, myint miMousey) {
-  myint miRange = miY2 - miY1;
-
-  ChildMap::const_iterator i;
-  for(i = GetChildren().begin(); i != GetChildren().end(); i++) {
-    CDasherNode *pChild = *i;
-
-    myint miNewy1 = miY1 + (miRange * pChild->m_iLbnd) / iNormalization;
-    myint miNewy2 = miY1 + (miRange * pChild->m_iHbnd) / iNormalization;
-    if(miMousey < miNewy2 && miMousey > miNewy1 && miMousex < miNewy2 - miNewy1)
-      return pChild->Get_node_under(iNormalization, miNewy1, miNewy2, miMousex, miMousey);
-  }
-  return this;
-}
-
 // kill ourselves and all other children except for the specified
 // child
 // FIXME this probably shouldn't be called after history stuff is working
@@ -166,11 +144,15 @@ void CDasherNode::SetFlag(int iFlag, bool bValue) {
     m_iFlags = m_iFlags & (~iFlag);
 }
 
-void CDasherNode::SetParent(CDasherNode *pNewParent) {
+void CDasherNode::Reparent(CDasherNode *pNewParent, unsigned int iLbnd, unsigned int iHbnd) {
+  DASHER_ASSERT(!m_pParent);
   DASHER_ASSERT(pNewParent);
   DASHER_ASSERT(!pNewParent->GetFlag(NF_ALLCHILDREN));
+  DASHER_ASSERT(iLbnd == (pNewParent->GetChildren().empty() ? 0 : pNewParent->GetChildren().back()->m_iHbnd));
   m_pParent = pNewParent;
   pNewParent->Children().push_back(this);
+  m_iLbnd = iLbnd;
+  m_iHbnd = iHbnd;
 }
 
 int CDasherNode::MostProbableChild() {
diff --git a/Src/DasherCore/DasherNode.h b/Src/DasherCore/DasherNode.h
index b48cfb5..511d042 100644
--- a/Src/DasherCore/DasherNode.h
+++ b/Src/DasherCore/DasherNode.h
@@ -104,13 +104,15 @@ class Dasher::CDasherNode:private NoClones {
 
   /// @brief Constructor
   ///
-  /// Note the flags of the new node are initialized to DEFAULT_FLAGS.
+  /// Note the flags of the new node are initialized to DEFAULT_FLAGS,
+  /// and the node has no parent, and range 0-CDasherModel::NORMALIZATION:
+  /// caller will likely want to change these via a call to Reparent().
   ///
   /// \param pParent Parent of the new node; automatically adds to end of parent's child list
   /// \param iOffset Index into text buffer of character to LHS of cursor _after_ this node is Output().
   /// \param iColour background colour of node (for transparent nodes, same colour as parent)
   /// \param pLabel label to render onto node, NULL if no label required.
-  CDasherNode(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, int iColour, CDasherScreen::Label *pLabel);
+  CDasherNode(int iOffset, int iColour, CDasherScreen::Label *pLabel);
 
   /// @brief Destructor
   ///
@@ -165,13 +167,6 @@ class Dasher::CDasherNode:private NoClones {
   ///
   inline unsigned int Range() const;
 
-  /// @brief Reset the range of a node
-  ///
-  /// @param iLower New lower bound
-  /// @param iUpper New upper bound
-  ///
-  inline void SetRange(unsigned int iLower, unsigned int iUpper);
-
   /// @brief Get the size of the most probable child
   ///
   /// @return The size
@@ -185,10 +180,13 @@ class Dasher::CDasherNode:private NoClones {
   inline const ChildMap & GetChildren() const;
   inline unsigned int ChildCount() const;
   inline CDasherNode *Parent() const;
-  void SetParent(CDasherNode *pNewParent);
-  // TODO: Should this be here?
-  CDasherNode *const Get_node_under(int, myint y1, myint y2, myint smousex, myint smousey);   // find node under given co-ords
-
+  
+  /// Makes the node be the child of a new parent, and set its range amongst
+  /// that parent's children. This node will be positioned AFTER any/all
+  /// existing children of the new parent; so TODO - iLower redundant?
+  /// Before the call is made, the (child) node must have no parent.
+  void Reparent(CDasherNode *pNewParent, unsigned int iLower, unsigned int iUpper);
+  
   /// @brief Orphan a child of this node
   ///
   /// Deletes all other children, and the node itself
@@ -268,12 +266,6 @@ class Dasher::CDasherNode:private NoClones {
   ///
   virtual bool GameSearchNode(symbol sym) {return false;}
 
-  /// Clone the context of the specified node, if it's an alphabet node;
-  /// else return an empty context. (Used by ConversionManager)
-  virtual CLanguageModel::Context CloneAlphContext(CLanguageModel *pLanguageModel) {
-    return pLanguageModel->CreateEmptyContext();
-  };
-
   virtual symbol GetAlphSymbol() {
     throw "Hack for pre-MandarinDasher ConversionManager::BuildTree method, needs to access CAlphabetManager-private struct";
   }
@@ -344,9 +336,5 @@ inline CDasherNode *CDasherNode::Parent() const {
   return m_pParent;
 }
 
-inline void CDasherNode::SetRange(unsigned int iLower, unsigned int iUpper) {
-  m_iLbnd = iLower;
-  m_iHbnd = iUpper;
-}
 }
 #endif /* #ifndef __DasherNode_h__ */
diff --git a/Src/DasherCore/IMEConversionHelper.cpp b/Src/DasherCore/IMEConversionHelper.cpp
index f386d67..e8cfb89 100644
--- a/Src/DasherCore/IMEConversionHelper.cpp
+++ b/Src/DasherCore/IMEConversionHelper.cpp
@@ -8,7 +8,7 @@
 #include <iostream>             //For testing 23 June 2005
 
 CIMEConversionHelper::CIMEConversionHelper(Dasher::CNodeCreationManager *pNCManager, Dasher::const CAlphInfo *pAlphabet)
- : CConversionHelper(pNCManager, pAlphabet) {
+ : CConversionManager(pNCManager, pAlphabet) {
   IsInit = 0;
   hIMC = ImmCreateContext();
   IsInit = 1;
diff --git a/Src/DasherCore/IMEConversionHelper.h b/Src/DasherCore/IMEConversionHelper.h
index 20ae7c0..1f4832b 100644
--- a/Src/DasherCore/IMEConversionHelper.h
+++ b/Src/DasherCore/IMEConversionHelper.h
@@ -4,10 +4,10 @@
 #include <windows.h>
 #include <imm.h>
 
-#include "ConversionHelper.h"
+#include "ConversionManager.h"
 /// \ingroup Model
 /// \{
-class CIMEConversionHelper : public CConversionHelper {
+class CIMEConversionHelper : public CConversionManager {
  public:
   CIMEConversionHelper(CNodeCreationManager *pNCManager, const CAlphInfo *pAlphabet);
   ~CIMEConversionHelper();
diff --git a/Src/DasherCore/Makefile.am b/Src/DasherCore/Makefile.am
index c4aff81..2b33044 100644
--- a/Src/DasherCore/Makefile.am
+++ b/Src/DasherCore/Makefile.am
@@ -40,8 +40,6 @@ libdashercore_a_SOURCES = \
 		CompassMode.h \
 		ControlManager.cpp \
 		ControlManager.h \
-		ConversionHelper.cpp \
-		ConversionHelper.h \
 		ConversionManager.cpp \
 		ConversionManager.h \
 		ConvertingAlphMgr.cpp \
diff --git a/Src/DasherCore/MandarinAlphMgr.cpp b/Src/DasherCore/MandarinAlphMgr.cpp
index 82adc6b..faa314f 100644
--- a/Src/DasherCore/MandarinAlphMgr.cpp
+++ b/Src/DasherCore/MandarinAlphMgr.cpp
@@ -147,11 +147,12 @@ CAlphabetManager::CAlphNode *CMandarinAlphMgr::GetRoot(CDasherNode *pParent, uns
 
   CAlphNode *pNewNode;
   if (p.first==0 || !bEnteredLast) {
-    pNewNode = new CGroupNode(pParent, iNewOffset, iLower, iUpper, NULL, 0, this, NULL);
+    pNewNode = new CGroupNode(iNewOffset, NULL, 0, this, NULL);
   } else {
     DASHER_ASSERT(p.first>0 && p.first<m_CHtext.size());
-    pNewNode = new CMandSym(pParent, iNewOffset, iLower, iUpper, this, p.first, 0);
+    pNewNode = new CMandSym(iNewOffset, this, p.first, 0);
   }
+  pNewNode->Reparent(pParent, iLower, iUpper);
   pNewNode->iContext = p.second;
   
   return pNewNode;
@@ -175,7 +176,7 @@ int CMandarinAlphMgr::GetCHColour(symbol CHsym, int iOffset) const {
   return iColour;
 }
 
-CDasherNode *CMandarinAlphMgr::CreateSymbolNode(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol) {
+CDasherNode *CMandarinAlphMgr::CreateSymbolNode(CAlphNode *pParent, symbol iSymbol) {
   
   //For every PY symbol (=syllable+tone, or "punctuation"),
   // m_pConversionsBySymbol identifies the possible chinese-alphabet symbols
@@ -183,24 +184,24 @@ CDasherNode *CMandarinAlphMgr::CreateSymbolNode(CAlphNode *pParent, unsigned int
   // punctuation character in the chinese alphabet). A CConvRoot thus offers a choice between them...
   
   if (m_pConversionsBySymbol[iSymbol].size()>1)
-    return CreateConvRoot(pParent, iLbnd, iHbnd, iSymbol);
+    return CreateConvRoot(pParent, iSymbol);
   
-  return CreateCHSymbol(pParent,pParent->iContext, iLbnd, iHbnd, *(m_pConversionsBySymbol[iSymbol].begin()), iSymbol);
+  return CreateCHSymbol(pParent,pParent->iContext, *(m_pConversionsBySymbol[iSymbol].begin()), iSymbol);
 }
 
-CMandarinAlphMgr::CConvRoot *CMandarinAlphMgr::CreateConvRoot(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iPYsym) {
+CMandarinAlphMgr::CConvRoot *CMandarinAlphMgr::CreateConvRoot(CAlphNode *pParent, symbol iPYsym) {
   
   // the same offset as we've still not entered/selected a symbol (leaf);
   // Colour is always 9 so ignore iBkgCol
-  CConvRoot *pConv = new CConvRoot(pParent, pParent->offset(), iLbnd, iHbnd, this, iPYsym);
+  CConvRoot *pConv = new CConvRoot(pParent->offset(), this, iPYsym);
     
   // and use the same context too (pinyin syll+tone is _not_ used as part of the LM context)
   pConv->iContext = m_pLanguageModel->CloneContext(pParent->iContext);
   return pConv;
 }
 
-CMandarinAlphMgr::CConvRoot::CConvRoot(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, CMandarinAlphMgr *pMgr, symbol pySym)
-: CAlphBase(pParent, iOffset, iLbnd, iHbnd, 9, NULL, pMgr), m_pySym(pySym) {
+CMandarinAlphMgr::CConvRoot::CConvRoot(int iOffset, CMandarinAlphMgr *pMgr, symbol pySym)
+: CAlphBase(iOffset, 9, NULL, pMgr), m_pySym(pySym) {
   DASHER_ASSERT(pMgr->m_pConversionsBySymbol[pySym].size()>1);
   //colour + label from ConversionManager.
 }
@@ -227,32 +228,27 @@ void CMandarinAlphMgr::CConvRoot::PopulateChildrenWithExisting(CMandSym *existin
     
     iCum = iHbnd;
     CMandSym *pNewNode = (existing)
-      ? existing->RebuildCHSymbol(this, iLbnd, iHbnd, it->first)
-      : mgr()->CreateCHSymbol(this, this->iContext, iLbnd, iHbnd, it->first, m_pySym);
-    
-    DASHER_ASSERT(GetChildren().back()==pNewNode);
+      ? existing->RebuildCHSymbol(this, it->first)
+      : mgr()->CreateCHSymbol(this, this->iContext, it->first, m_pySym);
+    pNewNode->Reparent(this, iLbnd, iHbnd);
   }
 }
 
-CMandarinAlphMgr::CMandSym *CMandarinAlphMgr::CreateCHSymbol(CDasherNode *pParent, CLanguageModel::Context iContext, unsigned int iLbnd, unsigned int iHbnd, symbol iCHsym, symbol iPYparent) {
+CMandarinAlphMgr::CMandSym *CMandarinAlphMgr::CreateCHSymbol(CDasherNode *pParent, CLanguageModel::Context iContext, symbol iCHsym, symbol iPYparent) {
   // TODO: Parameters here are placeholders - need to figure out
   // what's right 
 
   int iNewOffset = pParent->offset()+1;
   if (m_CHtext[iCHsym] == "\r\n") iNewOffset++;
-  CMandSym *pNewNode = new CMandSym(pParent, iNewOffset, iLbnd, iHbnd, this, iCHsym, iPYparent);
+  CMandSym *pNewNode = new CMandSym(iNewOffset, this, iCHsym, iPYparent);
   pNewNode->iContext = m_pLanguageModel->CloneContext(iContext);
   m_pLanguageModel->EnterSymbol(pNewNode->iContext, iCHsym);
   return pNewNode;
 }
 
-CDasherNode *CMandarinAlphMgr::CConvRoot::RebuildSymbol(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSym) {
-  if (iSym == m_pySym) {
-    SetParent(pParent);
-    SetRange(iLbnd,iHbnd);
-    return this;
-  }
-  return CAlphBase::RebuildSymbol(pParent, iLbnd, iHbnd, iSym);
+CDasherNode *CMandarinAlphMgr::CConvRoot::RebuildSymbol(CAlphNode *pParent, symbol iSym) {
+  if (iSym == m_pySym) return this;
+  return CAlphBase::RebuildSymbol(pParent, iSym);
 }
 
 bool CMandarinAlphMgr::CConvRoot::isInGroup(const SGroupInfo *pGroup) {
@@ -359,26 +355,24 @@ CDasherScreen::Label *CMandarinAlphMgr::GetLabel(int iCHsym) {
   return m_vLabels[iCHsym] = m_pScreen->MakeLabel(m_CHdisplayText[iCHsym]);
 }
 
-CMandarinAlphMgr::CMandSym::CMandSym(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, CMandarinAlphMgr *pMgr, symbol iSymbol, symbol pyParent)
-: CSymbolNode(pParent, iOffset, iLbnd, iHbnd, pMgr->GetCHColour(iSymbol,iOffset), pMgr->GetLabel(iSymbol), pMgr, iSymbol), m_pyParent(pyParent) {
+CMandarinAlphMgr::CMandSym::CMandSym(int iOffset, CMandarinAlphMgr *pMgr, symbol iSymbol, symbol pyParent)
+: CSymbolNode(iOffset, pMgr->GetCHColour(iSymbol,iOffset), pMgr->GetLabel(iSymbol), pMgr, iSymbol), m_pyParent(pyParent) {
 }
 
-CDasherNode *CMandarinAlphMgr::CMandSym::RebuildSymbol(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol) {
+CDasherNode *CMandarinAlphMgr::CMandSym::RebuildSymbol(CAlphNode *pParent, symbol iSymbol) {
   DASHER_ASSERT(m_pyParent!=0); //should have been computed in RebuildForwardsFromAncestor()
   if (iSymbol==m_pyParent) {
     //create the PY node that lead to this chinese
     if (mgr()->m_pConversionsBySymbol[m_pyParent].size()==1) {
       DASHER_ASSERT( *(mgr()->m_pConversionsBySymbol[m_pyParent].begin()) == this->iSymbol);
-      SetRange(iLbnd, iHbnd);
-      SetParent(pParent);
       return this;
     }
     //ok, will be a PY-to-Chinese conversion choice
-    CConvRoot *pConv = mgr()->CreateConvRoot(pParent, iLbnd, iHbnd, iSymbol);
+    CConvRoot *pConv = mgr()->CreateConvRoot(pParent, iSymbol);
     pConv->PopulateChildrenWithExisting(this);
     return pConv;
   }
-  return CAlphBase::RebuildSymbol(pParent, iLbnd, iHbnd, iSymbol);
+  return CAlphBase::RebuildSymbol(pParent, iSymbol);
 }
 
 bool CMandarinAlphMgr::CMandSym::isInGroup(const SGroupInfo *pGroup) {
@@ -387,14 +381,9 @@ bool CMandarinAlphMgr::CMandSym::isInGroup(const SGroupInfo *pGroup) {
   return pGroup->iStart <= m_pyParent && pGroup->iEnd > m_pyParent;
 }
 
-CMandarinAlphMgr::CMandSym *CMandarinAlphMgr::CMandSym::RebuildCHSymbol(CConvRoot *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iNewSym) {
-  if (iNewSym == this->iSymbol) {
-    //reuse existing node
-    SetParent(pParent);
-    SetRange(iLbnd, iHbnd);
-    return this;
-  }
-  return mgr()->CreateCHSymbol(pParent, pParent->iContext, iLbnd, iHbnd, iNewSym, pParent->m_pySym);
+CMandarinAlphMgr::CMandSym *CMandarinAlphMgr::CMandSym::RebuildCHSymbol(CConvRoot *pParent, symbol iNewSym) {
+  if (iNewSym == this->iSymbol) return this; //reuse existing node
+  return mgr()->CreateCHSymbol(pParent, pParent->iContext, iNewSym, pParent->m_pySym);
 }
 
 void CMandarinAlphMgr::CMandSym::RebuildForwardsFromAncestor(CAlphNode *pNewNode) {
diff --git a/Src/DasherCore/MandarinAlphMgr.h b/Src/DasherCore/MandarinAlphMgr.h
index 2db08fa..4432ecd 100644
--- a/Src/DasherCore/MandarinAlphMgr.h
+++ b/Src/DasherCore/MandarinAlphMgr.h
@@ -88,9 +88,9 @@ namespace Dasher {
     public:
       CMandarinAlphMgr *mgr() {return static_cast<CMandarinAlphMgr *>(CSymbolNode::mgr());}
       ///Symbol constructor: display text from CHAlphabet, colour from GetCHColour
-      CMandSym(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, CMandarinAlphMgr *pMgr, symbol iSymbol, symbol pyParent);
-      CDasherNode *RebuildSymbol(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol);
-      CMandSym *RebuildCHSymbol(CConvRoot *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iNewSym);
+      CMandSym(int iOffset, CMandarinAlphMgr *pMgr, symbol iSymbol, symbol pyParent);
+      CDasherNode *RebuildSymbol(CAlphNode *pParent, symbol iSymbol);
+      CMandSym *RebuildCHSymbol(CConvRoot *pParent, symbol iNewSym);
     protected:
       ///Override to compute which pinyin symbol to make our parent...
       void RebuildForwardsFromAncestor(CAlphNode *pNewNode);
@@ -109,7 +109,7 @@ namespace Dasher {
       class CConvRoot : public CAlphBase {
     public:
       /// \param pySym symbol in pinyin alphabet; must have >1 possible chinese conversion.
-      CConvRoot(CDasherNode *pParent, int iOffset, unsigned int iLbnd, unsigned int iHbnd, CMandarinAlphMgr *pMgr, symbol pySym);
+      CConvRoot(int iOffset, CMandarinAlphMgr *pMgr, symbol pySym);
       CMandarinAlphMgr *mgr() {return static_cast<CMandarinAlphMgr *>(CAlphBase::mgr());}
       void PopulateChildren();
       void PopulateChildrenWithExisting(CMandSym *existing);
@@ -117,7 +117,7 @@ namespace Dasher {
       CLanguageModel::Context iContext;
       void SetFlag(int iFlag, bool bValue);
       const symbol m_pySym;
-      CDasherNode *RebuildSymbol(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol);
+      CDasherNode *RebuildSymbol(CAlphNode *pParent, symbol iSymbol);
     protected:
       bool isInGroup(const SGroupInfo *pGroup);
     private:        
@@ -126,13 +126,13 @@ namespace Dasher {
     ///Called to create the node for a pinyin leaf symbol;
     /// Overridden to call either CreateConvRoot or CreateCHSymbol, according to #chinese symbols under specified pinyin
     /// \param iSymbol Symbol number in pinyin alphabet
-    virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iSymbol);
+    virtual CDasherNode *CreateSymbolNode(CAlphNode *pParent, symbol iSymbol);
 
     ///Creates a CConvRoot, for a Pinyin symbol with multiple possible chinese symbols.
     /// Colour is always 9 (opaque), so no need for background colour.
     /// \param pParent parent node, context will be taken from here
     /// \param iPYsym Symbol (leaf) in pinyin alphabet
-    CConvRoot *CreateConvRoot(CAlphNode *pParent, unsigned int iLbnd, unsigned int iHbnd, symbol iPYsym);
+    CConvRoot *CreateConvRoot(CAlphNode *pParent, symbol iPYsym);
       
     ///Creates a node for (i.e. that will actually enter) a chinese symbol
     /// \param pParent parent node: could be a CGroupNode (directly), if some pinyin symbol in that group had only
@@ -141,7 +141,7 @@ namespace Dasher {
     /// \param iContext parent node's context, from which to generate context for this node
     /// \param iCHsym symbol number in chinese alphabet
     /// \param pyParent pinyin-alphabet symbol which was used to enter this chinese symbol (if known, else 0)
-    CMandSym *CreateCHSymbol(CDasherNode *pParent, CLanguageModel::Context iContext, unsigned int iLbnd, unsigned int iHbnd, symbol iCHsym, symbol pyParent);
+    CMandSym *CreateCHSymbol(CDasherNode *pParent, CLanguageModel::Context iContext, symbol iCHsym, symbol pyParent);
 
     ///Gets the possible chinese symbols for a pinyin one, along with their probabilities in the specified context.
     ///Probabilities are computed by CPPMPYLanguageModel::GetPartProbs, then renormalized here. (TODO unnecessary?)
diff --git a/Src/DasherCore/NodeCreationManager.cpp b/Src/DasherCore/NodeCreationManager.cpp
index ddf72aa..5c870fb 100644
--- a/Src/DasherCore/NodeCreationManager.cpp
+++ b/Src/DasherCore/NodeCreationManager.cpp
@@ -164,7 +164,8 @@ void CNodeCreationManager::AddExtras(CDasherNode *pParent) {
 #endif
     //ACL leave offset as is - like its groupnode parent, but unlike its alphnode siblings,
     //the control node does not enter a symbol....
-    m_pControlManager->GetRoot(pParent, pParent->GetChildren().back()->Hbnd(), CDasherModel::NORMALIZATION, pParent->offset());
+    CDasherNode *ctl = m_pControlManager->GetRoot(pParent, pParent->offset());
+    ctl->Reparent(pParent, pParent->GetChildren().back()->Hbnd(), CDasherModel::NORMALIZATION);
   }
 }
 
diff --git a/Src/MacOSX/Dasher.xcodeproj/project.pbxproj b/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
index f57a05e..6592b6b 100755
--- a/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
+++ b/Src/MacOSX/Dasher.xcodeproj/project.pbxproj
@@ -41,7 +41,6 @@
 		1948BEB70C226CFD001DFA32 /* ColourIO.h in Headers */ = {isa = PBXBuildFile; fileRef = 1948BE110C226CFC001DFA32 /* ColourIO.h */; };
 		1948BEB80C226CFD001DFA32 /* ControlManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1948BE120C226CFC001DFA32 /* ControlManager.cpp */; };
 		1948BEB90C226CFD001DFA32 /* ControlManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1948BE130C226CFC001DFA32 /* ControlManager.h */; };
-		1948BEBC0C226CFD001DFA32 /* ConversionHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 1948BE160C226CFC001DFA32 /* ConversionHelper.h */; };
 		1948BEBD0C226CFD001DFA32 /* ConversionManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1948BE170C226CFC001DFA32 /* ConversionManager.cpp */; };
 		1948BEBE0C226CFD001DFA32 /* ConversionManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1948BE180C226CFC001DFA32 /* ConversionManager.h */; };
 		1948BEC10C226CFD001DFA32 /* CustomColours.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 1948BE1B0C226CFC001DFA32 /* CustomColours.cpp */; };
@@ -329,7 +328,6 @@
 		334DE238135E3E68007C8D6D /* control.textlabels.xml in Resources */ = {isa = PBXBuildFile; fileRef = 334DE236135E3E68007C8D6D /* control.textlabels.xml */; };
 		334DE239135E3E68007C8D6D /* control.xml in Resources */ = {isa = PBXBuildFile; fileRef = 334DE237135E3E68007C8D6D /* control.xml */; };
 		334DE23B135E3F4B007C8D6D /* control.dtd in Resources */ = {isa = PBXBuildFile; fileRef = 334DE23A135E3F4B007C8D6D /* control.dtd */; };
-		335901B41009E5A900821255 /* ConversionHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 335901B31009E5A900821255 /* ConversionHelper.cpp */; };
 		335DB0FB100B332C006DB155 /* alphabet.spyDict.xml in Resources */ = {isa = PBXBuildFile; fileRef = 335DB0FA100B332C006DB155 /* alphabet.spyDict.xml */; };
 		335DB101100B3358006DB155 /* training_spyDict.txt in Resources */ = {isa = PBXBuildFile; fileRef = 335DB100100B3358006DB155 /* training_spyDict.txt */; };
 		339055E81195FBD0001BE240 /* Queue.h in Headers */ = {isa = PBXBuildFile; fileRef = 339055E61195FBD0001BE240 /* Queue.h */; };
@@ -431,7 +429,6 @@
 		1948BE110C226CFC001DFA32 /* ColourIO.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ColourIO.h; sourceTree = "<group>"; };
 		1948BE120C226CFC001DFA32 /* ControlManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ControlManager.cpp; sourceTree = "<group>"; };
 		1948BE130C226CFC001DFA32 /* ControlManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ControlManager.h; sourceTree = "<group>"; };
-		1948BE160C226CFC001DFA32 /* ConversionHelper.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ConversionHelper.h; sourceTree = "<group>"; };
 		1948BE170C226CFC001DFA32 /* ConversionManager.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = ConversionManager.cpp; sourceTree = "<group>"; };
 		1948BE180C226CFC001DFA32 /* ConversionManager.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = ConversionManager.h; sourceTree = "<group>"; };
 		1948BE1B0C226CFC001DFA32 /* CustomColours.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CustomColours.cpp; sourceTree = "<group>"; };
@@ -735,7 +732,6 @@
 		334DE236135E3E68007C8D6D /* control.textlabels.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = control.textlabels.xml; sourceTree = "<group>"; };
 		334DE237135E3E68007C8D6D /* control.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = control.xml; sourceTree = "<group>"; };
 		334DE23A135E3F4B007C8D6D /* control.dtd */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = control.dtd; sourceTree = "<group>"; };
-		335901B31009E5A900821255 /* ConversionHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConversionHelper.cpp; sourceTree = "<group>"; };
 		335DB0FA100B332C006DB155 /* alphabet.spyDict.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = alphabet.spyDict.xml; sourceTree = "<group>"; };
 		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>"; };
@@ -929,8 +925,6 @@
 				1948BE110C226CFC001DFA32 /* ColourIO.h */,
 				1948BE120C226CFC001DFA32 /* ControlManager.cpp */,
 				1948BE130C226CFC001DFA32 /* ControlManager.h */,
-				335901B31009E5A900821255 /* ConversionHelper.cpp */,
-				1948BE160C226CFC001DFA32 /* ConversionHelper.h */,
 				1948BE170C226CFC001DFA32 /* ConversionManager.cpp */,
 				1948BE180C226CFC001DFA32 /* ConversionManager.h */,
 				1948BE1B0C226CFC001DFA32 /* CustomColours.cpp */,
@@ -1388,7 +1382,6 @@
 				1948BEB50C226CFD001DFA32 /* ClickFilter.h in Headers */,
 				1948BEB70C226CFD001DFA32 /* ColourIO.h in Headers */,
 				1948BEB90C226CFD001DFA32 /* ControlManager.h in Headers */,
-				1948BEBC0C226CFD001DFA32 /* ConversionHelper.h in Headers */,
 				1948BEBE0C226CFD001DFA32 /* ConversionManager.h in Headers */,
 				1948BEC20C226CFD001DFA32 /* CustomColours.h in Headers */,
 				1948BEC40C226CFD001DFA32 /* DasherButtons.h in Headers */,
@@ -1804,7 +1797,6 @@
 				3306E0220FFD1CE60017324C /* PPMPYLanguageModel.cpp in Sources */,
 				3306E1F70FFE6CAD0017324C /* Trainer.cpp in Sources */,
 				3306E33D0FFFB9880017324C /* MandarinAlphMgr.cpp in Sources */,
-				335901B41009E5A900821255 /* ConversionHelper.cpp in Sources */,
 				33135351102C6D8E00E28220 /* AlternatingDirectMode.cpp in Sources */,
 				33135353102C6D8E00E28220 /* CompassMode.cpp in Sources */,
 				33135355102C6D8E00E28220 /* ButtonMode.cpp in Sources */,
diff --git a/Src/iPhone/Dasher.xcodeproj/project.pbxproj b/Src/iPhone/Dasher.xcodeproj/project.pbxproj
index 6af3c32..ca50947 100755
--- a/Src/iPhone/Dasher.xcodeproj/project.pbxproj
+++ b/Src/iPhone/Dasher.xcodeproj/project.pbxproj
@@ -60,7 +60,6 @@
 		332F32B1103C8A1E008448D7 /* AlternatingDirectMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 332F32A6103C8A1E008448D7 /* AlternatingDirectMode.cpp */; };
 		332F32B2103C8A1E008448D7 /* ButtonMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 332F32A8103C8A1E008448D7 /* ButtonMode.cpp */; };
 		332F32B3103C8A1E008448D7 /* CompassMode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 332F32AA103C8A1E008448D7 /* CompassMode.cpp */; };
-		332F32B4103C8A1E008448D7 /* ConversionHelper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 332F32AC103C8A1E008448D7 /* ConversionHelper.cpp */; };
 		332F32B5103C8A1E008448D7 /* MandarinAlphMgr.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 332F32AD103C8A1E008448D7 /* MandarinAlphMgr.cpp */; };
 		332F32B6103C8A1E008448D7 /* Trainer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 332F32AF103C8A1E008448D7 /* Trainer.cpp */; };
 		332F34A3103D8F54008448D7 /* colour.blue.xml in Resources */ = {isa = PBXBuildFile; fileRef = 332F3496103D8F54008448D7 /* colour.blue.xml */; };
@@ -365,7 +364,6 @@
 		332F32A9103C8A1E008448D7 /* ButtonMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ButtonMode.h; sourceTree = "<group>"; };
 		332F32AA103C8A1E008448D7 /* CompassMode.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CompassMode.cpp; sourceTree = "<group>"; };
 		332F32AB103C8A1E008448D7 /* CompassMode.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CompassMode.h; sourceTree = "<group>"; };
-		332F32AC103C8A1E008448D7 /* ConversionHelper.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConversionHelper.cpp; sourceTree = "<group>"; };
 		332F32AD103C8A1E008448D7 /* MandarinAlphMgr.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MandarinAlphMgr.cpp; sourceTree = "<group>"; };
 		332F32AE103C8A1E008448D7 /* MandarinAlphMgr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MandarinAlphMgr.h; sourceTree = "<group>"; };
 		332F32AF103C8A1E008448D7 /* Trainer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Trainer.cpp; sourceTree = "<group>"; };
@@ -560,7 +558,6 @@
 		3344FD820F71717C00506EAA /* ColourIO.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ColourIO.h; sourceTree = "<group>"; };
 		3344FD830F71717C00506EAA /* ControlManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ControlManager.cpp; sourceTree = "<group>"; };
 		3344FD840F71717C00506EAA /* ControlManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ControlManager.h; sourceTree = "<group>"; };
-		3344FD870F71717C00506EAA /* ConversionHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConversionHelper.h; sourceTree = "<group>"; };
 		3344FD880F71717C00506EAA /* ConversionManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ConversionManager.cpp; sourceTree = "<group>"; };
 		3344FD890F71717C00506EAA /* ConversionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ConversionManager.h; sourceTree = "<group>"; };
 		3344FD8C0F71717C00506EAA /* CustomColours.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CustomColours.cpp; sourceTree = "<group>"; };
@@ -1189,7 +1186,6 @@
 				3344FD820F71717C00506EAA /* ColourIO.h */,
 				3344FD830F71717C00506EAA /* ControlManager.cpp */,
 				3344FD840F71717C00506EAA /* ControlManager.h */,
-				3344FD870F71717C00506EAA /* ConversionHelper.h */,
 				3344FD880F71717C00506EAA /* ConversionManager.cpp */,
 				3344FD890F71717C00506EAA /* ConversionManager.h */,
 				333FDB58139FB413009D018A /* ConvertingAlphMgr.cpp */,
@@ -1257,7 +1253,6 @@
 				332F32A9103C8A1E008448D7 /* ButtonMode.h */,
 				332F32AA103C8A1E008448D7 /* CompassMode.cpp */,
 				332F32AB103C8A1E008448D7 /* CompassMode.h */,
-				332F32AC103C8A1E008448D7 /* ConversionHelper.cpp */,
 				332F32AD103C8A1E008448D7 /* MandarinAlphMgr.cpp */,
 				332F32AE103C8A1E008448D7 /* MandarinAlphMgr.h */,
 				332F32AF103C8A1E008448D7 /* Trainer.cpp */,
@@ -1634,7 +1629,6 @@
 				332F32B1103C8A1E008448D7 /* AlternatingDirectMode.cpp in Sources */,
 				332F32B2103C8A1E008448D7 /* ButtonMode.cpp in Sources */,
 				332F32B3103C8A1E008448D7 /* CompassMode.cpp in Sources */,
-				332F32B4103C8A1E008448D7 /* ConversionHelper.cpp in Sources */,
 				332F32B5103C8A1E008448D7 /* MandarinAlphMgr.cpp in Sources */,
 				332F32B6103C8A1E008448D7 /* Trainer.cpp in Sources */,
 				339F8A330FF5088000282847 /* CalibrationController.mm in Sources */,



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