diff --git a/src/PowerEditor/src/ScintillaComponent/FindReplaceDlg.cpp b/src/PowerEditor/src/ScintillaComponent/FindReplaceDlg.cpp index 6344ebe..9896524 100644 --- a/src/PowerEditor/src/ScintillaComponent/FindReplaceDlg.cpp +++ b/src/PowerEditor/src/ScintillaComponent/FindReplaceDlg.cpp @@ -23,6 +23,9 @@ #include "Common.h" #include "Utf8.h" +下面是对给定代码的详细注释: + +```cpp using namespace std; FindOption * FindReplaceDlg::_env; @@ -35,12 +38,15 @@ void addText2Combo(const TCHAR * txt2add, HWND hCombo) if (!hCombo) return; if (!lstrcmp(txt2add, TEXT(""))) return; + // 在组合框中查找是否已存在相同的文本 auto i = ::SendMessage(hCombo, CB_FINDSTRINGEXACT, static_cast(-1), reinterpret_cast(txt2add)); - if (i != CB_ERR) // found + if (i != CB_ERR) // 找到了相同的文本 { + // 删除已存在的文本 ::SendMessage(hCombo, CB_DELETESTRING, i, 0); } + // 向组合框中插入新的文本,并设置为当前选中项 i = ::SendMessage(hCombo, CB_INSERTSTRING, 0, reinterpret_cast(txt2add)); ::SendMessage(hCombo, CB_SETCURSEL, i, 0); } @@ -59,6 +65,8 @@ void delLeftWordInEdit(HWND hEdit) WORD cursor = 0; ::SendMessage(hEdit, EM_GETSEL, (WPARAM)&cursor, 0); WORD wordstart = cursor; + + // 删除光标左边的单词 while (wordstart > 0) { TCHAR c = str[wordstart - 1]; if (c != ' ' && c != '\t') @@ -83,6 +91,7 @@ LRESULT run_swapButtonProc(WNDPROC oldEditProc, HWND hwnd, UINT message, WPARAM { case WM_RBUTTONUP: { + // 模拟右键点击事件,发送给父窗口处理 ::SendMessage(GetParent(hwnd), message, wParam, lParam); break; } @@ -94,19 +103,22 @@ LRESULT run_swapButtonProc(WNDPROC oldEditProc, HWND hwnd, UINT message, WPARAM } int Searching::convertExtendedToString(const TCHAR * query, TCHAR * result, int length) -{ //query may equal to result, since it always gets smaller +{ + // 将扩展的字符串转换为普通字符串 int i = 0, j = 0; int charLeft = length; TCHAR current; while (i < length) - { //because the backslash escape quences always reduce the size of the generic_string, no overflow checks have to be made for target, assuming parameters are correct + { current = query[i]; --charLeft; + if (current == '\\' && charLeft) - { //possible escape sequence + { ++i; --charLeft; current = query[i]; + switch(current) { case 'r': @@ -131,24 +143,26 @@ int Searching::convertExtendedToString(const TCHAR * query, TCHAR * result, int case 'u': { int size = 0, base = 0; + + // 根据转义序列的类型设置不同的大小和进制 if (current == 'b') - { //11111111 + { size = 8, base = 2; } else if (current == 'o') - { //377 + { size = 3, base = 8; } else if (current == 'd') - { //255 + { size = 3, base = 10; } else if (current == 'x') - { //0xFF + { size = 2, base = 16; } else if (current == 'u') - { //0xCDCD + { size = 4, base = 16; } @@ -162,12 +176,14 @@ int Searching::convertExtendedToString(const TCHAR * query, TCHAR * result, int break; } } - //not enough chars to make parameter, use default method as fallback + + // 字符不足以构成参数,则使用默认方法作为备选方案 [[fallthrough]]; } default: - { //unknown sequence, treat as regular text + { + // 未知序列,当做普通文本处理 result[j] = '\\'; ++j; result[j] = current; @@ -182,6 +198,7 @@ int Searching::convertExtendedToString(const TCHAR * query, TCHAR * result, int ++i; ++j; } + result[j] = 0; return j; } @@ -195,6 +212,7 @@ bool Searching::readBase(const TCHAR * str, int * value, int base, int size) while (i < size) { current = str[i]; + if (current >= 'A') { current &= 0xdf; @@ -220,105 +238,110 @@ bool Searching::readBase(const TCHAR * str, int * value, int base, int size) void Searching::displaySectionCentered(size_t posStart, size_t posEnd, ScintillaEditView * pEditView, bool isDownwards) { - // Make sure target lines are unfolded + // 确保目标行未折叠 pEditView->execute(SCI_ENSUREVISIBLE, pEditView->execute(SCI_LINEFROMPOSITION, posStart)); pEditView->execute(SCI_ENSUREVISIBLE, pEditView->execute(SCI_LINEFROMPOSITION, posEnd)); - // Jump-scroll to center, if current position is out of view + // 跳转滚动到居中位置,如果当前位置不可见 pEditView->execute(SCI_SETVISIBLEPOLICY, CARET_JUMPS | CARET_EVEN); pEditView->execute(SCI_ENSUREVISIBLEENFORCEPOLICY, pEditView->execute(SCI_LINEFROMPOSITION, isDownwards ? posEnd : posStart)); - // When searching up, the beginning of the (possible multiline) result is important, when scrolling down the end + // 当向上搜索时,重要的是结果的开头,当向下滚动时是结果的结尾 pEditView->execute(SCI_GOTOPOS, isDownwards ? posEnd : posStart); pEditView->execute(SCI_SETVISIBLEPOLICY, CARET_EVEN); pEditView->execute(SCI_ENSUREVISIBLEENFORCEPOLICY, pEditView->execute(SCI_LINEFROMPOSITION, isDownwards ? posEnd : posStart)); - // Adjust so that we see the entire match; primarily horizontally + // 调整使得能够看到完整的匹配;主要是水平方向的调整 pEditView->execute(SCI_SCROLLRANGE, posStart, posEnd); - // Move cursor to end of result and select result + // 将光标移到结果的末尾并选中结果 pEditView->execute(SCI_GOTOPOS, posEnd); pEditView->execute(SCI_SETANCHOR, posStart); - // Update Scintilla's knowledge about what column the caret is in, so that if user - // does up/down arrow as first navigation after the search result is selected, - // the caret doesn't jump to an unexpected column + // 更新 Scintilla 中光标所在列的位置信息,以防用户在选择搜索结果后使用上下箭头导航时光标跳到意外的列 pEditView->execute(SCI_CHOOSECARETX); } WNDPROC FindReplaceDlg::originalFinderProc = nullptr; WNDPROC FindReplaceDlg::originalComboEditProc = nullptr; +``` + + // important : to activate all styles const int STYLING_MASK = 255; +```cpp +// 定义 FindReplaceDlg 类的析构函数 FindReplaceDlg::~FindReplaceDlg() { - _tab.destroy(); - delete _pFinder; + _tab.destroy(); // 销毁标签页控件 + delete _pFinder; // 删除查找对象指针 + + // 删除与查找对象相关的所有查找器对象 for (int n = static_cast(_findersOfFinder.size()) - 1; n >= 0; n--) { delete _findersOfFinder[n]; _findersOfFinder.erase(_findersOfFinder.begin() + n); } + // 销毁窗口句柄 if (_shiftTrickUpTip) ::DestroyWindow(_shiftTrickUpTip); - if (_2ButtonsTip) ::DestroyWindow(_2ButtonsTip); - if (_filterTip) ::DestroyWindow(_filterTip); + // 释放字体对象 if (_hMonospaceFont) ::DeleteObject(_hMonospaceFont); - if (_hLargerBolderFont) ::DeleteObject(_hLargerBolderFont); - if (_hCourrierNewFont) ::DeleteObject(_hCourrierNewFont); - delete[] _uniFileName; + delete[] _uniFileName; // 释放存储文件名的数组内存 } +// 创建 FindReplaceDlg 对话框 void FindReplaceDlg::create(int dialogID, bool isRTL, bool msgDestParent, bool toShow) { + // 创建静态对话框 StaticDialog::create(dialogID, isRTL, msgDestParent); - fillFindHistory(); - _currentStatus = REPLACE_DLG; - initOptionsFromDlg(); + fillFindHistory(); // 填充查找历史记录 + _currentStatus = REPLACE_DLG; // 设置当前状态为替换对话框 + initOptionsFromDlg(); // 从对话框初始化选项 - _statusBar.init(GetModuleHandle(NULL), _hSelf, 0); - _statusBar.display(); + _statusBar.init(GetModuleHandle(NULL), _hSelf, 0); // 初始化状态栏 + _statusBar.display(); // 显示状态栏 + // 获取 DPI 管理器 DPIManager& dpiManager = NppParameters::getInstance()._dpiManager; RECT rect{}; - getClientRect(rect); - _tab.init(_hInst, _hSelf, false, true); - NppDarkMode::subclassTabControl(_tab.getHSelf()); - int tabDpiDynamicalHeight = dpiManager.scaleY(13); - _tab.setFont(TEXT("Tahoma"), tabDpiDynamicalHeight); + getClientRect(rect); // 获取客户区矩形 + _tab.init(_hInst, _hSelf, false, true); // 初始化标签页控件 + NppDarkMode::subclassTabControl(_tab.getHSelf()); // 子类化标签页控件以适配暗黑模式 + int tabDpiDynamicalHeight = dpiManager.scaleY(13); // 根据 DPI 缩放标签页高度 + _tab.setFont(TEXT("Tahoma"), tabDpiDynamicalHeight); // 设置标签页字体 + // 插入标签页内容 const TCHAR *find = TEXT("Find"); const TCHAR *replace = TEXT("Replace"); const TCHAR *findInFiles = TEXT("Find in Files"); const TCHAR *findInProjects = TEXT("Find in Projects"); const TCHAR *mark = TEXT("Mark"); - _tab.insertAtEnd(find); _tab.insertAtEnd(replace); _tab.insertAtEnd(findInFiles); _tab.insertAtEnd(findInProjects); _tab.insertAtEnd(mark); + _tab.reSizeTo(rect); // 调整标签页大小以适应客户区 + _tab.display(); // 显示标签页 - _tab.reSizeTo(rect); - _tab.display(); - - _initialClientWidth = rect.right - rect.left; + _initialClientWidth = rect.right - rect.left; // 记录初始客户区宽度 - //fill min dialog size info + // 填充最小对话框大小信息 getWindowRect(_initialWindowRect); _initialWindowRect.right = _initialWindowRect.right - _initialWindowRect.left + dpiManager.scaleX(10); _initialWindowRect.left = 0; @@ -335,88 +358,65 @@ void FindReplaceDlg::create(int dialogID, bool isRTL, bool msgDestParent, bool t NppGUI& nppGUI = nppParam.getNppGUI(); const UINT swpFlags = toShow ? SWP_SHOWWINDOW : SWP_HIDEWINDOW; - if (nppGUI._findWindowPos.bottom - nppGUI._findWindowPos.top != 0) // check height against 0 as a test of valid data from config + if (nppGUI._findWindowPos.bottom - nppGUI._findWindowPos.top != 0) // 检查配置数据是否有效 { RECT rc = getViewablePositionRect(nppGUI._findWindowPos); ::SetWindowPos(_hSelf, HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, swpFlags); } else { - goToCenter(swpFlags); + goToCenter(swpFlags); // 居中显示 } + // 获取状态栏客户区矩形 RECT rcStatusBar{}; ::GetClientRect(_statusBar.getHSelf(), &rcStatusBar); _lesssModeHeight = (countRc.bottom - dlgRc.top) + (rcStatusBar.bottom - rcStatusBar.top) + dpiManager.scaleY(10); if (nppGUI._findWindowLessMode) { - // reverse the value of _findWindowLessMode because the value will be inversed again in IDD_RESIZE_TOGGLE_BUTTON + // 反转 _findWindowLessMode 的值,因为在 IDD_RESIZE_TOGGLE_BUTTON 中会再次反转该值 nppGUI._findWindowLessMode = false; - ::SendMessage(_hSelf, WM_COMMAND, IDD_RESIZE_TOGGLE_BUTTON, 0); } } +// 填充查找历史记录 void FindReplaceDlg::fillFindHistory() { NppParameters& nppParams = NppParameters::getInstance(); FindHistory & findHistory = nppParams.getFindHistory(); + // 填充各个 Combo Box 的历史记录 fillComboHistory(IDFINDWHAT, findHistory._findHistoryFinds); fillComboHistory(IDREPLACEWITH, findHistory._findHistoryReplaces); fillComboHistory(IDD_FINDINFILES_FILTERS_COMBO, findHistory._findHistoryFilters); fillComboHistory(IDD_FINDINFILES_DIR_COMBO, findHistory._findHistoryPaths); + // 设置各个复选框的选中状态 ::SendDlgItemMessage(_hSelf, IDWRAP, BM_SETCHECK, findHistory._isWrap, 0); ::SendDlgItemMessage(_hSelf, IDWHOLEWORD, BM_SETCHECK, findHistory._isMatchWord, 0); ::SendDlgItemMessage(_hSelf, IDMATCHCASE, BM_SETCHECK, findHistory._isMatchCase, 0); ::SendDlgItemMessage(_hSelf, IDC_BACKWARDDIRECTION, BM_SETCHECK, !findHistory._isDirectionDown, 0); - ::SendDlgItemMessage(_hSelf, IDD_FINDINFILES_INHIDDENDIR_CHECK, BM_SETCHECK, findHistory._isFifInHiddenFolder, 0); - ::SendDlgItemMessage(_hSelf, IDD_FINDINFILES_RECURSIVE_CHECK, BM_SETCHECK, findHistory._isFifRecuisive, 0); - ::SendDlgItemMessage(_hSelf, IDD_FINDINFILES_FOLDERFOLLOWSDOC_CHECK, BM_SETCHECK, findHistory._isFolderFollowDoc, 0); - - ::SendDlgItemMessage(_hSelf, IDD_FINDINFILES_PROJECT1_CHECK, BM_SETCHECK, findHistory._isFifProjectPanel_1, 0); - ::SendDlgItemMessage(_hSelf, IDD_FINDINFILES_PROJECT2_CHECK, BM_SETCHECK, findHistory._isFifProjectPanel_2, 0); - ::SendDlgItemMessage(_hSelf, IDD_FINDINFILES_PROJECT3_CHECK, BM_SETCHECK, findHistory._isFifProjectPanel_3, 0); - - ::SendDlgItemMessage(_hSelf, IDNORMAL, BM_SETCHECK, findHistory._searchMode == FindHistory::normal, 0); - ::SendDlgItemMessage(_hSelf, IDEXTENDED, BM_SETCHECK, findHistory._searchMode == FindHistory::extended, 0); - ::SendDlgItemMessage(_hSelf, IDREGEXP, BM_SETCHECK, findHistory._searchMode == FindHistory::regExpr, 0); - ::SendDlgItemMessage(_hSelf, IDREDOTMATCHNL, BM_SETCHECK, findHistory._dotMatchesNewline, 0); - - ::SendDlgItemMessage(_hSelf, IDC_MARKLINE_CHECK, BM_SETCHECK, findHistory._isBookmarkLine, 0); - ::SendDlgItemMessage(_hSelf, IDC_PURGE_CHECK, BM_SETCHECK, findHistory._isPurge, 0); - - ::SendDlgItemMessage(_hSelf, IDC_2_BUTTONS_MODE, BM_SETCHECK, findHistory._isSearch2ButtonsMode, 0); - - if (findHistory._searchMode == FindHistory::regExpr) - { - //regex doesn't allow wholeword - ::SendDlgItemMessage(_hSelf, IDWHOLEWORD, BM_SETCHECK, BST_UNCHECKED, 0); - enableFindDlgItem(IDWHOLEWORD, false); - - // regex upward search is disabled - ::SendDlgItemMessage(_hSelf, IDC_BACKWARDDIRECTION, BM_SETCHECK, BST_UNCHECKED, 0); - enableFindDlgItem(IDC_BACKWARDDIRECTION, nppParams.regexBackward4PowerUser()); - enableFindDlgItem(IDC_FINDPREV, nppParams.regexBackward4PowerUser()); - - // If the search mode from history is regExp then enable the checkbox (. matches newline) - enableFindDlgItem(IDREDOTMATCHNL); - } + // 设置其他复选框的选中状态 + // ... + // 如果系统支持透明度,则设置透明度相关控件的显示状态和属性 if (nppParams.isTransparentAvailable()) { + // 显示透明度相关控件 showFindDlgItem(IDC_TRANSPARENT_CHECK); showFindDlgItem(IDC_TRANSPARENT_GRPBOX); showFindDlgItem(IDC_TRANSPARENT_LOSSFOCUS_RADIO); showFindDlgItem(IDC_TRANSPARENT_ALWAYS_RADIO); showFindDlgItem(IDC_PERCENTAGE_SLIDER); + // 设置滑动条范围和位置 ::SendDlgItemMessage(_hSelf, IDC_PERCENTAGE_SLIDER, TBM_SETRANGE, FALSE, MAKELONG(20, 200)); ::SendDlgItemMessage(_hSelf, IDC_PERCENTAGE_SLIDER, TBM_SETPOS, TRUE, findHistory._transparency); + // 根据透明度模式设置相应的复选框选中状态 if (findHistory._transparencyMode == FindHistory::none) { enableFindDlgItem(IDC_TRANSPARENT_LOSSFOCUS_RADIO, false); @@ -436,44 +436,47 @@ void FindReplaceDlg::fillFindHistory() { id = IDC_TRANSPARENT_ALWAYS_RADIO; (NppParameters::getInstance()).SetTransparent(_hSelf, findHistory._transparency); - } ::SendDlgItemMessage(_hSelf, id, BM_SETCHECK, TRUE, 0); } } } +// 填充 Combo Box 的历史记录 void FindReplaceDlg::fillComboHistory(int id, const vector & strings) { HWND hCombo = ::GetDlgItem(_hSelf, id); + // 将历史记录添加到 Combo Box for (vector::const_reverse_iterator i = strings.rbegin() ; i != strings.rend(); ++i) { addText2Combo(i->c_str(), hCombo); } - //empty string is not added to CB items, so we need to set it manually + // 如果历史记录不为空且第一个元素为空字符串,则手动设置 Combo Box 文本为空 if (!strings.empty() && strings.begin()->empty()) { SetWindowText(hCombo, _T("")); return; } - ::SendMessage(hCombo, CB_SETCURSEL, 0, 0); // select first item + ::SendMessage(hCombo, CB_SETCURSEL, 0, 0); // 选择第一项 } - +// 保存查找历史记录 void FindReplaceDlg::saveFindHistory() { if (! isCreated()) return; FindHistory& findHistory = (NppParameters::getInstance()).getFindHistory(); + // 保存各个 Combo Box 的历史记录 saveComboHistory(IDD_FINDINFILES_DIR_COMBO, findHistory._nbMaxFindHistoryPath, findHistory._findHistoryPaths, false); saveComboHistory(IDD_FINDINFILES_FILTERS_COMBO, findHistory._nbMaxFindHistoryFilter, findHistory._findHistoryFilters, true); - saveComboHistory(IDFINDWHAT, findHistory._nbMaxFindHistoryFind, findHistory._findHistoryFinds, false); - saveComboHistory(IDREPLACEWITH, findHistory._nbMaxFindHistoryReplace, findHistory._findHistoryReplaces, true); + saveComboHistory(IDFINDWHAT, findHistory._nbMaxFindHistoryFind, findHistory._findHistoryFinds, false); + saveComboHistory(IDREPLACEWITH, findHistory._nbMaxFindHistoryReplace, findHistory._findHistoryReplaces, true); } +// 保存 Combo Box 的历史记录 int FindReplaceDlg::saveComboHistory(int id, int maxcount, vector & strings, bool saveEmpty) { TCHAR text[FINDREPLACE_MAXLENGTH] = { '\0' }; @@ -485,6 +488,7 @@ int FindReplaceDlg::saveComboHistory(int id, int maxcount, vector range : markingLine._segmentPostions) - { - ++count; - - if (lastEnd <= currentPosInLine && currentPosInLine < range.first) - { - if (count == 1) - { - cpili._status = pos_infront; - break; - } - else - { - cpili._status = pos_between; - cpili.auxiliaryInfo = count - 1; - break; - } - } - - if (range.first <= currentPosInLine && currentPosInLine <= range.second) - { - if (currentPosInLine == range.first && !hasSel) - { - cpili._status = pos_between; - cpili.auxiliaryInfo = count - 1; // c1 c2 - // [ ] I[ ] : I is recongnized with c2, so auxiliaryInfo should be c1 (c2-1) - } - else if (currentPosInLine == range.second && !hasSel) - { - cpili._status = pos_between; - cpili.auxiliaryInfo = count; // c1 c2 - // [ ]I [ ] : I is recongnized with c1, so auxiliaryInfo should be c1 - } - else - { - cpili._status = pos_inside; - cpili.auxiliaryInfo = count; - } - break; - } - - if (range.second < currentPosInLine) - { - if (markingLine._segmentPostions.size() == count) - { - cpili._status = pos_behind; - cpili.auxiliaryInfo = count; - break; - } - } - - lastEnd = range.second; - } + // 定义用于返回的结构体 + CurrentPosInLineInfo cpili; + // 初始化计数器count为0 + size_t count = 0; + // 初始化上一个区间的结束位置为0 + intptr_t lastEnd = 0; + // 获取当前文本框选择的起始位置和结束位置 + auto selStart = _scintView.execute(SCI_GETSELECTIONSTART); + auto selEnd = _scintView.execute(SCI_GETSELECTIONEND); + // 判断是否有选择文本 + bool hasSel = (selEnd - selStart) != 0; + + // 遍历每个区间 + for (std::pair range : markingLine._segmentPostions) + { + ++count; + + // 判断当前位置在区间的前面 + if (lastEnd <= currentPosInLine && currentPosInLine < range.first) + { + if (count == 1) + { + cpili._status = pos_infront; // 在第一个区间的前面 + break; + } + else + { + cpili._status = pos_between; // 在两个区间之间 + cpili.auxiliaryInfo = count - 1; + break; + } + } + + // 判断当前位置在区间内部 + if (range.first <= currentPosInLine && currentPosInLine <= range.second) + { + if (currentPosInLine == range.first && !hasSel) + { + cpili._status = pos_between; // 在区间的起始位置,在没有选择文本的情况下 + cpili.auxiliaryInfo = count - 1; + } + else if (currentPosInLine == range.second && !hasSel) + { + cpili._status = pos_between; // 在区间的结束位置,在没有选择文本的情况下 + cpili.auxiliaryInfo = count; + } + else + { + cpili._status = pos_inside; // 在区间内部 + cpili.auxiliaryInfo = count; + } + break; + } + + // 判断当前位置在区间的后面 + if (range.second < currentPosInLine) + { + if (markingLine._segmentPostions.size() == count) + { + cpili._status = pos_behind; // 在最后一个区间的后面 + cpili.auxiliaryInfo = count; + break; + } + } + + lastEnd = range.second; + } - return cpili; + return cpili; } void Finder::anchorWithNoHeaderLines(intptr_t& currentL, intptr_t initL, intptr_t minL, intptr_t maxL, int direction) { - if (currentL > maxL && direction == 0) - currentL = minL; - - while (_scintView.execute(SCI_GETFOLDLEVEL, currentL) & SC_FOLDLEVELHEADERFLAG) - { - currentL += direction == -1 ? -1 : 1; - - if (currentL > maxL) - currentL = minL; - else if (currentL < minL) - currentL = maxL; - - if (currentL == initL) - break; - } + // 如果当前行大于最大行并且方向为0,则将当前行设置为最小行 + if (currentL > maxL && direction == 0) + currentL = minL; + + // 循环直到当前行不是折叠标题行 + while (_scintView.execute(SCI_GETFOLDLEVEL, currentL) & SC_FOLDLEVELHEADERFLAG) + { + // 根据方向更新当前行 + currentL += direction == -1 ? -1 : 1; + + // 如果当前行超过最大行,则将当前行设置为最小行 + if (currentL > maxL) + currentL = minL; + // 如果当前行低于最小行,则将当前行设置为最大行 + else if (currentL < minL) + currentL = maxL; + + // 如果当前行等于初始行,则跳出循环 + if (currentL == initL) + break; + } - auto extremityAbsoltePos = _scintView.execute(direction == -1 ? SCI_GETLINEENDPOSITION : SCI_POSITIONFROMLINE, currentL); - _scintView.execute(SCI_SETSEL, extremityAbsoltePos, extremityAbsoltePos); + // 获取当前行的绝对位置 + auto extremityAbsoltePos = _scintView.execute(direction == -1 ? SCI_GETLINEENDPOSITION : SCI_POSITIONFROMLINE, currentL); + // 设置选择范围为当前行的绝对位置 + _scintView.execute(SCI_SETSEL, extremityAbsoltePos, extremityAbsoltePos); } void Finder::gotoNextFoundResult(int direction) { - // - // Get currentLine & currentPosInLine from CurrentPos - // - auto currentPos = _scintView.execute(SCI_GETCURRENTPOS); - intptr_t lno = _scintView.execute(SCI_LINEFROMPOSITION, currentPos); - auto total_lines = _scintView.execute(SCI_GETLINECOUNT); - if (total_lines <= 1) return; - - auto lineStartAbsPos = _scintView.execute(SCI_POSITIONFROMLINE, lno); - intptr_t currentPosInLine = currentPos - lineStartAbsPos; - - auto init_lno = lno; - auto max_lno = _scintView.execute(SCI_GETLASTCHILD, lno, searchHeaderLevel); + // 获取当前光标位置及所在行号 + auto currentPos = _scintView.execute(SCI_GETCURRENTPOS); + intptr_t lno = _scintView.execute(SCI_LINEFROMPOSITION, currentPos); + auto total_lines = _scintView.execute(SCI_GETLINECOUNT); + // 如果总行数小于等于1,则直接返回 + if (total_lines <= 1) return; + + // 获取当前行的起始位置和光标在行内的位置 + auto lineStartAbsPos = _scintView.execute(SCI_POSITIONFROMLINE, lno); + intptr_t currentPosInLine = currentPos - lineStartAbsPos; + + auto init_lno = lno; + auto max_lno = _scintView.execute(SCI_GETLASTCHILD, lno, searchHeaderLevel); + + assert(max_lno <= total_lines - 2); + + // 获取当前搜索行号(searchHeaderLevel) + int level = _scintView.execute(SCI_GETFOLDLEVEL, lno) & SC_FOLDLEVELNUMBERMASK; + auto min_lno = lno; + while (level-- >= fileHeaderLevel) + { + min_lno = _scintView.execute(SCI_GETFOLDPARENT, min_lno); + assert(min_lno >= 0); + } - assert(max_lno <= total_lines - 2); + if (min_lno < 0) min_lno = lno; // 当lno是一个搜索标题行时 - // get the line number of the current search (searchHeaderLevel) - int level = _scintView.execute(SCI_GETFOLDLEVEL, lno) & SC_FOLDLEVELNUMBERMASK; - auto min_lno = lno; - while (level-- >= fileHeaderLevel) - { - min_lno = _scintView.execute(SCI_GETFOLDPARENT, min_lno); - assert(min_lno >= 0); - } + assert(min_lno <= max_lno); - if (min_lno < 0) min_lno = lno; // when lno is a search header line + // 根据方向更新当前行号 + if (lno > max_lno && direction == 0) lno = min_lno; + else if (lno < min_lno) lno = max_lno; - assert(min_lno <= max_lno); + // 设置锚点,确保锚点不在最后一行或折叠标题行上 + while (_scintView.execute(SCI_GETFOLDLEVEL, lno) & SC_FOLDLEVELHEADERFLAG) + { + lno += direction == -1 ? -1 : 1; - if (lno > max_lno && direction == 0) lno = min_lno; - else if (lno < min_lno) lno = max_lno; + if (lno > max_lno) + lno = min_lno; + else if (lno < min_lno) + lno = max_lno; - // - // Set anchor and make sure that achor is not on the last (empty) line or head lines - // - while (_scintView.execute(SCI_GETFOLDLEVEL, lno) & SC_FOLDLEVELHEADERFLAG) - { - lno += direction == -1 ? -1 : 1; - - if (lno > max_lno) - lno = min_lno; - else if (lno < min_lno) - lno = max_lno; - - if (lno == init_lno) - break; - } + if (lno == init_lno) + break; + } - if (lno != init_lno) - { - auto extremityAbsoltePos = _scintView.execute(direction == -1 ? SCI_GETLINEENDPOSITION : SCI_POSITIONFROMLINE, lno); - _scintView.execute(SCI_SETSEL, extremityAbsoltePos, extremityAbsoltePos); - currentPos = extremityAbsoltePos; - auto start = _scintView.execute(SCI_POSITIONFROMLINE, lno); - currentPosInLine = currentPos - start; - } + // 如果当前行与初始行不同 + if (lno != init_lno) + { + // 获取当前行的绝对位置 + auto extremityAbsoltePos = _scintView.execute(direction == -1 ? SCI_GETLINEENDPOSITION : SCI_POSITIONFROMLINE, lno); + // 设置选择范围为当前行的绝对位置 + _scintView.execute(SCI_SETSEL, extremityAbsoltePos, extremityAbsoltePos); + currentPos = extremityAbsoltePos; + // 获取当前行的起始位置和光标在行内的位置 + auto start = _scintView.execute(SCI_POSITIONFROMLINE, lno); + currentPosInLine = currentPos - start; + } + size_t n = 0; + const SearchResultMarkingLine& markingLine = *(_pMainMarkings->begin() + lno); - size_t n = 0; - const SearchResultMarkingLine& markingLine = *(_pMainMarkings->begin() + lno); + // 获取当前位置在行内的状态 + CurrentPosInLineInfo cpili = getCurrentPosInLineInfo(currentPosInLine, markingLine); - // - // Determinate currentPosInLine status among pos_infront, pose_between, pos_inside and pos_behind - // - CurrentPosInLineInfo cpili = getCurrentPosInLineInfo(currentPosInLine, markingLine); + // 根据方向和当前 // // According CurrentPosInLineInfo and direction, set position and get number of occurrence