Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*
3 : : * This file is part of the LibreOffice project.
4 : : *
5 : : * This Source Code Form is subject to the terms of the Mozilla Public
6 : : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : : *
9 : : * This file incorporates work covered by the following license notice:
10 : : *
11 : : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : : * contributor license agreements. See the NOTICE file distributed
13 : : * with this work for additional information regarding copyright
14 : : * ownership. The ASF licenses this file to you under the Apache
15 : : * License, Version 2.0 (the "License"); you may not use this file
16 : : * except in compliance with the License. You may obtain a copy of
17 : : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : : */
19 : :
20 : : #include <editeng/TreeHead.hxx>
21 : : #include <editeng/Node.hxx>
22 : :
23 : 33334 : Node::Node(TreeHead* const pHead, Node* const pParent,
24 : : const sal_Unicode cKey, const int nProbability ) :
25 : : m_cKey( cKey ),
26 : : m_nKeyProbability( nProbability ),
27 : : m_nHighestProbaInSubtree( 0 ),
28 : : m_pParent( pParent ),
29 : : m_pSuggest( NULL ),
30 : : m_pHead( pHead ),
31 : 33334 : m_nChildren( 0 )
32 : : {
33 : 33334 : }
34 : :
35 : 33334 : Node::~Node()
36 : : {
37 [ - + ]: 33334 : }
38 : :
39 : 320 : void Node::removeChild(Node*& pChild)
40 : : {
41 : 320 : const sal_Unicode cKey = pChild->m_cKey;
42 : :
43 [ + - ]: 320 : if ( pChild )
44 : : {
45 [ + - ]: 320 : delete pChild;
46 : 320 : pChild = NULL;
47 : 320 : --m_nChildren;
48 : : }
49 : :
50 [ + + ]: 320 : if ( !isSeparatedlyHandled( cKey ) )
51 : : {
52 : 100 : std::list<Node*>::iterator i = m_lChildren.begin();
53 [ + + ]: 210 : while ( i != m_lChildren.end() )
54 : : {
55 [ + + ]: 110 : if ( !(*i) )
56 : : {
57 [ + - ]: 100 : i = m_lChildren.erase( i );
58 : : }
59 : : else
60 : : {
61 : 10 : ++i;
62 : : }
63 : : }
64 : : }
65 : 320 : }
66 : :
67 : 86487 : void Node::insertKey(OUString sKey, const int nProbability)
68 : : {
69 [ + + ]: 86487 : if ( !sKey.isEmpty() )
70 : : {
71 : 83653 : const sal_Unicode cKey = sKey[0];
72 : 83653 : sKey = sKey.copy( 1 );
73 : :
74 : 83653 : Node*& pChild = getChildRef( cKey, true );
75 : :
76 [ + + ]: 83653 : if ( !pChild )
77 : : {
78 : 32949 : pChild = m_pHead->newNode( this, cKey );
79 : 32949 : ++m_nChildren;
80 : : }
81 : :
82 [ + - ]: 83653 : pChild->insertKey( sKey, nProbability );
83 : : }
84 : : else
85 : : {
86 : 2834 : m_nKeyProbability += nProbability;
87 [ + - ]: 2834 : if ( m_pParent )
88 : : {
89 : : // inform parent about change
90 [ + + ]: 2834 : int probability = m_nHighestProbaInSubtree > m_nKeyProbability ? m_nHighestProbaInSubtree : m_nKeyProbability;
91 : 2834 : m_pParent->childHasChanged( this, probability);
92 : : }
93 : : }
94 : 86487 : }
95 : :
96 : : // Removes a complete keyword starting from this node of the tree.
97 : 510 : void Node::removeKey(OUString sKey)
98 : : {
99 [ + + ]: 510 : if ( !sKey.isEmpty() )
100 : : {
101 : 475 : Node*& pChild = getChildRef( sKey[0] );
102 : :
103 [ + + ]: 475 : if ( pChild )
104 : : {
105 : : // recursive call downwards
106 [ + - ]: 470 : pChild->removeKey( sKey.copy( 1 ) );
107 : : }
108 : : // Else: Keyword to be removed couldn't be found within the tree.
109 : : // No further changes are going to be made.
110 : : }
111 : : else // If we are the node to be removed...
112 : : {
113 : : // ... remove our entry from tree...
114 : 35 : m_nKeyProbability = 0;
115 : : // ... and make sure our parent is updated.
116 : 35 : m_pParent->childHasChanged( this, m_nHighestProbaInSubtree, this != m_pHead->m_pCurrent );
117 : : }
118 : 510 : }
119 : :
120 : 400 : Node *Node::advanceKey(const sal_Unicode cKey)
121 : : {
122 : 400 : Node*& pChild = getChildRef( cKey, true );
123 : :
124 [ + + ]: 400 : if ( !pChild )
125 : : {
126 : 285 : pChild = m_pHead->newNode( this, cKey );
127 : : }
128 : :
129 : 400 : return pChild;
130 : : }
131 : :
132 : 68442 : void Node::childHasChanged(Node *pChild, const int nProbability, bool bAllowRemoval)
133 : : {
134 [ + + ]: 68442 : if ( nProbability > m_nHighestProbaInSubtree )
135 : : {
136 : 65152 : m_pSuggest = pChild;
137 : 65152 : m_nHighestProbaInSubtree = nProbability;
138 : :
139 [ + + ]: 65152 : if ( m_pParent ) // recursive call upwards
140 : : {
141 [ + + ]: 65068 : int probabilityChange = nProbability > m_nKeyProbability ? nProbability : m_nKeyProbability;
142 : 65068 : m_pParent->childHasChanged( this, probabilityChange );
143 : : }
144 : : }
145 [ + + ][ + + ]: 3290 : else if ( !nProbability || nProbability < m_nHighestProbaInSubtree )
146 : : {
147 : 1070 : bool bNewEvaluationRequired = m_pSuggest == pChild;
148 : :
149 [ + + ][ + - ]: 1070 : if ( !nProbability && bAllowRemoval )
150 : : {
151 : : // Remove child. Caller needs to make sure we are allowed to.
152 : 310 : removeChild( getChildRef( pChild->m_cKey ) );
153 : : }
154 : :
155 [ + + ]: 1070 : if ( bNewEvaluationRequired )
156 : : {
157 : : // This is used to store whether we need to inform our parent about
158 : : // the changes within this node.
159 : : bool bNodeProbabilityChanged;
160 : :
161 [ + - ]: 520 : reevaluateSuggestion( bNodeProbabilityChanged );
162 : :
163 : : // If necessary, inform our parent about change via recursive call
164 [ + - ][ + + ]: 520 : if ( bNodeProbabilityChanged && m_pParent )
165 : : {
166 [ + - ][ + - ]: 480 : bAllowRemoval = bAllowRemoval && this != m_pHead->m_pCurrent;
167 [ + + ]: 480 : int probabilityChange = m_nHighestProbaInSubtree > m_nKeyProbability ? m_nHighestProbaInSubtree : m_nKeyProbability;
168 [ + - ]: 520 : m_pParent->childHasChanged( this, probabilityChange, bAllowRemoval );
169 : : }
170 : : }
171 : : }
172 : 68442 : }
173 : :
174 : 520 : void Node::reevaluateSuggestion(bool& bNodeProbabilityChanged)
175 : : {
176 [ + + ]: 520 : if ( m_nChildren ) // find child with highest probability
177 : : {
178 : 385 : int nSuggest = 0;
179 : 385 : Node* pSuggest = NULL;
180 : :
181 : : // find child with highest probability in array
182 [ + - ]: 385 : evaluateSeparateStorage( nSuggest, pSuggest );
183 : :
184 : : // do the same thing within list
185 [ + + ]: 395 : for ( std::list<Node*>::iterator i = m_lChildren.begin(); i != m_lChildren.end(); ++i )
186 : : {
187 [ + - ]: 10 : if ( (*i)->m_nHighestProbaInSubtree > nSuggest )
188 : : {
189 : 10 : nSuggest = (*i)->m_nHighestProbaInSubtree;
190 : 10 : pSuggest = (*i);
191 : : }
192 [ - + ]: 10 : if ( (*i)->m_nKeyProbability > nSuggest )
193 : : {
194 : 0 : nSuggest = (*i)->m_nKeyProbability;
195 : 0 : pSuggest = (*i);
196 : : }
197 : : }
198 : :
199 : : // determine whether we need to inform our parent
200 : 385 : bNodeProbabilityChanged = m_nHighestProbaInSubtree != nSuggest;
201 : :
202 : 385 : m_pSuggest = pSuggest;
203 : 385 : m_nHighestProbaInSubtree = nSuggest;
204 : : }
205 : : else // there are no children
206 : : {
207 : 135 : m_pSuggest = NULL;
208 : 135 : m_nHighestProbaInSubtree = 0;
209 : :
210 : 135 : bNodeProbabilityChanged = true;
211 : : }
212 : 520 : }
213 : :
214 : : Node* Node::our_pNodeNullPointer = NULL;
215 : :
216 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|