|
1 /* |
|
2 * Copyright (c) 2002-2005 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0"" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Implementation of the vkb data manager |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // system includes |
|
20 |
|
21 |
|
22 // user includes |
|
23 #include "AknFepVkbPinyinAnalyser.h" |
|
24 #include "AknFepVkbPinyinAnalyserDb.h" |
|
25 |
|
26 class TSpellBand |
|
27 { |
|
28 public: |
|
29 int iStart; |
|
30 int iCount; |
|
31 }; |
|
32 |
|
33 |
|
34 class TSpellAnalysis : public TPriQueLink |
|
35 { |
|
36 public: |
|
37 RArray<TInt> iSeparators; |
|
38 TSpellAnalysis() |
|
39 { |
|
40 iPriority = -0x10000; |
|
41 } |
|
42 ~TSpellAnalysis() |
|
43 { |
|
44 iSeparators.Close(); |
|
45 } |
|
46 |
|
47 TSpellAnalysis(const TSpellAnalysis& aSource) |
|
48 { |
|
49 iPriority = aSource.iPriority; |
|
50 for( TInt i = 0; i < aSource.iSeparators.Count(); ++i ) |
|
51 { |
|
52 iSeparators.Append(aSource.iSeparators[i]); |
|
53 } |
|
54 } |
|
55 void Calculate() |
|
56 { |
|
57 iPriority = (iSeparators.Count() + 1) << 16; |
|
58 TInt multi = 12; |
|
59 for( TInt i = 0; i < iSeparators.Count(); ++i ) |
|
60 { |
|
61 iPriority += ( 6 - iSeparators[i]) << multi; |
|
62 if( multi >= 3 ) |
|
63 { |
|
64 multi -= 3; |
|
65 } |
|
66 } |
|
67 iPriority = -iPriority; |
|
68 } |
|
69 TInt GetStartPos() |
|
70 { |
|
71 if( iSeparators.Count() == 0) |
|
72 { |
|
73 return 0; |
|
74 } |
|
75 else |
|
76 { |
|
77 return iSeparators[ iSeparators.Count() - 1 ]; |
|
78 } |
|
79 } |
|
80 void AddSeparator(TInt aPos) |
|
81 { |
|
82 iSeparators.Append(aPos); |
|
83 Calculate(); |
|
84 } |
|
85 }; |
|
86 |
|
87 // ----------------------------------------------------------------------------- |
|
88 // CAknFepVkbPinyinAnalyser::CAknFepVkbPinyinAnalyser |
|
89 // (other items were commented in a header). |
|
90 // ----------------------------------------------------------------------------- |
|
91 // |
|
92 CAknFepVkbPinyinAnalyser::CAknFepVkbPinyinAnalyser() |
|
93 { |
|
94 iAnalysisFlag = EFalse; |
|
95 } |
|
96 |
|
97 // ----------------------------------------------------------------------------- |
|
98 // CAknFepVkbPinyinAnalyser::NewL |
|
99 // (other items were commented in a header). |
|
100 // ----------------------------------------------------------------------------- |
|
101 // |
|
102 CAknFepVkbPinyinAnalyser* CAknFepVkbPinyinAnalyser::NewL( CPinyinAnalyserDbFeed* aDb ) |
|
103 { |
|
104 CAknFepVkbPinyinAnalyser* self = new ( ELeave ) CAknFepVkbPinyinAnalyser(); |
|
105 CleanupStack::PushL(self); |
|
106 self->ConstructL( aDb ); |
|
107 CleanupStack::Pop(); |
|
108 return self; |
|
109 } |
|
110 |
|
111 // ----------------------------------------------------------------------------- |
|
112 // CAknFepVkbPinyinAnalyser::~CAknFepVkbPinyinAnalyser |
|
113 // (other items were commented in a header). |
|
114 // ----------------------------------------------------------------------------- |
|
115 // |
|
116 CAknFepVkbPinyinAnalyser::~CAknFepVkbPinyinAnalyser() |
|
117 { |
|
118 delete []iParagraph; |
|
119 delete []iSpellLibrary; |
|
120 delete iLastResult; |
|
121 delete iDb; |
|
122 } |
|
123 |
|
124 |
|
125 void CAknFepVkbPinyinAnalyser::ConstructL( CPinyinAnalyserDbFeed* aDb ) |
|
126 { |
|
127 ASSERT( aDb != NULL ); |
|
128 iDb = aDb; |
|
129 |
|
130 TInt length = iDb->GetSpellCount(); |
|
131 |
|
132 iSpellLibrary = new(ELeave) TPtrC[length]; |
|
133 for(TInt i = 0; i < length; ++i ) |
|
134 { |
|
135 iSpellLibrary[i].Set( aDb->GetSpellByIndex( i ) ); |
|
136 } |
|
137 |
|
138 TInt current = 0; |
|
139 TInt pinyinElementCount = iDb->GetSpellElementCount(); |
|
140 iParagraph = new(ELeave) TSpellBand[pinyinElementCount]; |
|
141 iParagraph[current].iStart = 0; |
|
142 for(TInt i = 0; i < length; ++i ) |
|
143 { |
|
144 if( iSpellLibrary[i][0] != iDb->GetSpellElementByIndex( current ) ) |
|
145 { |
|
146 iParagraph[current].iCount = i - iParagraph[current].iStart; |
|
147 current++; |
|
148 iParagraph[current].iStart = i; |
|
149 while( iSpellLibrary[i][0] != iDb->GetSpellElementByIndex( current ) ) |
|
150 { |
|
151 iParagraph[current].iCount = 0; |
|
152 current ++; |
|
153 iParagraph[current].iStart = i; |
|
154 } |
|
155 } |
|
156 } |
|
157 |
|
158 iParagraph[current].iCount = length - iParagraph[current].iStart; |
|
159 |
|
160 } |
|
161 |
|
162 |
|
163 HBufC* CAknFepVkbPinyinAnalyser::LastAnalysisResult() |
|
164 { |
|
165 return iLastResult; |
|
166 } |
|
167 |
|
168 TBool CAknFepVkbPinyinAnalyser::AnalyzeL(const TDesC& aInputString) |
|
169 { |
|
170 delete iLastResult; |
|
171 iLastResult = NULL; |
|
172 |
|
173 iLastResult = HBufC::NewL(aInputString.Length() * 2); |
|
174 |
|
175 if( aInputString.Length() < 1 ) |
|
176 { |
|
177 return ETrue; |
|
178 } |
|
179 |
|
180 if( aInputString.Length() == 1 ) |
|
181 { |
|
182 iLastResult->Des().Append( aInputString[0] ); |
|
183 if ( iDb->IsFirstElement( aInputString[0] ) ) |
|
184 { |
|
185 return ETrue; |
|
186 } |
|
187 else |
|
188 { |
|
189 return EFalse; |
|
190 } |
|
191 } |
|
192 |
|
193 int first = 0; |
|
194 int second = 1; |
|
195 int previous = 0; |
|
196 iAnalysisFlag = ETrue; |
|
197 //rough spilit |
|
198 for(; second < aInputString.Length(); first++, second++ ) |
|
199 { |
|
200 if( !iDb->IsNormalElement(aInputString[first]) ) |
|
201 { |
|
202 //go to detail analysis |
|
203 if( first > previous) |
|
204 { |
|
205 TPtrC toanalysis = aInputString.Mid(previous, first - previous); |
|
206 DetailAnalyse(toanalysis); |
|
207 } |
|
208 |
|
209 iLastResult->Des().Append(aInputString[first]); |
|
210 previous = first + 1; |
|
211 } |
|
212 else if(!iDb->IsNormalElement(aInputString[second]) ) |
|
213 { |
|
214 //go to detail analysis |
|
215 if( second > previous) |
|
216 { |
|
217 TPtrC toanalysis = aInputString.Mid(previous, second - previous); |
|
218 DetailAnalyse(toanalysis); |
|
219 } |
|
220 |
|
221 iLastResult->Des().Append(aInputString[second]); |
|
222 previous = second + 1; |
|
223 first ++; |
|
224 second ++; |
|
225 } |
|
226 else if( iDb->GetSpellElementType( aInputString[first]) == ESpellVowel || |
|
227 iDb->GetSpellElementType( aInputString[second]) == ESpellVowel) |
|
228 { |
|
229 continue; |
|
230 } |
|
231 else if( iDb->GetSpellElementType( aInputString[first]) == ESpellConsonant || |
|
232 iDb->GetSpellElementType( aInputString[second]) == ESpellConsonant ) |
|
233 { |
|
234 //go to detail analysis |
|
235 TPtrC toanalysis = aInputString.Mid(previous, second - previous); |
|
236 DetailAnalyse(toanalysis); |
|
237 iLastResult->Des().Append(KProgramSeparator); |
|
238 previous = second; |
|
239 } |
|
240 else |
|
241 { |
|
242 if( (aInputString[second] == L'h' && ( aInputString[first] == L'z' || |
|
243 aInputString[first] == L'c' || aInputString[first] == L's')) || //ch, sh, zh |
|
244 (aInputString[second] == L'g' && aInputString[first] == L'n') || //ng |
|
245 (aInputString[second] == L'n' && aInputString[first] == L'h') //hn |
|
246 ) |
|
247 { |
|
248 } |
|
249 else |
|
250 { |
|
251 //go to detail analysis |
|
252 TPtrC toanalysis = aInputString.Mid(previous, second - previous); |
|
253 DetailAnalyse(toanalysis); |
|
254 iLastResult->Des().Append(KProgramSeparator); |
|
255 previous = second; |
|
256 } |
|
257 } |
|
258 } |
|
259 |
|
260 if( aInputString.Length() <= previous || second > aInputString.Length() ) |
|
261 { |
|
262 return iAnalysisFlag; |
|
263 } |
|
264 |
|
265 TPtrC toanalysis = aInputString.Mid(previous, second - previous); |
|
266 DetailAnalyse(toanalysis); |
|
267 return iAnalysisFlag; |
|
268 } |
|
269 |
|
270 TSpellAnalysis* CreateTSpellAnalysisL() |
|
271 { |
|
272 return new(ELeave) TSpellAnalysis(); |
|
273 } |
|
274 TBool CAknFepVkbPinyinAnalyser::DetailAnalyse(const TDesC& aInputString) |
|
275 { |
|
276 TPriQue<TSpellAnalysis> open; |
|
277 TSpellAnalysis* p = NULL; |
|
278 TRAP_IGNORE( p = CreateTSpellAnalysisL()); |
|
279 |
|
280 open.Add(*p); |
|
281 |
|
282 int sameLength; |
|
283 int startPos; |
|
284 TBool findRes; |
|
285 TSpellAnalysis* pNext = NULL; |
|
286 |
|
287 while( !open.IsEmpty() ) |
|
288 { |
|
289 pNext = open.First(); |
|
290 pNext->Deque(); |
|
291 |
|
292 startPos = pNext->GetStartPos(); |
|
293 findRes = FindSpell(aInputString.Mid(startPos), sameLength); |
|
294 |
|
295 if( findRes || sameLength + startPos == aInputString.Length()) |
|
296 { |
|
297 //got it! |
|
298 int start = 0; |
|
299 for( TInt j = 0; j < pNext->iSeparators.Count(); ++j ) |
|
300 { |
|
301 iLastResult->Des().Append(aInputString.Mid(start, pNext->iSeparators[j] - start)); |
|
302 start = pNext->iSeparators[j]; |
|
303 iLastResult->Des().Append(KProgramSeparator); |
|
304 } |
|
305 |
|
306 iLastResult->Des().Append(aInputString.Mid(start, aInputString.Length() - start)); |
|
307 break; |
|
308 } |
|
309 else if( sameLength == 0 ) |
|
310 { |
|
311 delete pNext; |
|
312 pNext = NULL; |
|
313 } |
|
314 else |
|
315 { |
|
316 int partLength = sameLength - 1; |
|
317 while( partLength > 0 ) |
|
318 { |
|
319 int templen; |
|
320 if( FindSpell(aInputString.Mid(startPos, partLength), templen) ) |
|
321 { |
|
322 TSpellAnalysis* q = new TSpellAnalysis(*pNext); |
|
323 q->AddSeparator(startPos + partLength); |
|
324 open.Add(*q); |
|
325 } |
|
326 partLength --; |
|
327 } |
|
328 pNext->AddSeparator(startPos + sameLength); |
|
329 open.Add(*pNext); |
|
330 } |
|
331 } |
|
332 if( pNext ) |
|
333 { |
|
334 delete pNext; |
|
335 pNext = NULL; |
|
336 while( !open.IsEmpty() ) |
|
337 { |
|
338 TSpellAnalysis* p = open.First(); |
|
339 p->Deque(); |
|
340 delete p; |
|
341 } |
|
342 return true; |
|
343 } |
|
344 else |
|
345 { |
|
346 //not found |
|
347 /* |
|
348 FindSpell(aInputString, sameLength); |
|
349 int offset = 0; |
|
350 TBool rtn = sameLength > 0; |
|
351 while( sameLength > 0 ) |
|
352 { |
|
353 iLastResult->Des().Append(aInputString.Mid(offset, sameLength)); |
|
354 iLastResult->Des().Append(KProgramSeparator); |
|
355 offset += sameLength; |
|
356 FindSpell(aInputString.Mid(offset), sameLength); |
|
357 } |
|
358 */ |
|
359 //FindSpell(aInputString, sameLength); |
|
360 int offset = 0; |
|
361 |
|
362 while( offset < aInputString.Length() ) |
|
363 { |
|
364 FindSpell(aInputString.Mid(offset), sameLength); |
|
365 |
|
366 if( sameLength ) |
|
367 { |
|
368 iLastResult->Des().Append(aInputString.Mid(offset, sameLength)); |
|
369 iLastResult->Des().Append(KProgramSeparator); |
|
370 offset += sameLength; |
|
371 } |
|
372 else |
|
373 { |
|
374 iLastResult->Des().Append(aInputString.Mid(offset, 1)); |
|
375 |
|
376 iLastResult->Des().Append(KProgramSeparator); |
|
377 |
|
378 offset += 1; |
|
379 } |
|
380 } |
|
381 if( iLastResult->Des()[ iLastResult->Length() - 1 ] == KProgramSeparator ) |
|
382 { |
|
383 iLastResult->Des().SetLength( iLastResult->Length() - 1 ); |
|
384 } |
|
385 iAnalysisFlag = EFalse; |
|
386 return EFalse; |
|
387 } |
|
388 } |
|
389 |
|
390 TBool CAknFepVkbPinyinAnalyser::FindSpell(const TDesC& aSpell, TInt& aSameLength) |
|
391 { |
|
392 int index = aSpell[0] - iDb->GetSpellElementByIndex( 0 ); |
|
393 |
|
394 int start = iParagraph[index].iStart; |
|
395 int end = iParagraph[index].iCount + iParagraph[index].iStart - 1; |
|
396 int mid = ( start + end ) >> 1; |
|
397 int result = 0; |
|
398 aSameLength = 0; |
|
399 while( mid > start && mid < end ) |
|
400 { |
|
401 result = Compare(iSpellLibrary[mid], aSpell, aSameLength); |
|
402 if( result == 0 ) |
|
403 { |
|
404 return true; |
|
405 } |
|
406 else if( result < 0 ) |
|
407 { |
|
408 start = mid; |
|
409 mid = (start + end ) >> 1; |
|
410 } |
|
411 else |
|
412 { |
|
413 end = mid; |
|
414 mid = (start + end) >> 1; |
|
415 } |
|
416 } |
|
417 int newLength; |
|
418 if( result > 0 ) |
|
419 { |
|
420 result = Compare(iSpellLibrary[start], aSpell, newLength); |
|
421 } |
|
422 else |
|
423 { |
|
424 result = Compare(iSpellLibrary[end], aSpell, newLength); |
|
425 } |
|
426 newLength > aSameLength ? aSameLength = newLength : aSameLength; |
|
427 |
|
428 return result == 0; |
|
429 } |
|
430 |
|
431 TInt CAknFepVkbPinyinAnalyser::Compare(const TDesC& aFirst, const TDesC& aSecond, |
|
432 TInt& aSameLength) |
|
433 { |
|
434 aSameLength = 0; |
|
435 |
|
436 TInt length = aFirst.Length() > aSecond.Length() ? aSecond.Length() : aFirst.Length(); |
|
437 |
|
438 for( TInt i = 0; i < length; ++i ) |
|
439 { |
|
440 if( aFirst[i] != aSecond[i] ) |
|
441 { |
|
442 return aFirst[i] - aSecond[i]; |
|
443 } |
|
444 |
|
445 aSameLength ++; |
|
446 } |
|
447 |
|
448 return aFirst.Length() - aSecond.Length(); |
|
449 } |
|
450 |
|
451 // End of File |