| 41 | } |
| 42 | |
| 43 | Sci::Position QRegexSearch::FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s, bool caseSensitive, bool word, bool wordStart, Scintilla::FindOption flags, Sci::Position *length) |
| 44 | { |
| 45 | Q_UNUSED(caseSensitive); |
| 46 | Q_UNUSED(word) |
| 47 | Q_UNUSED(wordStart) |
| 48 | // ----------------------------------------------------------------------------------------------------------------------- |
| 49 | // NOTE: This section of code has to be very careful about what units of measure is being used. Scintilla wants to operate |
| 50 | // in units of bytes (e.g. position 3 is 3 bytes into the text). Qt wants to operate in units of UTF16 chars. The trouble is |
| 51 | // when you start using characters that are >1 byte a piece. Meaning position 3 (3 bytes into a file) could be 1 character. |
| 52 | // ----------------------------------------------------------------------------------------------------------------------- |
| 53 | |
| 54 | // Make sure the positiosn are outside of characters |
| 55 | minPos = doc->MovePositionOutsideChar(minPos, 1, false); |
| 56 | maxPos = doc->MovePositionOutsideChar(maxPos, -1, false); |
| 57 | |
| 58 | //qInfo(Q_FUNC_INFO); |
| 59 | //qInfo("\tminPos %d", minPos); |
| 60 | //qInfo("\tmaxPos %d", maxPos); |
| 61 | //qInfo("\ts %s", s); |
| 62 | //qInfo("\tcaseSensitive %s", caseSensitive ? "true" : "false"); |
| 63 | //qInfo("\tword %s", word ? "true" : "false"); |
| 64 | //qInfo("\twordStart %s", wordStart ? "true" : "false"); |
| 65 | //qInfo("\tflags %d", flags); |
| 66 | |
| 67 | // No need to search an empty range |
| 68 | if (minPos == maxPos) |
| 69 | return -1; |
| 70 | |
| 71 | auto options = QRegularExpression::MultilineOption | QRegularExpression::UseUnicodePropertiesOption; |
| 72 | |
| 73 | if (!FlagSet(flags, FindOption::MatchCase)) |
| 74 | options |= QRegularExpression::CaseInsensitiveOption; |
| 75 | |
| 76 | // TODO: does (*ANYCRLF) need prepended to the search string? |
| 77 | QRegularExpression re(s, options); |
| 78 | if (!re.isValid()) |
| 79 | return -1; // Invalid regular expression |
| 80 | |
| 81 | // Get the bytes from the document. No need to go past maxPos bytes |
| 82 | // Not actually sure if this copies the data or not |
| 83 | const Sci::Position rangeLength = maxPos - minPos; |
| 84 | const QString utf8 = QString::fromUtf8(doc->RangePointer(minPos, rangeLength), rangeLength); |
| 85 | |
| 86 | // NOTE: QString uses UTF16 counts since QChars are 16 bits |
| 87 | QRegularExpressionMatch m = re.match(utf8, 0, QRegularExpression::NormalMatch, QRegularExpression::NoMatchOption); |
| 88 | |
| 89 | if (!m.hasMatch()) |
| 90 | return -1; // No match |
| 91 | |
| 92 | match = m; |
| 93 | |
| 94 | // NOTE: Returned started is the index into the QString which uses UTF16 |
| 95 | const int positionStart = doc->GetRelativePositionUTF16(minPos, match.capturedStart(0)); |
| 96 | |
| 97 | // Now move ahead however many characters we matched. Again, based on UTF16 count |
| 98 | const int positionEnd = doc->GetRelativePositionUTF16(positionStart, match.capturedLength(0)); |
| 99 | |
| 100 | // The length is the number of bytes that was matched |
nothing calls this directly
no outgoing calls
no test coverage detected