📄 document.cxx
字号:
endOfLine = endPos; } } else { if (line == lineRangeEnd) { if ((endPos != startOfLine) && (s[0] == '^')) continue; // Can't match start of line if end position after start of line startOfLine = endPos; } if (line == lineRangeStart) { if ((startPos != endOfLine) && (searchEnd == '$')) continue; // Can't match end of line if start position before end of line endOfLine = startPos; } } DocumentIndexer di(this, endOfLine); int success = pre->Execute(di, startOfLine, endOfLine); if (success) { pos = pre->bopat[0]; lenRet = pre->eopat[0] - pre->bopat[0]; if (increment == -1) { // Check for the last match on this line. int repetitions = 1000; // Break out of infinite loop while (success && (pre->eopat[0] <= endOfLine) && (repetitions--)) { success = pre->Execute(di, pos+1, endOfLine); if (success) { if (pre->eopat[0] <= minPos) { pos = pre->bopat[0]; lenRet = pre->eopat[0] - pre->bopat[0]; } else { success = 0; } } } } break; } } *length = lenRet; return pos; } else { bool forward = minPos <= maxPos; int increment = forward ? 1 : -1; // Range endpoints should not be inside DBCS characters, but just in case, move them. int startPos = MovePositionOutsideChar(minPos, increment, false); int endPos = MovePositionOutsideChar(maxPos, increment, false); // Compute actual search ranges needed int lengthFind = *length; if (lengthFind == -1) lengthFind = static_cast<int>(strlen(s)); int endSearch = endPos; if (startPos <= endPos) { endSearch = endPos - lengthFind + 1; } //Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind); char firstChar = s[0]; if (!caseSensitive) firstChar = static_cast<char>(MakeUpperCase(firstChar)); int pos = forward ? startPos : (startPos - 1); while (forward ? (pos < endSearch) : (pos >= endSearch)) { char ch = CharAt(pos); if (caseSensitive) { if (ch == firstChar) { bool found = true; if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false; for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) { ch = CharAt(pos + posMatch); if (ch != s[posMatch]) found = false; } if (found) { if ((!word && !wordStart) || word && IsWordAt(pos, pos + lengthFind) || wordStart && IsWordStartAt(pos)) return pos; } } } else { if (MakeUpperCase(ch) == firstChar) { bool found = true; if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false; for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) { ch = CharAt(pos + posMatch); if (MakeUpperCase(ch) != MakeUpperCase(s[posMatch])) found = false; } if (found) { if ((!word && !wordStart) || word && IsWordAt(pos, pos + lengthFind) || wordStart && IsWordStartAt(pos)) return pos; } } } pos += increment; if (dbcsCodePage && (pos >= 0)) { // Ensure trying to match from start of character pos = MovePositionOutsideChar(pos, increment, false); } } } //Platform::DebugPrintf("Not found\n"); return -1;}const char *Document::SubstituteByPosition(const char *text, int *length) { if (!pre) return 0; delete []substituted; substituted = 0; DocumentIndexer di(this, Length()); if (!pre->GrabMatches(di)) return 0; unsigned int lenResult = 0; for (int i = 0; i < *length; i++) { if (text[i] == '\\') { if (text[i + 1] >= '1' && text[i + 1] <= '9') { unsigned int patNum = text[i + 1] - '0'; lenResult += pre->eopat[patNum] - pre->bopat[patNum]; i++; } else { switch (text[i + 1]) { case 'a': case 'b': case 'f': case 'n': case 'r': case 't': case 'v': i++; } lenResult++; } } else { lenResult++; } } substituted = new char[lenResult + 1]; if (!substituted) return 0; char *o = substituted; for (int j = 0; j < *length; j++) { if (text[j] == '\\') { if (text[j + 1] >= '1' && text[j + 1] <= '9') { unsigned int patNum = text[j + 1] - '0'; unsigned int len = pre->eopat[patNum] - pre->bopat[patNum]; if (pre->pat[patNum]) // Will be null if try for a match that did not occur memcpy(o, pre->pat[patNum], len); o += len; j++; } else { j++; switch (text[j]) { case 'a': *o++ = '\a'; break; case 'b': *o++ = '\b'; break; case 'f': *o++ = '\f'; break; case 'n': *o++ = '\n'; break; case 'r': *o++ = '\r'; break; case 't': *o++ = '\t'; break; case 'v': *o++ = '\v'; break; default: *o++ = '\\'; j--; } } } else { *o++ = text[j]; } } *o = '\0'; *length = lenResult; return substituted;}int Document::LinesTotal() { return cb.Lines();}void Document::ChangeCase(Range r, bool makeUpperCase) { for (int pos = r.start; pos < r.end;) { int len = LenChar(pos); if (len == 1) { char ch = CharAt(pos); if (makeUpperCase) { if (IsLowerCase(ch)) { ChangeChar(pos, static_cast<char>(MakeUpperCase(ch))); } } else { if (IsUpperCase(ch)) { ChangeChar(pos, static_cast<char>(MakeLowerCase(ch))); } } } pos += len; }}void Document::SetDefaultCharClasses(bool includeWordClass) { charClass.SetDefaultCharClasses(includeWordClass);}void Document::SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass) { charClass.SetCharClasses(chars, newCharClass);}void Document::SetStylingBits(int bits) { stylingBits = bits; stylingBitsMask = 0; for (int bit = 0; bit < stylingBits; bit++) { stylingBitsMask <<= 1; stylingBitsMask |= 1; }}void Document::StartStyling(int position, char mask) { stylingMask = mask; endStyled = position;}bool Document::SetStyleFor(int length, char style) { if (enteredCount != 0) { return false; } else { enteredCount++; style &= stylingMask; int prevEndStyled = endStyled; if (cb.SetStyleFor(endStyled, length, style, stylingMask)) { DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER, prevEndStyled, length); NotifyModified(mh); } endStyled += length; enteredCount--; return true; }}bool Document::SetStyles(int length, char *styles) { if (enteredCount != 0) { return false; } else { enteredCount++; bool didChange = false; int startMod = 0; int endMod = 0; for (int iPos = 0; iPos < length; iPos++, endStyled++) { PLATFORM_ASSERT(endStyled < Length()); if (cb.SetStyleAt(endStyled, styles[iPos], stylingMask)) { if (!didChange) { startMod = endStyled; } didChange = true; endMod = endStyled; } } if (didChange) { DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER, startMod, endMod - startMod + 1); NotifyModified(mh); } enteredCount--; return true; }}bool Document::EnsureStyledTo(int pos) { if (pos > GetEndStyled()) { IncrementStyleClock(); // Ask the watchers to style, and stop as soon as one responds. for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) { watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos); } } return pos <= GetEndStyled();}void Document::IncrementStyleClock() { styleClock++; if (styleClock > 0x100000) { styleClock = 0; }}bool Document::AddWatcher(DocWatcher *watcher, void *userData) { for (int i = 0; i < lenWatchers; i++) { if ((watchers[i].watcher == watcher) && (watchers[i].userData == userData)) return false; } WatcherWithUserData *pwNew = new WatcherWithUserData[lenWatchers + 1]; if (!pwNew) return false; for (int j = 0; j < lenWatchers; j++) pwNew[j] = watchers[j]; pwNew[lenWatchers].watcher = watcher; pwNew[lenWatchers].userData = userData; delete []watchers; watchers = pwNew; lenWatchers++; return true;}bool Document::RemoveWatcher(DocWatcher *watcher, void *userData) { for (int i = 0; i < lenWatchers; i++) { if ((watchers[i].watcher == watcher) && (watchers[i].userData == userData)) { if (lenWatchers == 1) { delete []watchers; watchers = 0; lenWatchers = 0; } else { WatcherWithUserData *pwNew = new WatcherWithUserData[lenWatchers]; if (!pwNew) return false; for (int j = 0; j < lenWatchers - 1; j++) { pwNew[j] = (j < i) ? watchers[j] : watchers[j + 1]; } delete []watchers; watchers = pwNew; lenWatchers--; } return true; } } return false;}void Document::NotifyModifyAttempt() { for (int i = 0; i < lenWatchers; i++) { watchers[i].watcher->NotifyModifyAttempt(this, watchers[i].userData); }}void Document::NotifySavePoint(bool atSavePoint) { for (int i = 0; i < lenWatchers; i++) { watchers[i].watcher->NotifySavePoint(this, watchers[i].userData, atSavePoint); }}void Document::NotifyModified(DocModification mh) { for (int i = 0; i < lenWatchers; i++) { watchers[i].watcher->NotifyModified(this, mh, watchers[i].userData); }}bool Document::IsWordPartSeparator(char ch) { return (WordCharClass(ch) == CharClassify::ccWord) && IsPunctuation(ch);}int Document::WordPartLeft(int pos) { if (pos > 0) { --pos; char startChar = cb.CharAt(pos); if (IsWordPartSeparator(startChar)) { while (pos > 0 && IsWordPartSeparator(cb.CharAt(pos))) { --pos; } } if (pos > 0) { startChar = cb.CharAt(pos); --pos; if (IsLowerCase(startChar)) { while (pos > 0 && IsLowerCase(cb.CharAt(pos))) --pos; if (!IsUpperCase(cb.CharAt(pos)) && !IsLowerCase(cb.CharAt(pos))) ++pos; } else if (IsUpperCase(startChar)) { while (pos > 0 && IsUpperCase(cb.CharAt(pos))) --pos; if (!IsUpperCase(cb.CharAt(pos))) ++pos; } else if (IsADigit(startChar)) { while (pos > 0 && IsADigit(cb.CharAt(pos))) --pos; if (!IsADigit(cb.CharAt(pos))) ++pos; } else if (IsPunctuation(startChar)) { while (pos > 0 && IsPunctuation(cb.CharAt(pos))) --pos; if (!IsPunctuation(cb.CharAt(pos))) ++pos; } else if (isspacechar(startChar)) { while (pos > 0 && isspacechar(cb.CharAt(pos))) --pos; if (!isspacechar(cb.CharAt(pos))) ++pos; } else if (!isascii(startChar)) { while (pos > 0 && !isascii(cb.CharAt(pos))) --pos; if (isascii(cb.CharAt(pos))) ++pos; } else { ++pos; } } } return pos;}int Document::WordPartRight(int pos) { char startChar = cb.CharAt(pos); int length = Length(); if (IsWordPartSeparator(startChar)) { while (pos < length && IsWordPartSeparator(cb.CharAt(pos))) ++pos; startChar = cb.CharAt(pos); } if (!isascii(startChar)) { while (pos < length && !isascii(cb.CharAt(pos))) ++pos; } else if (IsLowerCase(startChar)) { while (pos < length && IsLowerCase(cb.CharAt(pos))) ++pos; } else if (IsUpperCase(startChar)) { if (IsLowerCase(cb.CharAt(pos + 1))) { ++pos; while (pos < length && IsLowerCase(cb.CharAt(pos))) ++pos; } else { while (pos < length && IsUpperCase(cb.CharAt(pos))) ++pos; } if (IsLowerCase(cb.CharAt(pos)) && IsUpperCase(cb.CharAt(pos - 1))) --pos; } else if (IsADigit(startChar)) { while (pos < length && IsADigit(cb.CharAt(pos))) ++pos; } else if (IsPunctuation(startChar)) { while (pos < length && IsPunctuation(cb.CharAt(pos))) ++pos; } else if (isspacechar(startChar)) { while (pos < length && isspacechar(cb.CharAt(pos))) ++pos; } else { ++pos; } return pos;}bool IsLineEndChar(char c) { return (c == '\n' || c == '\r');}int Document::ExtendStyleRange(int pos, int delta, bool singleLine) { int sStart = cb.StyleAt(pos); if (delta < 0) { while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))) ) pos--; pos++; } else { while (pos < (Length()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))) ) pos++; } return pos;}static char BraceOpposite(char ch) { switch (ch) { case '(': return ')'; case ')': return '('; case '[': return ']'; case ']': return '['; case '{': return '}'; case '}': return '{'; case '<': return '>'; case '>': return '<'; default: return '\0'; }}// TODO: should be able to extend styled region to find matching braceint Document::BraceMatch(int position, int /*maxReStyle*/) { char chBrace = CharAt(position); char chSeek = BraceOpposite(chBrace); if (chSeek == '\0') return - 1; char styBrace = static_cast<char>(StyleAt(position) & stylingBitsMask); int direction = -1; if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<') direction = 1; int depth = 1; position = position + direction; while ((position >= 0) && (position < Length())) { position = MovePositionOutsideChar(position, direction); char chAtPos = CharAt(position); char styAtPos = static_cast<char>(StyleAt(position) & stylingBitsMask); if ((position > GetEndStyled()) || (styAtPos == styBrace)) { if (chAtPos == chBrace) depth++; if (chAtPos == chSeek) depth--; if (depth == 0) return position; } position = position + direction; } return - 1;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -