[dasher/relicence] Reverting



commit 07f53a86c1e34960c4f37f0260fcd41c65a9eba0
Author: Gavin Henderson <gavin henderson hotmail co uk>
Date:   Mon May 23 15:40:02 2022 +0100

    Reverting

 Src/DasherCore/DasherModel.cpp      | 243 ++++++++++++++++++++-
 Src/DasherCore/DasherNode.cpp       | 159 ++++++++------
 Src/DasherCore/DasherNode.h         | 156 +++++++++++++-
 Src/DasherCore/DasherViewSquare.cpp | 415 +++++++++++++++++++++++++++++++++++-
 maint/list-all-source-files         |   3 -
 maint/list-all-text-files           |   3 -
 6 files changed, 883 insertions(+), 96 deletions(-)
---
diff --git a/Src/DasherCore/DasherModel.cpp b/Src/DasherCore/DasherModel.cpp
index 3bc9a220..57b62c5f 100644
--- a/Src/DasherCore/DasherModel.cpp
+++ b/Src/DasherCore/DasherModel.cpp
@@ -572,8 +572,157 @@ void CDasherModel::ScheduleZoom(dasherint y1, dasherint y2, int nsteps) {
 }
 
 
-void CDasherModel::ClearScheduledSteps() {
-  m_deGotoQueue.clear();
+void CDasherModel::Push_Node(CDasherNode* pNode) 
+{
+       if ( pNode->Children() )
+       {
+               // if there are children just give them a poke
+               unsigned int i;
+               for (i=0;i< pNode->ChildCount() ;i++)
+                       pNode->Children()[i]->Alive(true);
+               return;
+       }
+
+       // This ASSERT seems to routinely fail
+       //DASHER_ASSERT(pNode->Symbol()!=0);
+
+
+       // if we haven't got a context then derive it
+       
+       if (! pNode->Context() )
+       {
+
+               CLanguageModel::Context cont;
+               // sym0
+               if ( pNode->Symbol() < m_pcAlphabet->GetNumberTextSymbols() && pNode->Symbol()>0) 
+               {
+                       CDasherNode* pParent = pNode->Parent();
+                       DASHER_ASSERT (pParent != NULL) ;
+                       // Normal symbol - derive context from parent
+                       cont =  m_pLanguageModel->CloneContext( pParent->Context() );
+                       m_pLanguageModel->EnterSymbol( cont, pNode->Symbol() );
+               }
+               else
+               {
+                       // For new "root" nodes (such as under control mode), we want to 
+                       // mimic the root context
+                       cont = CreateEmptyContext();
+                       EnterText(cont, ". ");
+               }
+               pNode->SetContext(cont);
+
+       }
+
+       pNode->Alive(true);
+
+       if ( pNode->Symbol()== GetControlSymbol() || pNode->ControlChild() ) 
+       {
+
+               ControlTree* pControlTreeChildren = pNode->GetControlTree();
+       
+               if ( pControlTreeChildren == NULL ) 
+               { 
+                       // Root of the tree 
+                       pControlTreeChildren = GetControlTree();
+               }
+               else 
+               { 
+                       // some way down
+                       pControlTreeChildren = pControlTreeChildren->children;
+               }
+
+               // Count total number of children
+
+               // Always 1 child for a root symbol
+               int iChildCount=1;
+
+               // Control children
+               ControlTree* pTemp = pControlTreeChildren;
+               while(pTemp != NULL)
+               {
+                       iChildCount++;
+                       pTemp = pTemp->next;
+               }
+               
+               // Now we go back and build the node tree         
+               int quantum=int(GetLongParameter(LP_NORMALIZATION)/iChildCount);
+
+               CDasherNode** ppChildren = new CDasherNode* [iChildCount];
+
+               ColorSchemes ChildScheme;
+               if (pNode->ColorScheme() == Nodes1)
+               {
+                       ChildScheme = Nodes2;
+               } 
+               else 
+               {
+                       ChildScheme = Nodes1;
+               }
+
+               int i=0;
+               // First a root node that takes up back to the text alphabet
+               ppChildren[i]=new 
CDasherNode(*this,pNode,0,0,Opts::Nodes1,0,int((i+1)*quantum),m_pLanguageModel,false,240);
+               i++;
+
+               // Now the control children
+               pTemp = pControlTreeChildren;
+               while( pTemp != NULL)
+               {
+                       if (pTemp->colour != -1)
+                       {
+                               ppChildren[i]=new 
CDasherNode(*this,pNode,0,i,ChildScheme,int(i*quantum),int((i+1)*quantum),m_pLanguageModel,true,pTemp->colour,
 pTemp);
+                       } 
+                       else 
+                       {
+                               ppChildren[i]=new 
CDasherNode(*this,pNode,0,i,ChildScheme,int(i*quantum),int((i+1)*quantum),m_pLanguageModel,true,(i%99)+11, 
pTemp);
+                       }
+                       i++;
+                       pTemp = pTemp->next;
+               }
+               pNode->SetChildren(ppChildren, iChildCount);
+               return;
+       }
+
+       vector<symbol> newchars;   // place to put this list of characters
+       vector<unsigned int> cum;   // for the probability list
+
+       GetProbs(pNode->Context(),newchars,cum,GetLongParameter(LP_NORMALIZATION));
+       int iChildCount=newchars.size();
+
+       DASHER_TRACEOUTPUT("ChildCount %d\n",iChildCount);
+       // work out cumulative probs in place
+       for (int i=1;i<iChildCount;i++)
+               cum[i]+=cum[i-1];
+
+       CDasherNode** ppChildren = new CDasherNode *[iChildCount];
+
+       // create the children
+       ColorSchemes NormalScheme, SpecialScheme;
+       if (( pNode->ColorScheme()==Nodes1 ) || (pNode->ColorScheme()==Special1 ))
+       {
+               NormalScheme = Nodes2;
+               SpecialScheme = Special2;
+       } 
+       else 
+       {
+               NormalScheme = Nodes1;
+               SpecialScheme = Special1;
+       }
+
+       ColorSchemes ChildScheme;
+
+       int iLbnd=0;
+       for (int j=0; j< iChildCount; j++)
+       {
+               if (newchars[j]== GetSpaceSymbol())
+                       ChildScheme = SpecialScheme;
+               else
+                       ChildScheme = NormalScheme;
+               ppChildren[j]=new 
CDasherNode(*this,pNode,newchars[j],j,ChildScheme,iLbnd,cum[j],m_pLanguageModel,false,GetColour(j));
+               iLbnd = cum[j];
+       }
+       pNode->SetChildren(ppChildren,iChildCount);
+
 }
 
 
@@ -588,7 +737,95 @@ void CDasherModel::AbortOffset() {
   m_Rootmin += m_iDisplayOffset;
   m_Rootmax += m_iDisplayOffset;
 
-  m_iDisplayOffset = 0;
+//////
+// This section calculates the exact dasher coordinate they want to be aiming at
+// and then draws the pointer there
+    myint currDasherMax, currDasherMin, currDasherRange;
+
+    // Current location in the target string that we are comparing
+    // for correctness
+    CDasherNode *currNode = m_model->Root();
+
+    if(!currNode)
+        return INT64_MIN;
+
+    myint norm = GetLongParameter(LP_NORMALIZATION);
+    // These represent the scaled range of dasher coordinates
+    // start at the current root but grow as you backtrack
+    currDasherMax = m_model->Rootmax();
+    currDasherMin = m_model->Rootmin();
+    currDasherRange = currDasherMax - currDasherMin;
+
+    // Now find the normalized dasher coordinates for the node we're using as
+    // the "correct path" node, the last correctly typed symbol 
+    // (or going back as far as we can without overflow)
+    while(positionOfRoot > posOfFirstDifference)
+    {
+        // IF no parent, but not yet at node of first difference
+        // need to just draw up or down arrow again
+        if(!currNode->Parent())
+        {
+            if( alphabetmap.Get(CurrentTarget.substr(posOfFirstDifference,1), &KeyIsPrefix) < 
+                    alphabetmap.Get(Context.substr(posOfFirstDifference,1), &KeyIsPrefix) )
+                return INT64_MIN+1;
+            else
+                return INT64_MAX;
+        }
+
+        myint nodeupper, nodelower, noderange;
+        
+        nodeupper = currNode->Hbnd();
+        nodelower = currNode->Lbnd();
+        noderange = nodeupper-nodelower;
+
+        currDasherMax += (norm - nodeupper) * currDasherRange / noderange;
+        currDasherMin -= nodelower * currDasherRange / noderange;
+        currDasherRange =  currDasherMax - currDasherMin;
+
+        currNode = currNode->Parent();
+        positionOfRoot--;
+    }
+
+
+    // The location we examine first is where we last matched a symbol
+    // So, matching 3 symbols means we look at element 3 (zero-based), 4th elem
+    int currLocation = positionOfRoot;
+
+    DASHER_ASSERT(currNode);
+  
+    // With the original root's dasher coordinates, find where pointer should be
+    // Go through this loop until no child is found along the target string
+    bool foundChild=true;
+    while(foundChild)
+    {
+        foundChild = false;
+        int childrencount = currNode->ChildCount();
+         
+        if(childrencount > 0)
+        {
+            CDasherNode **children = currNode->Children();
+            for(int ii = 0; ii<childrencount; ii++)
+            {
+                int symbol = 
m_model->GetAlphabet().GetAlphabetMap().Get(CurrentTarget.substr(currLocation,1), &KeyIsPrefix);
+                if(children[ii]->Symbol() == symbol)
+                {
+                    foundChild = true;
+                    currLocation++;
+                    currNode = children[ii];
+                    
+                    // Calculate new dasher high/low/range coords for the child we want
+                    currDasherMax -= ((norm - currNode->Hbnd()) * currDasherRange)  / norm;
+                    currDasherMin += currNode->Lbnd() * currDasherRange / norm;
+                    currDasherRange = currDasherMax - currDasherMin;
+                    break;
+                }
+            }
+        }
+        else
+            break;
+    }
+
+    return (currDasherMax - currDasherRange/2);
 }
 
 void CDasherModel::LimitRoot(int iMaxWidth) {
diff --git a/Src/DasherCore/DasherNode.cpp b/Src/DasherCore/DasherNode.cpp
index 899641f3..826e2693 100644
--- a/Src/DasherCore/DasherNode.cpp
+++ b/Src/DasherCore/DasherNode.cpp
@@ -59,52 +59,92 @@ CDasherNode::~CDasherNode() {
   iNumNodes--;
 }
 
-void CDasherNode::Trace() const {
-  /* TODO sort out
-     dchar out[256];
-     if (m_Symbol)
-     wsprintf(out,TEXT("%7x %3c %7x %5d %7x  %5d %8x %8x      
\n"),this,m_Symbol,m_iGroup,m_context,m_Children,m_Cscheme,m_iLbnd,m_iHbnd);
-     else
-     wsprintf(out,TEXT("%7x     %7x %5d %7x  %5d %8x %8x      
\n"),this,m_iGroup,m_context,m_Children,m_Cscheme,m_iLbnd,m_iHbnd);
-
-     OutputDebugString(out);
-
-     if (m_Children) {
-     unsigned int i;
-     for (i=1;i<m_iChars;i++)
-     m_Children[i]->Dump_node();
-     }
-   */
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherNode::Get_string_under(const int iNormalization,const myint miY1,const myint miY2,const myint 
miMousex,const myint miMousey, vector<symbol> &vString) const
+{
+       // we are over (*this) node so add it to the string 
+       vString.push_back(m_Symbol);
+       
+       // look for children who might also be under the coords
+       if (m_ppChildren)
+       {
+               myint miRange=miY2-miY1;
+               unsigned int i;
+               for (i=1;i<m_iChildCount;i++) 
+               {
+                       myint miNewy1=miY1+(miRange* Children()[i]->m_iLbnd)/iNormalization;
+                       myint miNewy2=miY1+(miRange* Children()[i]->m_iHbnd)/iNormalization;
+                       if (miMousey<miNewy2 && miMousey>miNewy1 && miMousex<miNewy2-miNewy1) 
+                       {
+                               
Children()[i]->Get_string_under(iNormalization,miNewy1,miNewy2,miMousex,miMousey,vString);
+                               return;
+                       }
+               }
+       }
+       return;
 }
 
-void CDasherNode::GetContext(CDasherInterfaceBase *pInterface, const CAlphabetMap *pAlphabet, vector<symbol> 
&vContextSymbols, int iOffset, int iLength) {
-  if (!GetFlag(NF_SEEN)) {
-    DASHER_ASSERT(m_pParent);
-    if (m_pParent) m_pParent->GetContext(pInterface, pAlphabet, vContextSymbols, iOffset,iLength);
-  } else {
-    std::string strContext = pInterface->GetContext(iOffset, iLength);
-    pAlphabet->GetSymbols(vContextSymbols, strContext);
-  }
+/////////////////////////////////////////////////////////////////////////////
+
+CDasherNode * const CDasherNode::Get_node_under(int iNormalization,myint miY1,myint miY2,myint 
miMousex,myint miMousey) 
+{
+       if ( Children() ) 
+       {
+               myint miRange=miY2-miY1;
+//             m_iAge=0;
+               m_bAlive=true;
+               unsigned int i;
+               for (i=0;i<m_iChildCount;i++) 
+               {
+                       CDasherNode* pChild = Children()[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
-void CDasherNode::OrphanChild(CDasherNode *pChild) {
-  DASHER_ASSERT(ChildCount() > 0);
-
-  ChildMap::const_iterator i;
-  for(i = GetChildren().begin(); i != GetChildren().end(); i++) {
-    if((*i) != pChild) {
-      (*i)->Delete_children();
-      delete (*i);
-    }
-  }
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherNode::OrphanChild(CDasherNode* pChild)
+{
+       DASHER_ASSERT ( Children() ) ;
+
+       int i; 
+       for (i=0;i< ChildCount(); i++) 
+       {
+               if ( Children()[i] != pChild )
+               {
+                       Children()[i]->Delete_children();
+                       delete Children()[i];
+               }
+
+       }
+       delete [] m_ppChildren;
+       m_ppChildren=0;
+       m_iChildCount=0;
+}
 
   pChild->m_pParent=NULL;
 
-  Children().clear();
-  SetFlag(NF_ALLCHILDREN, false);
+// Delete nephews
+void CDasherNode::DeleteNephews(int iChild)
+{
+       DASHER_ASSERT ( Children() ) ;
+
+       int i; 
+       for (i=0;i< ChildCount(); i++) 
+       {
+               if (i != iChild)
+               {
+                       Children()[i]->Delete_children();
+               }
+
+       }
 }
 
 // Delete nephews of the child which has the specified symbol
@@ -125,34 +165,19 @@ void CDasherNode::DeleteNephews(CDasherNode *pChild) {
 void CDasherNode::Delete_children() {
 //  std::cout << "Start: " << this << std::endl;
 
-  ChildMap::iterator i;
-  for(i = Children().begin(); i != Children().end(); i++) {
-    //    std::cout << "CNM: " << (*i)->MgrID() << (*i) << " " << (*i)->Parent() << std::endl;
-    delete (*i);
-  }
-  Children().clear();
-  //  std::cout << "NM: " << MgrID() << std::endl;
-  SetFlag(NF_ALLCHILDREN, false);
-  onlyChildRendered = NULL;
-}
-
-void CDasherNode::SetFlag(int iFlag, bool bValue) {
-
- if(bValue)
-    m_iFlags = m_iFlags | iFlag;
-  else
-    m_iFlags = m_iFlags & (~iFlag);
-}
-
-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;
+void CDasherNode::Delete_children() 
+{
+       if (m_ppChildren) 
+       {
+               for (int i=0;i<m_iChildCount;i++) 
+               {
+                    m_ppChildren[i]->Delete_children();
+                    delete m_ppChildren[i];
+               }
+               delete [] m_ppChildren;
+               m_ppChildren=0; 
+               m_iChildCount=0;
+       }
 }
 
 int CDasherNode::MostProbableChild() {
diff --git a/Src/DasherCore/DasherNode.h b/Src/DasherCore/DasherNode.h
index 3b6ff854..2a7010ce 100644
--- a/Src/DasherCore/DasherNode.h
+++ b/Src/DasherCore/DasherNode.h
@@ -24,10 +24,100 @@
 #include "../Common/Common.h"
 #include "../Common/NoClones.h"
 #include "LanguageModelling/LanguageModel.h"
-#include "DasherTypes.h"
-#include "NodeManager.h"
-#include "Alphabet/AlphabetMap.h"
-#include "DasherScreen.h"
+
+
+// CDasherNode represents a rectangle and character 
+
+namespace Dasher {class CDasherNode;class CDasherModel;}
+class Dasher::CDasherNode : private NoClones
+{
+public:
+       
+       CDasherNode(const CDasherModel& dashermodel, CDasherNode *parent,symbol Symbol, 
+               int iphase, Opts::ColorSchemes ColorScheme,
+               int ilbnd,int ihbnd,
+               CLanguageModel *lm, bool ControlChild, int Colour, ControlTree *controltree);
+
+       ~CDasherNode();
+       
+       // Node relationships
+       CDasherNode ** const Children() const;
+       unsigned int ChildCount() const {return m_iChildCount;}
+       CDasherNode* Parent() const {return m_pParent;}
+       bool NodeIsParent(CDasherNode *oldnode) const;
+       void SetChildren(CDasherNode** ppChildren, int iChildCount);
+       
+       // Orphan Child
+       void OrphanChild(CDasherNode* pChild);
+       
+       void DeleteNephews(int iChild);
+
+       // Lower and higher bounds, and the range
+       int Lbnd() const;
+       int Hbnd() const;
+       int Range() const;
+       
+       // 'Alive' - this could do with an overhaul
+       bool Alive() const {return m_bAlive;}
+       void Alive(bool b) {m_bAlive = b;}
+       void Kill()  {m_bAlive=0;}
+
+       // 'Seen' - this could do with an overhaul
+       bool isSeen() const {return m_bSeen;}
+       void Seen(bool seen) {m_bSeen=seen;}
+       
+       // ControlNode-related
+       bool ControlChild() const {return m_bControlChild;}
+       ControlTree* GetControlTree() {return m_controltree;}
+       
+       //unsigned int Group() const {return m_iGroup;}
+       symbol Symbol() const {return m_Symbol;}
+       int Phase() const {return m_iPhase;}
+
+       // DJW Sort out the colour scheme / phase confusion
+       Opts::ColorSchemes ColorScheme() const {return m_ColorScheme;}
+       int Colour() const {return m_iColour;}
+       
+       CDasherNode* const Get_node_under(int,myint y1,myint y2,myint smousex,myint smousey); // find node 
under given co-ords
+       void Get_string_under(const int,const myint y1,const myint y2,const myint smousex,const myint 
smousey,std::vector<symbol>&) const; // get string under given co-ords
+
+       void Delete_children();
+       void Trace() const;                                // diagnostic
+
+       // Set/replace the context
+       void SetContext(CLanguageModel::Context Context);
+       CLanguageModel::Context Context() const;
+
+private:
+
+       const int m_iLbnd,m_iHbnd;// the cumulative lower and upper bound prob relative to parent
+       //const unsigned int m_iGroup;       // group membership - e.g. 0=nothing 1=caps 2=punc
+       const symbol m_Symbol;             // the character to display
+       
+       CDasherNode** m_ppChildren;          // pointer to array of children
+       unsigned int m_iChildCount;                // number of children
+       
+       bool m_bAlive;                     // if true, then display node, else dont bother
+       //bool m_bControlNode;               // if true, node is a control node
+       bool m_bControlChild;              // if true, node is offspring of a control node
+       bool m_bSeen;                      // if true, node has been output already
+       Opts::ColorSchemes m_ColorScheme;
+       int m_iPhase;                      // index for coloring
+       int m_iColour;                     // for the advanced colour mode
+
+       const CDasherModel& m_DasherModel;
+
+       // Language Modelling 
+       CLanguageModel* m_pLanguageModel;   // pointer to the language model - in future, could be different 
for each node      
+       CLanguageModel::Context m_Context;
+
+       CDasherNode *m_pParent;             // pointer to parent
+       ControlTree *m_controltree;
+
+       enum {
+               typeRoot=0,
+               typeSymbol=1
+       };
 
 namespace Dasher {
   class CDasherNode;
@@ -309,8 +399,33 @@ namespace Dasher {
 
 namespace Dasher {
 
-inline unsigned int CDasherNode::Lbnd() const {
-  return m_iLbnd;
+inline CDasherNode::CDasherNode(const CDasherModel& dashermodel, CDasherNode* pParent,symbol Symbol, int 
iphase, ColorSchemes ColorScheme,int ilbnd,int ihbnd,CLanguageModel *lm, bool ControlChild, int Colour=-1, 
ControlTree *controltree=0)
+       :  m_DasherModel(dashermodel), m_iLbnd(ilbnd), m_iHbnd(ihbnd), 
+       m_iChildCount(0), m_bAlive(true), m_bControlChild(ControlChild), m_bSeen(false), 
+       m_ColorScheme(ColorScheme), m_iPhase(iphase), m_iColour(Colour), m_Symbol(Symbol), 
+       m_pLanguageModel(lm), m_ppChildren(0), m_pParent(pParent), m_Context(NULL), 
+       m_controltree(controltree)
+{
+
+       /*
+       switch (ColorScheme) {
+               case Nodes1:
+                       m_ColorScheme = Nodes2;
+                       break;
+               case Nodes2:
+                       m_ColorScheme = Nodes1;
+                       break;
+               case Special1:
+                       m_ColorScheme = Special2;
+                       break;
+               case Special2:
+                       m_ColorScheme = Special1;
+                       break;
+               case default:
+                       m_ColorScheme = ColorScheme;
+                       break;
+       }
+       */
 }
 
 inline unsigned int CDasherNode::Hbnd() const {
@@ -321,12 +436,33 @@ inline unsigned int CDasherNode::Range() const {
   return m_iHbnd - m_iLbnd;
 }
 
-inline CDasherNode::ChildMap &CDasherNode::Children() {
-  return m_mChildren;
+/////////////////////////////////////////////////////////////////////////////
+
+inline int CDasherNode::Lbnd() const {return m_iLbnd;}
+
+/////////////////////////////////////////////////////////////////////////////
+
+inline int CDasherNode::Hbnd() const {return m_iHbnd;}
+
+/////////////////////////////////////////////////////////////////////////////
+
+inline int CDasherNode::Range() const {return m_iHbnd-m_iLbnd;}
+
+/////////////////////////////////////////////////////////////////////////////
+
+inline void CDasherNode::SetChildren(CDasherNode** ppChildren, int iChildCount)
+{
+       // DJW - please make sure DASHER_ASSERT is implemented on your platform
+       DASHER_ASSERT(m_ppChildren == NULL);
+       m_ppChildren = ppChildren;
+       m_iChildCount = iChildCount;
 }
 
-inline const CDasherNode::ChildMap &CDasherNode::GetChildren() const {
-  return m_mChildren;
+/////////////////////////////////////////////////////////////////////////////
+
+inline CDasherNode** const CDasherNode::Children() const
+{
+       return m_ppChildren;
 }
 
 inline unsigned int CDasherNode::ChildCount() const {
diff --git a/Src/DasherCore/DasherViewSquare.cpp b/Src/DasherCore/DasherViewSquare.cpp
index bd919943..5c39515c 100644
--- a/Src/DasherCore/DasherViewSquare.cpp
+++ b/Src/DasherCore/DasherViewSquare.cpp
@@ -54,7 +54,159 @@ static char THIS_FILE[] = __FILE__;
 // anything which uses radically different co-ordinate transforms, and
 // we can always override if necessary.
 
-// FIXME - duplicated 'mode' code throught - needs to be fixed (actually, mode related stuff, Input2Dasher 
etc should probably be at least partially in some other class)
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherViewSquare::RenderNodes()
+{
+  Screen().Blank();
+  
+  DASHER_ASSERT(DasherModel().Root()!=0);
+  
+  //DASHER_TRACEOUTPUT("RenderNodes\n");
+  
+  // Render nodes to screen object (should use off screen buffer)
+  
+  RecursiveRender(DasherModel().Root(), DasherModel().Rootmin(), DasherModel().Rootmax(), 
DasherVisibleMaxX());
+  
+  // DelayDraw the text nodes
+  m_DelayDraw.Draw(Screen());
+
+  Crosshair(DasherModel().DasherOX()); // add crosshair
+}
+
+void CDasherViewSquare::HandleEvent( Dasher::CEvent *pEvent ) {
+       // Let the parent class do its stuff
+       CDasherView::HandleEvent( pEvent );
+
+       // And then interpret events for ourself
+       if(     pEvent->m_iEventType == 1 ) {
+               Dasher::CParameterNotificationEvent     *pEvt( static_cast<     
Dasher::CParameterNotificationEvent     * >( pEvent     ));
+               switch( pEvt->m_iParameter ) {
+
+                       default:
+                               break;
+               }
+       }
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+int CDasherViewSquare::RecursiveRender(CDasherNode* pRender, myint y1,myint y2,int mostleft)
+{
+       DASHER_ASSERT_VALIDPTR_RW(pRender);
+
+       // Decide which colour to use when rendering the child
+
+       int Color;
+
+       if (GetBoolParameter(BP_COLOUR_MODE)==true) 
+       {
+         if (pRender->Colour()!=-1) {
+           Color = pRender->Colour();
+         } else {
+           if (pRender->Symbol()==DasherModel().GetSpaceSymbol()) {
+             Color = 9;
+           } else if (pRender->Symbol()==DasherModel().GetControlSymbol()) {
+             Color = 8;
+           } else {
+             Color = (pRender->Symbol()%3)+10;
+           }
+         }
+       } else {
+         Color = pRender->Phase()%3; 
+       }
+
+       if ((pRender->ColorScheme()%2)==1 && Color<130 && GetBoolParameter(BP_COLOUR_MODE)==true) { // We 
don't loop on high
+         Color+=130;                                // colours
+       }
+
+       //      DASHER_TRACEOUTPUT("%x ",Render);
+       
+       std::string display;
+       if (pRender->GetControlTree()!=NULL) 
+               display = pRender->GetControlTree()->text;
+
+       if (RenderNode(pRender->Symbol(), Color, pRender->ColorScheme(), y1, y2, mostleft, display))
+       {
+               // yuk
+               if (!pRender->ControlChild() && pRender->Symbol() < 
DasherModel().GetAlphabet().GetNumberTextSymbols() )
+                       RenderGroups(pRender, y1, y2);
+       }
+       else
+       {
+               pRender->Kill();
+               return 0;
+       }
+
+       int iChildCount = pRender->ChildCount();
+       if (!iChildCount)
+         return 0;
+
+       int norm=GetLongParameter(LP_NORMALIZATION);
+       for (int i=0; i< iChildCount; i++) 
+       {
+               CDasherNode* pChild = pRender->Children()[i];
+               if ( pChild->Alive() ) 
+               {
+                       myint Range=y2-y1;
+                       myint newy1=y1+(Range * pChild->Lbnd() )/norm;
+                       myint newy2=y1+(Range * pChild->Hbnd() )/norm;
+                       RecursiveRender(pChild, newy1, newy2, mostleft);
+               }
+       }
+       return 1;
+
+
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherViewSquare::RenderGroups(CDasherNode* Render, myint y1, myint y2)
+{
+       CDasherNode** Children = Render->Children();
+       if (!Children)
+               return;
+       int current=0;
+       int lower=0;
+       int upper=0;
+    std::string Label="";
+
+       myint range=y2-y1;
+       
+       const CAlphabet& alphabet = DasherModel().GetAlphabet();
+
+       for (int iGroup=1; iGroup < alphabet.GetGroupCount();  iGroup++) 
+       {
+               int lower = alphabet.GetGroupStart(iGroup);
+               int upper = alphabet.GetGroupEnd(iGroup);
+       
+               myint lbnd=Children[lower]->Lbnd();
+               myint hbnd=Children[upper-1]->Hbnd();
+               myint newy1=y1+(range*lbnd)/(int)GetLongParameter(LP_NORMALIZATION);
+               myint newy2=y1+(range*hbnd)/(int)GetLongParameter(LP_NORMALIZATION);
+               int mostleft;
+               if (GetBoolParameter(BP_COLOUR_MODE)==true) 
+               {
+                       std::string Label = DasherModel().GroupLabel(iGroup);
+                       int Colour = DasherModel().GroupColour(iGroup);
+                  
+            if (Colour!=-1) 
+                       {
+                               
RenderNode(0,DasherModel().GroupColour(iGroup),Opts::Groups,newy1,newy2,mostleft,Label);
+                       } 
+                       else 
+                       {
+                           RenderNode(0,(current%3)+110,Opts::Groups,newy1,newy2,mostleft,Label);
+                       }
+               } 
+               else 
+               {
+                       RenderNode(0,current-1,Opts::Groups,newy1,newy2,mostleft,Label);
+               }
+       }
+}
+
+/////////////////////////////////////////////////////////////////////////////
 
 CDasherViewSquare::CDasherViewSquare(CSettingsUser *pCreateFrom, CDasherScreen *DasherScreen, 
Opts::ScreenOrientations orient)
 : CDasherView(DasherScreen,orient), CSettingsUserObserver(pCreateFrom), m_Y1(4), m_Y2(0.95 * 
CDasherModel::MAX_Y), m_Y3(0.05 * CDasherModel::MAX_Y), m_bVisibleRegionValid(false) {
@@ -72,15 +224,258 @@ void CDasherViewSquare::SetOrientation(Opts::ScreenOrientations newOrient) {
   SetScaleFactor();
 }
 
-void CDasherViewSquare::HandleEvent(int iParameter) {
-  switch (iParameter) {
-    case LP_MARGIN_WIDTH:
-    case BP_NONLINEAR_Y:
-    case LP_NONLINEAR_X:
-    case LP_GEOMETRY:
-      m_bVisibleRegionValid = false;
-      SetScaleFactor();
-  }
+/////////////////////////////////////////////////////////////////////////////
+
+int CDasherViewSquare::RenderNode(const symbol Character, const int Color, Opts::ColorSchemes ColorScheme,
+       myint y1, myint y2, int& mostleft, const std::string& displaytext)
+{
+       DASHER_ASSERT(y2>=y1);
+
+// //  DASHER_TRACEOUTPUT("RenderNode Symbol:%d Colour:%d, ColourScheme:%d Display:%s 
\n",Character,Color,ColorScheme,displaytext.c_str());
+//     //DASHER_TRACEOUTPUT("RenderNode %I64d %I64d",y1,y2);
+
+//     // Get the screen positions of the node in co-ords such that dasher RHS runs from 0 to 
DasherModel.DasherY
+//     screenint s1,s2;
+//     Cint32 iSize = dashery2screen(y1,y2,s1,s2);
+
+//     // Actual height in pixels
+//     Cint32 iHeight = Cint32( (Cint32) (iSize * CanvasY)/ (Cint32) DasherModel().DasherY() );
+
+//     if (iHeight <=1)
+//             return 0;
+
+//     // horizontal width of the square is controlled by the true size (y2-y1) in Dasher world
+
+               
+//     // All squares are right-aligned.
+//     screenint iRight=CanvasX;
+               
+//     screenint iNewleft=iLeft, iNewtop=s1, iNewright=iRight, iNewbottom=s2;
+
+//     // Do the rotation
+//     MapScreen(&iNewleft, &iNewtop);
+//     MapScreen(&iNewright, &iNewbottom);
+
+//     DASHER_TRACEOUTPUT("--------- %i %i\n",iNewtop,iNewbottom);
+
+       //Screen().DrawRectangle(iNewleft, iNewtop, iNewright, iNewbottom, Color, ColorScheme);
+
+
+       // FIXME - Get sensibel limits here (to allow for non-linearities)
+
+       screenint s1,s2;
+       Cint32 iSize = dashery2screen(y1,y2,s1,s2);
+
+       // Actual height in pixels
+       Cint32 iHeight = Cint32( (Cint32) (iSize * CanvasY)/ (Cint32) DasherModel().DasherY() );
+
+       if( iHeight <= 1 )
+         return 0; // We're too small to render
+
+       if(( y1 > DasherVisibleMaxY() ) || ( y2 < DasherVisibleMinY() ))
+         return 0; // We're entirely off screen, so don't render.
+
+       myint iDasherSize( y2 - y1 );
+#
+       // FIXME - get rid of pointless assignment below
+
+       int iTruncation( GetLongParameter(LP_TRUNCATION) ); // Trucation farction times 100;
+       int iTruncationType( GetLongParameter(LP_TRUNCATIONTYPE) );
+
+       if( iTruncation == 0 ) { // Regular squares
+         DasherDrawRectangle( iDasherSize, y2, 0, y1, Color, ColorScheme );
+       }
+       else {
+         int iDasherY( DasherModel().DasherY() );
+
+         int iSpacing( iDasherY / 128 ); // FIXME - assuming that this is an integer below
+
+
+         int iXStart;
+         
+         switch( iTruncationType ) {
+         case 0:
+           iXStart = 0;
+           break;
+         case 1:
+           iXStart = iSize - iSize * iTruncation / 200;
+           break;
+         case 2:
+           iXStart = iSize - iSize * iTruncation / 100;
+           break;
+         }
+
+
+         int iTipMin( (y2 - y1) * iTruncation / (200) + y1 );
+         int iTipMax( y2 - (y2 - y1) * iTruncation / (200) );
+         
+         
+
+         int iLowerMin( ((y1+1) / iSpacing)*iSpacing );
+         int iLowerMax( ((iTipMin-1) / iSpacing )*iSpacing );
+
+         int iUpperMin( ((iTipMax+1) / iSpacing )*iSpacing );
+         int iUpperMax( ((y2-1) / iSpacing)*iSpacing );
+
+         if( iLowerMin < 0 )
+           iLowerMin = 0;
+         
+         if( iLowerMax < 0 )
+           iLowerMax = 0;
+
+         if( iUpperMin < 0 )
+           iUpperMin = 0;
+         
+         if( iUpperMax < 0 )
+           iUpperMax = 0;
+         
+
+         if( iLowerMin > iDasherY )
+           iLowerMin = iDasherY;
+         
+         if( iLowerMax > iDasherY )
+           iLowerMax = iDasherY;
+
+         if( iUpperMin > iDasherY )
+           iUpperMin = iDasherY;
+         
+         if( iUpperMax > iDasherY )
+           iUpperMax = iDasherY;
+
+         while( iLowerMin < y1 ) 
+           iLowerMin += iSpacing;
+
+         while( iLowerMax > iTipMin)
+           iLowerMax -= iSpacing;
+          
+         while( iUpperMin < iTipMax )
+           iUpperMin += iSpacing;
+
+         while( iUpperMax > y2 )
+           iUpperMax -= iSpacing;
+
+
+         int iLowerCount( (iLowerMax - iLowerMin) / iSpacing + 1 );
+         int iUpperCount( (iUpperMax - iUpperMin) / iSpacing + 1 );
+
+         if( iLowerCount < 0 )
+           iLowerCount = 0;
+         
+         if( iUpperCount < 0 )
+           iUpperCount = 0;
+
+         int iTotalCount( iLowerCount + iUpperCount + 6 );
+
+         myint *x =  new myint[iTotalCount] ;
+         myint *y =  new myint[iTotalCount] ;
+
+         // Weird duplication here is to make truncated squares possible too
+
+         x[0] = 0;
+         y[0] = y1;
+         x[1] = iXStart;
+         y[1] = y1;
+
+         x[iLowerCount + 2] = iDasherSize;
+         y[iLowerCount + 2] = iTipMin;
+         x[iLowerCount + 3] = iDasherSize;
+         y[iLowerCount + 3] = iTipMax;
+
+         x[iTotalCount - 2] = iXStart;
+         y[iTotalCount - 2] = y2;
+         x[iTotalCount - 1] = 0;
+         y[iTotalCount - 1] = y2;
+
+         for( int i(0); i < iLowerCount; ++i ) {
+           x[i+2] = (iLowerMin + i * iSpacing - y1) * (iDasherSize - iXStart) / (iTipMin - y1) + iXStart;
+           y[i+2] = iLowerMin + i * iSpacing;
+         }
+
+         for( int j(0); j < iUpperCount; ++j ) {
+           x[j+iLowerCount + 4] = (y2 - (iUpperMin + j * iSpacing)) * (iDasherSize - iXStart) / (y2 - 
iTipMax) + iXStart;
+           y[j+iLowerCount + 4] = iUpperMin + j * iSpacing;
+         }
+         
+         DasherPolygon( x, y, iTotalCount, Color );
+
+       delete x;
+       delete y;
+
+       }
+       
+       myint iDasherAnchorX( iDasherSize );
+
+       myint iDasherAnchorY( (std::min(y2 , DasherVisibleMaxY()) + std::max(y1, DasherVisibleMinY()))/2 );
+       
+       std::string sDisplayText;
+       
+       if( displaytext != std::string("") )
+         sDisplayText = displaytext;
+       else
+         sDisplayText = DasherModel().GetDisplayText(Character);
+       
+       DasherDrawText( iDasherAnchorX, y1, iDasherAnchorX, y2, sDisplayText, mostleft );
+       
+       return 1;
+}
+
+/////////////////////////////////////////////////////////////////////////////
+
+void CDasherViewSquare::CheckForNewRoot()
+{
+       CDasherNode * const root=DasherModel().Root();
+       CDasherNode ** const children=root->Children();
+
+
+       myint y1=DasherModel().Rootmin();
+       myint y2=DasherModel().Rootmax();
+
+       // This says that the root node must enclose everything visible.
+       // Tiny probability characters near the bottom will cause a problem
+       // with forcing to reparent to the previous one.
+
+       if ((y1>myint(0) || y2 < DasherModel().DasherY() || dasherx2screen(y2-y1)>0)) {
+               DasherModel().Reparent_root(root->Lbnd(),root->Hbnd());
+               return;
+       }
+
+       if (children==0)
+               return;
+
+       int alive=0;
+       int theone=0;
+       unsigned int i;
+
+       // Find whether there is exactly one alive child; if more, we don't care.
+       for (i=0;i<root->ChildCount();i++) 
+       {
+               if (children[i]->Alive()) 
+               {
+                       alive++;
+                       theone=i;
+            if(alive>1) break; 
+               }
+       }
+
+       if (alive==1) 
+       {         
+       // We must have zoomed sufficiently that only one child of the root node 
+       // is still alive.  Let's make it the root.
+
+         y1=DasherModel().Rootmin();
+         y2=DasherModel().Rootmax();
+         myint range=y2-y1;
+
+         myint newy1=y1+(range*children[theone]->Lbnd())/(int)GetLongParameter(LP_NORMALIZATION);
+         myint newy2=y1+(range*children[theone]->Hbnd())/(int)GetLongParameter(LP_NORMALIZATION);
+         if (newy1<myint(0) && newy2> DasherModel().DasherY()) {
+           myint left=dasherx2screen(newy2-newy1);
+           if (left<myint(0)) {
+             DasherModel().Make_root(theone);
+             return;
+           }
+         }
+       }
 }
 
 CDasherNode *CDasherViewSquare::Render(CDasherNode *pRoot, myint iRootMin, myint iRootMax,


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