Merge pull request 'lbs 合并' (#13) from lba_new into master

gongao_branch
por68nab5 10 months ago
commit 689b83b158

@ -23,6 +23,9 @@
#include "Common.h" #include "Common.h"
#include "Utf8.h" #include "Utf8.h"
```cpp
using namespace std; using namespace std;
FindOption * FindReplaceDlg::_env; FindOption * FindReplaceDlg::_env;
@ -35,12 +38,15 @@ void addText2Combo(const TCHAR * txt2add, HWND hCombo)
if (!hCombo) return; if (!hCombo) return;
if (!lstrcmp(txt2add, TEXT(""))) return; if (!lstrcmp(txt2add, TEXT(""))) return;
// 在组合框中查找是否已存在相同的文本
auto i = ::SendMessage(hCombo, CB_FINDSTRINGEXACT, static_cast<WPARAM>(-1), reinterpret_cast<LPARAM>(txt2add)); auto i = ::SendMessage(hCombo, CB_FINDSTRINGEXACT, static_cast<WPARAM>(-1), reinterpret_cast<LPARAM>(txt2add));
if (i != CB_ERR) // found if (i != CB_ERR) // 找到了相同的文本
{ {
// 删除已存在的文本
::SendMessage(hCombo, CB_DELETESTRING, i, 0); ::SendMessage(hCombo, CB_DELETESTRING, i, 0);
} }
// 向组合框中插入新的文本,并设置为当前选中项
i = ::SendMessage(hCombo, CB_INSERTSTRING, 0, reinterpret_cast<LPARAM>(txt2add)); i = ::SendMessage(hCombo, CB_INSERTSTRING, 0, reinterpret_cast<LPARAM>(txt2add));
::SendMessage(hCombo, CB_SETCURSEL, i, 0); ::SendMessage(hCombo, CB_SETCURSEL, i, 0);
} }
@ -59,6 +65,8 @@ void delLeftWordInEdit(HWND hEdit)
WORD cursor = 0; WORD cursor = 0;
::SendMessage(hEdit, EM_GETSEL, (WPARAM)&cursor, 0); ::SendMessage(hEdit, EM_GETSEL, (WPARAM)&cursor, 0);
WORD wordstart = cursor; WORD wordstart = cursor;
// 删除光标左边的单词
while (wordstart > 0) { while (wordstart > 0) {
TCHAR c = str[wordstart - 1]; TCHAR c = str[wordstart - 1];
if (c != ' ' && c != '\t') if (c != ' ' && c != '\t')
@ -83,6 +91,7 @@ LRESULT run_swapButtonProc(WNDPROC oldEditProc, HWND hwnd, UINT message, WPARAM
{ {
case WM_RBUTTONUP: case WM_RBUTTONUP:
{ {
// 模拟右键点击事件,发送给父窗口处理
::SendMessage(GetParent(hwnd), message, wParam, lParam); ::SendMessage(GetParent(hwnd), message, wParam, lParam);
break; 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) 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 i = 0, j = 0;
int charLeft = length; int charLeft = length;
TCHAR current; TCHAR current;
while (i < length) 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]; current = query[i];
--charLeft; --charLeft;
if (current == '\\' && charLeft) if (current == '\\' && charLeft)
{ //possible escape sequence {
++i; ++i;
--charLeft; --charLeft;
current = query[i]; current = query[i];
switch(current) switch(current)
{ {
case 'r': case 'r':
@ -131,24 +143,26 @@ int Searching::convertExtendedToString(const TCHAR * query, TCHAR * result, int
case 'u': case 'u':
{ {
int size = 0, base = 0; int size = 0, base = 0;
// 根据转义序列的类型设置不同的大小和进制
if (current == 'b') if (current == 'b')
{ //11111111 {
size = 8, base = 2; size = 8, base = 2;
} }
else if (current == 'o') else if (current == 'o')
{ //377 {
size = 3, base = 8; size = 3, base = 8;
} }
else if (current == 'd') else if (current == 'd')
{ //255 {
size = 3, base = 10; size = 3, base = 10;
} }
else if (current == 'x') else if (current == 'x')
{ //0xFF {
size = 2, base = 16; size = 2, base = 16;
} }
else if (current == 'u') else if (current == 'u')
{ //0xCDCD {
size = 4, base = 16; size = 4, base = 16;
} }
@ -162,12 +176,14 @@ int Searching::convertExtendedToString(const TCHAR * query, TCHAR * result, int
break; break;
} }
} }
//not enough chars to make parameter, use default method as fallback
// 字符不足以构成参数,则使用默认方法作为备选方案
[[fallthrough]]; [[fallthrough]];
} }
default: default:
{ //unknown sequence, treat as regular text {
// 未知序列,当做普通文本处理
result[j] = '\\'; result[j] = '\\';
++j; ++j;
result[j] = current; result[j] = current;
@ -182,6 +198,7 @@ int Searching::convertExtendedToString(const TCHAR * query, TCHAR * result, int
++i; ++i;
++j; ++j;
} }
result[j] = 0; result[j] = 0;
return j; return j;
} }
@ -195,6 +212,7 @@ bool Searching::readBase(const TCHAR * str, int * value, int base, int size)
while (i < size) while (i < size)
{ {
current = str[i]; current = str[i];
if (current >= 'A') if (current >= 'A')
{ {
current &= 0xdf; 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) 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, posStart));
pEditView->execute(SCI_ENSUREVISIBLE, pEditView->execute(SCI_LINEFROMPOSITION, posEnd)); 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_SETVISIBLEPOLICY, CARET_JUMPS | CARET_EVEN);
pEditView->execute(SCI_ENSUREVISIBLEENFORCEPOLICY, pEditView->execute(SCI_LINEFROMPOSITION, isDownwards ? posEnd : posStart)); 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_GOTOPOS, isDownwards ? posEnd : posStart);
pEditView->execute(SCI_SETVISIBLEPOLICY, CARET_EVEN); pEditView->execute(SCI_SETVISIBLEPOLICY, CARET_EVEN);
pEditView->execute(SCI_ENSUREVISIBLEENFORCEPOLICY, pEditView->execute(SCI_LINEFROMPOSITION, isDownwards ? posEnd : posStart)); 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); pEditView->execute(SCI_SCROLLRANGE, posStart, posEnd);
// Move cursor to end of result and select result // 将光标移到结果的末尾并选中结果
pEditView->execute(SCI_GOTOPOS, posEnd); pEditView->execute(SCI_GOTOPOS, posEnd);
pEditView->execute(SCI_SETANCHOR, posStart); pEditView->execute(SCI_SETANCHOR, posStart);
// Update Scintilla's knowledge about what column the caret is in, so that if user // 更新 Scintilla 中光标所在列的位置信息,以防用户在选择搜索结果后使用上下箭头导航时光标跳到意外的列
// does up/down arrow as first navigation after the search result is selected,
// the caret doesn't jump to an unexpected column
pEditView->execute(SCI_CHOOSECARETX); pEditView->execute(SCI_CHOOSECARETX);
} }
WNDPROC FindReplaceDlg::originalFinderProc = nullptr; WNDPROC FindReplaceDlg::originalFinderProc = nullptr;
WNDPROC FindReplaceDlg::originalComboEditProc = nullptr; WNDPROC FindReplaceDlg::originalComboEditProc = nullptr;
```
// important : to activate all styles // important : to activate all styles
const int STYLING_MASK = 255; const int STYLING_MASK = 255;
```cpp
// 定义 FindReplaceDlg 类的析构函数
FindReplaceDlg::~FindReplaceDlg() FindReplaceDlg::~FindReplaceDlg()
{ {
_tab.destroy(); _tab.destroy(); // 销毁标签页控件
delete _pFinder; delete _pFinder; // 删除查找对象指针
// 删除与查找对象相关的所有查找器对象
for (int n = static_cast<int32_t>(_findersOfFinder.size()) - 1; n >= 0; n--) for (int n = static_cast<int32_t>(_findersOfFinder.size()) - 1; n >= 0; n--)
{ {
delete _findersOfFinder[n]; delete _findersOfFinder[n];
_findersOfFinder.erase(_findersOfFinder.begin() + n); _findersOfFinder.erase(_findersOfFinder.begin() + n);
} }
// 销毁窗口句柄
if (_shiftTrickUpTip) if (_shiftTrickUpTip)
::DestroyWindow(_shiftTrickUpTip); ::DestroyWindow(_shiftTrickUpTip);
if (_2ButtonsTip) if (_2ButtonsTip)
::DestroyWindow(_2ButtonsTip); ::DestroyWindow(_2ButtonsTip);
if (_filterTip) if (_filterTip)
::DestroyWindow(_filterTip); ::DestroyWindow(_filterTip);
// 释放字体对象
if (_hMonospaceFont) if (_hMonospaceFont)
::DeleteObject(_hMonospaceFont); ::DeleteObject(_hMonospaceFont);
if (_hLargerBolderFont) if (_hLargerBolderFont)
::DeleteObject(_hLargerBolderFont); ::DeleteObject(_hLargerBolderFont);
if (_hCourrierNewFont) if (_hCourrierNewFont)
::DeleteObject(_hCourrierNewFont); ::DeleteObject(_hCourrierNewFont);
delete[] _uniFileName; delete[] _uniFileName; // 释放存储文件名的数组内存
} }
// 创建 FindReplaceDlg 对话框
void FindReplaceDlg::create(int dialogID, bool isRTL, bool msgDestParent, bool toShow) void FindReplaceDlg::create(int dialogID, bool isRTL, bool msgDestParent, bool toShow)
{ {
// 创建静态对话框
StaticDialog::create(dialogID, isRTL, msgDestParent); StaticDialog::create(dialogID, isRTL, msgDestParent);
fillFindHistory(); fillFindHistory(); // 填充查找历史记录
_currentStatus = REPLACE_DLG; _currentStatus = REPLACE_DLG; // 设置当前状态为替换对话框
initOptionsFromDlg(); initOptionsFromDlg(); // 从对话框初始化选项
_statusBar.init(GetModuleHandle(NULL), _hSelf, 0); _statusBar.init(GetModuleHandle(NULL), _hSelf, 0); // 初始化状态栏
_statusBar.display(); _statusBar.display(); // 显示状态栏
// 获取 DPI 管理器
DPIManager& dpiManager = NppParameters::getInstance()._dpiManager; DPIManager& dpiManager = NppParameters::getInstance()._dpiManager;
RECT rect{}; RECT rect{};
getClientRect(rect); getClientRect(rect); // 获取客户区矩形
_tab.init(_hInst, _hSelf, false, true); _tab.init(_hInst, _hSelf, false, true); // 初始化标签页控件
NppDarkMode::subclassTabControl(_tab.getHSelf()); NppDarkMode::subclassTabControl(_tab.getHSelf()); // 子类化标签页控件以适配暗黑模式
int tabDpiDynamicalHeight = dpiManager.scaleY(13); int tabDpiDynamicalHeight = dpiManager.scaleY(13); // 根据 DPI 缩放标签页高度
_tab.setFont(TEXT("Tahoma"), tabDpiDynamicalHeight); _tab.setFont(TEXT("Tahoma"), tabDpiDynamicalHeight); // 设置标签页字体
// 插入标签页内容
const TCHAR *find = TEXT("Find"); const TCHAR *find = TEXT("Find");
const TCHAR *replace = TEXT("Replace"); const TCHAR *replace = TEXT("Replace");
const TCHAR *findInFiles = TEXT("Find in Files"); const TCHAR *findInFiles = TEXT("Find in Files");
const TCHAR *findInProjects = TEXT("Find in Projects"); const TCHAR *findInProjects = TEXT("Find in Projects");
const TCHAR *mark = TEXT("Mark"); const TCHAR *mark = TEXT("Mark");
_tab.insertAtEnd(find); _tab.insertAtEnd(find);
_tab.insertAtEnd(replace); _tab.insertAtEnd(replace);
_tab.insertAtEnd(findInFiles); _tab.insertAtEnd(findInFiles);
_tab.insertAtEnd(findInProjects); _tab.insertAtEnd(findInProjects);
_tab.insertAtEnd(mark); _tab.insertAtEnd(mark);
_tab.reSizeTo(rect); // 调整标签页大小以适应客户区
_tab.display(); // 显示标签页
_tab.reSizeTo(rect); _initialClientWidth = rect.right - rect.left; // 记录初始客户区宽度
_tab.display();
_initialClientWidth = rect.right - rect.left;
//fill min dialog size info // 填充最小对话框大小信息
getWindowRect(_initialWindowRect); getWindowRect(_initialWindowRect);
_initialWindowRect.right = _initialWindowRect.right - _initialWindowRect.left + dpiManager.scaleX(10); _initialWindowRect.right = _initialWindowRect.right - _initialWindowRect.left + dpiManager.scaleX(10);
_initialWindowRect.left = 0; _initialWindowRect.left = 0;
@ -335,88 +358,65 @@ void FindReplaceDlg::create(int dialogID, bool isRTL, bool msgDestParent, bool t
NppGUI& nppGUI = nppParam.getNppGUI(); NppGUI& nppGUI = nppParam.getNppGUI();
const UINT swpFlags = toShow ? SWP_SHOWWINDOW : SWP_HIDEWINDOW; 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); RECT rc = getViewablePositionRect(nppGUI._findWindowPos);
::SetWindowPos(_hSelf, HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, swpFlags); ::SetWindowPos(_hSelf, HWND_TOP, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, swpFlags);
} }
else else
{ {
goToCenter(swpFlags); goToCenter(swpFlags); // 居中显示
} }
// 获取状态栏客户区矩形
RECT rcStatusBar{}; RECT rcStatusBar{};
::GetClientRect(_statusBar.getHSelf(), &rcStatusBar); ::GetClientRect(_statusBar.getHSelf(), &rcStatusBar);
_lesssModeHeight = (countRc.bottom - dlgRc.top) + (rcStatusBar.bottom - rcStatusBar.top) + dpiManager.scaleY(10); _lesssModeHeight = (countRc.bottom - dlgRc.top) + (rcStatusBar.bottom - rcStatusBar.top) + dpiManager.scaleY(10);
if (nppGUI._findWindowLessMode) 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; nppGUI._findWindowLessMode = false;
::SendMessage(_hSelf, WM_COMMAND, IDD_RESIZE_TOGGLE_BUTTON, 0); ::SendMessage(_hSelf, WM_COMMAND, IDD_RESIZE_TOGGLE_BUTTON, 0);
} }
} }
// 填充查找历史记录
void FindReplaceDlg::fillFindHistory() void FindReplaceDlg::fillFindHistory()
{ {
NppParameters& nppParams = NppParameters::getInstance(); NppParameters& nppParams = NppParameters::getInstance();
FindHistory & findHistory = nppParams.getFindHistory(); FindHistory & findHistory = nppParams.getFindHistory();
// 填充各个 Combo Box 的历史记录
fillComboHistory(IDFINDWHAT, findHistory._findHistoryFinds); fillComboHistory(IDFINDWHAT, findHistory._findHistoryFinds);
fillComboHistory(IDREPLACEWITH, findHistory._findHistoryReplaces); fillComboHistory(IDREPLACEWITH, findHistory._findHistoryReplaces);
fillComboHistory(IDD_FINDINFILES_FILTERS_COMBO, findHistory._findHistoryFilters); fillComboHistory(IDD_FINDINFILES_FILTERS_COMBO, findHistory._findHistoryFilters);
fillComboHistory(IDD_FINDINFILES_DIR_COMBO, findHistory._findHistoryPaths); fillComboHistory(IDD_FINDINFILES_DIR_COMBO, findHistory._findHistoryPaths);
// 设置各个复选框的选中状态
::SendDlgItemMessage(_hSelf, IDWRAP, BM_SETCHECK, findHistory._isWrap, 0); ::SendDlgItemMessage(_hSelf, IDWRAP, BM_SETCHECK, findHistory._isWrap, 0);
::SendDlgItemMessage(_hSelf, IDWHOLEWORD, BM_SETCHECK, findHistory._isMatchWord, 0); ::SendDlgItemMessage(_hSelf, IDWHOLEWORD, BM_SETCHECK, findHistory._isMatchWord, 0);
::SendDlgItemMessage(_hSelf, IDMATCHCASE, BM_SETCHECK, findHistory._isMatchCase, 0); ::SendDlgItemMessage(_hSelf, IDMATCHCASE, BM_SETCHECK, findHistory._isMatchCase, 0);
::SendDlgItemMessage(_hSelf, IDC_BACKWARDDIRECTION, BM_SETCHECK, !findHistory._isDirectionDown, 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()) if (nppParams.isTransparentAvailable())
{ {
// 显示透明度相关控件
showFindDlgItem(IDC_TRANSPARENT_CHECK); showFindDlgItem(IDC_TRANSPARENT_CHECK);
showFindDlgItem(IDC_TRANSPARENT_GRPBOX); showFindDlgItem(IDC_TRANSPARENT_GRPBOX);
showFindDlgItem(IDC_TRANSPARENT_LOSSFOCUS_RADIO); showFindDlgItem(IDC_TRANSPARENT_LOSSFOCUS_RADIO);
showFindDlgItem(IDC_TRANSPARENT_ALWAYS_RADIO); showFindDlgItem(IDC_TRANSPARENT_ALWAYS_RADIO);
showFindDlgItem(IDC_PERCENTAGE_SLIDER); showFindDlgItem(IDC_PERCENTAGE_SLIDER);
// 设置滑动条范围和位置
::SendDlgItemMessage(_hSelf, IDC_PERCENTAGE_SLIDER, TBM_SETRANGE, FALSE, MAKELONG(20, 200)); ::SendDlgItemMessage(_hSelf, IDC_PERCENTAGE_SLIDER, TBM_SETRANGE, FALSE, MAKELONG(20, 200));
::SendDlgItemMessage(_hSelf, IDC_PERCENTAGE_SLIDER, TBM_SETPOS, TRUE, findHistory._transparency); ::SendDlgItemMessage(_hSelf, IDC_PERCENTAGE_SLIDER, TBM_SETPOS, TRUE, findHistory._transparency);
// 根据透明度模式设置相应的复选框选中状态
if (findHistory._transparencyMode == FindHistory::none) if (findHistory._transparencyMode == FindHistory::none)
{ {
enableFindDlgItem(IDC_TRANSPARENT_LOSSFOCUS_RADIO, false); enableFindDlgItem(IDC_TRANSPARENT_LOSSFOCUS_RADIO, false);
@ -436,44 +436,47 @@ void FindReplaceDlg::fillFindHistory()
{ {
id = IDC_TRANSPARENT_ALWAYS_RADIO; id = IDC_TRANSPARENT_ALWAYS_RADIO;
(NppParameters::getInstance()).SetTransparent(_hSelf, findHistory._transparency); (NppParameters::getInstance()).SetTransparent(_hSelf, findHistory._transparency);
} }
::SendDlgItemMessage(_hSelf, id, BM_SETCHECK, TRUE, 0); ::SendDlgItemMessage(_hSelf, id, BM_SETCHECK, TRUE, 0);
} }
} }
} }
// 填充 Combo Box 的历史记录
void FindReplaceDlg::fillComboHistory(int id, const vector<generic_string> & strings) void FindReplaceDlg::fillComboHistory(int id, const vector<generic_string> & strings)
{ {
HWND hCombo = ::GetDlgItem(_hSelf, id); HWND hCombo = ::GetDlgItem(_hSelf, id);
// 将历史记录添加到 Combo Box
for (vector<generic_string>::const_reverse_iterator i = strings.rbegin() ; i != strings.rend(); ++i) for (vector<generic_string>::const_reverse_iterator i = strings.rbegin() ; i != strings.rend(); ++i)
{ {
addText2Combo(i->c_str(), hCombo); 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()) if (!strings.empty() && strings.begin()->empty())
{ {
SetWindowText(hCombo, _T("")); SetWindowText(hCombo, _T(""));
return; return;
} }
::SendMessage(hCombo, CB_SETCURSEL, 0, 0); // select first item ::SendMessage(hCombo, CB_SETCURSEL, 0, 0); // 选择第一项
} }
// 保存查找历史记录
void FindReplaceDlg::saveFindHistory() void FindReplaceDlg::saveFindHistory()
{ {
if (! isCreated()) return; if (! isCreated()) return;
FindHistory& findHistory = (NppParameters::getInstance()).getFindHistory(); FindHistory& findHistory = (NppParameters::getInstance()).getFindHistory();
// 保存各个 Combo Box 的历史记录
saveComboHistory(IDD_FINDINFILES_DIR_COMBO, findHistory._nbMaxFindHistoryPath, findHistory._findHistoryPaths, false); saveComboHistory(IDD_FINDINFILES_DIR_COMBO, findHistory._nbMaxFindHistoryPath, findHistory._findHistoryPaths, false);
saveComboHistory(IDD_FINDINFILES_FILTERS_COMBO, findHistory._nbMaxFindHistoryFilter, findHistory._findHistoryFilters, true); saveComboHistory(IDD_FINDINFILES_FILTERS_COMBO, findHistory._nbMaxFindHistoryFilter, findHistory._findHistoryFilters, true);
saveComboHistory(IDFINDWHAT, findHistory._nbMaxFindHistoryFind, findHistory._findHistoryFinds, false); saveComboHistory(IDFINDWHAT, findHistory._nbMaxFindHistoryFind, findHistory._findHistoryFinds, false);
saveComboHistory(IDREPLACEWITH, findHistory._nbMaxFindHistoryReplace, findHistory._findHistoryReplaces, true); saveComboHistory(IDREPLACEWITH, findHistory._nbMaxFindHistoryReplace, findHistory._findHistoryReplaces, true);
} }
// 保存 Combo Box 的历史记录
int FindReplaceDlg::saveComboHistory(int id, int maxcount, vector<generic_string> & strings, bool saveEmpty) int FindReplaceDlg::saveComboHistory(int id, int maxcount, vector<generic_string> & strings, bool saveEmpty)
{ {
TCHAR text[FINDREPLACE_MAXLENGTH] = { '\0' }; TCHAR text[FINDREPLACE_MAXLENGTH] = { '\0' };
@ -485,6 +488,7 @@ int FindReplaceDlg::saveComboHistory(int id, int maxcount, vector<generic_string
strings.clear(); strings.clear();
// 如果允许保存空字符串,则检查 Combo Box 文本是否为空,并加入历史记录
if (saveEmpty) if (saveEmpty)
{ {
if (::GetWindowTextLength(hCombo) == 0) if (::GetWindowTextLength(hCombo) == 0)
@ -493,6 +497,7 @@ int FindReplaceDlg::saveComboHistory(int id, int maxcount, vector<generic_string
} }
} }
// 保存 Combo Box 中的文本到历史记录
for (int i = 0 ; i < count ; ++i) for (int i = 0 ; i < count ; ++i)
{ {
auto cbTextLen = ::SendMessage(hCombo, CB_GETLBTEXTLEN, i, 0); auto cbTextLen = ::SendMessage(hCombo, CB_GETLBTEXTLEN, i, 0);
@ -504,13 +509,14 @@ int FindReplaceDlg::saveComboHistory(int id, int maxcount, vector<generic_string
} }
return count; return count;
} }
```
//更新数据Combo
void FindReplaceDlg::updateCombos() void FindReplaceDlg::updateCombos()
{ {
updateCombo(IDREPLACEWITH); updateCombo(IDREPLACEWITH);
updateCombo(IDFINDWHAT); updateCombo(IDFINDWHAT);
} }
//
void FindReplaceDlg::updateCombo(int comboID) void FindReplaceDlg::updateCombo(int comboID)
{ {
HWND hCombo = ::GetDlgItem(_hSelf, comboID); HWND hCombo = ::GetDlgItem(_hSelf, comboID);
@ -725,162 +731,181 @@ bool Finder::canFind(const TCHAR *fileName, size_t lineNumber, size_t* indexToSt
// [ ] [ ] [ Y [ ] : pos_between 3 // [ ] [ ] [ Y [ ] : pos_between 3
// [ ] [ ] Y [ ] [ ] : pos_between 2 // [ ] [ ] Y [ ] [ ] : pos_between 2
// [ ] [ ] [ ] [ ] Y : pos_behind 4 // [ ] [ ] [ ] [ ] Y : pos_behind 4
```cpp
Finder::CurrentPosInLineInfo Finder::getCurrentPosInLineInfo(intptr_t currentPosInLine, const SearchResultMarkingLine& markingLine) const Finder::CurrentPosInLineInfo Finder::getCurrentPosInLineInfo(intptr_t currentPosInLine, const SearchResultMarkingLine& markingLine) const
{ {
CurrentPosInLineInfo cpili; // 定义用于返回的结构体
size_t count = 0; CurrentPosInLineInfo cpili;
intptr_t lastEnd = 0; // 初始化计数器count为0
auto selStart = _scintView.execute(SCI_GETSELECTIONSTART); size_t count = 0;
auto selEnd = _scintView.execute(SCI_GETSELECTIONEND); // 初始化上一个区间的结束位置为0
bool hasSel = (selEnd - selStart) != 0; intptr_t lastEnd = 0;
// 获取当前文本框选择的起始位置和结束位置
for (std::pair<intptr_t, intptr_t> range : markingLine._segmentPostions) auto selStart = _scintView.execute(SCI_GETSELECTIONSTART);
{ auto selEnd = _scintView.execute(SCI_GETSELECTIONEND);
++count; // 判断是否有选择文本
bool hasSel = (selEnd - selStart) != 0;
if (lastEnd <= currentPosInLine && currentPosInLine < range.first)
{ // 遍历每个区间
if (count == 1) for (std::pair<intptr_t, intptr_t> range : markingLine._segmentPostions)
{ {
cpili._status = pos_infront; ++count;
break;
} // 判断当前位置在区间的前面
else if (lastEnd <= currentPosInLine && currentPosInLine < range.first)
{ {
cpili._status = pos_between; if (count == 1)
cpili.auxiliaryInfo = count - 1; {
break; cpili._status = pos_infront; // 在第一个区间的前面
} break;
} }
else
if (range.first <= currentPosInLine && currentPosInLine <= range.second) {
{ cpili._status = pos_between; // 在两个区间之间
if (currentPosInLine == range.first && !hasSel) cpili.auxiliaryInfo = count - 1;
{ break;
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) if (range.first <= currentPosInLine && currentPosInLine <= range.second)
{ {
cpili._status = pos_between; if (currentPosInLine == range.first && !hasSel)
cpili.auxiliaryInfo = count; // c1 c2 {
// [ ]I [ ] : I is recongnized with c1, so auxiliaryInfo should be c1 cpili._status = pos_between; // 在区间的起始位置,在没有选择文本的情况下
} cpili.auxiliaryInfo = count - 1;
else }
{ else if (currentPosInLine == range.second && !hasSel)
cpili._status = pos_inside; {
cpili.auxiliaryInfo = count; cpili._status = pos_between; // 在区间的结束位置,在没有选择文本的情况下
} cpili.auxiliaryInfo = count;
break; }
} else
{
if (range.second < currentPosInLine) cpili._status = pos_inside; // 在区间内部
{ cpili.auxiliaryInfo = count;
if (markingLine._segmentPostions.size() == count) }
{ break;
cpili._status = pos_behind; }
cpili.auxiliaryInfo = count;
break; // 判断当前位置在区间的后面
} if (range.second < currentPosInLine)
} {
if (markingLine._segmentPostions.size() == count)
lastEnd = range.second; {
} 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) void Finder::anchorWithNoHeaderLines(intptr_t& currentL, intptr_t initL, intptr_t minL, intptr_t maxL, int direction)
{ {
if (currentL > maxL && direction == 0) // 如果当前行大于最大行并且方向为0则将当前行设置为最小行
currentL = minL; if (currentL > maxL && direction == 0)
currentL = minL;
while (_scintView.execute(SCI_GETFOLDLEVEL, currentL) & SC_FOLDLEVELHEADERFLAG)
{ // 循环直到当前行不是折叠标题行
currentL += direction == -1 ? -1 : 1; while (_scintView.execute(SCI_GETFOLDLEVEL, currentL) & SC_FOLDLEVELHEADERFLAG)
{
if (currentL > maxL) // 根据方向更新当前行
currentL = minL; currentL += direction == -1 ? -1 : 1;
else if (currentL < minL)
currentL = maxL; // 如果当前行超过最大行,则将当前行设置为最小行
if (currentL > maxL)
if (currentL == initL) currentL = minL;
break; // 如果当前行低于最小行,则将当前行设置为最大行
} 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) 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 currentPos = _scintView.execute(SCI_GETCURRENTPOS); auto total_lines = _scintView.execute(SCI_GETLINECOUNT);
intptr_t lno = _scintView.execute(SCI_LINEFROMPOSITION, currentPos); // 如果总行数小于等于1则直接返回
auto total_lines = _scintView.execute(SCI_GETLINECOUNT); if (total_lines <= 1) return;
if (total_lines <= 1) return;
// 获取当前行的起始位置和光标在行内的位置
auto lineStartAbsPos = _scintView.execute(SCI_POSITIONFROMLINE, lno); auto lineStartAbsPos = _scintView.execute(SCI_POSITIONFROMLINE, lno);
intptr_t currentPosInLine = currentPos - lineStartAbsPos; intptr_t currentPosInLine = currentPos - lineStartAbsPos;
auto init_lno = lno; auto init_lno = lno;
auto max_lno = _scintView.execute(SCI_GETLASTCHILD, lno, searchHeaderLevel); 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) assert(min_lno <= max_lno);
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);
}
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; if (lno > max_lno)
else if (lno < min_lno) lno = max_lno; lno = min_lno;
else if (lno < min_lno)
lno = max_lno;
// if (lno == init_lno)
// Set anchor and make sure that achor is not on the last (empty) line or head lines break;
// }
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) // 如果当前行与初始行不同
{ if (lno != init_lno)
auto extremityAbsoltePos = _scintView.execute(direction == -1 ? SCI_GETLINEENDPOSITION : SCI_POSITIONFROMLINE, lno); {
_scintView.execute(SCI_SETSEL, extremityAbsoltePos, extremityAbsoltePos); // 获取当前行的绝对位置
currentPos = extremityAbsoltePos; auto extremityAbsoltePos = _scintView.execute(direction == -1 ? SCI_GETLINEENDPOSITION : SCI_POSITIONFROMLINE, lno);
auto start = _scintView.execute(SCI_POSITIONFROMLINE, lno); // 设置选择范围为当前行的绝对位置
currentPosInLine = currentPos - start; _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 // According CurrentPosInLineInfo and direction, set position and get number of occurrence

Loading…
Cancel
Save