| 661 | } |
| 662 | |
| 663 | RegularAreaRect *TextPagePrivate::findTextInternalForward(int searchID, const QString &_query, TextComparisonFunction comparer, TextEntity::List::ConstIterator start, int start_offset, TextEntity::List::ConstIterator end) |
| 664 | { |
| 665 | // normalize query search all unicode (including glyphs) |
| 666 | // Use NFKC for search operations. Use NFC for copy, makeWord, and export operations. |
| 667 | const QString query = _query.normalized(QString::NormalizationForm_KC); |
| 668 | |
| 669 | // j is the current position in our query |
| 670 | // queryLeft is the length of the query we have left to match |
| 671 | int j = 0, queryLeft = query.length(); |
| 672 | |
| 673 | TextEntity::List::ConstIterator it = start; |
| 674 | int offset = start_offset; |
| 675 | |
| 676 | TextEntity::List::ConstIterator it_begin = TextEntity::List::ConstIterator(); |
| 677 | int offset_begin = 0; // dummy initial value to suppress compiler warnings |
| 678 | |
| 679 | while (it != end) { |
| 680 | const TextEntity &curEntity = *it; |
| 681 | const QString &str = curEntity.text().normalized(QString::NormalizationForm_KC); |
| 682 | const int strLen = str.length(); |
| 683 | const int adjustedLen = stringLengthAdaptedWithHyphen(str, it, m_words.constEnd()); |
| 684 | // adjustedLen <= strLen |
| 685 | |
| 686 | if (offset >= strLen) { |
| 687 | it++; |
| 688 | offset = 0; |
| 689 | continue; |
| 690 | } |
| 691 | |
| 692 | if (it_begin == TextEntity::List::ConstIterator()) { |
| 693 | it_begin = it; |
| 694 | offset_begin = offset; |
| 695 | } |
| 696 | |
| 697 | // Let the user write the hyphen or not when searching for text |
| 698 | int matchedLen = -1; |
| 699 | for (int matchingLen = strLen; matchingLen >= adjustedLen; matchingLen--) { |
| 700 | // we have equal (or less than) area of the query left as the length of the current |
| 701 | // entity |
| 702 | const int min = qMin(queryLeft, matchingLen - offset); |
| 703 | if (comparer(QStringView {str}.mid(offset, min), QStringView {query}.mid(j, min))) { |
| 704 | matchedLen = min; |
| 705 | break; |
| 706 | } |
| 707 | } |
| 708 | |
| 709 | if (matchedLen == -1) { |
| 710 | // we have not matched |
| 711 | // this means we do not have a complete match |
| 712 | // we need to get back to query start |
| 713 | // and continue the search from this place |
| 714 | #ifdef DEBUG_TEXTPAGE |
| 715 | qCDebug(OkularCoreDebug) << "\tnot matched"; |
| 716 | #endif |
| 717 | j = 0; |
| 718 | queryLeft = query.length(); |
| 719 | it = it_begin; |
| 720 | offset = offset_begin + 1; |
no test coverage detected