210 |
154 |
211 // --------------------------------------------------------------------------- |
155 // --------------------------------------------------------------------------- |
212 // Compares two strings against others. |
156 // Compares two strings against others. |
213 // --------------------------------------------------------------------------- |
157 // --------------------------------------------------------------------------- |
214 // |
158 // |
215 TInt CFindUtilKorean::IsFindMatch( |
159 TBool CFindUtilKorean::IsFindMatchL( |
216 const TDesC& aItemString, |
160 const TDesC& aItemString, |
217 const TDesC& aSearchText, |
161 const TDesC& aSearchText ) |
218 const TMatchFlag aFlag) |
162 { |
219 { |
163 TBool result( EFalse ); |
220 |
|
221 #ifdef _DEBUG |
|
222 TRAP_IGNORE( |
|
223 HBufC8* bufItemString = HBufC8::NewLC((aItemString.Length() + 1) * 2); |
|
224 HBufC8* bufSearchText = HBufC8::NewLC((aSearchText.Length() + 1) * 2); |
|
225 TPtr8 ptrItemString(bufItemString->Des()); |
|
226 ptrItemString.FillZ(ptrItemString.MaxLength()); |
|
227 TPtr8 ptrSearchText(bufSearchText->Des()); |
|
228 ptrSearchText.FillZ(ptrSearchText.MaxLength()); |
|
229 iConv->ConvertFromUnicode(ptrItemString, aItemString); |
|
230 iConv->ConvertFromUnicode(ptrSearchText, aSearchText); |
|
231 RDebug::Printf("DBG: comparing %s, %s", bufItemString->Ptr(), bufSearchText->Ptr()); |
|
232 CleanupStack::PopAndDestroy(2); |
|
233 ); |
|
234 #endif |
|
235 |
164 |
236 // To disable the wildchar matching provided by MatchC. |
165 // To disable the wildchar matching provided by MatchC. |
237 if ( aFlag == EMatchFlagNone && |
166 if ( KErrNotFound != aSearchText.Locate( KLitQuestion ) && |
238 KErrNotFound != aSearchText.Locate( KLitQuestion ) && |
|
239 KErrNotFound != aSearchText.Locate( KLitStar ) ) |
167 KErrNotFound != aSearchText.Locate( KLitStar ) ) |
240 { |
168 { |
241 #ifdef _DEBUG |
169 return EFalse; |
242 RDebug::Printf("DBG: comparing includes wild"); |
|
243 #endif |
|
244 return KErrNotFound; |
|
245 } |
170 } |
246 |
171 |
247 #if 1 // 2009.08.14 consonent based search |
|
248 TUint flag = aFlag; |
|
249 |
|
250 TInt lenItemString = aItemString.Length(); |
|
251 TInt lenSearchText = aSearchText.Length(); |
|
252 |
|
253 // detect asterik in end of string |
|
254 if (lenSearchText > 0 && aSearchText[lenSearchText - 1] == KLitStar) |
|
255 { |
|
256 flag |= EMatchFlagAsterikInLast; |
|
257 lenSearchText--; |
|
258 } |
|
259 |
|
260 // set asterik start |
|
261 if (!IsPhoneBookProcess(iCurrentProcessUid3) || |
|
262 (aSearchText.Length() > 0 && aSearchText[0] == KLitStar)) |
|
263 { |
|
264 flag |= EMatchFlagAsterikInStart; |
|
265 } |
|
266 |
|
267 if (lenItemString < lenSearchText) |
|
268 { |
|
269 return KErrNotFound; |
|
270 } |
|
271 |
|
272 if (IsPhoneBookProcess(iCurrentProcessUid3)) |
|
273 { |
|
274 TInt i = 0; |
|
275 TInt j = 0; |
|
276 for (; i < lenItemString && j < lenSearchText; i++) |
|
277 { |
|
278 TChar ch(aItemString[i]); |
|
279 if (IsFindWordSeparator(ch)) |
|
280 { |
|
281 continue; |
|
282 } |
|
283 |
|
284 if (MatchConsonentBased(ch, aSearchText[j])) |
|
285 { |
|
286 j++; |
|
287 } |
|
288 else |
|
289 { |
|
290 break; |
|
291 } |
|
292 } |
|
293 |
|
294 if (j == lenSearchText) |
|
295 return 0; |
|
296 } |
|
297 |
|
298 for (TInt i = 0; i < lenItemString - lenSearchText + 1; i++) |
|
299 { |
|
300 if (!(flag & EMatchFlagAsterikInStart)) |
|
301 { |
|
302 if (0 != i && !IsFindWordSeparator(aItemString[i - 1])) |
|
303 { |
|
304 continue; |
|
305 } |
|
306 } |
|
307 |
|
308 TBool matched(ETrue); |
|
309 for (TInt j = 0; j < lenSearchText; j++) |
|
310 { |
|
311 if (!MatchConsonentBased(aItemString[i + j], aSearchText[j])) |
|
312 { |
|
313 #ifdef _DEBUG |
|
314 RDebug::Printf("DBG: mismatch between %d %d", i + j, j); |
|
315 #endif |
|
316 matched = EFalse; |
|
317 break; |
|
318 } |
|
319 } |
|
320 |
|
321 if (matched) |
|
322 { |
|
323 #ifdef _DEBUG |
|
324 RDebug::Print(_L("DBG: comparing matched")); |
|
325 #endif |
|
326 return i; |
|
327 } |
|
328 } |
|
329 |
|
330 return KErrNotFound; |
|
331 |
|
332 #else |
|
333 // Convert aItemString to single jamo's. |
172 // Convert aItemString to single jamo's. |
334 HBufC* itemString = HBufC::NewLC( aItemString.Length() * KMaxLengthDecomposedSyllable ); |
173 HBufC* itemString = HBufC::NewLC( aItemString.Length() * KMaxLengthDecomposedSyllable ); |
335 DecomposeToPlainJamos( aItemString, itemString ); |
174 DecomposeToPlainJamos( aItemString, itemString ); |
336 |
175 |
337 HBufC* searchText = HBufC::NewLC( aSearchText.Length() * KMaxLengthDecomposedSyllable + 2 ); |
176 HBufC* searchText = HBufC::NewLC( aSearchText.Length() * KMaxLengthDecomposedSyllable + 2 ); |
338 searchText->Des().Append( KLitStar ); |
177 searchText->Des().Append( KLitStar ); |
339 |
178 |
340 // Convert aSearchText to single jamo's. |
179 // Convert aSearchText to single jamo's. |
341 DecomposeToPlainJamos( aSearchText, searchText ); |
180 DecomposeToPlainJamos( aSearchText, searchText ); |
342 searchText->Des().Append( KLitStar ); |
181 searchText->Des().Append( KLitStar ); |
343 |
182 |
344 // Compare strings containing plain jamo's against others. |
183 // Compare strings containing plain jamo's against others. |
345 for ( TInt i = 0; i < itemString->Length() && !result; i++ ) |
184 for ( TInt i = 0; i < itemString->Length() && !result; i++ ) |
346 { |
185 { |
347 if ( 0 == i || IsFindWordSeparator( |
186 if ( 0 == i || IsFindWordSeparator( |
348 static_cast<TChar>( itemString->Des()[ i - 1 ] ) ) ) |
187 static_cast<TChar>( itemString->Des()[ i - 1 ] ) ) ) |
349 { |
188 { |
350 if ( KErrNotFound != itemString->Mid( i ).MatchC( *searchText ) ) |
189 if ( KErrNotFound != itemString->Mid( i ).MatchC( *searchText ) ) |
351 { |
190 { |
352 result = ETrue; // match found |
191 result = ETrue; // match found |
353 } |
192 } |
354 } |
193 } |
355 } |
194 } |
356 |
195 |
357 CleanupStack::PopAndDestroy( searchText ); |
196 CleanupStack::PopAndDestroy( searchText ); |
358 CleanupStack::PopAndDestroy( itemString ); |
197 CleanupStack::PopAndDestroy( itemString ); |
359 |
198 |
360 return result; |
199 return result; |
361 #endif |
|
362 } |
200 } |
363 |
201 |
364 // --------------------------------------------------------------------------- |
202 // --------------------------------------------------------------------------- |
365 // Decomposes given string to plain jamos. |
203 // Decomposes given string to plain jamos. |
366 // --------------------------------------------------------------------------- |
204 // --------------------------------------------------------------------------- |
518 return ETrue; |
340 return ETrue; |
519 } |
341 } |
520 |
342 |
521 // In case that both of strings contain some characters, |
343 // In case that both of strings contain some characters, |
522 // matching is made with function below. |
344 // matching is made with function below. |
523 #ifdef _DEBUG |
345 return IsFindMatchL( aItemString, aSearchText ); |
524 RDebug::Printf("DBG: Comparing from MatchRefineL"); |
|
525 #endif |
|
526 |
|
527 return (IsFindMatch( aItemString, aSearchText ) != KErrNotFound); |
|
528 } |
346 } |
529 |
347 |
530 // ----------------------------------------------------------------------------- |
348 // ----------------------------------------------------------------------------- |
531 // CFindUtilKorean::MatchAdaptiveRefineL |
349 // CFindUtilKorean::MatchAdaptiveRefineL |
532 // (other items were commented in a header). |
350 // (other items were commented in a header). |
533 // ----------------------------------------------------------------------------- |
351 // ----------------------------------------------------------------------------- |
534 // |
352 // |
535 TBool CFindUtilKorean::MatchAdaptiveRefineL(const TDesC& aItemString, |
353 TBool CFindUtilKorean::MatchAdaptiveRefineL( const TDesC& /*aItemString*/, |
536 const TDesC& aSearchText, HBufC*& aNextChars) |
354 const TDesC& /*aSearchText*/, HBufC*& /*aNextChars*/ ) |
537 { |
355 { |
538 if (aSearchText.Length() == 0) |
356 return 0; |
539 { |
357 } |
540 TakeIntoNextCharsL(aNextChars, aItemString[0]); |
358 |
541 return ETrue; |
359 // --------------------------------------------------------------------------- |
542 } |
360 // It checks whether aWord is valid. |
543 else |
361 // --------------------------------------------------------------------------- |
544 { |
362 // |
545 const TInt lenItemString = aItemString.Length(); |
363 TBool CFindUtilKorean::IsWordValidForMatching( const TDesC& /*aWord*/ ) |
546 const TInt lenSearchText = aSearchText.Length(); |
364 { |
547 |
|
548 if (lenItemString < lenSearchText) |
|
549 { |
|
550 return EFalse; |
|
551 } |
|
552 |
|
553 #ifdef _DEBUG |
|
554 RDebug::Printf("DBG: Comparing from MatchAdaptiveRefineL"); |
|
555 #endif |
|
556 TInt idx = IsFindMatch(aItemString, aSearchText, |
|
557 EMatchFlagAsterikInLast); |
|
558 |
|
559 if (idx == KErrNotFound) |
|
560 { |
|
561 return EFalse; |
|
562 } |
|
563 |
|
564 TLex lexItemString(aItemString); |
|
565 if (IsPhoneBookProcess(iCurrentProcessUid3) && idx == 0) |
|
566 { |
|
567 // find out the position next to last matched string. |
|
568 // work through strings when it reaches length of search string, |
|
569 // while skipping spaces due to ingnoring space matching scheme. |
|
570 for (TInt compareCount = 0; compareCount < lenSearchText;) |
|
571 { |
|
572 if (!IsFindWordSeparator(lexItemString.Get())) |
|
573 { |
|
574 compareCount++; |
|
575 } |
|
576 } |
|
577 |
|
578 if (lexItemString.Eos()) |
|
579 return EFalse; |
|
580 |
|
581 // Skip spaces |
|
582 while (IsFindWordSeparator(lexItemString.Peek())) |
|
583 { |
|
584 lexItemString.Inc(); |
|
585 } |
|
586 |
|
587 if (lexItemString.Eos()) |
|
588 { |
|
589 return EFalse; |
|
590 } |
|
591 } |
|
592 else |
|
593 { |
|
594 lexItemString.Inc(idx + lenSearchText); |
|
595 } |
|
596 |
|
597 TChar next = lexItemString.Peek(); |
|
598 if (next == 0) |
|
599 { |
|
600 // nothing to take |
|
601 } |
|
602 else |
|
603 { |
|
604 TakeIntoNextCharsL(aNextChars, next); |
|
605 } |
|
606 } |
|
607 |
|
608 return ETrue; |
365 return ETrue; |
609 } |
366 } |
610 |
367 |
611 void CFindUtilKorean::TakeIntoNextCharsL(HBufC*& aNextChars, |
|
612 TChar aCharToInsert) |
|
613 { |
|
614 // examine the characters to be inserted |
|
615 TBuf<3> jamo; |
|
616 if (IsHangulSyllable(aCharToInsert)) |
|
617 { |
|
618 Decompose(aCharToInsert, jamo); |
|
619 } |
|
620 else if (IsHangulCompatibilityJamo(aCharToInsert)) |
|
621 { |
|
622 TUint16 ljamo = |
|
623 conversionTableFromCompatibilityJamoToJamo[(TInt)aCharToInsert - KCBase]; |
|
624 jamo.Append(ljamo); |
|
625 } |
|
626 else |
|
627 { |
|
628 aCharToInsert.UpperCase(); |
|
629 } |
|
630 |
|
631 TPtr nextChar(aNextChars->Des()); |
|
632 TBool reAlloced(EFalse); |
|
633 |
|
634 // in case there is no character in the list |
|
635 if (nextChar.Length() == 0) |
|
636 { |
|
637 __ASSERT_ALWAYS(nextChar.MaxLength() > 2, User::Panic(_L("FINDUTIL"), __LINE__)); |
|
638 |
|
639 // Hangul only |
|
640 if (jamo.Length() && ISLJamo(jamo[0])) |
|
641 { |
|
642 const TChar consonentToInsert = |
|
643 conversionTableFromLJamoToCompatibilityJamo[jamo[0] - KLBase]; |
|
644 |
|
645 InsertNextCharsL(aNextChars, reAlloced, consonentToInsert); |
|
646 |
|
647 // if Jamo only character, return... |
|
648 if (jamo.Length() == 1) |
|
649 { |
|
650 return; |
|
651 } |
|
652 } |
|
653 |
|
654 InsertNextCharsL(aNextChars, reAlloced, aCharToInsert); |
|
655 return; |
|
656 } |
|
657 |
|
658 TBool jamoInserted(EFalse); |
|
659 TInt length = nextChar.Length(); |
|
660 const TBool isPB(IsPhoneBookProcess(iCurrentProcessUid3)); |
|
661 |
|
662 for (TInt i = 0; i < length; i++) |
|
663 { |
|
664 const TChar ch = nextChar[i]; |
|
665 // Hangul consonent check |
|
666 if (!jamoInserted && jamo.Length() && ISLJamo(jamo[0])) |
|
667 { |
|
668 const TChar consonentToInsert = |
|
669 conversionTableFromLJamoToCompatibilityJamo[jamo[0] - KLBase]; |
|
670 |
|
671 if (ch == consonentToInsert) |
|
672 { |
|
673 // Jamo only character finished |
|
674 if (jamo.Length() == 1) |
|
675 { |
|
676 return; |
|
677 } |
|
678 |
|
679 jamoInserted = ETrue; |
|
680 } |
|
681 else if ((isPB && !IsCompatibilityJamo(ch)) || (ch > consonentToInsert)) |
|
682 { |
|
683 InsertNextCharsL(aNextChars, reAlloced, consonentToInsert, i); |
|
684 // Jamo only character finished |
|
685 if (jamo.Length() == 1) |
|
686 { |
|
687 return; |
|
688 } |
|
689 |
|
690 jamoInserted = ETrue; |
|
691 } |
|
692 else |
|
693 { |
|
694 // pass |
|
695 } |
|
696 } |
|
697 // Hangul or Latin |
|
698 else |
|
699 { |
|
700 if (ch == aCharToInsert) |
|
701 { |
|
702 return; // already exist |
|
703 } |
|
704 else if (isPB && IsCompatibilityJamo(ch)) |
|
705 { |
|
706 // pass |
|
707 } |
|
708 else if (ch > aCharToInsert) |
|
709 { |
|
710 InsertNextCharsL(aNextChars, reAlloced, aCharToInsert, i); |
|
711 return; // finished |
|
712 } |
|
713 else |
|
714 { |
|
715 // pass |
|
716 } |
|
717 } |
|
718 |
|
719 if (reAlloced) |
|
720 { |
|
721 nextChar.Set(aNextChars->Des()); |
|
722 length = nextChar.Length(); |
|
723 } |
|
724 } |
|
725 |
|
726 InsertNextCharsL(aNextChars, reAlloced, aCharToInsert); |
|
727 } |
|
728 |
|
729 void CFindUtilKorean::InsertNextCharsL(HBufC*& aNextChars, TBool& aReAlloced, |
|
730 const TChar& aChar, const TInt aIndex) |
|
731 { |
|
732 aReAlloced = EFalse; |
|
733 TPtr ptr(aNextChars->Des()); |
|
734 const TInt len = ptr.Length(); |
|
735 const TInt maxLen = ptr.MaxLength(); |
|
736 |
|
737 if (KErrNotFound != ptr.Locate(aChar)) |
|
738 { |
|
739 // Do not insert duplicate characters |
|
740 return; |
|
741 } |
|
742 |
|
743 if (len == maxLen) |
|
744 { |
|
745 aNextChars = aNextChars->ReAllocL(maxLen + KNextCharsGranuarity); |
|
746 ptr.Set(aNextChars->Des()); |
|
747 aReAlloced = ETrue; |
|
748 |
|
749 #ifdef _DEBUG |
|
750 RDebug::Printf("DBG: Next Character buffer created with %d", |
|
751 ptr.MaxLength()); |
|
752 #endif |
|
753 } |
|
754 |
|
755 if (aIndex == KErrNotFound) |
|
756 { |
|
757 ptr.Append(aChar); |
|
758 } |
|
759 else |
|
760 { |
|
761 TBuf<1> buf; |
|
762 buf.Append(aChar); |
|
763 ptr.Insert(aIndex, buf); |
|
764 } |
|
765 } |
|
766 |
|
767 // --------------------------------------------------------------------------- |
|
768 // It checks whether aWord is valid. |
|
769 // --------------------------------------------------------------------------- |
|
770 // |
|
771 TBool CFindUtilKorean::IsWordValidForMatching(const TDesC& /*aWord*/) |
|
772 { |
|
773 return ETrue; |
|
774 } |
|
775 |
|
776 TBool CFindUtilKorean::MatchConsonentBased(const TChar& aA, const TChar& aB) |
|
777 { |
|
778 TBuf<3> jamoItemString; |
|
779 TBuf<3> jamoSearchText; |
|
780 DecomposeChar(aA, jamoItemString); |
|
781 DecomposeChar(aB, jamoSearchText); |
|
782 const TInt lenJamoItemString = jamoItemString.Length(); |
|
783 const TInt lenJamoSearchText = jamoSearchText.Length(); |
|
784 |
|
785 // check consonent match for one character |
|
786 if (lenJamoSearchText == 1 && |
|
787 ISLJamo(jamoItemString[0]) && ISLJamo(jamoSearchText[0])) |
|
788 { |
|
789 if (jamoItemString[0] == jamoSearchText[0]) |
|
790 { |
|
791 return ETrue; |
|
792 } |
|
793 } |
|
794 else |
|
795 { |
|
796 TChar chItemString(aA); |
|
797 TChar chSearchText(aB); |
|
798 chItemString.UpperCase(); |
|
799 chSearchText.UpperCase(); |
|
800 if (chItemString == chSearchText) |
|
801 { |
|
802 return ETrue; |
|
803 } |
|
804 } |
|
805 return EFalse; |
|
806 } |
|
807 // End of file |
368 // End of file |