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/LatinLookupTree.hxx>
21 : #include <editeng/LatinTreeNode.hxx>
22 :
23 26 : LatinLookupTree::LatinLookupTree(OUString sLanguage) :
24 26 : LookupTree( sLanguage )
25 : {
26 1378 : for ( sal_Unicode i = 0; i < 52; ++i )
27 : {
28 1352 : m_pLeaves[i] = NULL;
29 : }
30 26 : }
31 :
32 78 : LatinLookupTree::~LatinLookupTree()
33 : {
34 26 : freeMemory();
35 52 : }
36 :
37 50 : void LatinLookupTree::returnToRoot()
38 : {
39 50 : if ( m_pCurrent == m_pHead )
40 82 : return;
41 :
42 : // If there is no entry in this node or the tree that sprouts from it.
43 46 : if ( m_pCurrent &&
44 : m_pCurrent->m_pParent &&
45 18 : !m_pCurrent->m_nChildren &&
46 10 : !m_pCurrent->m_nKeyProbability )
47 : {
48 6 : m_pCurrent->m_pParent->childHasChanged( m_pCurrent, 0, true );
49 : }
50 :
51 18 : m_pCurrent = m_pHead;
52 : }
53 :
54 16 : void LatinLookupTree::gotoNode(OUString sNode)
55 : {
56 16 : returnToRoot();
57 :
58 : // walk down the tree...
59 148 : for ( int i = 0; i < sNode.getLength(); i++ )
60 : {
61 132 : m_pCurrent = m_pCurrent->advanceKey( sNode[i] );
62 : }
63 16 : }
64 :
65 28 : void LatinLookupTree::advance(const sal_Unicode cKey)
66 : {
67 28 : m_pCurrent = m_pCurrent->advanceKey( cKey );
68 28 : }
69 :
70 8 : void LatinLookupTree::goBack()
71 : {
72 8 : if ( m_pCurrent->m_pParent ) // if we're not at the root
73 : {
74 8 : const Node* const pChild = m_pCurrent;
75 8 : m_pCurrent = m_pCurrent->m_pParent; // set focus to parent
76 :
77 : // if this is an unused tree leaf
78 8 : if ( !pChild->m_nChildren && !pChild->m_nKeyProbability )
79 : {
80 4 : m_pCurrent->removeChild( m_pCurrent->getChildRef( pChild->m_cKey ) );
81 : }
82 : }
83 8 : }
84 :
85 43 : void LatinLookupTree::insert(OUString sKey, const int nProbability)
86 : {
87 43 : if ( !sKey.isEmpty() && nProbability > 0 )
88 : {
89 43 : insertKey( sKey, nProbability );
90 : }
91 43 : }
92 :
93 4 : void LatinLookupTree::insert(const int nProbability)
94 : {
95 4 : if ( m_pCurrent == this )
96 4 : return;
97 :
98 : // change probability
99 4 : int proba = m_pCurrent->m_nKeyProbability += nProbability;
100 :
101 : // inform his parent
102 4 : m_pCurrent->m_pParent->childHasChanged( m_pCurrent, proba );
103 : }
104 :
105 16 : void LatinLookupTree::remove(OUString sKey)
106 : {
107 16 : returnToRoot();
108 :
109 16 : if ( !sKey.isEmpty() )
110 : {
111 16 : removeKey( sKey );
112 : }
113 16 : }
114 :
115 84 : OUString LatinLookupTree::suggestAutoCompletion() const
116 : {
117 84 : if ( !m_pCurrent )
118 0 : return OUString();
119 :
120 84 : Node* pWalker = m_pCurrent;
121 :
122 84 : int distance = 0, nTargetProbability = 0;
123 84 : OUString sSuggestion;
124 :
125 722 : while ( pWalker->m_pSuggest && ( distance < 2 ||
126 : // Make sure the suggestion is at least 2 chars long.
127 : nTargetProbability == pWalker->m_nHighestProbaInSubtree ) )
128 : {
129 554 : if ( distance < 2 )
130 124 : nTargetProbability = pWalker->m_nHighestProbaInSubtree;
131 :
132 : // follow the tree along the suggested route
133 554 : pWalker = pWalker->m_pSuggest;
134 554 : ++distance;
135 554 : sSuggestion += OUString(pWalker->m_cKey);
136 : }
137 :
138 84 : return sSuggestion;
139 : }
140 :
141 0 : void LatinLookupTree::clear()
142 : {
143 0 : freeMemory();
144 0 : }
145 :
146 8 : bool LatinLookupTree::isSeparatedlyHandled(const sal_Unicode cKey) const
147 : {
148 : return
149 : ( cKey >= sal_Unicode('a') && cKey <= sal_Unicode('z') )
150 8 : || ( cKey >= sal_Unicode('A') && cKey <= sal_Unicode('Z') );
151 : }
152 :
153 89 : Node*& LatinLookupTree::getChildRef(const sal_Unicode cKey, bool bCreatePlaceholder)
154 : {
155 89 : int pos = -1;
156 :
157 : // determine position in array if possible
158 89 : if ( cKey >= sal_Unicode('a') && cKey <= sal_Unicode('z') )
159 : {
160 47 : pos = cKey - our_nLowerCaseA;
161 : }
162 42 : else if ( cKey >= sal_Unicode('A') && cKey <= sal_Unicode('Z') )
163 : {
164 38 : pos = cKey - our_nUpperCaseA + 26;
165 : }
166 :
167 89 : if ( pos != -1 )
168 : {
169 85 : return m_pLeaves[pos];
170 : }
171 : else
172 : {
173 4 : for ( std::list<Node*>::iterator i = m_lChildren.begin(); i != m_lChildren.end(); ++i )
174 : {
175 2 : if ( (*i)->m_cKey == cKey )
176 : {
177 2 : return *i;
178 : }
179 : }
180 2 : if ( bCreatePlaceholder )
181 : {
182 : // Create new entry in case there isn't one.
183 2 : m_lChildren.push_back( NULL );
184 2 : return *(--m_lChildren.end());
185 : }
186 : else
187 : {
188 0 : return our_pNodeNullPointer;
189 : }
190 : }
191 : }
192 :
193 14 : void LatinLookupTree::evaluateSeparateStorage(int& nSuggest, Node*& pSuggest) const
194 : {
195 742 : for ( sal_Unicode i = 0; i < 52; ++i )
196 : {
197 728 : if ( m_pLeaves[i] )
198 : {
199 20 : if ( m_pLeaves[i]->m_nHighestProbaInSubtree > nSuggest )
200 : {
201 20 : nSuggest = m_pLeaves[i]->m_nHighestProbaInSubtree;
202 20 : pSuggest = m_pLeaves[i];
203 : }
204 20 : if ( m_pLeaves[i]->m_nKeyProbability > nSuggest )
205 : {
206 0 : nSuggest = m_pLeaves[i]->m_nKeyProbability;
207 0 : pSuggest = m_pLeaves[i];
208 : }
209 : }
210 : }
211 14 : }
212 :
213 26 : void LatinLookupTree::freeMemory()
214 : {
215 : // remove nodes from array
216 1378 : for ( sal_Unicode i = 0; i < 52; ++i )
217 : {
218 1352 : if ( m_pLeaves[i] )
219 : {
220 11 : m_pLeaves[i]->freeMemory();
221 11 : delete m_pLeaves[i];
222 11 : m_pLeaves[i] = NULL;
223 : }
224 : }
225 : // clear list
226 54 : while ( m_lChildren.size() )
227 : {
228 2 : Node* pTmp = m_lChildren.front();
229 2 : m_lChildren.pop_front();
230 2 : delete pTmp;
231 : }
232 26 : }
233 :
234 268 : Node* LatinLookupTree::newNode(Node* pParent, const sal_Unicode cKey, const int nProbability)
235 : {
236 268 : return new LatinTreeNode( this, pParent, cKey, nProbability );
237 : }
238 :
239 : const unsigned int LatinLookupTree::our_nLowerCaseA = 97;
240 : const unsigned int LatinLookupTree::our_nUpperCaseA = 65;
241 :
242 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|