tagging release
[dasher.git] / trunk / Src / DasherCore / DasherNode.cpp
blobc350ab675c0cb2d67b1596c023fa226bf2700b5b
1 // DasherNode.cpp
2 //
3 // Copyright (c) 2007 David Ward
4 //
5 // This file is part of Dasher.
6 //
7 // Dasher is free software; you can redistribute it and/or modify
8 // it under the terms of the GNU General Public License as published by
9 // the Free Software Foundation; either version 2 of the License, or
10 // (at your option) any later version.
12 // Dasher is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with Dasher; if not, write to the Free Software
19 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "../Common/Common.h"
23 #include "AlphabetManager.h"
25 #include "DasherNode.h"
27 using namespace Dasher;
28 using namespace Opts;
29 using namespace std;
31 // Track memory leaks on Windows to the line that new'd the memory
32 #ifdef _WIN32
33 #ifdef _DEBUG
34 #define DEBUG_NEW new( _NORMAL_BLOCK, THIS_FILE, __LINE__ )
35 #define new DEBUG_NEW
36 #undef THIS_FILE
37 static char THIS_FILE[] = __FILE__;
38 #endif
39 #endif
41 // TODO: put this back to being inlined
42 CDasherNode::~CDasherNode() {
43 // std::cout << "Deleting node: " << this << std::endl;
44 // Release any storage that the node manager has allocated,
45 // unreference ref counted stuff etc.
46 Delete_children();
48 m_pNodeManager->ClearNode( this );
49 m_pNodeManager->Unref();
51 // std::cout << "done." << std::endl;
53 delete m_pDisplayInfo;
57 void CDasherNode::Trace() const {
58 /* TODO sort out
59 dchar out[256];
60 if (m_Symbol)
61 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);
62 else
63 wsprintf(out,TEXT("%7x %7x %5d %7x %5d %8x %8x \n"),this,m_iGroup,m_context,m_Children,m_Cscheme,m_iLbnd,m_iHbnd);
65 OutputDebugString(out);
67 if (m_Children) {
68 unsigned int i;
69 for (i=1;i<m_iChars;i++)
70 m_Children[i]->Dump_node();
75 bool CDasherNode::NodeIsParent(CDasherNode *oldnode) const {
76 if(oldnode == m_pParent)
77 return true;
78 else
79 return false;
83 CDasherNode *const CDasherNode::Get_node_under(int iNormalization, myint miY1, myint miY2, myint miMousex, myint miMousey) {
84 myint miRange = miY2 - miY1;
86 // TODO: Manipulating flags in a 'get' method?
87 SetFlag(NF_ALIVE, true);
89 ChildMap::const_iterator i;
90 for(i = GetChildren().begin(); i != GetChildren().end(); i++) {
91 CDasherNode *pChild = *i;
93 myint miNewy1 = miY1 + (miRange * pChild->m_iLbnd) / iNormalization;
94 myint miNewy2 = miY1 + (miRange * pChild->m_iHbnd) / iNormalization;
95 if(miMousey < miNewy2 && miMousey > miNewy1 && miMousex < miNewy2 - miNewy1)
96 return pChild->Get_node_under(iNormalization, miNewy1, miNewy2, miMousex, miMousey);
98 return this;
101 // kill ourselves and all other children except for the specified
102 // child
103 // FIXME this probably shouldn't be called after history stuff is working
104 void CDasherNode::OrphanChild(CDasherNode *pChild) {
105 DASHER_ASSERT(ChildCount() > 0);
107 ChildMap::const_iterator i;
108 for(i = GetChildren().begin(); i != GetChildren().end(); i++) {
109 if((*i) != pChild) {
110 (*i)->Delete_children();
111 delete (*i);
115 pChild->SetParent(NULL);
117 Children().clear();
118 SetFlag(NF_ALLCHILDREN, false);
121 // Delete nephews of the child which has the specified symbol
122 // TODO: Need to allow for subnode
123 void CDasherNode::DeleteNephews(CDasherNode *pChild) {
124 DASHER_ASSERT(Children().size() > 0);
126 ChildMap::iterator i;
127 for(i = Children().begin(); i != Children().end(); i++) {
128 if((*i)->GetFlag(NF_SUBNODE))
129 (*i)->DeleteNephews(pChild);
130 else {
131 if(*i != pChild) {
132 (*i)->Delete_children();
138 // TODO: Need to allow for subnodes
139 // TODO: Incorporate into above routine
140 void CDasherNode::Delete_children() {
141 // CAlphabetManager::SAlphabetData *pParentUserData(static_cast<CAlphabetManager::SAlphabetData *>(m_pUserData));
143 // if((GetDisplayInfo()->strDisplayText)[0] == 'e')
144 // std::cout << "ed: " << this << " " << pParentUserData->iContext << " " << pParentUserData->iOffset << std::endl;
146 // std::cout << "Start: " << this << std::endl;
148 ChildMap::iterator i;
149 for(i = Children().begin(); i != Children().end(); i++) {
150 // std::cout << "CNM: " << (*i)->m_pNodeManager << " (" << (*i)->m_pNodeManager->GetID() << ") " << (*i) << " " << (*i)->Parent() << std::endl;
151 delete (*i);
153 Children().clear();
154 // std::cout << "NM: " << m_pNodeManager << std::endl;
155 SetFlag(NF_ALLCHILDREN, false);
158 // Gets the probability of this node, conditioned on the parent
159 double CDasherNode::GetProb(int iNormalization) {
160 return (double) (m_iHbnd - m_iLbnd) / (double) iNormalization;
163 void CDasherNode::ConvertWithAncestors() {
164 if(GetFlag(NF_CONVERTED))
165 return;
167 SetFlag(NF_CONVERTED, true);
169 if(m_pParent)
170 m_pParent->ConvertWithAncestors();
173 void CDasherNode::SetFlag(int iFlag, bool bValue) {
174 if(bValue)
175 m_iFlags = m_iFlags | iFlag;
176 else
177 m_iFlags = m_iFlags & (~iFlag);
179 m_pNodeManager->SetFlag(this, iFlag, bValue);
182 void CDasherNode::SetParent(CDasherNode *pNewParent) {
183 m_pParent = pNewParent;
186 int CDasherNode::MostProbableChild() {
187 int iMax(0);
188 int iCurrent;
190 for(ChildMap::iterator it(m_mChildren.begin()); it != m_mChildren.end(); ++it) {
191 iCurrent = (*it)->Range();
193 if(iCurrent > iMax)
194 iMax = iCurrent;
197 return iMax;