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