diff --git a/changelog.txt b/changelog.txt index 8a713b8..5ff7b6d 100755 --- a/changelog.txt +++ b/changelog.txt @@ -1,3 +1,34 @@ +Ndd V1.23 发布 20230226 +功能: +1 希望可以支持xml按照层次折叠和展开操作 +2 能否增加自动刷新和滚动文本功能,以及手动重新打开文件。提供tailf方式。 +3 建议 查找与替换 添加ESC键响应,ESC键退出查找替换窗体 +4 查找替换没有默认选中 +5 新窗口打开的文件,不能再拖放回去 +6 无法计算选中内容的行数 +7 json 格式化,提供json格式化插件,命令行插件等 +8 高清屏幕适配一些列问题 +9 能否支持在软件内设置文件关联。安装包支持 +10 希望记录一下关闭软件时的标签页 +11 增加md5/sha计算 + +改进: +1 新建文件缩进参考线会消失 +2 XML 文件 注释部分文字偏小看不清 +3 关闭编辑器之后,编辑器的设置窗口还在,如果多次就会有下图的样子 +4 Ctrl+F时,建议文本框内的内容默认选中 +5 建议程序打开时tab页为最后关闭时tab页 +6 选中多个文件右键打开时会启动多个窗口,而非多个标签, +7 双击英文句点全部文本都会高亮 +8 command只能-缩小,+没用 不能放大 +9 CTRL+F搜索框丢失焦点后,再用快捷键CTRL+F不能自动聚焦 +10 已设置的快捷键可以取消 +11 希望显示总字数 +12 Ctrl+S时,并不能删除.swp临时文件,建议隐藏.swp文件 +13 建议 增加 打开当前文件目录下 命令提示符的功能 +14 显示空格的问题 +15 鼠标选择文本后高亮 + Ndd V1.22 预发布 20230202 1 提供大文本、超大文本打开两种方式;并尽量显示行号。 2 增加ASM语言的语法高亮;增加shell语法高亮。 diff --git a/src/CmpareMode.cpp b/src/CmpareMode.cpp index ae8a250..270d62a 100755 --- a/src/CmpareMode.cpp +++ b/src/CmpareMode.cpp @@ -1,4 +1,4 @@ -#include "CmpareMode.h" +#include "CmpareMode.h" #include "Encode.h" #include "rcglobal.h" @@ -132,7 +132,6 @@ CODE_ID CmpareMode::getTextFileEncodeType(uchar* fileFpr, int fileLength, QStrin //是否跳过前面的LE头。默认不跳过。只有文件块开头第一块,才需要跳过。 bool CmpareMode::tranUnicodeLeToUtf8Bytes(uchar* fileFpr, const int fileLength, QString &outUtf8Bytes, bool isSkipHead) { - int lineNums = 0; CODE_ID code = CODE_ID::UNICODE_LE; int lineStartPos = (isSkipHead ? 2:0); //uicode_le前面有2个特殊标识,故跳过2 @@ -984,7 +983,9 @@ CODE_ID CmpareMode::readLineFromFile(uchar* m_fileFpr, const int fileLength, con //扫描文件的字符编码,不输出文件 -CODE_ID CmpareMode::scanFileRealCode(QString filePath) +//扫描多少行scanLineNum 默认100 +//如果是-1 之前全部扫描 +CODE_ID CmpareMode::scanFileRealCode(QString filePath, int scanLineNum) { QFile file(filePath); file.open(QIODevice::ReadOnly); @@ -1052,8 +1053,10 @@ CODE_ID CmpareMode::scanFileRealCode(QString filePath) ++lineNums; - //最多扫描200行,加块速度。速度与精确性的权衡 - if (lineNums >= 200) + //默认最多扫描200行,加块速度。速度与精确性的权衡 + //对于打开文件,默认扫描前面的200行,加快速度。 + //对于编码转换,为了精确,默认全部都要处理 + if ((scanLineNum != -1) && (lineNums >= scanLineNum)) { break; } @@ -1095,3 +1098,56 @@ CODE_ID CmpareMode::scanFileOutPut(CODE_ID code, QString filePath, QList #include #include @@ -70,8 +70,9 @@ public: static CODE_ID judgeFinalTextCode(CODE_ID code, bool isExistUnKownCode, bool isExistGbk, bool isExistUtf8); static CODE_ID readLineFromFile(uchar * m_fileFpr, const int fileLength, const CODE_ID fileCode, QList& lineInfoVec,int& maxLineSize, int& charsNums, bool &isMaybeHexFile); - static CODE_ID scanFileRealCode(QString filePath); + static CODE_ID scanFileRealCode(QString filePath,int scanLineNum=200); static CODE_ID scanFileOutPut(CODE_ID code, QString filePath, QList& outputLineInfoVec, int & maxLineSize, int & charsNums, bool &isHexFile); + static CODE_ID scanFileOutPut(QFile& pFile, CODE_ID code, QString filePath, QString& outText, bool& existGrbledCode); static CODE_ID getTextFileEncodeType(uchar* fileFpr, int fileLength, QString filePath="", bool isCheckHead = true); static bool tranUnicodeLeToUtf8Bytes(uchar* fileFpr, const int fileLength, QString& outUtf8Bytes, bool isSkipHead=false); diff --git a/src/RealCompare.qrc b/src/RealCompare.qrc index eb1a277..bfc9ab1 100755 --- a/src/RealCompare.qrc +++ b/src/RealCompare.qrc @@ -145,5 +145,7 @@ Resources/img/expand.png Resources/img/fold.png qss/common.qss + notepad/tailf.png + Resources/edit/styledeepblue/tailf.png diff --git a/src/RealCompare.rc b/src/RealCompare.rc index e5433f3..03b2837 100755 Binary files a/src/RealCompare.rc and b/src/RealCompare.rc differ diff --git a/src/RealCompareToMinGw.rc b/src/RealCompareToMinGw.rc new file mode 100755 index 0000000..26799a9 --- /dev/null +++ b/src/RealCompareToMinGw.rc @@ -0,0 +1,38 @@ +#include + +IDI_ICON1 ICON DISCARDABLE ".\\Resources\\edit\\global\\ndd.ico" + +LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,22,0,0 + PRODUCTVERSION 1,22,0,0 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS VS_FF_DEBUG +#else + FILEFLAGS 0x0L +#endif + FILEOS VOS__WINDOWS32 + FILETYPE VFT_DLL + FILESUBTYPE 0x0L + BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "080404b0" + BEGIN + VALUE "FileDescription", "notepad-- v1.22.0\0" + VALUE "FileVersion", "1.22.0.0\0" + VALUE "LegalCopyright", "Copyright (C) 2020-2023\0" + VALUE "OriginalFilename", "Notepad--.exe\0" + VALUE "ProductName", "notepad-- \0" + VALUE "ProductVersion", "1.22.0.0\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0804, 1200 + END + END +/* End of Version info */ + diff --git a/src/Resources/edit/global/ndd.ico b/src/Resources/edit/global/ndd.ico index ffb8800..2dd20d2 100755 Binary files a/src/Resources/edit/global/ndd.ico and b/src/Resources/edit/global/ndd.ico differ diff --git a/src/Resources/edit/styledark/mark.png b/src/Resources/edit/styledark/mark.png index 8690a0e..090bbef 100755 Binary files a/src/Resources/edit/styledark/mark.png and b/src/Resources/edit/styledark/mark.png differ diff --git a/src/Resources/edit/styledeepblue/tailf.png b/src/Resources/edit/styledeepblue/tailf.png new file mode 100755 index 0000000..f284627 Binary files /dev/null and b/src/Resources/edit/styledeepblue/tailf.png differ diff --git a/src/batchfindreplace.cpp b/src/batchfindreplace.cpp index 0a49e15..e305b9f 100755 --- a/src/batchfindreplace.cpp +++ b/src/batchfindreplace.cpp @@ -3,6 +3,7 @@ #include "ccnotepad.h" #include "progresswin.h" #include "nddsetting.h" +#include "ctipwin.h" #include #include @@ -172,42 +173,25 @@ void BatchFindReplace::on_findBtClick() if (m_mainNotepad != nullptr && m_mainNotepad) { int rowNums = ui.findReplaceTable->rowCount(); - if (rowNums == 0) { + CTipWin::showTips(this, tr("Please fresh first !"), 1200); return; } - ProgressWin* loadFileProcessWin = new ProgressWin(this); - - loadFileProcessWin->setWindowModality(Qt::WindowModal); - - loadFileProcessWin->info(tr("total %1 keyword, please wait ...").arg(rowNums)); - - loadFileProcessWin->setTotalSteps(rowNums); - - loadFileProcessWin->show(); - int foundTimes = 0; + QStringList findKeyList; + for (int i = 0; i < rowNums; ++i) { QTableWidgetItem* item = ui.findReplaceTable->item(i, 0); if (item != nullptr && !item->text().isEmpty()) { - if (loadFileProcessWin->isCancel()) - { - break; - } - - foundTimes += m_mainNotepad->findAtBack(item->text()); - - loadFileProcessWin->moveStep(); - - QCoreApplication::processEvents(); + findKeyList.append(item->text()); } } - delete loadFileProcessWin; + foundTimes = m_mainNotepad->findAtBack(findKeyList); ui.statusBar->showMessage(tr("Batch Find Finished! total %1 found.").arg(foundTimes),10000); } @@ -216,11 +200,15 @@ void BatchFindReplace::on_findBtClick() //½øÐÐÅúÁ¿Ì滻¹¤×÷ void BatchFindReplace::on_replaceBtClick() { - if (m_mainNotepad != nullptr && m_mainNotepad) + if (m_mainNotepad != nullptr) { int rowNums = ui.findReplaceTable->rowCount(); + if (rowNums == 0) + { + CTipWin::showTips(this, tr("Please fresh first !"), 1200); + return; + } - int replaceTimes = 0; QStringList findKeyList; QStringList replaceKeyList; @@ -241,9 +229,9 @@ void BatchFindReplace::on_replaceBtClick() } } } - replaceTimes = m_mainNotepad->replaceAtBack(findKeyList, replaceKeyList); + m_mainNotepad->replaceAtBack(findKeyList, replaceKeyList); - ui.statusBar->showMessage(tr("Batch Replace Finished, total Replace %1 times !").arg(replaceTimes), 10000); + ui.statusBar->showMessage(tr("Batch Replace Finished, total Replace %1 times !").arg(findKeyList.size()), 10000); } } @@ -332,40 +320,24 @@ void BatchFindReplace::on_mark() int rowNums = ui.findReplaceTable->rowCount(); if (rowNums == 0) { + CTipWin::showTips(this, tr("Please fresh first !"), 1200); return; } - int markTimes = 0; - ProgressWin* loadFileProcessWin = new ProgressWin(this); - - loadFileProcessWin->setWindowModality(Qt::WindowModal); - - loadFileProcessWin->info(tr("total %1 keyword, please wait ...").arg(rowNums)); - - loadFileProcessWin->setTotalSteps(rowNums); - - loadFileProcessWin->show(); + QStringList findKeyList; for (int i = 0; i < rowNums; ++i) { QTableWidgetItem* item = ui.findReplaceTable->item(i, 0); if (item != nullptr && !item->text().isEmpty()) { - if (loadFileProcessWin->isCancel()) - { - break; - } - - markTimes += m_mainNotepad->markAtBack(item->text()); - - loadFileProcessWin->moveStep(); - - QCoreApplication::processEvents(); + findKeyList.append(item->text()); } } - delete loadFileProcessWin; + markTimes = m_mainNotepad->markAtBack(findKeyList); + ui.statusBar->showMessage(tr("Batch Mark Finished, total Mark %1 times !").arg(markTimes), 10000); } } diff --git a/src/bigfilemessage.cpp b/src/bigfilemessage.cpp index 247d876..9eac27c 100755 --- a/src/bigfilemessage.cpp +++ b/src/bigfilemessage.cpp @@ -1,4 +1,5 @@ #include "bigfilemessage.h" +#include "nddsetting.h" BigFileMessage::BigFileMessage(QWidget *parent) : QDialog(parent), m_result(-1) @@ -41,19 +42,19 @@ void BigFileMessage::slot_okBt() { if (ui.textMode->isChecked()) { - m_result = TXT_TYPE;//普通文本 + m_result = TXT_TYPE;//ÆÕͨÎı¾ } else if(ui.bigTextMode->isChecked()) { - m_result = BIG_TEXT_RO_TYPE; //小于8G的大文本 + m_result = BIG_TEXT_RO_TYPE; //СÓÚ8GµĴóÎı¾ } else if (ui.superBigTextMode->isChecked()) { - m_result = SUPER_BIG_TEXT_RO_TYPE;//8G以上的大文本 + m_result = SUPER_BIG_TEXT_RO_TYPE;//8GÒÔÉϵĴóÎı¾ } else if (ui.hexMode->isChecked()) { - m_result = HEX_TYPE;//二进制 + m_result = HEX_TYPE;//¶þ½øÖÆ } done(m_result); } @@ -62,4 +63,4 @@ void BigFileMessage::slot_cancelBt() { m_result = -1; done(m_result); -} +} \ No newline at end of file diff --git a/src/cceditor/ccnotepad.cpp b/src/cceditor/ccnotepad.cpp index ed766b2..0818475 100755 --- a/src/cceditor/ccnotepad.cpp +++ b/src/cceditor/ccnotepad.cpp @@ -1,4 +1,4 @@ -#include +#include #include "ccnotepad.h" #include "filemanager.h" #include "Encode.h" @@ -25,6 +25,7 @@ #include "batchfindreplace.h" #include "langextset.h" #include "shortcutkeymgr.h" +#include "md5hash.h" #include "CmpareMode.h" #ifdef NO_PLUGIN @@ -33,6 +34,9 @@ #include "pluginGl.h" #endif +#ifdef Q_OS_WIN +#include "dectfilechanges.h" +#endif #include #include @@ -72,7 +76,6 @@ #endif #include - #ifdef Q_OS_WIN extern bool s_isAdminAuth; @@ -99,34 +102,30 @@ int CCNotePad::s_zoomValue = 0; QString CCNotePad::s_lastOpenDirPath = ""; - -//QFont CCNotePad::s_txtFont; -//QFont CCNotePad::s_proLangFont; - - QList *CCNotePad::s_padInstances = nullptr; //文件保存的路径,qstring -const char* Edit_View_FilePath = "filePath"; +static const char* Edit_View_FilePath = "filePath"; //int 新文件的id序号。非新建文件为-1 -const char* Edit_File_New = "newfile"; +static const char* Edit_File_New = "newfile"; //是否修改 true false -const char* Edit_Text_Change = "change"; - -//编码类型,int -const char* Edit_Text_Code = "code"; +static const char* Edit_Text_Change = "change"; //line行尾符号 -const char* Edit_Text_End = "lineend"; +static const char* Edit_Text_End = "lineend"; //外部修改 -const char* Modify_Outside = "modify"; +static const char* Modify_Outside = "modify"; //文档类型 1:text 2 hex -const char* Doc_Type = "type"; +static const char* Doc_Type = "type"; +//tail状态 0 关闭 1开启 +static const char* Tail_Status = "tail"; + +static const int MSG_EXIST_TIME = 8000; void setFileOpenAttrProperty(QWidget* pwidget, OpenAttr attr) { @@ -187,12 +186,13 @@ void setFileNewIndexProperty(QWidget* pwidget, int index) pwidget->setProperty(Edit_File_New, v); } +//新文件的id,非新文件为-1 int getFileNewIndexProperty(QWidget* pwidget) { return pwidget->property(Edit_File_New).toInt(); } -void setTextChangeProperty(QWidget* pwidget, bool status) +inline void setTextChangeProperty(QWidget* pwidget, bool status) { QVariant v(status); pwidget->setProperty(Edit_Text_Change, v); @@ -225,6 +225,17 @@ int getEndTypeProperty(QWidget* pwidget) return pwidget->property(Edit_Text_End).toInt(); } +void setFileTailProperty(QWidget* pwidget, int type) +{ + QVariant v(type); + pwidget->setProperty(Tail_Status, v); +} + +int getFileTailProperty(QWidget* pwidget) +{ + return pwidget->property(Tail_Status).toInt(); +} + //根据当前路径,得到交互文件的名称 QString getSwapFilePath(QString filePath) { @@ -341,6 +352,7 @@ const char *ZoomoutIcon32 = ":/Resources/edit/styledeepblue/zoomout.png"; const char *CrlfIcon32 = ":/Resources/edit/styledeepblue/crlf.png"; const char *WhiteIcon32 = ":/Resources/edit/styledeepblue/white.png"; const char *IndentIcon32 = ":/Resources/edit/styledeepblue/indentGuide.png"; +const char* TailfIcon32 = ":/Resources/edit/styledeepblue/tailf.png"; const char *FileCompareIcon32 = ":/Resources/edit/styledeepblue/filecompare.png"; const char *DirCompareIcon32 = ":/Resources/edit/styledeepblue/dircompare.png"; const char *BinCmpIcon32 = ":/Resources/edit/styledeepblue/bincmp.png"; @@ -418,6 +430,7 @@ const char* ZoomoutIcon = ":/notepad/zoomOut.png"; const char* CrlfIcon = ":/notepad/wrap.png"; const char* WhiteIcon = ":/notepad/invisibleChar.png"; const char* IndentIcon = ":/notepad/indentGuide.png"; +const char* TailfIcon = ":/notepad/tailf.png"; const char* FileCompareIcon = ":/notepad/cmpfile.png"; const char* DirCompareIcon = ":/notepad/cmpdir.png"; const char* BinCmpIcon = ":/notepad/cmpbin.png"; @@ -439,6 +452,8 @@ QString watchFilePath; QStringList CCNotePad::s_findHistroy; +QStringList CCNotePad::s_replaceHistroy; + int CCNotePad::s_autoWarp = 0; //自动换行 int CCNotePad::s_indent = 0; //自动缩进 int CCNotePad::s_showblank = 0; //显示空白 @@ -482,6 +497,8 @@ FileExtLexer s_fileExtMapLexerId[FileExtMapLexerIdLen] = { {QString("lua"), L_LUA}, {QString("sql"), L_SQL}, {QString("yml"), L_YAML}, +{QString("m"), L_MATLAB}, +{QString("md"), L_MARKDOWN}, {QString("nsi"), L_NSIS}, {QString("nsh"), L_NSIS}, {QString("v"), L_VERILOG}, @@ -556,8 +573,8 @@ void initFileTypeLangMap() { ExtLexerManager::getInstance()->addNewExtType(ext, lexerId, tagName); - } -} + } + } } //最后加载用户自定义的文件后缀名和语法关联文件 @@ -585,7 +602,7 @@ void CCNotePad::initLexerNameToIndex() data.setValue(int(L_ASM)); ui.actionAssembly->setData(data); m_lexerNameToIndex.insert("asm", pNodes[i]); - ++i; + ++i; pNodes[i].pAct = ui.actionbash; pNodes[i].index = L_BASH; @@ -1076,7 +1093,8 @@ LexerInfo CCNotePad::getLangLexerIdByFileExt(QString filePath) CCNotePad::CCNotePad(bool isMainWindows, QWidget *parent) : QMainWindow(parent), m_cutFile(nullptr),m_copyFile(nullptr), m_dockSelectTreeWin(nullptr), \ m_pResultWin(nullptr),m_isQuitCancel(false), m_tabRightClickMenu(nullptr), m_shareMem(nullptr),m_isMainWindows(isMainWindows),\ - m_openInNewWinAct(nullptr), m_showFileDirAct(nullptr), m_timerAutoSave(nullptr), m_curColorIndex(-1), m_fileListView(nullptr), m_isInReloadFile(false), m_isToolMenuLoaded(false) + m_openInNewWinAct(nullptr), m_showFileDirAct(nullptr), m_showCmdAct(nullptr), m_timerAutoSave(nullptr), m_curColorIndex(-1), \ + m_fileListView(nullptr), m_isInReloadFile(false), m_isToolMenuLoaded(false), m_isRecentFileLoaded(false) { ui.setupUi(this); @@ -1227,6 +1245,7 @@ void CCNotePad::quickshow() //启用拖动 setAcceptDrops(true); + initFileTypeLangMap(); initLexerNameToIndex(); @@ -1277,15 +1296,24 @@ void CCNotePad::quickshow() m_saveFile->setEnabled(false); m_saveAllFile->setEnabled(false); - initReceneOpenFileMenu(); + //initReceneOpenFileMenu(); + //延迟加载最近菜单列表 + connect(ui.menuRecene_File, &QMenu::aboutToShow, this, &CCNotePad::on_loadReceneFile); //最后加入退出菜单 ui.menuFile->addSeparator(); + +#if 0 m_quitAction = ui.menuFile->addAction(tr("Quit"), this, &CCNotePad::slot_quit); m_quitAction->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Q)); +#endif connect(ui.editTabWidget, &QTabWidget::currentChanged, this, &CCNotePad::slot_tabCurrentChanged, Qt::UniqueConnection); connect(ui.editTabWidget, &QTabWidget::tabBarClicked, this, &CCNotePad::slot_tabBarClicked, Qt::QueuedConnection); + + //双击在新窗口中打开 + connect(ui.editTabWidget, &QTabWidget::tabBarDoubleClicked, this, &CCNotePad::on_tabBarDoubleClicked, Qt::QueuedConnection); + ui.editTabWidget->installEventFilter(this); m_fileWatch = new QFileSystemWatcher(this); @@ -1475,14 +1503,7 @@ void CCNotePad::setUserDefShortcutKey(int shortcutId) ui.actionGoline->setShortcut(keySeq); break; - - case File_Compare_ID: - break; - case Dir_Compare_ID: - break; - case Bin_Compare_ID: - break; - + case Trans_code_ID: keySeq = ShortcutKeyMgr::getUserDefShortcutKey(Trans_code); m_transcode->setShortcut(keySeq); @@ -1503,13 +1524,136 @@ void CCNotePad::setUserDefShortcutKey(int shortcutId) case Format_Json_ID: keySeq = ShortcutKeyMgr::getUserDefShortcutKey(Format_Json); m_formatJson->setShortcut(keySeq); - + break; + + case ADD_DEL_LINE_COM: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(ADD_DELETE_LINE_COMMENT); + registerCommentShortKey(ADD_DEL_LINE_COM, keySeq); + break; + + case ADD_BK_COM: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(ADD_BLOCK_COMMENT); + registerCommentShortKey(ADD_BK_COM, keySeq); + break; + + case DEL_BK_COM: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(CANCEL_BLOCK_COMMENT); + registerCommentShortKey(DEL_BK_COM, keySeq); + break; + + case S_K_FOLD_1: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(FOLD_1); + registerFoldShortKey(S_K_FOLD_1, keySeq, false); + break; + case S_K_FOLD_2: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(FOLD_2); + registerFoldShortKey(S_K_FOLD_2, keySeq, false); + break; + case S_K_FOLD_3: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(FOLD_3); + registerFoldShortKey(S_K_FOLD_3, keySeq, false); + break; + case S_K_FOLD_4: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(FOLD_4); + registerFoldShortKey(S_K_FOLD_4, keySeq, false); + break; + case S_K_FOLD_5: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(FOLD_5); + registerFoldShortKey(S_K_FOLD_5, keySeq, false); + break; + case S_K_FOLD_6: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(FOLD_6); + registerFoldShortKey(S_K_FOLD_6, keySeq, false); + break; + case S_K_FOLD_7: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(FOLD_7); + registerFoldShortKey(S_K_FOLD_7, keySeq, false); + break; + case S_K_FOLD_8: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(FOLD_8); + registerFoldShortKey(S_K_FOLD_8, keySeq, false); + break; + case S_K_UNFOLD_1: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(UNFOLD_1); + registerFoldShortKey(S_K_UNFOLD_1, keySeq, true); + break; + case S_K_UNFOLD_2: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(UNFOLD_2); + registerFoldShortKey(S_K_UNFOLD_2, keySeq, true); + break; + case S_K_UNFOLD_3: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(UNFOLD_3); + registerFoldShortKey(S_K_UNFOLD_3, keySeq, true); + break; + case S_K_UNFOLD_4: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(UNFOLD_4); + registerFoldShortKey(S_K_UNFOLD_4, keySeq, true); + break; + case S_K_UNFOLD_5: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(UNFOLD_5); + registerFoldShortKey(S_K_UNFOLD_5, keySeq, true); + break; + case S_K_UNFOLD_6: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(UNFOLD_6); + registerFoldShortKey(S_K_UNFOLD_6, keySeq, true); + break; + case S_K_UNFOLD_7: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(UNFOLD_7); + registerFoldShortKey(S_K_UNFOLD_7, keySeq, true); + break; + case S_K_UNFOLD_8: + keySeq = ShortcutKeyMgr::getUserDefShortcutKey(UNFOLD_8); + registerFoldShortKey(S_K_UNFOLD_8, keySeq, true); break; default: break; } } + +void CCNotePad::registerFoldShortKey(int type, QKeySequence& keySeq, bool isFold) +{ + QShortcut* pStc = new QShortcut(this); + pStc->setKey(keySeq); + pStc->setContext(Qt::WidgetWithChildrenShortcut); + connect(pStc, &QShortcut::activated, this, [=]() { + doFold(type, isFold); + }); +} + +//注册注释快捷键 +void CCNotePad::registerCommentShortKey(int type, QKeySequence& keySeq) +{ + QShortcut* pStc = new QShortcut(this); + pStc->setKey(keySeq); + pStc->setContext(Qt::WidgetWithChildrenShortcut); + connect(pStc, &QShortcut::activated, this, [=]() { + doComment(type); + }); +} + +//注释问题。 +void CCNotePad::doComment(int type) +{ + QWidget* pw = ui.editTabWidget->currentWidget(); + ScintillaEditView* pEdit = dynamic_cast(pw); + if (pEdit != nullptr && !pEdit->isReadOnly()) + { + pEdit->comment(type); + } +} + +void CCNotePad::doFold(int type, bool mode) +{ + QWidget* pw = ui.editTabWidget->currentWidget(); + ScintillaEditView* pEdit = dynamic_cast(pw); + if (pEdit != nullptr) + { + pEdit->collapse((mode?(type - S_K_UNFOLD_1): (type - S_K_FOLD_1)), mode); + } +} + + //设置用户自定义快捷键 void CCNotePad::setUserDefShortcutKey() { @@ -1537,9 +1681,7 @@ void CCNotePad::slot_dynamicLoadToolMenu() { m_isToolMenuLoaded = true; -#ifdef NO_PLUGIN - connect(ui.actionPlugin_Manager, &QAction::triggered, this, &CCNotePad::slot_pluginMgr); -#endif + connect(ui.actionPlugin_Manager, &QAction::triggered, this, &CCNotePad::slot_pluginMgr, Qt::UniqueConnection); QMenu* formatMenu = new QMenu(tr("Format Language"), this); m_formatXml = formatMenu->addAction(tr("Format Xml"), this, &CCNotePad::slot_formatXml); @@ -1552,20 +1694,25 @@ void CCNotePad::slot_dynamicLoadToolMenu() #ifdef NO_PLUGIN //动态加载插件 + m_pluginList.clear(); loadPluginLib(); #endif } } -#ifdef NO_PLUGIN + void CCNotePad::slot_pluginMgr() { +#ifdef NO_PLUGIN PluginMgr* pWin = new PluginMgr(this, m_pluginList); pWin->setAttribute(Qt::WA_DeleteOnClose); pWin->show(); +#else + QMessageBox::warning(this, "info", u8"便携版本不支持插件,请下载插件版!"); +#endif } - +#ifdef NO_PLUGIN void CCNotePad::loadPluginLib() { QString strDir = qApp->applicationDirPath(); @@ -1610,9 +1757,6 @@ void CCNotePad::onPlugFound(NDD_PROC_DATA& procData, QMenu* pUserData) { return; } - - - m_pluginList.append(procData); } @@ -1632,8 +1776,10 @@ void CCNotePad::onPlugWork(bool check) if (pMainCallBack != NULL) { std::function foundCallBack = std::bind(&CCNotePad::getCurEditView, this); + std::function pluginCallBack = std::bind(&CCNotePad::pluginInvoke, this, std::placeholders::_1, std::placeholders::_2); + + pMainCallBack(this, plugPath, foundCallBack, pluginCallBack, nullptr); - pMainCallBack(this, plugPath, foundCallBack, nullptr); } else { @@ -1656,8 +1802,9 @@ void CCNotePad::sendParaToPlugin(NDD_PROC_DATA& procData) if (pMainCallBack != NULL) { std::function foundCallBack = std::bind(&CCNotePad::getCurEditView, this); + std::function pluginCallBack = std::bind(&CCNotePad::pluginInvoke, this, std::placeholders::_1, std::placeholders::_2); - pMainCallBack(this, plugPath, foundCallBack, &procData); + pMainCallBack(this, plugPath, foundCallBack, pluginCallBack, &procData); } else { @@ -1915,7 +2062,12 @@ void CCNotePad::slot_changeChinese() //如果已经加载了,则冲加载,否则中英文切换不生效 if (m_isToolMenuLoaded) { +#ifdef NO_PLUGIN + ui.menuPlugin->clear(); + ui.menuPlugin->addAction(ui.actionPlugin_Manager); +#endif ui.menuTools->clear(); + m_isToolMenuLoaded = false; slot_dynamicLoadToolMenu(); } @@ -1947,6 +2099,10 @@ void CCNotePad::slot_changeEnglish() //如果已经加载了,则冲加载,否则中英文切换不生效 if (m_isToolMenuLoaded) { +#ifdef NO_PLUGIN + ui.menuPlugin->clear(); + ui.menuPlugin->addAction(ui.actionPlugin_Manager); +#endif ui.menuTools->clear(); m_isToolMenuLoaded = false; slot_dynamicLoadToolMenu(); @@ -1996,7 +2152,7 @@ void CCNotePad::initNotePadSqlOptions() ScintillaEditView::s_noUseTab = (1 == NddSetting::getKeyValueFromNumSets(key1)) ? true : false; ScintillaEditView::s_bigTextSize = NddSetting::getKeyValueFromNumSets(MAX_BIG_TEXT); - if (ScintillaEditView::s_bigTextSize < 50 || ScintillaEditView::s_bigTextSize > 300) + if (ScintillaEditView::s_bigTextSize < 50 || ScintillaEditView::s_bigTextSize > 600) { ScintillaEditView::s_bigTextSize = 100; } @@ -2088,9 +2244,60 @@ void CCNotePad::slot_tabBarDoubleClicked(int index) } } -void CCNotePad::slot_tabBarClicked(int index) +//tab的双击行为 +void CCNotePad::on_tabBarDoubleClicked(int index) +{ + //如果是主窗口,则分出去;反之则回到主窗口 + QWidget* pw = ui.editTabWidget->widget(index); + if (pw == nullptr || (-1 != getFileNewIndexProperty(pw))) + { + return; + } + + if (m_isMainWindows) + { + openFileInNewWin(index); + } + else + { + //一个窗口时,分出去后,当前直接关闭 + bool isQuit = (ui.editTabWidget->count() == 1); + + if (pw != nullptr) + { + QString filePath = getFilePathProperty(pw); + + tabClose(index, true); + + if (s_padInstances != nullptr) + { + for (int i = 0; i < s_padInstances->size(); ++i) + { + CCNotePad* c = s_padInstances->at(i); + if (c->m_isMainWindows) + { + c->openFile(filePath); + } + } + } + + if(isQuit) + { + close(); + } + } + + } +} + +void CCNotePad::slot_tabBarClicked(int index) { QWidget* pw = ui.editTabWidget->widget(index); + if (pw == nullptr) + { + return; + } + int docType = getDocTypeProperty(pw); if (TXT_TYPE == docType) { @@ -2118,6 +2325,11 @@ void CCNotePad::slot_tabBarClicked(int index) m_tabRightClickMenu->addAction(tr("Current Document Sava as..."), this, &CCNotePad::slot_actionSaveAsFile_toggle); m_openInNewWinAct = m_tabRightClickMenu->addAction(tr("Open in New Window"),this, &CCNotePad::slot_openFileInNewWin); m_showFileDirAct = m_tabRightClickMenu->addAction(tr("Show File in Explorer..."), this, &CCNotePad::slot_showFileInExplorer); + +#ifdef Q_OS_WIN + //每种linux mac系统的打开cmd终端方式均不一样,暂时只支持windows + m_showCmdAct = m_tabRightClickMenu->addAction(tr("Cmd in Explorer..."), this, &CCNotePad::slot_showCmdInExplorer); +#endif m_tabRightClickMenu->addSeparator(); m_openWithText = m_tabRightClickMenu->addAction(tr("Reload With Text Mode"), this, &CCNotePad::slot_reOpenTextMode); @@ -2134,11 +2346,17 @@ void CCNotePad::slot_tabBarClicked(int index) { m_openInNewWinAct->setEnabled(true); m_showFileDirAct->setEnabled(true); +#ifdef Q_OS_WIN + m_showCmdAct->setEnabled(true); +#endif } else { m_openInNewWinAct->setEnabled(false); m_showFileDirAct->setEnabled(false); +#ifdef Q_OS_WIN + m_showCmdAct->setEnabled(false); +#endif } @@ -2275,28 +2493,86 @@ void CCNotePad::slot_showFileInExplorer() showFileInExplorer(path); } +//打开cmd窗口 -void CCNotePad::slot_openFileInNewWin() +#ifdef Q_OS_WIN +void CCNotePad::slot_showCmdInExplorer() { QString path; QWidget* pw = ui.editTabWidget->currentWidget(); if (pw != nullptr) { path = pw->property(Edit_View_FilePath).toString(); - slot_actionClose(true); + } - CCNotePad* pNewWin = new CCNotePad(false,nullptr); + QFileInfo fi(path); + QString dirEment = fi.absolutePath(); + + + HWND hWnd = (HWND)this->effectiveWinId(); + HINSTANCE res = ::ShellExecute(hWnd, TEXT("open"), TEXT("cmd"), TEXT(""), dirEment.toStdWString().data(), SW_SHOW); + + //参考 https://msdn.microsoft.com/en-us/library/windows/desktop/bb762153(v=vs.85).aspx + int retResult = static_cast(reinterpret_cast(res)); + if (retResult <= 32) + { + ui.statusBar->showMessage(tr("open cmd in file dir %1 failed.").arg(dirEment)); + } +#if 0 + //下面方法不能分离式,主界面关闭后,cmd也消失了 + QStringList arguments; + arguments << "/K"; + arguments << "title"; + arguments << "child process"; + + QProcess* myProcess = new QProcess(this); + QString program = "C:/Windows/System32/cmd.exe"; + myProcess->setCreateProcessArgumentsModifier([](QProcess::CreateProcessArguments* args) + { + //args->startupInfo->wShowWindow = SW_SHOWMAXIMIZED;//此成员变量设置此有效,QT5.12 + args->flags |= CREATE_NEW_CONSOLE; + args->startupInfo->dwFlags &= ~STARTF_USESTDHANDLES; + args->startupInfo->dwFlags |= STARTF_USEFILLATTRIBUTE; + args->startupInfo->dwFillAttribute = FOREGROUND_INTENSITY; + //args->startupInfo->dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + }); + myProcess->start(program, arguments); +#endif +} +#endif + +//把文件在新窗口中打开。如果是新文件,则不行 +void CCNotePad::openFileInNewWin(int index) +{ + QString path; + QWidget* pw = ui.editTabWidget->widget(index); + if (pw != nullptr) + { + if (-1 != getFileNewIndexProperty(pw)) + { + return; + } + + path = getFilePathProperty(pw); + slot_tabClose(index); + + CCNotePad* pNewWin = new CCNotePad(false, nullptr); pNewWin->quickshow(); pNewWin->setShareMem(this->getShareMem()); pNewWin->setAttribute(Qt::WA_DeleteOnClose); pNewWin->openFile(path); - + #ifdef uos adjustWInPos(pNewWin); #endif s_padInstances->append(pNewWin); } } +void CCNotePad::slot_openFileInNewWin() +{ + int curIndex = ui.editTabWidget->currentIndex(); + openFileInNewWin(curIndex); +} //int defLexerId:如果失败,则按照该语法类型的id赋值;如果-1则不给与默认值。 //因为发现如果是新建的文件,而且手动设置了语法,其文件名还是*.txt,此时如果根据 @@ -2362,7 +2638,6 @@ void CCNotePad::slot_tabCurrentChanged(int index) int docType = getDocTypeProperty(pw); if (HEX_TYPE == docType) { - setWindowTitleMode(filePath, OpenAttr::HexReadOnly); fileListSetCurItem(filePath); return; @@ -2385,9 +2660,9 @@ void CCNotePad::slot_tabCurrentChanged(int index) m_saveFile->setEnabled(false); } + if (TXT_TYPE == docType) { - //setWindowTitle(pw->property(Edit_View_FilePath).toString()); setWindowTitleMode(filePath, (OpenAttr)pw->property(Open_Attr).toInt()); } else if (BIG_TEXT_RO_TYPE == docType) @@ -2403,6 +2678,7 @@ void CCNotePad::slot_tabCurrentChanged(int index) syncCurDocEncodeToMenu(pw); syncCurDocLineEndStatusToMenu(pw); syncCurDocLexerToMenu(pw); + syncCurDocTailfToMenu(pw); ScintillaEditView* pEdit = dynamic_cast(pw); @@ -2563,6 +2839,7 @@ void CCNotePad::setShoctIcon(int iconSize) m_wordwrap->setIcon(QIcon(CrlfIcon)); m_allWhite->setIcon(QIcon(WhiteIcon)); m_indentGuide->setIcon(QIcon(IndentIcon)); + m_tailf->setIcon(QIcon(TailfIcon)); m_preHexPage->setIcon(QIcon(PreHexIcon)); m_nextHexPage->setIcon(QIcon(NextHexIcon)); m_gotoHexPage->setIcon(QIcon(GotoHexIcon)); @@ -2593,6 +2870,7 @@ void CCNotePad::setShoctIcon(int iconSize) m_wordwrap->setIcon(QIcon(CrlfIcon32)); m_allWhite->setIcon(QIcon(WhiteIcon32)); m_indentGuide->setIcon(QIcon(IndentIcon32)); + m_tailf->setIcon(QIcon(TailfIcon32)); m_preHexPage->setIcon(QIcon(PreHexIcon32)); m_nextHexPage->setIcon(QIcon(NextHexIcon32)); m_gotoHexPage->setIcon(QIcon(GotoHexIcon32)); @@ -2776,7 +3054,6 @@ void CCNotePad::initToolBar() m_wordwrap->setFixedSize(ICON_SIZE, ICON_SIZE); m_wordwrap->setToolTip(tr("Word Wrap")); ui.mainToolBar->addWidget(m_wordwrap); - ui.actionWrap->setChecked((s_autoWarp != QsciScintilla::WrapNone)); m_allWhite = new QToolButton(ui.mainToolBar); @@ -2801,6 +3078,14 @@ void CCNotePad::initToolBar() m_indentGuide->setToolTip(tr("Indent Guide")); ui.mainToolBar->addWidget(m_indentGuide); + m_tailf = new QToolButton(ui.mainToolBar); + m_tailf->setCheckable(true); + m_tailf->setChecked(false); + connect(m_tailf, &QAbstractButton::clicked, this, &CCNotePad::on_tailfile); + m_tailf->setFixedSize(ICON_SIZE, ICON_SIZE); + m_tailf->setToolTip(tr("tailf file")); + ui.mainToolBar->addWidget(m_tailf); + ui.mainToolBar->addSeparator(); m_preHexPage = new QToolButton(ui.mainToolBar); @@ -2974,45 +3259,6 @@ void CCNotePad::initToolBar() syncBlankShowStatus(); } - -//void CCNotePad::slot_skinStyleGroup(QAction* /*action*/) -//{ -// //切换图标 -// setShoctIcon(m_curIconSize); -// -// if (s_curStyleId != StyleSet::m_curStyleId) -// { -// //if (DEEP_BLACK == StyleSet::m_curStyleId) -// //{ -// // //如果不存在暗黑配置,则需要修正一次。后续如果存在了,则不需要再修正颜色 -// // if (!QtLangSet::isExistDarkLangSetings()) -// // { -// // QtLangSet::setAllLangFontFgColorToDarkStyle(); -// //} -// //} -// s_curStyleId = StyleSet::m_curStyleId; -// } -// -// for (int i = ui.editTabWidget->count() - 1; i >= 0; --i) -// { -// QWidget* pw = ui.editTabWidget->widget(i); -// ScintillaEditView *pEdit = dynamic_cast(pw); -// if (pEdit != nullptr) -// { -// pEdit->adjuctSkinStyle(); -// autoSetDocLexer(pEdit); -// } -// else -// { -// ScintillaHexEditView* pEdit = dynamic_cast(pw); -// if (pEdit != nullptr) -// { -// pEdit->adjuctSkinStyle(); -// } -// } -// } -//} - void CCNotePad::setZoomLabelValue(int zoomValue) { m_zoomLabel->setText(tr("Zoom: %1%").arg(zoomValue)); @@ -3128,7 +3374,15 @@ void CCNotePad::slot_lexerActTrig(QAction *action) //保存最近打开文件到数据库。文件只有在关闭时,才写入最近列表。不关闭的下次自动恢复打开 void CCNotePad::saveReceneOpenFile() { - QString rFile("recentopenfile"); + int clearOpenfilelist = NddSetting::getKeyValueFromDelayNumSets(CLEAR_OPENFILE_ON_CLOSE); + //开启了关闭时清空打开历史列表 + if (clearOpenfilelist == 1) + { + NddSetting::updataKeyValueFromDelaySets(RECENT_OPEN_FILE, ""); + return; + } + + QString rFile(RECENT_OPEN_FILE); const int maxRecord = 15; @@ -3152,23 +3406,31 @@ void CCNotePad::saveReceneOpenFile() if (!fileText.isEmpty()) { QString fileSaveText = fileText.join('|'); - NddSetting::updataKeyValueFromSets(rFile, fileSaveText); + NddSetting::updataKeyValueFromDelaySets(rFile, fileSaveText); } - else - { - NddSetting::updataKeyValueFromSets(rFile, ""); } } + + +//从最近列表中加载最近打开历史文件,到菜单中 +void CCNotePad::on_loadReceneFile() +{ + if (!m_isRecentFileLoaded) + { + m_isRecentFileLoaded = true; + + initReceneOpenFileMenu(); +} } //从数据库读取最近对比的文件列表 void CCNotePad::initReceneOpenFileMenu() { - QString rFile("recentopenfile"); + QString rFile(RECENT_OPEN_FILE); if (NddSetting::isDbExist()) { - QString fileStr = NddSetting::getKeyValueFromSets(rFile); + QString fileStr = NddSetting::getKeyValueFromDelaySets(rFile); QStringList fileList = fileStr.split('|'); @@ -3279,17 +3541,104 @@ void CCNotePad::setLangsDescLable(QString &langDesc) m_langDescLabel->setText(tr("Language: %1").arg(langDesc)); } -void CCNotePad::reloadEditFile(ScintillaEditView* pEidt) +//重新加载文件。这里有个问题,文件的序号会跳动,要解决跳动问题。 +//这里不能销毁当前pedit,加载编码也要保持不变。而且加载的文件一定是普通文本模式 +//目前只在文本文件被修改后,外部自动加载的场景 +//如果isTailfOn == true, 则从startReadSize开始读取文件,不从头读取。startReadSize=-1则还是从头,否则从startReadSize开始 +void CCNotePad::reloadEditFile(ScintillaEditView* pEdit, bool isTailfOn, qint64 startReadSize) { - QString filePath = pEidt->property(Edit_View_FilePath).toString(); + QString filePath = pEdit->property(Edit_View_FilePath).toString(); - //设置为非脏,直接关闭,关闭后再打开 - pEidt->setProperty(Edit_Text_Change, QVariant(false)); - tabClose(pEidt); - openFile(filePath); + CODE_ID code = (CODE_ID)getCodeTypeProperty(pEdit); + RC_LINE_FORM lineEnd; + int lineNum = 0; + + if (!isTailfOn) + { + lineNum = pEdit->getCurrentLineNumber(); } -bool CCNotePad::checkRoladFile(ScintillaEditView* pEdit) + //下面这个clear会触发文本修改,要避免不必要的消息循环。先屏蔽一些信号 + disEnableEditTextChangeSign(pEdit); + if (isTailfOn && startReadSize != -1) + { + //如果是tail模式,则不要直接把文档清空 + } + else + { + pEdit->clear(); + } + pEdit->setProperty(Edit_Text_Change, QVariant(false)); + setSaveButtonStatus(false); + + int errCode = 0; + + if (isTailfOn && startReadSize != -1) + { + //使用tailf读取尾部一部分数据;而不是全部读取 + errCode = FileManager::getInstance().loadFileDataInTextFromOffset(pEdit, filePath, code, this, startReadSize); + } + else + { + errCode = FileManager::getInstance().loadFileDataInText(pEdit, filePath, code, lineEnd, nullptr, false, this); + } + + enableEditTextChangeSign(pEdit); + + if (6 == errCode) + { + //可能存在乱码,给出警告。还是以编辑模式打开 + ui.statusBar->showMessage(tr("File %1 open success. But Exist Garbled code !")); + } + else if (errCode != 0) + { + ui.statusBar->showMessage(tr("reload file %1 failed").arg(filePath)); + return; + } + + if (isTailfOn) + { + lineNum = pEdit->lines(); + } + pEdit->execute(SCI_GOTOLINE, lineNum - 1); + +} + +#ifdef Q_OS_WIN +void CCNotePad::on_roladFile(ScintillaEditView* pEdit,quint64 lastSize, qint64 curSize) +{ + pEdit->setProperty(Modify_Outside, QVariant(true)); + checkRoladFile(pEdit, lastSize); +} +#endif + +void CCNotePad::doReloadTxtFile(ScintillaEditView* pEdit, bool isOnTail, qint64 startReadSize) +{ + //reloadEditFile 里面会关闭和新增tab,触发一系列的currentChanged + disconnect(ui.editTabWidget, &QTabWidget::currentChanged, this, &CCNotePad::slot_tabCurrentChanged); + reloadEditFile(pEdit, isOnTail, startReadSize); + pEdit->setProperty(Modify_Outside, QVariant(false)); + connect(ui.editTabWidget, &QTabWidget::currentChanged, this, &CCNotePad::slot_tabCurrentChanged, Qt::UniqueConnection); +}; + +//初次进入文件tailf模式。把文件清空,而且只留100行文件 +void CCNotePad::firstTimeIntoTail(ScintillaEditView* pEdit, int remainLineNums) +{ + int lineCount = pEdit->lines(); + int startLineNum = 0; + if (lineCount >= remainLineNums) + { + startLineNum = lineCount - remainLineNums; + } + int pos = pEdit->execute(SCI_POSITIONFROMLINE, startLineNum); + disEnableEditTextChangeSign(pEdit); + pEdit->clear(); + enableEditTextChangeSign(pEdit); + doReloadTxtFile(pEdit, true, pos); +} + +//startReadSize == -1 则从头开始读取。否则从startReadSize开始 +bool CCNotePad::checkRoladFile(ScintillaEditView* pEdit, qint64 startReadSize) { if (pEdit != nullptr && pEdit->property(Modify_Outside).toBool()) { @@ -3301,21 +3650,62 @@ bool CCNotePad::checkRoladFile(ScintillaEditView* pEdit) m_isInReloadFile = true; - QString filePath = pEdit->property(Edit_View_FilePath).toString(); + int tailStatus = getFileTailProperty(pEdit); - QApplication::beep(); - - if (QMessageBox::Yes == QMessageBox::question(this, tr("Reload"), tr("\"%1\" This file has been modified by another program. Do you want to reload it?").arg(filePath))) + if (tailStatus != 1) { - //reloadEditFile 里面会关闭和新增tab,触发一系列的currentChanged - disconnect(ui.editTabWidget, &QTabWidget::currentChanged, this, &CCNotePad::slot_tabCurrentChanged); - reloadEditFile(pEdit); - connect(ui.editTabWidget, &QTabWidget::currentChanged, this, &CCNotePad::slot_tabCurrentChanged, Qt::UniqueConnection); + QApplication::beep(); + } + + //如果是开启了taif,则不提示,直接重新加载文件 + if (tailStatus == 1) + { + //如果是进入tailf模式,但是startReadSize == -1.则什么也不干。 + //等监控超时后,后续走tailf差异读取模式。 + if (startReadSize == -1) + { + //这里什么也不做。坐等超时后,走下面的逻辑 } else { + //如果文件大于3000行,则删除内容,只保留当前100行,继续tailf + if (pEdit->lines() < 3000) + { + doReloadTxtFile(pEdit, true, startReadSize); + } + else + { + firstTimeIntoTail(pEdit,100); + } + + } + + } + else + { + QString filePath = pEdit->property(Edit_View_FilePath).toString(); + + int ret = QMessageBox::question(this, tr("Reload"), tr("\"%1\" This file has been modified by another program. Do you want to reload it?").arg(filePath), tr("Yes[Reload]"), tr("No[Drop]"), tr("On Tailf")); + if(ret == 0) + { + doReloadTxtFile(pEdit, false, startReadSize); + } + else if (ret == 1) + { + //放弃 pEdit->setProperty(Modify_Outside, QVariant(false)); } + else if (ret == 2) + { + m_tailf->setChecked(true); + + //这里也是首次开启tailf + //读取最后3000行的内容。进入tailf模式 + firstTimeIntoTail(pEdit,3000); + //开启监控 + tailfile(true,pEdit); + } + } m_isInReloadFile = false; @@ -3374,7 +3764,8 @@ void CCNotePad::enableEditTextChangeSign(ScintillaEditView* pEdit) //直到保存后,再放开 void CCNotePad::disEnableEditTextChangeSign(ScintillaEditView* pEdit) { - pEdit->disconnect(SIGNAL(textChanged())); + //pEdit->disconnect(SIGNAL(textChanged())); + disconnect(pEdit, &ScintillaEditView::textChanged, this, &CCNotePad::slot_editViewMofidyChange); } //编辑框文本变化后,设置对应的变化状态 @@ -3421,12 +3812,10 @@ void CCNotePad::updateCurTabSaveStatus() { if (pw->property(Edit_Text_Change).toBool()) { - //m_saveFile->setIcon(QIcon(NeedSaveBarIcon)); m_saveFile->setEnabled(true); } else { - //m_saveFile->setIcon(QIcon(NoNeedSaveBarIcon)); m_saveFile->setEnabled(false); } } @@ -3436,14 +3825,6 @@ void CCNotePad::updateCurTabSaveStatus() void CCNotePad::setSaveButtonStatus(bool needSave) { m_saveFile->setEnabled(needSave); - //if (needSave) - //{ - // //m_saveFile->setIcon(QIcon(NeedSaveBarIcon)); - //} - //else - //{ - // //m_saveFile->setIcon(QIcon(NoNeedSaveBarIcon)); - //} } void CCNotePad::setSaveAllButtonStatus(bool needSave) @@ -3467,8 +3848,13 @@ QAction* findItemInMenuByName(QMenu* menu, QString name) void CCNotePad::dealRecentFileMenuWhenColseFile(QString closeFilePath) { + //无条件加载一次,避免没有初始化 + on_loadReceneFile(); + QAction* act = nullptr; + getRegularFilePath(closeFilePath); + //如果关闭的文件,已经在最近列表中,则移动到最前面即可 int index = m_receneOpenFileList.indexOf(closeFilePath); if (-1 != index) @@ -3484,9 +3870,8 @@ void CCNotePad::dealRecentFileMenuWhenColseFile(QString closeFilePath) } else { - act = new QAction(closeFilePath, ui.menuFile); + act = new QAction(closeFilePath, ui.menuRecene_File); act->setObjectName(closeFilePath); - connect(act, &QAction::triggered, this, &CCNotePad::slot_openReceneFile); } @@ -3502,11 +3887,8 @@ void CCNotePad::dealRecentFileMenuWhenColseFile(QString closeFilePath) QString curTopActionPath = m_receneOpenFileList.first(); QAction* topAct = findItemInMenuByName(ui.menuRecene_File, curTopActionPath); - if (topAct != nullptr) - { ui.menuRecene_File->insertAction(topAct, act); } - } m_receneOpenFileList.push_front(closeFilePath); @@ -3517,7 +3899,7 @@ void CCNotePad::dealRecentFileMenuWhenColseFile(QString closeFilePath) QAction* lastAct = findItemInMenuByName(ui.menuRecene_File, k); if (lastAct != nullptr) { - ui.menuRecene_File->removeAction(act); + ui.menuRecene_File->removeAction(lastAct); lastAct->deleteLater(); } @@ -3577,14 +3959,35 @@ void CCNotePad::tabClose(int index, bool isInQuit) //关闭之前,检查是否要保存。如果文档为脏,则询问是否要保存 ScintillaEditView* pEdit = dynamic_cast(pw); + + //关闭之前先检测是否在tailf模式,否则要回收tailf线程,不然可能崩溃 +#ifdef Q_OS_WIN + if (pEdit != nullptr) + { + pEdit->deleteTailFileThread(); + } +#endif + if ((pEdit != nullptr) && (pEdit->property(Edit_Text_Change).toBool())) { QApplication::beep(); - int ret = QMessageBox::question(this, tr("Do you want to save changes to before closing?"), tr("If you don't save the changes you made in file %1, you'll lose them forever.").arg(filePath), tr("Yes"), tr("No"), tr("Cancel")); - + QMessageBox askSave(QMessageBox::Question, tr("Do you want to save changes to before closing?"), \ + tr("If you don't save the changes you made in file %1, you'll lose them forever.").arg(filePath), \ + QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, this); + QPushButton* okButton = (QPushButton *) askSave.button(QMessageBox::Yes); + okButton->setText(tr("&Yes")); + + okButton = (QPushButton*)askSave.button(QMessageBox::No); + okButton->setText(tr("&No")); + + okButton = (QPushButton*)askSave.button(QMessageBox::Cancel); + okButton->setText(tr("&Cancel")); + + int ret = askSave.exec(); + //保存 - if (ret == 0) + if (ret == QMessageBox::Yes) { saveTabEdit(index); @@ -3594,14 +3997,13 @@ void CCNotePad::tabClose(int index, bool isInQuit) return; } } - else if (ret == 2) + else if (ret == QMessageBox::Cancel) { m_isQuitCancel = true; return; } } - ui.editTabWidget->removeTab(index); QVariant v = pw->property(Edit_File_New); @@ -3685,7 +4087,12 @@ ScintillaEditView* CCNotePad::newTxtFile(QString name, int index, QString conten if (!contentPath.isEmpty()) { int ret = FileManager::getInstance().loadFileDataInText(pEdit, contentPath, code, lineEnd, nullptr, false, this); - if (ret != 0) + if (6 == ret) + { + //可能存在乱码,给出警告。还是以编辑模式打开 + ui.statusBar->showMessage(tr("File %1 open success. But Exist Garbled code !")); + } + else if (ret != 0) { ui.statusBar->showMessage(tr("Restore Last Temp File %1 Failed").arg(contentPath)); } @@ -3720,6 +4127,7 @@ ScintillaEditView* CCNotePad::newTxtFile(QString name, int index, QString conten QVariant editTextCode((int)code); pEdit->setProperty(Edit_Text_Code, editTextCode); syncCurDocEncodeToMenu(pEdit); + syncCurDocTailfToMenu(pEdit); setDocTypeProperty(pEdit, TXT_TYPE); @@ -3759,9 +4167,15 @@ ScintillaEditView* CCNotePad::newTxtFile(QString name, int index, QString conten autoSetDocLexer(pEdit); int zoomValue = 100 + 10 * s_zoomValue; - ui.statusBar->showMessage(tr("New File Finished [Text Mode] Zoom %1%").arg(zoomValue), 8000); + ui.statusBar->showMessage(tr("New File Finished [Text Mode] Zoom %1%").arg(zoomValue), MSG_EXIST_TIME); setZoomLabelValue(zoomValue); + //缩进线要在autoSetDocLexer之后,发现lexer会修改缩进参考线 + if (s_indent == 1) + { + pEdit->setIndentGuide(true); + } + addFileListView(name, pEdit); pEdit->viewport()->setFocus(); @@ -3831,9 +4245,9 @@ bool CCNotePad::reloadTextFileWithCode(CODE_ID code) if (docType == TXT_TYPE) { int errCode = FileManager::getInstance().loadFileDataInText(pEdit, filePath, code, lineEnd, this, false,this); - if (errCode == 5) + if (errCode == 6) { - //只读模式。暂时什么也不做 + //有乱码 } else if (errCode != 0) { @@ -3953,6 +4367,7 @@ bool CCNotePad::openBigTextRoFile(QString filePath) setDocEolMode(pEdit, lineEnd); syncCurDocEncodeToMenu(pEdit); + syncCurDocTailfToMenu(pEdit); setFileOpenAttrProperty(pEdit, OpenAttr::BigTextReadOnly); setWindowTitleMode(filePath, OpenAttr::BigTextReadOnly); @@ -4039,6 +4454,7 @@ bool CCNotePad::openSuperBigTextFile(QString filePath) setDocEolMode(pEdit, lineEnd); syncCurDocEncodeToMenu(pEdit); + syncCurDocTailfToMenu(pEdit); setFileOpenAttrProperty(pEdit, OpenAttr::SuperBigTextReadOnly); setWindowTitleMode(filePath, OpenAttr::SuperBigTextReadOnly); @@ -4195,11 +4611,11 @@ bool CCNotePad::openTextFile(QString filePath, bool isCheckHex, CODE_ID code) //用户同意以二进制格式打开文件 return openHexFile(filePath); } - else if (5 == ret) - { - isReadOnly = true; - //只读模式 - } + //else if (5 == ret) + //{ + // isReadOnly = true; + // //只读模式 + //} else if (6 == ret) { //可能存在乱码,给出警告。还是以编辑模式打开 @@ -4276,12 +4692,17 @@ void CCNotePad::setNormalTextEditInitPro(ScintillaEditView* pEdit, QString fileP setTextChangeProperty(pEdit, isModifyed); //如果是脏,还需要设置保存等按钮 + m_saveFile->setEnabled(isModifyed); + if (isModifyed) { - m_saveFile->setEnabled(true); m_saveAllFile->setEnabled(true); ui.editTabWidget->setTabIcon(curIndex, QIcon(TabNeedSave)); } + else + { + ui.editTabWidget->setTabIcon(curIndex, QIcon(TabNoNeedSave)); + } QVariant editTextCode((int)code); pEdit->setProperty(Edit_Text_Code, editTextCode); @@ -4309,14 +4730,14 @@ void CCNotePad::setNormalTextEditInitPro(ScintillaEditView* pEdit, QString fileP setFileOpenAttrProperty(pEdit, OpenAttr::Text); setWindowTitleMode(filePath, OpenAttr::Text); int zoomValue = 100 + 10 * s_zoomValue; - ui.statusBar->showMessage(tr("File %1 Open Finished [Text Mode] Zoom %2%").arg(filePath).arg(zoomValue), 8000); + ui.statusBar->showMessage(tr("File %1 Open Finished [Text Mode] Zoom %2%").arg(filePath).arg(zoomValue), MSG_EXIST_TIME); setZoomLabelValue(zoomValue); } else { setFileOpenAttrProperty(pEdit, OpenAttr::TextReadOnly); setWindowTitleMode(filePath, OpenAttr::TextReadOnly); - ui.statusBar->showMessage(tr("File %1 Open Finished [Text ReadOnly Mode] (Note: display up to 50K bytes ...)").arg(fi.fileName()), 8000); + ui.statusBar->showMessage(tr("File %1 Open Finished [Text ReadOnly Mode] (Note: display up to 50K bytes ...)").arg(fi.fileName()), MSG_EXIST_TIME); } if (pEdit->lexer() == nullptr) @@ -4623,10 +5044,12 @@ bool CCNotePad::openHexFile(QString filePath) syncCurDocEncodeToMenu(pEdit); + syncCurDocTailfToMenu(pEdit); + setFileOpenAttrProperty(pEdit, OpenAttr::HexReadOnly); setWindowTitleMode(filePath, OpenAttr::HexReadOnly); - ui.statusBar->showMessage(tr("File %1 Open Finished [Hex ReayOnly Mode]").arg(filePath),8000); + ui.statusBar->showMessage(tr("File %1 Open Finished [Hex ReayOnly Mode]").arg(filePath),MSG_EXIST_TIME); addFileListView(filePath, pEdit); @@ -4811,12 +5234,11 @@ bool CCNotePad::tryRestoreFile(QString filePath) bool CCNotePad::openFile(QString filePath, int lineNum) { s_padTimes++; - + //如果是相对路径 getRegularFilePath(filePath); QFileInfo fi(filePath); - QString fileLabel(fi.fileName()); - + if (!fi.exists()) { QApplication::beep(); @@ -4846,7 +5268,7 @@ bool CCNotePad::openFile(QString filePath, int lineNum) } } - ui.statusBar->showMessage(tr("file %1 already open at tab %2").arg(filePath).arg(retIndex),8000); + ui.statusBar->showMessage(tr("file %1 already open at tab %2").arg(filePath).arg(retIndex),MSG_EXIST_TIME); return true; } @@ -4885,6 +5307,11 @@ void CCNotePad::slot_slectionChanged() void CCNotePad::slot_actionOpenFile_toggle(bool /*checked*/) { + if (s_lastOpenDirPath.isEmpty()) + { + s_lastOpenDirPath = NddSetting::getKeyValueFromDelaySets(LAST_OPEN_DIR); + } + QFileDialog fd(this,QString(), s_lastOpenDirPath); fd.setFileMode(QFileDialog::ExistingFile); @@ -4902,6 +5329,7 @@ void CCNotePad::slot_actionOpenFile_toggle(bool /*checked*/) } } +#if 0 #ifdef _WIN32 void hide_file(const QString& szFile) { @@ -4913,12 +5341,13 @@ void hide_file(const QString& szFile) #endif // !UNICODE } #endif // _WIN32 +#endif //bool isBakWrite:是否进行保护写,即先写swap文件,再写源文件。这样可以避免突然断电导致源文件被清空 //isBakWrite 是否写保护swp文件,默认true。只有新文件时不需要,因为新文件不存在覆盖写的问题 //isStatic 是否静默:不弹出对话框,在外部批量查找替换文件夹时使用,避免弹窗中断。默认false //isClearSwpFile:是否回收swp交换文件,在外部批量查找替换文件夹时使用,替换后直接删除swp文件。默认false -bool CCNotePad::saveFile(QString fileName, ScintillaEditView* pEdit, bool isBakWrite, bool isStatic,bool isClearSwpFile) +bool CCNotePad::saveFile(QString fileName, ScintillaEditView* pEdit, bool isBakWrite, bool isStatic,bool /*isClearSwpFile*/) { QFile srcfile(fileName); @@ -5003,7 +5432,7 @@ bool CCNotePad::saveFile(QString fileName, ScintillaEditView* pEdit, bool isBak QTextCodec::setCodecForLocale(QTextCodec::codecForName("UTF-8")); //自动转换不会带UTF-8 BOM,所以自己要在前面写个BOM头。这是一个例外。需要手动写入头 - //其他必然BL LE则不需要。 + //其他编码BL LE则不需要。 QByteArray codeFlag = Encode::getEncodeStartFlagByte(dstCode); if (!codeFlag.isEmpty()) @@ -5052,7 +5481,7 @@ bool CCNotePad::saveFile(QString fileName, ScintillaEditView* pEdit, bool isBak bool success = saveWork(swapfile, fileName, true); if (success) { -#ifdef _WIN32 +#if 0 //不要这个了,windows下无条件删除 if (!isClearSwpFile) { hide_file(swapFilePath); @@ -5064,10 +5493,18 @@ bool CCNotePad::saveFile(QString fileName, ScintillaEditView* pEdit, bool isBak return false; } } +#ifdef _WIN32 + //windows下面如果保存成功,则无条件删除swap文件,许多用户反感这个.swap文件存在 + if (success) + { + QFile::remove(swapFilePath); + } +#else if (success && isClearSwpFile) { QFile::remove(swapFilePath); } +#endif } return true; @@ -5470,24 +5907,12 @@ void CCNotePad::initTabNewOne() } } -//退出所有 +//退出所有。暂时不要了,默认alt+f4. void CCNotePad::slot_quit(bool) { close(); -#if 0 - slot_closeAllFile(true); - - //中途取消了关闭,则不退出 - if (m_isQuitCancel) - { - m_isQuitCancel = false; - return; } - exit(0); -#endif -} - void CCNotePad::slot_saveAllFile() { int index = ui.editTabWidget->currentIndex(); @@ -5767,6 +6192,8 @@ void CCNotePad::closeFileStatic(int index, QSettings& qs) removeWatchFilePath(filePath); pw->deleteLater(); } + + void CCNotePad::closeAllFileStatic() { QString tempFileList = QString("notepad/temp/list"); @@ -5783,6 +6210,13 @@ void CCNotePad::closeAllFileStatic() qs.clear(); + int curIndexWhenQuit = ui.editTabWidget->currentIndex(); + + NddSetting::updataKeyValueFromNumSets(LAST_ACTION_TAB_INDEX, curIndexWhenQuit); + + //这里是静默退出,反正要退出了,把槽函数取消一下,避免下面setCurrentIndex再触发做无用功 + disconnect(ui.editTabWidget, &QTabWidget::currentChanged, this, &CCNotePad::slot_tabCurrentChanged); + //从尾部开始依次调用保存所有文件。没修改的不需要保存 for (int i = ui.editTabWidget->count() - 1; i >= 0; --i) { @@ -5920,8 +6354,12 @@ void CCNotePad::closeEvent(QCloseEvent * event) } } + //保存上次打开目录 + if (!CCNotePad::s_lastOpenDirPath.isEmpty()) + { + NddSetting::updataKeyValueFromDelaySets(LAST_OPEN_DIR, CCNotePad::s_lastOpenDirPath); + } //保存大小 - QByteArray curGeo = saveGeometry(); NddSetting::updataKeyByteArrayValue(WIN_POS, curGeo); @@ -6222,6 +6660,145 @@ void CCNotePad::slot_indentGuide(bool willBeShowed) NddSetting::updataKeyValueFromNumSets(INDENT_KEY, s_indent); } +#ifdef Q_OS_WIN +TCHAR* CharToWchar(const QString& str) +{ + QByteArray ba = str.toUtf8(); + char* data = ba.data(); //以上两步不能直接简化为“char *data = str.toUtf8().data();” + int charLen = strlen(data); + int len = MultiByteToWideChar(CP_ACP, 0, data, charLen, NULL, 0); + TCHAR* buf = new TCHAR[len + 1]; + MultiByteToWideChar(CP_ACP, 0, data, charLen, buf, len); + buf[len] = '\0'; + return buf; +} +#endif + +void CCNotePad::tailfile(bool isOn, ScintillaEditView* pEdit) +{ + if (pEdit == nullptr || (TXT_TYPE != getDocTypeProperty(pEdit) || (-1 != getFileNewIndexProperty(pEdit)))) + { + m_tailf->setChecked(false); + ui.statusBar->showMessage(tr("Only Text File Can Use it !"), MSG_EXIST_TIME); + return; + } + + if (isOn) + { + if (1 == getFileTailProperty(pEdit)) + { + return; + } + + pEdit->setReadOnly(true); + setFileTailProperty(pEdit, 1); + ui.statusBar->showMessage(tr("File %1 into tailf mode, readonly !").arg(getFilePathProperty(pEdit)), MSG_EXIST_TIME); + +#ifdef Q_OS_WIN + + auto checkFileChange = [this](ScintillaEditView* pEdit) { + + QString filePath = getFilePathProperty(pEdit); + + TCHAR* fullFileName = CharToWchar(filePath); + + DectFileChanges fileChanges; + fileChanges.AddFile(fullFileName, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE); + + //单独开启一个线程,去监控文件大小的变化 + HANDLE eventHandle = ::CreateEvent(nullptr, TRUE, FALSE, nullptr); + + HANDLE changeHandles[] = { eventHandle }; + + bool toBeGoon = true; + + while (toBeGoon) + { + DWORD waitStatus = ::WaitForMultipleObjects(_countof(changeHandles), changeHandles, FALSE, 1000); + switch (waitStatus) + { + case WAIT_OBJECT_0 + 0: + // User removes this folder or file browser is closed + { + toBeGoon = false; + } + break; + + case WAIT_TIMEOUT: + { + if (fileChanges.DetectChanges()) + { + //这里不能直接更新,而是要发生信号出去。否则跨线程访问,可能发生错误或告警 + //pEdit->setProperty(Modify_Outside, QVariant(true)); + //checkRoladFile(pEdit); + quint64 lastSize = 0; + quint64 curSize = 0; + + fileChanges.getDiffFileSize(lastSize,curSize); + emit this->tailFileChange(pEdit, lastSize, curSize); + } + //如果退出监控。这里要注意,一定要是volidate的,否则多线程获取不到该变化 + //使用了原子变量,效果是一样的,多个线程均可见 + if (!(pEdit->m_isInTailStatus)) + { + toBeGoon = false; + } + } + break; + + case WAIT_IO_COMPLETION: + // Nothing to do. + break; + } + } + + qDebug() << "listen file quit ..."; + fileChanges.Terminate(); + }; + + connect(this, &CCNotePad::tailFileChange, this, &CCNotePad::on_roladFile, Qt::QueuedConnection); + + pEdit->m_isInTailStatus = true; + + std::thread* pListenThread = new std::thread(checkFileChange, pEdit); + + QVariant t((qlonglong)pListenThread); + pEdit->setProperty(Tail_Thread, t); + +#endif // Q_OS_WIN + + } + else + { +#ifdef Q_OS_WIN + if (!pEdit->m_isInTailStatus) + { + return; + } +#endif + setFileTailProperty(pEdit, 0); + +#ifdef Q_OS_WIN + pEdit->deleteTailFileThread(); +#endif + + pEdit->setReadOnly(false); + +#ifdef Q_OS_WIN + disconnect(this, &CCNotePad::tailFileChange, this, &CCNotePad::on_roladFile); +#endif + } +} + +//实时开启文件变化tailf。20230218发现一个问题。 +//文件没有关闭,只是flush时,无法实时刷新。所有要在windows上单独监控文件大小改变 +void CCNotePad::on_tailfile(bool isOn) +{ + QWidget* pw = ui.editTabWidget->currentWidget(); + ScintillaEditView* pEdit = dynamic_cast(pw); + tailfile(isOn, pEdit); +} + void CCNotePad::find(FindTabIndex findType) { initFindWindow(findType); @@ -6247,20 +6824,16 @@ void CCNotePad::slot_find() { initFindWindow(FIND_TAB); FindWin* pFind = dynamic_cast(m_pFindWin.data()); -#ifdef uos + //必须要激活一下,所谓激活就是让当前这个查找窗口,获取焦点,是所有窗口中的当前活动窗口 pFind->activateWindow(); -#endif pFind->showNormal(); #ifdef uos adjustWInPos(pFind); #endif - - pFind->setFocus(); - pFind->setCurrentTab(FIND_TAB); } //在后台查找关键字 -int CCNotePad::findAtBack(QString keyword) +int CCNotePad::findAtBack(QStringList& keyword) { initFindWindow(); FindWin* pFind = dynamic_cast(m_pFindWin.data()); @@ -6269,7 +6842,7 @@ int CCNotePad::findAtBack(QString keyword) } //在后台替换关键字 -//在后台替换关键字 +//在后台批量替换关键字 int CCNotePad::replaceAtBack(QStringList& keyword, QStringList& replace) { initFindWindow(); @@ -6278,11 +6851,11 @@ int CCNotePad::replaceAtBack(QStringList& keyword, QStringList& replace) } //在后台高亮关键字 -int CCNotePad::markAtBack(QString keyword) +int CCNotePad::markAtBack(QStringList& keyword) { initFindWindow(); FindWin* pFind = dynamic_cast(m_pFindWin.data()); - return pFind->markAllWord(keyword); + return pFind->markAtBack(keyword); } //返回值:0 正常 1 选择自动为空 @@ -6319,15 +6892,21 @@ int CCNotePad::initFindWindow(FindTabIndex type) QVariant history = qs.value("keys", ""); s_findHistroy = history.toStringList(); } + if (qs.contains("replace")) + { + QVariant replaceHistory = qs.value("replace", ""); + s_replaceHistroy = replaceHistory.toStringList(); + } } pFind->setFindHistory(&s_findHistroy); - + pFind->setReplaceHistory(&s_replaceHistroy); + pFind->setTabWidget(ui.editTabWidget); if((TXT_TYPE == docType) || (BIG_TEXT_RO_TYPE == docType) || (SUPER_BIG_TEXT_RO_TYPE == docType)) { - connect(pFind, &FindWin::sign_findAllInCurDoc, this, &CCNotePad::slot_showFindAllInCurDocResult); + //connect(pFind, &FindWin::sign_findAllInCurDoc, this, &CCNotePad::slot_showFindAllInCurDocResult); connect(pFind, &FindWin::sign_findAllInOpenDoc, this, &CCNotePad::slot_showfindAllInOpenDocResult); connect(pFind, &FindWin::sign_replaceSaveFile, this, &CCNotePad::slot_saveFile); connect(pFind, &FindWin::sign_clearResult, this, &CCNotePad::slot_clearFindResult); @@ -6349,6 +6928,7 @@ int CCNotePad::initFindWindow(FindTabIndex type) pFind = dynamic_cast(m_pFindWin.data()); } + pFind->setCurrentTab(type); if ((TXT_TYPE == docType) || (BIG_TEXT_RO_TYPE == docType) || (SUPER_BIG_TEXT_RO_TYPE == docType)) { @@ -6359,6 +6939,8 @@ int CCNotePad::initFindWindow(FindTabIndex type) if (FIND_TAB == type) { pFind->setFindText(text); + pFind->keywordWinGetFouse(FIND_TAB); + //如果字段比较短,则字段填充到替换中 if (text.size() <= 60) { @@ -6368,6 +6950,7 @@ int CCNotePad::initFindWindow(FindTabIndex type) else if (REPLACE_TAB == type) { pFind->setReplaceFindText(text); + pFind->keywordWinGetFouse(REPLACE_TAB); //如果字段比较短,则字段填充到替换中 if (text.size() <= 60) { @@ -6377,7 +6960,13 @@ int CCNotePad::initFindWindow(FindTabIndex type) else if (DIR_FIND_TAB == type) { pFind->setDirFindText(text); + pFind->keywordWinGetFouse(DIR_FIND_TAB); } + else if (MARK_TAB == type) + { + pFind->setMarkFindText(text); + pFind->keywordWinGetFouse(MARK_TAB); + } } else { @@ -6419,6 +7008,13 @@ void CCNotePad::slot_saveSearchHistory() s_findHistroy = s_findHistroy.mid(0, 15); } qs.setValue("keys", s_findHistroy); + + if (s_replaceHistroy.count() > 15) + { + s_replaceHistroy = s_replaceHistroy.mid(0, 15); + } + qs.setValue("replace", s_replaceHistroy); + qs.sync(); } @@ -6426,7 +7022,6 @@ void CCNotePad::slot_replace() { initFindWindow(REPLACE_TAB); FindWin* pFind = dynamic_cast(m_pFindWin.data()); - pFind->setCurrentTab(REPLACE_TAB); pFind->activateWindow(); pFind->showNormal(); #ifdef uos @@ -6511,8 +7106,8 @@ void CCNotePad::clearHighlightWord(QString signWord, ScintillaEditView* pEdit) delete r; curMarkRecord.removeAt(i); } - } + void CCNotePad::slot_clearWordHighlight() { QWidget* pw = ui.editTabWidget->currentWidget(); @@ -6648,7 +7243,9 @@ void CCNotePad::initFindResultDockWin() m_dockSelectTreeWin->setAllowedAreas(Qt::LeftDockWidgetArea| Qt::RightDockWidgetArea |Qt::BottomDockWidgetArea); m_pResultWin = new FindResultWin(m_dockSelectTreeWin); - connect(m_pResultWin, &FindResultWin::itemDoubleClicked, this, &CCNotePad::slot_findResultItemDoubleClick); + //connect(m_pResultWin, &FindResultWin::itemDoubleClicked, this, &CCNotePad::slot_findResultItemDoubleClick); + connect(m_pResultWin, &FindResultWin::lineDoubleClicked, this, &CCNotePad::on_findResultlineDoubleClick); + connect(m_pResultWin, &FindResultWin::showMsg, this, [this](QString& msg) { ui.statusBar->showMessage(msg,5000); }); @@ -6762,16 +7359,62 @@ void CCNotePad::slot_findResultItemDoubleClick(const QModelIndex &index) } +//双击文件leve=2的节点后,显示文件并定位到文件位置中去高亮 +void CCNotePad::on_findResultlineDoubleClick(QString* pFilePath, int pos, int end) +{ + auto locationCurrentEdit = [this](QString filePath)->ScintillaEditView* { + + getRegularFilePath(filePath); + + ScintillaEditView* pEdit = dynamic_cast(ui.editTabWidget->currentWidget()); + if (pEdit != nullptr && (filePath == getFilePathProperty(pEdit))) + { + return pEdit; + } + + //不在则遍历插值定位到 + for (int i = 0; i < ui.editTabWidget->count(); ++i) + { + pEdit = dynamic_cast(ui.editTabWidget->widget(i)); + if (pEdit != nullptr && (filePath == getFilePathProperty(pEdit))) + { + ui.editTabWidget->setCurrentIndex(i); + return pEdit; + } + } + + //走到这里,说明文档已经关闭,不在当前打开框中 + //还是没有找到,则新建打开文件 + if (openFile(filePath)) + { + ScintillaEditView* pEdit = dynamic_cast(ui.editTabWidget->currentWidget()); + return pEdit; + } + + ui.statusBar->showMessage(tr("file %1 was not exists !").arg(filePath), 5000); + QApplication::beep(); + return nullptr; + }; + + ScintillaEditView* pCurEdit = locationCurrentEdit(*pFilePath); + if (pCurEdit != nullptr) + { + pCurEdit->execute(SCI_SETSEL, pos, end); + } +} + +#if 0 void CCNotePad::slot_showFindAllInCurDocResult(FindRecords* record) { initFindResultDockWin(); m_dockSelectTreeWin->setWindowTitle(tr("Find result - %1 hit").arg(record->records.size())); - m_pResultWin->appendResultsToShow(record); + //m_pResultWin->appendResultsToShow(record); m_dockSelectTreeWin->show(); } +#endif void CCNotePad::slot_showfindAllInOpenDocResult(QVector* record, int hits, QString whatFind) { @@ -6854,7 +7497,7 @@ bool CCNotePad::convertDocLineEnd(RC_LINE_FORM endStatus) ScintillaEditView* pEdit = dynamic_cast(pw); if (pEdit != nullptr && pEdit->isReadOnly()) { - ui.statusBar->showMessage(tr("The ReadOnly document does not allow this operation."), 8000); + ui.statusBar->showMessage(tr("The ReadOnly document does not allow this operation."), MSG_EXIST_TIME); QApplication::beep(); return false; } @@ -7039,11 +7682,11 @@ void CCNotePad::transDocToEncord(CODE_ID destCode) //等到文件保存时才执行 if (srcCode != newCode) { - QVariant editTextCode((int)newCode); - pEdit->setProperty(Edit_Text_Code, editTextCode); + setCodeTypeProperty(pEdit, (int)newCode); - QVariant textChanged(true); - pEdit->setProperty(Edit_Text_Change, textChanged); + setTextChangeProperty(pEdit, true); + + ui.editTabWidget->setTabIcon(ui.editTabWidget->currentIndex(), QIcon(TabNeedSave)); setSaveButtonStatus(true); setSaveAllButtonStatus(true); @@ -7095,6 +7738,11 @@ void CCNotePad::syncCurDocEncodeToMenu(QWidget* curEdit) } } +//同步当前的tailf状态 +void CCNotePad::syncCurDocTailfToMenu(QWidget* curEdit) +{ + m_tailf->setChecked(1 == getFileTailProperty(curEdit)); +} //同步当前文档的编码状态到菜单的Encode中。即每次切换当前编辑后,菜单上面的编码状态要同步 void CCNotePad::syncCurDocLineEndStatusToMenu(QWidget* curEdit) @@ -7164,17 +7812,17 @@ void CCNotePad::cmpSelectFile() void CCNotePad::slot_compareFile() { - //此部分是对比软件的商业代码,开源版本不包含对比功能。 + //此部分是对比软件的商业插件代码,开源版本不包含对比功能。 } void CCNotePad::slot_compareDir() { - //此部分是对比软件的商业代码,开源版本不包含对比功能。 + //此部分是对比软件的商业插件代码,开源版本不包含对比功能。 } void CCNotePad::slot_binCompare() { - //此部分是对比软件的商业代码,开源版本不包含对比功能。 + //此部分是对比软件的商业插件代码,开源版本不包含对比功能。 } @@ -7300,7 +7948,8 @@ void CCNotePad::slot_gotoHexPage() { if (m_pHexGotoWin.isNull()) { - m_pHexGotoWin = new HexFileGoto(); + m_pHexGotoWin = new HexFileGoto(this); + m_pHexGotoWin->setWindowFlag(Qt::Window); HexFileGoto* pHexGoto = dynamic_cast(m_pHexGotoWin.data()); @@ -7354,7 +8003,7 @@ void CCNotePad::slot_hexGotoFile(qint64 addr) if (addr < 0) { - ui.statusBar->showMessage(tr("Error file offset addr , please check !"), 8000); + ui.statusBar->showMessage(tr("Error file offset addr , please check !"), MSG_EXIST_TIME); QApplication::beep(); return; } @@ -7379,7 +8028,7 @@ void CCNotePad::slot_hexGotoFile(qint64 addr) if (addr < 0) { - ui.statusBar->showMessage(tr("Error file offset addr , please check !"), 8000); + ui.statusBar->showMessage(tr("Error file offset addr , please check !"), MSG_EXIST_TIME); QApplication::beep(); return; } @@ -7426,20 +8075,21 @@ void CCNotePad::slot_about() void CCNotePad::slot_aboutNdd() { - AboutNdd* pWin = new AboutNdd(); + AboutNdd* pWin = new AboutNdd(this); + pWin->setWindowFlag(Qt::Window); pWin->setAttribute(Qt::WA_DeleteOnClose); QString title = tr("Notepad-- Version %1").arg(VersionStr); pWin->setWindowTitle(title); pWin->appendText(title); -// int status = NddSetting::getKeyValueFromNumSets(SOFT_STATUS); -// if (1 == status) -// { -// pWin->appendText(tr("Registered Version")); -// } -// else -// { -// pWin->appendText(tr("Free Trial")); -// } + int status = NddSetting::getKeyValueFromNumSets(SOFT_STATUS); + if (1 == status) + { + pWin->appendText(tr("Registered Version")); + } + else + { + pWin->appendText(tr("Free Trial")); + } pWin->show(); registerEscKeyShort(pWin); #ifdef uos @@ -7510,18 +8160,29 @@ void CCNotePad::dropEvent(QDropEvent* e) e->accept(); } +void CCNotePad::dragLeaveEvent(QDragLeaveEvent* event) +{ + qDebug() << "drag level"; +} + //目前只有一个Tabwidget的双击事件。 bool CCNotePad::eventFilter(QObject * watched, QEvent * event) { - if (watched == ui.editTabWidget && event->type() == QEvent::MouseButtonDblClick) + switch (event->type()) { + case QEvent::MouseButtonDblClick: + if (watched == ui.editTabWidget) + { slot_actionNewFile_toggle(true); m_saveFile->setEnabled(false); return true; // 注意这里一定要返回true,表示你要过滤该事件原本的实现 } - return false; + break; + default: + break; +} + return QObject::eventFilter(watched, event);; } - #ifdef Q_OS_WIN static const ULONG_PTR CUSTOM_TYPE = 10000; @@ -7642,12 +8303,21 @@ void CCNotePad::slot_batch_rename() void CCNotePad::slot_options() { - OptionsView* p = new OptionsView(this,nullptr); - p->setAttribute(Qt::WA_DeleteOnClose); - //p->setWindowModality(Qt::ApplicationModal); + OptionsView* p = nullptr; + + if (m_optionsView.isNull()) + { + m_optionsView = new OptionsView(this, this); + m_optionsView->setWindowFlag(Qt::Window); + m_optionsView->setAttribute(Qt::WA_DeleteOnClose); + + p = dynamic_cast(m_optionsView.data()); connect(p, &OptionsView::sendTabFormatChange, this, &CCNotePad::slot_tabFormatChange); - //connect(p, &OptionsView::signTxtFontChange, this, &CCNotePad::slot_txtFontChange); - //connect(p, &OptionsView::signProLangFontChange, this, &CCNotePad::slot_proLangFontChange); + } + else + { + p = dynamic_cast(m_optionsView.data()); + } p->show(); registerEscKeyShort(p); @@ -7758,7 +8428,8 @@ void CCNotePad::slot_tabFormatChange(bool tabLenChange, bool useTabChange) void CCNotePad::slot_donate() { - Donate* pWin = new Donate(); + Donate* pWin = new Donate(this); + pWin->setWindowFlag(Qt::Window); pWin->setAttribute(Qt::WA_DeleteOnClose); pWin->show(); registerEscKeyShort(pWin); @@ -7807,6 +8478,11 @@ void CCNotePad::getCurUseLexerTags(QVector& tags) } } +QtLangSet* CCNotePad::getLangSet() +{ + slot_langFormat(); + return dynamic_cast(m_langSetWin.data()); +} void CCNotePad::slot_langFormat() { @@ -7818,11 +8494,21 @@ void CCNotePad::slot_langFormat() { initTag = pEdit->lexer()->lexerTag(); } + QtLangSet* pWin = nullptr; + + if (m_langSetWin.isNull()) + { + m_langSetWin = new QtLangSet(initTag, this); + pWin = dynamic_cast(m_langSetWin.data()); - QtLangSet* pWin = new QtLangSet(initTag,this); pWin->setAttribute(Qt::WA_DeleteOnClose); connect(pWin, &QtLangSet::viewStyleChange, this, &CCNotePad::slot_viewStyleChange); connect(pWin, &QtLangSet::viewLexerChange, this, &CCNotePad::slot_viewLexerChange); + } + else + { + pWin = dynamic_cast(m_langSetWin.data()); + } pWin->show(); registerEscKeyShort(pWin); #ifdef uos @@ -7970,7 +8656,7 @@ bool CCNotePad::restoreDirtyExistFile(QString& filePath, QString& tempFilePath) if (!tempFilePath.isEmpty()) { int ret = FileManager::getInstance().loadFileDataInText(pEdit, tempFilePath, code, lineEnd, nullptr, false,this); - if (ret != 0) + if ((ret != 6) && (ret != 0)) { isLoadOrgin = true; ui.statusBar->showMessage(tr("Restore Last Temp File %1 Failed").arg(tempFilePath), 5000); @@ -8000,10 +8686,14 @@ bool CCNotePad::restoreDirtyExistFile(QString& filePath, QString& tempFilePath) //用户同意以二进制格式打开文件 return openHexFile(filePath); } - else if (5 == ret) + //else if (5 == ret) + //{ + // isReadOnly = true; + // //只读模式 + //} + else if (6 == ret) { - isReadOnly = true; - //只读模式 + //存在乱码,还是打开 } else if (0 != ret) { @@ -8191,6 +8881,10 @@ int CCNotePad::restoreLastFiles() } } } + //恢复完毕后,恢复上次的标签页 + int curIndexWhenQuit = NddSetting::getKeyValueFromNumSets(LAST_ACTION_TAB_INDEX); + ui.editTabWidget->setCurrentIndex(curIndexWhenQuit); + return fileList.size(); } @@ -8227,7 +8921,8 @@ void CCNotePad::slot_columnBlockEdit() { if (m_columnEditWin.isNull()) { - m_columnEditWin = new ColumnEdit(); + m_columnEditWin = new ColumnEdit(this); + m_columnEditWin->setWindowFlag(Qt::Window); m_columnEditWin->setAttribute(Qt::WA_DeleteOnClose); ColumnEdit* pWin = dynamic_cast(m_columnEditWin.data()); pWin->setTabWidget(ui.editTabWidget); @@ -8258,7 +8953,7 @@ void CCNotePad::transCurUpperOrLower(TextCaseType type) { if (pEdit->isReadOnly()) { - ui.statusBar->showMessage(tr("The ReadOnly document does not allow this operation."), 8000); + ui.statusBar->showMessage(tr("The ReadOnly document does not allow this operation."), MSG_EXIST_TIME); QApplication::beep(); return; } @@ -8346,7 +9041,7 @@ ScintillaEditView* CCNotePad::getCurEditView() { if (_pEditView->isReadOnly()) { - ui.statusBar->showMessage(tr("The ReadOnly document does not allow this operation."), 8000); + ui.statusBar->showMessage(tr("The ReadOnly document does not allow this operation."), MSG_EXIST_TIME); QApplication::beep(); return nullptr; } @@ -8365,7 +9060,7 @@ void CCNotePad::spaceTabConvert(SpaceTab type) { if (_pEditView->isReadOnly()) { - ui.statusBar->showMessage(tr("The ReadOnly document does not allow this operation."), 8000); + ui.statusBar->showMessage(tr("The ReadOnly document does not allow this operation."), MSG_EXIST_TIME); QApplication::beep(); return; } @@ -8822,7 +9517,7 @@ void CCNotePad::slot_findNext() } else { - ui.statusBar->showMessage(tr("what find is null !"), 8000); + ui.statusBar->showMessage(tr("what find is null !"), MSG_EXIST_TIME); } } @@ -8847,7 +9542,7 @@ void CCNotePad::slot_findPrev() } else { - ui.statusBar->showMessage(tr("what find is null !"), 8000); + ui.statusBar->showMessage(tr("what find is null !"), MSG_EXIST_TIME); } } @@ -8911,7 +9606,7 @@ void CCNotePad::slot_formatXml() if (reader.hasError()) { - ui.statusBar->showMessage(tr("XML format error, please check!"), 8000); + ui.statusBar->showMessage(tr("XML format error, please check!"), MSG_EXIST_TIME); QApplication::beep(); return; } @@ -8941,7 +9636,7 @@ void CCNotePad::slot_formatJson() if (QJsonParseError::NoError != parseError.error) { - ui.statusBar->showMessage(tr("JSON format error, please check!"),8000); + ui.statusBar->showMessage(tr("JSON format error, please check!"),MSG_EXIST_TIME); QApplication::beep(); return; } @@ -8953,10 +9648,10 @@ void CCNotePad::slot_formatJson() //清空历史打开记录 void CCNotePad::slot_clearHistoryOpenList() { - ui.menuRecene_File->clear(); m_receneOpenFileList.clear(); + NddSetting::updataKeyValueFromDelaySets(RECENT_OPEN_FILE, ""); } void CCNotePad::slot_showToolBar(bool check) @@ -9068,3 +9763,139 @@ void CCNotePad::slot_shortcutManager() #endif pWin->show(); } + +//处理当前按下ESC后,需要处理退出的事件 +void CCNotePad::on_quitActiveWindow() +{ + if (!m_pFindWin.isNull()&& m_pFindWin->isVisible()) + { + m_pFindWin->close(); + } + if (!m_columnEditWin.isNull() && m_columnEditWin->isVisible()) + { + m_columnEditWin->close(); + } + if (!m_langSetWin.isNull() && m_langSetWin->isVisible()) + { + m_langSetWin->close(); + } + if (!m_optionsView.isNull() && m_optionsView->isVisible()) + { + m_optionsView->close(); + } +} + +#if 0 +//修改主题颜色//暂时不开始,发现MAC下有不开启深色的配置 +void CCNotePad::changeAppFontColor(QColor color) +{ + //把存在的界面都关闭。发现如果不关闭,颜色不会更新 + + if (!m_pFindWin.isNull()) + { + QByteArray curGeo = m_pFindWin->saveGeometry(); + NddSetting::updataKeyByteArrayValue(FINDWINSIZE, curGeo); + + m_pFindWin.data()->deleteLater(); + } + + if (!m_pHexGotoWin.isNull()) + { + m_pHexGotoWin.data()->close(); + } + + if (!m_columnEditWin.isNull()) + { + m_columnEditWin.data()->close(); + } + + + //filelistwin还存在 + if (!m_dockFileListWin.isNull()) + { + NddSetting::updataKeyValueFromNumSets(FILELISTSHOW, 1); + m_dockFileListWin.data()->close(); + } + + if (m_dockSelectTreeWin != nullptr) + { + m_dockSelectTreeWin->deleteLater(); + m_dockSelectTreeWin = nullptr; + } +} +#endif + +void CCNotePad::on_md5hash() +{ + Md5hash* pWin = new Md5hash(this); + pWin->setWindowFlag(Qt::Window); + pWin->setAttribute(Qt::WA_DeleteOnClose); + pWin->show(); +} + + +#ifdef NO_PLUGIN +//插件中调用主程序的功能。 +//cmdId 执行什么动作,一定固定后,主程序不能随便修改,否则会引发兼容性问题。 +bool CCNotePad::pluginInvoke(int cmdId, void* data) +{ + bool ret = false; + switch (cmdId) + { + case 1: + { + //新建一个文件。 + slot_actionNewFile_toggle(true); + + //默认不需要。 + if (data != nullptr) + { + QVariant* pVar = (QVariant*)data; + //回传回去新建文件的名称 + ScintillaEditView* pw = getCurEditView(); + if (pw != nullptr) + { + pVar->setValue(getFilePathProperty(pw)); + } + + } + ret = true; + } + break; + case 2: + { + //设定当前编辑器的语言。0 js 1 json + int lang = *((int*)data); + + LangType langs = ((lang == 0) ? L_JAVASCRIPT : L_JSON); + + ScintillaEditView* pEdit = getCurEditView(); + if (pEdit != nullptr) + { + QsciLexer* curLexer = pEdit->lexer(); + if (curLexer == nullptr) + { + //设定为目标语法 + QsciLexer* lexer = ScintillaEditView::createLexer(langs); + pEdit->setLexer(lexer); + } + else if (curLexer->lexerId() != langs) + { + pEdit->setLexer(nullptr); + delete curLexer; + curLexer = nullptr; + + QsciLexer* lexer = ScintillaEditView::createLexer(langs); + pEdit->setLexer(lexer); + } + syncCurDocLexerToMenu(pEdit); + } + ret = true; + } + + default: + break; + } + return ret; +} +#endif \ No newline at end of file diff --git a/src/cceditor/ccnotepad.h b/src/cceditor/ccnotepad.h index 0b63a5c..b6723bf 100755 --- a/src/cceditor/ccnotepad.h +++ b/src/cceditor/ccnotepad.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -35,6 +35,10 @@ struct HexFileMgr; struct TextFileMgr; struct BigTextEditFileMgr; +static const char* Tail_Thread = "tailthread"; + +//编码类型,int +static const char* Edit_Text_Code = "code"; enum OpenAttr { Text = 1, @@ -83,6 +87,7 @@ enum NddDocType { //打开模式。1 文本 2 二进制 3 大文本只读 4 文本只读 //const char* Open_Attr = "openid"; class FileListView; +class QtLangSet; class CCNotePad : public QMainWindow { @@ -100,18 +105,7 @@ public: void initLexerNameToIndex(); static LexerInfo getLangLexerIdByFileExt(QString filePath); -#if 0 - static QFont & getTxtFont() - { - return s_txtFont; - } - static QFont & getProLangFont() - { - return s_proLangFont; - } -#endif - bool openFile(QString filePath, int lineNum=-1); bool tryRestoreFile(QString filePath); @@ -143,8 +137,8 @@ public: void clearHighlightWord(QString signWord, ScintillaEditView* pEdit = nullptr); bool closeFileByEditWidget(QWidget* pEdit); void showChangePageTips(QWidget* pEdit); - int markAtBack(QString keyword); - int findAtBack(QString keyword); + int markAtBack(QStringList& keyword); + int findAtBack(QStringList& keyword); int replaceAtBack(QStringList& keyword, QStringList& replace); void updateThemes(); @@ -154,10 +148,15 @@ public: void changeMarkColor(int sytleId); void setUserDefShortcutKey(int shortcutId); + + QtLangSet* getLangSet(); signals: void signSendRegisterKey(QString key); void signRegisterReplay(int code); void signLinkNetServer(); +#ifdef Q_OS_WIN + void tailFileChange(ScintillaEditView*,qint64 lastSize, qint64 curSize); +#endif public slots: void slot_changeChinese(); void slot_changeEnglish(); @@ -171,8 +170,10 @@ public slots: void slot_actionCloseNonCurDoc(); void slot_actionCloseLeftAll(); void slot_actionCloseRightAll(); + void slot_quit(bool); + void slot_closeAllFile(bool); void slot_batch_convert(); void slot_batch_rename(); @@ -183,17 +184,21 @@ public slots: void slot_viewLexerChange(QString tag); void slot_findInDir(); void slot_showFileInExplorer(); +#ifdef Q_OS_WIN + void slot_showCmdInExplorer(); +#endif void slot_wordHighlight(); void slot_clearWordHighlight(); void slot_clearMark(); void slot_zoomValueChange(); - + void on_quitActiveWindow(); protected: void closeEvent(QCloseEvent *event) override; void dragEnterEvent(QDragEnterEvent* event) override; void dropEvent(QDropEvent* e) override; + void dragLeaveEvent(QDragLeaveEvent* event); bool eventFilter(QObject *watched, QEvent *event)override; #ifdef Q_OS_WIN bool nativeEvent(const QByteArray &eventType, void *message, long *result) override; @@ -232,7 +237,9 @@ private slots: void slot_findResultPosChangeed(Qt::DockWidgetArea area); void slot_findResultItemDoubleClick(const QModelIndex & index); +#if 0 void slot_showFindAllInCurDocResult(FindRecords * record); +#endif void slot_showfindAllInOpenDocResult(QVector* record, int hits, QString whatFind); void slot_clearFindResult(); void slot_convertWinLineEnd(bool); @@ -260,6 +267,7 @@ private slots: void slot_compareDir(); void slot_binCompare(); void slot_tabBarClicked(int index); + void on_tabBarDoubleClicked(int index); void slot_reOpenTextMode(); void slot_reOpenHexMode(); void slot_selectLeftFile(); @@ -338,15 +346,23 @@ private slots: void slot_showToolBar(bool); void slot_dynamicLoadToolMenu(); void slot_batchFind(); -#ifdef NO_PLUGIN + void on_loadReceneFile(); void slot_pluginMgr(); +#ifdef NO_PLUGIN void onPlugWork(bool check); void sendParaToPlugin(NDD_PROC_DATA& procData); + //cmdId 执行什么动作,一定固定后,主程序不能随便修改,否则会引发兼容性问题。 + bool pluginInvoke(int cmdId, void* data); #endif void slot_showWebAddr(bool check); void slot_langFileSuffix(); void slot_shortcutManager(); void on_lineEndChange(int index); + void on_tailfile(bool isOn); +#ifdef Q_OS_WIN + void on_roladFile(ScintillaEditView* pEdit,quint64 lastSize, qint64 curSize); +#endif + void on_md5hash(); private: void initFindResultDockWin(); @@ -376,6 +392,7 @@ private: void syncCurDocEncodeToMenu(QWidget * curEdit); void syncCurDocLineEndStatusToMenu(QWidget * curEdit); void syncCurDocLexerToMenu(QWidget* pEdit); + void syncCurDocTailfToMenu(QWidget* curEdit); void cmpSelectFile(); @@ -385,11 +402,15 @@ private: void addWatchFilePath(QString filePath); void removeWatchFilePath(QString filePath); - bool checkRoladFile(ScintillaEditView * pEdit); - void reloadEditFile(ScintillaEditView * pEidt); + void doReloadTxtFile(ScintillaEditView* pEdit, bool isOnTail, qint64 startReadSize); + void firstTimeIntoTail(ScintillaEditView* pEdit, int remainLineNums=100); + bool checkRoladFile(ScintillaEditView * pEdit, qint64 startReadSize=-1); + void reloadEditFile(ScintillaEditView * pEidt, bool isTailfOn = false, qint64 startReadSize=-1); int initFindWindow(FindTabIndex type= FIND_TAB); void setToFileRightMenu(); + void initReceneCmp(); + void saveReceneCmp(); QString getShortName(const QString& name); @@ -445,6 +466,7 @@ private: void init_toolsMenu(); void changeBlankShowStatus(int showBlank); void syncBlankShowStatus(); + void openFileInNewWin(int index); #ifdef NO_PLUGIN void loadPluginLib(); void loadPluginProcs(QString strLibDir, QMenu* pMenu); @@ -453,7 +475,13 @@ private: void setUserDefShortcutKey(); void setNormalTextEditInitPro(ScintillaEditView* pEdit, QString filePath, CODE_ID code, RC_LINE_FORM lineEnd, bool isReadOnly, bool isModifyed); + void registerCommentShortKey(int type, QKeySequence& keySeq); void dealRecentFileMenuWhenColseFile(QString closeFilePath); + void registerFoldShortKey(int type, QKeySequence& keySeq, bool isFold); + void doFold(int type, bool mode); + void doComment(int type); + void tailfile(bool isOn, ScintillaEditView* pEdit); + void on_findResultlineDoubleClick(QString* pFilePath, int pos, int end); private: Ui::CCNotePad ui; @@ -478,11 +506,15 @@ private: QActionGroup *m_pLexerActGroup; QActionGroup *m_pIconSize; +#if 0 QAction* m_quitAction; +#endif //关闭时,询问保存文件,用户点击了取消,此时不能走关闭程序 //设置一个标志记录该状态,确定最终是否要退出 bool m_isQuitCancel; + //是否主窗口。可以打开多个,但是只有第一个是主窗口 + bool m_isMainWindows; QMap m_lexerNameToIndex; @@ -493,12 +525,17 @@ private: QString m_cmpRightFilePath; QPointer m_pFindWin; - QPointer m_columnEditWin; + QPointer m_columnEditWin; + QPointer m_langSetWin; + QPointer m_optionsView; + QSharedMemory* m_shareMem; - //是否主窗口。可以打开多个,但是只有第一个是主窗口 - bool m_isMainWindows; + + + QList m_cmpDirMgr; + QList m_cmpFileMgr; //最近打开的对比文件和目录列表。做一个环形区 //保存在数据库中 @@ -511,6 +548,7 @@ private: QAction* m_openInNewWinAct; QAction* m_showFileDirAct; + QAction* m_showCmdAct; QAction* m_openWithText; QAction* m_openWithHex; @@ -528,6 +566,7 @@ private: QPointer m_pHexGotoWin; static QStringList s_findHistroy; + static QStringList s_replaceHistroy; static int s_padTimes; int m_curSoftLangs; //当前语言0:自动 1 中文 2 英语 @@ -563,6 +602,7 @@ private: QToolButton* m_wordwrap; QToolButton* m_allWhite; QToolButton* m_indentGuide; + QToolButton* m_tailf; QToolButton* m_preHexPage; QToolButton* m_nextHexPage; QToolButton* m_gotoHexPage; @@ -585,10 +625,13 @@ private: bool m_isInitBookMarkAct; + bool m_isRecentFileLoaded; + QListm_styleMarkActList; QList m_pluginList; public: + static QString s_lastOpenDirPath; static int s_restoreLastFile; //自动恢复上次打开的文件 static int s_curStyleId; diff --git a/src/cceditor/ccnotepad.ui b/src/cceditor/ccnotepad.ui index fe1a604..ddb12f8 100755 --- a/src/cceditor/ccnotepad.ui +++ b/src/cceditor/ccnotepad.ui @@ -57,9 +57,6 @@ 22 - - Qt::ElideNone - true @@ -69,6 +66,9 @@ true + + false + @@ -506,6 +506,7 @@ T&ools + @@ -1626,6 +1627,9 @@ Column Block Editing + + Alt+X + @@ -2060,6 +2064,11 @@ Plugin Manager + + + Md5/Sha + + @@ -3474,6 +3483,22 @@ + + actionMd5_Sha + triggered() + CCNotePad + on_md5hash() + + + -1 + -1 + + + 728 + 394 + + + slot_actionNewFile_toggle(bool) @@ -3577,5 +3602,6 @@ slot_showWebAddr(bool) slot_langFileSuffix() slot_shortcutManager() + on_md5hash() diff --git a/src/cceditor/filemanager.cpp b/src/cceditor/filemanager.cpp index 96383cc..0da279c 100755 --- a/src/cceditor/filemanager.cpp +++ b/src/cceditor/filemanager.cpp @@ -1,4 +1,4 @@ -#include "filemanager.h" +#include "filemanager.h" #include "scintillaeditview.h" #include "scintillahexeditview.h" #include "CmpareMode.h" @@ -9,7 +9,9 @@ #include #include #include +#include +LangType detectLanguage(QString& headContent, QString& filepath); FileManager::FileManager():m_lastErrorCode(NONE_ERROR) { @@ -218,6 +220,68 @@ void FileManager::delNewFileNode(int fileIndex) } } +//和loadFileDataInText类似,但是不是从头开始读取文件,而是从startReadSize开始 +//不检查编码,直接按照fileTextCode进行读取 +int FileManager::loadFileDataInTextFromOffset(ScintillaEditView* editView, QString filePath, CODE_ID fileTextCode, QWidget* msgBoxParent, quint64 startReadSize) +{ + QFile file(filePath); + + //如果文件不存在,直接返回 + if (!file.exists()) + { + return -1; + } + + QFlags power = QFile::permissions(filePath); + + //直接以只读的方式打开,至于能不能保存,是保存时需要考虑的问题。 + //只需要在保存的时候获取admin权限即可 + QIODevice::OpenMode mode; + + mode = QIODevice::ExistingOnly | QIODevice::ReadOnly; + + if (!file.open(mode)) + { + QMessageBox::warning(msgBoxParent, tr("Error"), tr("Open File %1 failed").arg(filePath)); + return 2; + } + + quint64 fileSize = file.size(); + + //如果文件是空的。检查一下,有可能在临时文件损坏情况下出现,外面需要使用 + if (fileSize == 0) + { + file.close(); + return 0; + } + + //如果读取的内容,超过了当前文件大小,则直接返回。这里是返回0,视作成功,没有新内容要读 + if (startReadSize >= fileSize) + { + file.close(); + return 0; + } + + QByteArray bytes; + + if (file.seek(startReadSize)) + { + //读取后面所有的内容 + bytes = file.readAll(); + } + + file.close(); + + QString text; + + Encode::tranStrToUNICODE(fileTextCode, bytes.data(), bytes.count(), text); + + editView->append(text); + + return 0; +} + +#if 0 //这里是以文本方式加载文件。但是可能遇到的是二进制文件,里面会做判断 //二进制时hexAsk是否询问,当用户指定打开格式时,不需要询问 @@ -406,6 +470,172 @@ int FileManager::loadFileDataInText(ScintillaEditView* editView, QString filePat return 0; } +#endif + +//20230304新增加:不再一行一行读取文件,而是一次性读取到内存,加快文本文件打开时的处理速度 +//这里是以文本方式加载文件。但是可能遇到的是二进制文件,里面会做判断 +//二进制时hexAsk是否询问,当用户指定打开格式时,不需要询问 +//MsgBoxParent::尽量把这个给一下,让MsgBox有图标,不那么难看。 +int FileManager::loadFileDataInText(ScintillaEditView* editView, QString filePath, CODE_ID& fileTextCode, RC_LINE_FORM& lineEnd, CCNotePad* callbackObj, bool hexAsk, QWidget* msgBoxParent) +{ + QFile file(filePath); + + //如果文件不存在,直接返回 + if (!file.exists()) + { + return -1; + } + + QFlags power = QFile::permissions(filePath); + + //直接以只读的方式打开,至于能不能保存,是保存时需要考虑的问题。 + //只需要在保存的时候获取admin权限即可 + QIODevice::OpenMode mode; + + mode = QIODevice::ExistingOnly | QIODevice::ReadOnly; + + if (!file.open(mode)) + { + qDebug() << file.error(); +#ifdef Q_OS_WIN + //打开失败,这里一般是权限问题导致。如果是windows,在外面申请权限后继续处理 + if (QFileDevice::OpenError == file.error()) + { + if (callbackObj != nullptr) + { + return callbackObj->runAsAdmin(filePath); + } + return 1; + } +#endif +#ifdef Q_OS_UNIX + QMessageBox::warning(msgBoxParent, tr("Error"), tr("Open File %1 failed").arg(filePath)); +#endif + return 2; + } + + qint64 fileSize = file.size(); + + //如果文件是空的。检查一下,有可能在临时文件损坏情况下出现,外面需要使用 + if (fileSize == 0) + { + m_lastErrorCode = ERROR_TYPE::OPEN_EMPTY_FILE; + file.close(); + return 0; + } + + qint64 bufferSizeRequested = fileSize + qMin((qint64)(1 << 20), (qint64)(fileSize / 6)); + + if (bufferSizeRequested > INT_MAX) + { + QMessageBox::warning(msgBoxParent, tr("Error"), tr("File is too big to be opened by Notepad--")); + file.close(); + return 3; + } + + QString fileText; + bool isErrorCode = false; + + fileTextCode = CmpareMode::scanFileOutPut(file, fileTextCode, filePath, fileText, isErrorCode); + + //如果文件是空的。检查一下,有可能在临时文件损坏情况下出现,外面需要使用 + if (fileText.size() == 0) + { + m_lastErrorCode = ERROR_TYPE::OPEN_EMPTY_FILE; + file.close(); + return 0; + } + + if (isErrorCode && hexAsk) + { + //检测到文件很可能是二进制文件,询问用户,是否以二进制加载 + int ret = QMessageBox::question(msgBoxParent, tr("Open with Text or Hex? [Exist Garbled Code]"), tr("The file %1 is likely to be binary. Do you want to open it in binary?").arg(filePath), tr("Hex Open"), tr("Text Open"), tr("Cancel")); + + if (ret == 0) + { + //16进制打开 + file.close(); + return 4; + } + else if (ret == 1) + { + //继续以文本打开 + } + else + { + //取消,不打开 + file.close(); + return 2; + } + } + + //以第一行的换行为文本的换行符。暂时只考虑win unix 。mac \r 已经淘汰,暂时不管 + lineEnd = RC_LINE_FORM::UNKNOWN_LINE; + + int pos = fileText.indexOf("\n"); + if (pos >=1) + { + if (fileText[pos - 1] == QChar('\r')) + { + lineEnd = RC_LINE_FORM::DOS_LINE; + } + else + { + lineEnd = RC_LINE_FORM::UNIX_LINE; + } + } + + if (lineEnd == UNKNOWN_LINE) + { +#ifdef _WIN32 + lineEnd = DOS_LINE; +#else + lineEnd = UNIX_LINE; +#endif + } + + file.close(); + + + //优先根据文件后缀来确定其语法风格 + LexerInfo lxdata = CCNotePad::getLangLexerIdByFileExt(filePath); + + if (lxdata.lexerId != L_TXT) + { + QsciLexer* lexer = editView->createLexer(lxdata.lexerId, lxdata.tagName); + editView->setLexer(lexer); + } + else + { + //利用前面100个字符,进行一个编程语言的判断 + QString headContens = fileText.mid(0, 100); + + LangType _language = detectLanguage(headContens, filePath); + + if (_language >= 0 && _language < L_EXTERNAL) + { + QsciLexer* lexer = editView->createLexer(_language); + editView->setLexer(lexer); + } + } + + //如果检测到时16进制文件,但是强行以二进制打开,则有限走setUtf8Text。 + if (!isErrorCode) + { + editView->setText(fileText); + } + else + { + //20230203有github用户反馈,说存在乱码的文件被截断,所以后续还是不走截断 + editView->setText(fileText); + + return 6; + } + + return 0; +} + + //加载文件,只为查找使用 int FileManager::loadFileForSearch(ScintillaEditView* editView, QString filePath) { @@ -413,15 +643,9 @@ int FileManager::loadFileForSearch(ScintillaEditView* editView, QString filePath QFlags power = QFile::permissions(filePath); - if (!power.testFlag(QFile::ReadOwner)) - { - //文件不能读 - return 1; - } - QIODevice::OpenMode mode; - if (!power.testFlag(QFile::WriteOwner)) + if (!power.testFlag(QFile::WriteUser)) { //文件不能写 mode = QIODevice::ExistingOnly | QIODevice::ReadOnly; @@ -433,7 +657,7 @@ int FileManager::loadFileForSearch(ScintillaEditView* editView, QString filePath if (!file.open(mode)) { - qDebug() << file.error(); + //qDebug() << file.error(); return 2; } @@ -441,46 +665,30 @@ int FileManager::loadFileForSearch(ScintillaEditView* editView, QString filePath qint64 bufferSizeRequested = fileSize + qMin((qint64)(1 << 20), (qint64)(fileSize / 6)); - // As a 32bit application, we cannot allocate 2 buffer of more than INT_MAX size (it takes the whole address space) if (bufferSizeRequested > INT_MAX) { file.close(); return 3; } - QList outputLineInfoVec; - - int maxLineSize = 0; - int charsNums = 0; - bool isHexFile = false; - + bool existGrbledCode = false; + QString outText; CODE_ID fileTextCode = CODE_ID::UNKOWN; - CmpareMode::scanFileOutPut(fileTextCode, filePath, outputLineInfoVec, maxLineSize, charsNums, isHexFile); + fileTextCode = CmpareMode::scanFileOutPut(file, fileTextCode, filePath, outText, existGrbledCode); - if (isHexFile) + //20230218 这里必须指明一下编码,否则后续会导致编码被修改 + editView->setProperty(Edit_Text_Code, fileTextCode); + + if (existGrbledCode) { - qDebug() << filePath; + //qDebug() << filePath; file.close(); return 4; } - - if (maxLineSize > 0) - { - editView->execute(SCI_SETSCROLLWIDTH, maxLineSize * 10); - } - - QString text; - text.reserve(charsNums + 1); - - for (QList::iterator it = outputLineInfoVec.begin(); it != outputLineInfoVec.end(); ++it) - { - text.append(it->unicodeStr); - } - file.close(); - editView->setText(text); + editView->setText(outText); return 0; } @@ -1220,95 +1428,52 @@ void FileManager::closeBigTextRoFileHand(QString filepath) } } -//检查文件的编程语言 -LangType FileManager::detectLanguageFromTextBegining(const unsigned char *data, size_t dataLen) +//初步检查文件的编程语言。两个标准: 1 文件头部标签 2 文件特定名称 +LangType detectLanguage(QString& headContent, QString& filepath) { struct FirstLineLanguages { - std::string pattern; + QString pattern; LangType lang; }; - // Is the buffer at least the size of a BOM? - if (dataLen <= 3) - return L_TXT; - - // Eliminate BOM if present - size_t i = 0; - if ((data[0] == 0xEF && data[1] == 0xBB && data[2] == 0xBF) || // UTF8 BOM - (data[0] == 0xFE && data[1] == 0xFF && data[2] == 0x00) || // UTF16 BE BOM - (data[0] == 0xFF && data[1] == 0xFE && data[2] == 0x00)) // UTF16 LE BOM - i += 3; - - // Skip any space-like char - for (; i < dataLen; ++i) - { - if (data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r') - break; - } - - // Create the buffer to need to test - const size_t longestLength = 40; // shebangs can be large - std::string buf2Test = std::string((const char *)data + i, longestLength); - - // Is there a \r or \n in the buffer? If so, truncate it - auto cr = buf2Test.find("\r"); - auto nl = buf2Test.find("\n"); - auto crnl = qMin(cr, nl); - if (crnl != std::string::npos && crnl < longestLength) - buf2Test = std::string((const char *)data + i, crnl); - - // First test for a Unix-like Shebang - // See https://en.wikipedia.org/wiki/Shebang_%28Unix%29 for more details about Shebang - std::string shebang = "#!"; - - size_t foundPos = buf2Test.find(shebang); - if (foundPos == 0) - { - // Make a list of the most commonly used languages - const size_t NB_SHEBANG_LANGUAGES = 7; - FirstLineLanguages ShebangLangs[NB_SHEBANG_LANGUAGES] = { - { "sh", L_BASH }, - { "python", L_PYTHON }, - { "perl", L_PERL }, - { "php", L_PHP }, - { "ruby", L_RUBY }, - { "node", L_JAVASCRIPT }, - { "Makefile", L_MAKEFILE} - }; - - // Go through the list of languages - for (i = 0; i < NB_SHEBANG_LANGUAGES; ++i) - { - if (buf2Test.find(ShebangLangs[i].pattern) != std::string::npos) - { - return ShebangLangs[i].lang; - } - } - - // Unrecognized shebang (there is always room for improvement ;-) - return L_TXT; - } - - // Are there any other patterns we know off? - const size_t NB_FIRST_LINE_LANGUAGES = 5; - FirstLineLanguages languages[NB_FIRST_LINE_LANGUAGES] = { + const size_t FIRST_LINE_LANGUAGES = 5; + FirstLineLanguages languages[FIRST_LINE_LANGUAGES] = { { " blocks;//ÿһ¿éµÄË÷Òý¡£´ò¿ªÎļþµÄʱºò£¬ÐèҪ½¨Á¢¸ÃË÷Òý + QVector blocks;//每一块的索引。打开文件的时候,需要建立该索引 BigTextEditFileMgr():filePtr(nullptr), file(nullptr), m_curBlockIndex(0), loadWithCode(CODE_ID::UNKOWN), lineEndType(RC_LINE_FORM::UNKNOWN_LINE) { @@ -154,8 +154,13 @@ public: void delNewFileNode(int fileIndex); - int loadFileDataInText(ScintillaEditView * editView, QString filePath, CODE_ID & fileTextCode, RC_LINE_FORM &lineEnd, CCNotePad * callbackObj=nullptr, bool hexAsk = true, QWidget* MsgBoxParent=nullptr); + int loadFileDataInTextFromOffset(ScintillaEditView* editView, QString filePath, CODE_ID fileTextCode, QWidget* msgBoxParent, quint64 startReadSize); + //下面这个是旧函数,之前对比时候用的。 + //int loadFileDataInText(ScintillaEditView * editView, QString filePath, CODE_ID & fileTextCode, RC_LINE_FORM &lineEnd, CCNotePad * callbackObj=nullptr, bool hexAsk = true, QWidget* MsgBoxParent=nullptr); + + int loadFileDataInText(ScintillaEditView* editView, QString filePath, CODE_ID& fileTextCode, RC_LINE_FORM& lineEnd, CCNotePad* callbackObj = nullptr, bool hexAsk = true, QWidget* msgBoxParent = nullptr); + int loadFileForSearch(ScintillaEditView * editView, QString filePath); //int loadFileData(ScintillaEditView * editView, QString filePath, CODE_ID & fileTextCode, RC_LINE_FORM & lineEnd); @@ -188,8 +193,6 @@ public: void closeBigTextRoFileHand(QString filepath); - LangType detectLanguageFromTextBegining(const unsigned char * data, size_t dataLen); - static FileManager& getInstance() { static FileManager instance; return instance; diff --git a/src/columnedit.ui b/src/columnedit.ui index 94f0329..53011ad 100755 --- a/src/columnedit.ui +++ b/src/columnedit.ui @@ -153,7 +153,7 @@ - 1 + -100 diff --git a/src/ctipwin.cpp b/src/ctipwin.cpp index f894ad8..8c07c2d 100755 --- a/src/ctipwin.cpp +++ b/src/ctipwin.cpp @@ -34,3 +34,29 @@ void CTipWin::slot_delayClose() close(); } + +void CTipWin::showTips(QWidget* parent, QString text, int sec, bool isMousePos) +{ + + if (parent != nullptr) + { + CTipWin* pWin = new CTipWin(); + pWin->setTipText(text); + pWin->setAttribute(Qt::WA_DeleteOnClose); + pWin->showMsg(sec); + + if (!isMousePos) + { + QPoint pos = parent->pos(); + QSize size = parent->size(); + + QPoint newPos(pos.x() + 10, pos.y() + size.height() - 20); + pWin->move(newPos); + } + else + { + pWin->move(parent->cursor().pos()); +} + + } +} diff --git a/src/ctipwin.h b/src/ctipwin.h index c5a3cb5..a762436 100755 --- a/src/ctipwin.h +++ b/src/ctipwin.h @@ -12,6 +12,7 @@ public: ~CTipWin(); void setTipText(QString text); void showMsg(int sec = 2000); + static void showTips(QWidget* parent, QString text, int sec, bool isMousePos = false); private slots: void slot_delayClose(); diff --git a/src/ctipwin.ui b/src/ctipwin.ui index a00e6f9..e0d00b4 100755 --- a/src/ctipwin.ui +++ b/src/ctipwin.ui @@ -7,7 +7,7 @@ 0 0 295 - 69 + 35 diff --git a/src/dectfilechanges.cpp b/src/dectfilechanges.cpp new file mode 100755 index 0000000..337c3ff --- /dev/null +++ b/src/dectfilechanges.cpp @@ -0,0 +1,72 @@ +#include "dectfilechanges.h" + +#ifdef WIN32 + +DectFileChanges::DectFileChanges():m_lastFileSize(0), m_curFileSize(0) +{ + _szFile = NULL; + _dwNotifyFilter = 0; +} + + +DectFileChanges::~DectFileChanges() +{ +} + + +BOOL DectFileChanges::DetectChanges() { + + WIN32_FILE_ATTRIBUTE_DATA fInfo; + BOOL rValue = FALSE; + ::GetFileAttributesEx(_szFile, GetFileExInfoStandard, &fInfo); + + if ((_dwNotifyFilter & FILE_NOTIFY_CHANGE_SIZE) && (fInfo.nFileSizeHigh != _lastFileInfo.nFileSizeHigh || fInfo.nFileSizeLow != _lastFileInfo.nFileSizeLow)) { + rValue = TRUE; + } + + if ((_dwNotifyFilter & FILE_NOTIFY_CHANGE_LAST_WRITE) && (fInfo.ftLastWriteTime.dwHighDateTime != _lastFileInfo.ftLastWriteTime.dwHighDateTime || fInfo.ftLastWriteTime.dwLowDateTime != _lastFileInfo.ftLastWriteTime.dwLowDateTime)) { + rValue = TRUE; + } + + if (rValue) + { + m_lastFileSize = getFileSize(_lastFileInfo); + } + _lastFileInfo = fInfo; + + if (rValue) + { + m_curFileSize = getFileSize(_lastFileInfo); + } + return rValue; +} + +void DectFileChanges::AddFile(LPCTSTR szFile, DWORD dwNotifyFilter) +{ + _szFile = szFile; + _dwNotifyFilter = dwNotifyFilter; + ::GetFileAttributesEx(szFile, GetFileExInfoStandard, &_lastFileInfo); +} + + +void DectFileChanges::Terminate() +{ + _szFile = NULL; + _dwNotifyFilter = 0; +} +quint64 DectFileChanges::getFileSize(WIN32_FILE_ATTRIBUTE_DATA& data) +{ + quint64 fileSize = data.nFileSizeHigh; + fileSize = (fileSize << 32); + fileSize += data.nFileSizeLow; + + return fileSize; +} + +void DectFileChanges::getDiffFileSize(quint64& lastSize, quint64& curSize) +{ + lastSize = m_lastFileSize; + curSize = m_curFileSize; +} + +#endif diff --git a/src/dectfilechanges.h b/src/dectfilechanges.h new file mode 100755 index 0000000..4a17d65 --- /dev/null +++ b/src/dectfilechanges.h @@ -0,0 +1,41 @@ +#pragma once + +#ifdef WIN32 + +#include + +#ifndef VC_EXTRALEAN +#define VC_EXTRALEAN +#endif + +//ÏÂÃæNOMINMAX±£֤std::min²»Öظ´¶¨Òå +#define NOMINMAX + +#include +#include + +class DectFileChanges +{ +public: + DectFileChanges(); + ~DectFileChanges(); + void AddFile(LPCTSTR szDirectory, DWORD dwNotifyFilter); + BOOL DetectChanges(); + void Terminate(); + + void getDiffFileSize(quint64& lastSize, quint64& curSize); + +private: + quint64 getFileSize(WIN32_FILE_ATTRIBUTE_DATA& data); + +private: + LPCTSTR _szFile = nullptr; + DWORD _dwNotifyFilter = 0; + WIN32_FILE_ATTRIBUTE_DATA _lastFileInfo = {}; + + quint64 m_lastFileSize; + quint64 m_curFileSize; + +}; + +#endif diff --git a/src/encodeconvert.cpp b/src/encodeconvert.cpp index c17022e..7cdb18a 100755 --- a/src/encodeconvert.cpp +++ b/src/encodeconvert.cpp @@ -289,7 +289,7 @@ QFuture EncodeConvert::commitTask(std::function EncodeConvert::checkFileCode(QString filePath, QTreeWidgetItem* item) { EncodeThreadParameter_* p = new EncodeThreadParameter_(filePath); @@ -298,7 +298,8 @@ QFuture EncodeConvert::checkFileCode(QString filePath, //int 0相等 1 不等 return commitTask([](EncodeThreadParameter_* parameter)->EncodeThreadParameter_* { - parameter->code = CmpareMode::scanFileRealCode(parameter->filepath); + //整个文件都要扫描完毕。还是怕太慢,最多1000行吧 + parameter->code = CmpareMode::scanFileRealCode(parameter->filepath,1000); return parameter; } , p); @@ -473,6 +474,7 @@ void EncodeConvert::scanFileCode() { iter->selfItem->setText(2, QString("--")); } + //20230304 编码转换这里,不能仅仅只识别已知后缀文件,要失败所有文件 else if ((iter->type == RC_FILE) && DocTypeListView::isSupportExt(fileSuffix(iter->relativePath))) { QFutureWatcher* futureWatcher = new QFutureWatcher(); diff --git a/src/findresultview.cpp b/src/findresultview.cpp new file mode 100755 index 0000000..39d1802 --- /dev/null +++ b/src/findresultview.cpp @@ -0,0 +1,288 @@ +#include "findresultview.h" +#include "styleset.h" +#include "findresultwin.h" +#include "ctipwin.h" +#include "Scintilla.h" + +#include + + +const int MARGE_FOLDER = 1; +const int STYLE_COLOUR_TITLE = 1; +const int STYLE_COLOUR_DEST_FILE = 2; +const int STYLE_COLOUR_KEYWORD_HIGH = 3; +const int STYLE_COLOUR_KEYWORD_BACK_HIGH = 4; +const int STYLE_DEEP_COLOUR_KEYWORD_HIGH = 5; //ÉîɫģʽÏÂÃæµÄǰ¾°ɫ +const int STYLE_DEEP_COLOUR_DEST_FILE = 6; + +static void getFoldColor(QColor& fgColor, QColor& bgColor, QColor& activeFgColor) +{ + //ÕâÀ￴ÆðÀ´·´Áˣ¬µ«ÊÇʵ¼ʴúÂë¾ÍÊÇÈç´Ë + fgColor = StyleSet::s_global_style->fold.bgColor; + bgColor = StyleSet::s_global_style->fold.fgColor; + + activeFgColor = StyleSet::s_global_style->fold_active.fgColor; + +} + +void FindResultView::setFoldColor(int margin, QColor fgClack, QColor bkColor, QColor foreActive) +{ + SendScintilla(SCI_MARKERSETFORE, margin, fgClack); + SendScintilla(SCI_MARKERSETBACK, margin, bkColor); + SendScintilla(SCI_MARKERSETBACKSELECTED, margin, foreActive); +} + +FindResultView::FindResultView(QWidget *parent) + : QsciScintilla(parent) +{ + //ͨ¹ýfold·¢Ï֣¬¾¡Á¿ʹÓÃqscintµĹ¦Äܣ¬ÒòΪËû×öÁ˴óÁ¿·âװºͼò»¯ + setFolding(BoxedTreeFoldStyle, MARGE_FOLDER); + + SendScintilla(SCI_SETMARGINWIDTHN, MARGE_FOLDER, 14); + + SendScintilla(SCI_MARKERSETFORE, SC_MARKNUM_FOLDERSUB, QColor(0xff,0,0)); + + setCaretLineVisible(true); + SendScintilla(SCI_SETSCROLLWIDTHTRACKING, true); + SendScintilla(SCI_SETCARETLINEBACK, StyleSet::s_global_style->current_line_background_color.bgColor); + + QColor foldfgColor = Qt::white, foldbgColor = Qt::gray, activeFoldFgColor = Qt::red; + getFoldColor(foldfgColor, foldbgColor, activeFoldFgColor); + setFoldMarginColors(StyleSet::s_global_style->fold_margin.fgColor, StyleSet::s_global_style->fold_margin.bgColor); + setFoldColor(SC_MARKNUM_FOLDEROPEN, foldfgColor, foldbgColor, activeFoldFgColor); + setFoldColor(SC_MARKNUM_FOLDER, foldfgColor, foldbgColor, activeFoldFgColor); + setFoldColor(SC_MARKNUM_FOLDERSUB, foldfgColor, foldbgColor, activeFoldFgColor); + setFoldColor(SC_MARKNUM_FOLDERTAIL, foldfgColor, foldbgColor, activeFoldFgColor); + setFoldColor(SC_MARKNUM_FOLDEREND, foldfgColor, foldbgColor, activeFoldFgColor); + setFoldColor(SC_MARKNUM_FOLDEROPENMID, foldfgColor, foldbgColor, activeFoldFgColor); + setFoldColor(SC_MARKNUM_FOLDERMIDTAIL, foldfgColor, foldbgColor, activeFoldFgColor); + + SendScintilla(SCI_STYLESETSIZE, STYLE_DEFAULT, 12); + + if (!StyleSet::isCurrentDeepStyle()) + { + this->setPaper(StyleSet::s_global_style->default_style.bgColor); + + SendScintilla(SCI_STYLESETBACK, STYLE_COLOUR_TITLE, 0xffbbbb); + SendScintilla(SCI_STYLESETBACK, STYLE_COLOUR_DEST_FILE, 0xd5ffd5); + SendScintilla(SCI_STYLESETEOLFILLED, STYLE_COLOUR_TITLE, true); + SendScintilla(SCI_STYLESETEOLFILLED, STYLE_COLOUR_DEST_FILE, true); + SendScintilla(SCI_STYLESETFORE, STYLE_COLOUR_KEYWORD_HIGH, 0x4080ff); + SendScintilla(SCI_STYLESETBACK, STYLE_COLOUR_KEYWORD_BACK_HIGH, 0xbfffff); + + } + else + { + this->setColor(StyleSet::s_global_style->default_style.fgColor); + this->setPaper(StyleSet::s_global_style->default_style.bgColor); + + //QColor& col = StyleSet::s_global_style->default_style.fgColor; + //sptr_t fgLParam = (col.blue() << 16) | (col.green() << 8) | col.red(); + + QColor& col2 = StyleSet::s_global_style->default_style.bgColor; + sptr_t bklParam = (col2.blue() << 16) | (col2.green() << 8) | col2.red(); + + SendScintilla(SCI_STYLESETBACK, STYLE_COLOUR_TITLE, 0xffbbbb); + SendScintilla(SCI_STYLESETEOLFILLED, STYLE_COLOUR_TITLE, true); + //SendScintilla(SCI_STYLESETFORE, STYLE_COLOUR_TITLE, fgLParam); + + SendScintilla(SCI_STYLESETBACK, STYLE_DEEP_COLOUR_DEST_FILE, bklParam); + SendScintilla(SCI_STYLESETFORE, STYLE_DEEP_COLOUR_DEST_FILE, 0x99cc99); + //SendScintilla(SCI_STYLESETFORE, STYLE_DEEP_COLOUR_DEST_FILE, fgLParam); + //SendScintilla(SCI_STYLESETBOLD, STYLE_DEEP_COLOUR_DEST_FILE, 1);//Õâ¸öÎ޷¨ÉúЧ¡£¿ÉÄÜÊÇqscint bug + + //ÎÄ×ÖҪ´óһºţ¬ȻºóÑÕɫÊÇÂÌɫ + SendScintilla(SCI_STYLESETSIZE, STYLE_DEEP_COLOUR_DEST_FILE, 14); + + SendScintilla(SCI_STYLESETFORE, STYLE_DEEP_COLOUR_KEYWORD_HIGH, 0x00aaff); + SendScintilla(SCI_STYLESETBACK, STYLE_DEEP_COLOUR_KEYWORD_HIGH, bklParam); + + + //¸øÐкÅʹÓà + SendScintilla(SCI_STYLESETFORE, STYLE_COLOUR_KEYWORD_HIGH, 0x4080ff); + SendScintilla(SCI_STYLESETBACK, STYLE_COLOUR_KEYWORD_HIGH, bklParam); + } + + + this->setReadOnly(true); + + m_resultWin = dynamic_cast(parent); +} + +FindResultView::~FindResultView() +{} + +//ÉèÖÃÐб³¾°ɫ +void FindResultView::setLineBackColorStyle(int line, int style) +{ + int startPos = SendScintilla(SCI_POSITIONFROMLINE, line); + int len = SendScintilla(SCI_LINELENGTH, line); + + SendScintilla(SCI_STARTSTYLING, startPos); + SendScintilla(SCI_SETSTYLING, len, style); +} + +//ÉèÖÃÐÐǰ¾°ɫ¡£line Ðкţ¬´ÓÏà¶ÔÐÐposµÄλÖÿªʼ +void FindResultView::setLineColorStyle(int line, int offsetPos, int length, int style) +{ + int startPos = SendScintilla(SCI_POSITIONFROMLINE, line); + SendScintilla(SCI_STARTSTYLING, startPos + offsetPos); + SendScintilla(SCI_SETSTYLING, length, style); +} + + +void FindResultView::mouseDoubleClickEvent(QMouseEvent* /*e*/) +{ + //QsciScintilla::mouseDoubleClickEvent(e); + + int line = 0; + int index = 0; + + this->getCursorPosition(&line,&index); + + emit lineDoubleClick(line); +} + +void FindResultView::contextUserDefineMenuEvent(QMenu* menu) +{ + if (menu != nullptr) + { + //Òƶ¯һÏÂλÖà + + QAction* pCopy = menu->findChild("copy"); + if (pCopy != nullptr) + { + menu->removeAction(pCopy); + } + + menu->addAction(tr("Fold All"), this, &FindResultView::on_foldAll); + menu->addAction(tr("Expand All"), this, &FindResultView::on_expandAll); + + menu->addSeparator(); + + if (pCopy != nullptr) + { + menu->addAction(pCopy); + } + menu->addAction(tr("copy select line"), this, &FindResultView::on_copySelectLine); + menu->addAction(tr("warp"), this, &FindResultView::on_warp); + + menu->addSeparator(); + + menu->addAction(tr("clear"), this, &FindResultView::on_clear); + menu->addAction(tr("close"), this, &FindResultView::on_close); + + + } + menu->move(cursor().pos()); //Èò˵¥ÏÔʾµÄλÖÃÔÚÊó±êµÄ×ø±êÉÏ + menu->show(); +} + +void FindResultView::on_foldAll() +{ + for (int i = 0; i < m_resultWin->m_resultLineInfo.size(); ++i) + { + const ResultLineInfo& lineInfo = m_resultWin->m_resultLineInfo.at(i); + + //Èç¹ûÊÇ1¼¶±ðµÄÐУ¬Ôò½øÐÐһ¸öÊÕÆð²Ù×÷ + if ((lineInfo.level == 1) || (lineInfo.level == 0)) + { + SendScintilla(SCI_FOLDLINE, i, (long)SC_FOLDACTION_CONTRACT); + } + } +} + +void FindResultView::on_expandAll() +{ + for (int i = 0; i < m_resultWin->m_resultLineInfo.size(); ++i) + { + const ResultLineInfo& lineInfo = m_resultWin->m_resultLineInfo.at(i); + + //Èç¹ûÊÇ1¼¶±ðµÄÐУ¬Ôò½øÐÐһ¸öÊÕÆð²Ù×÷ + if ((lineInfo.level == 1) || (lineInfo.level == 0)) + { + SendScintilla(SCI_FOLDLINE, i, SC_FOLDACTION_EXPAND); + } + } +} + +//¸´ÖÆѡÖеÄÄÚÈÝ +//void FindResultView::on_copySelect() +//{ +// QString word = selectedText(); +// if (!word.isEmpty()) +// { +// QClipboard* clipboard = QApplication::clipboard(); +// clipboard->setText(word); +// +// CTipWin::showTips(this, tr("Copy to clipboard Finished!"), 1200,true); +// } +//} + +//¸´ÖÆѡÖÐÐÐ +void FindResultView::on_copySelectLine() +{ + int startPos = SendScintilla(SCI_GETSELECTIONSTART); + int endPos = SendScintilla(SCI_GETSELECTIONEND); + + int startLine = SendScintilla(SCI_LINEFROMPOSITION, startPos); + int endLine = SendScintilla(SCI_LINEFROMPOSITION, endPos); + + int start = SendScintilla(SCI_POSITIONFROMLINE, startLine); + int end = SendScintilla(SCI_POSITIONFROMLINE, endLine+1); + + char *dest = new char[end - start + 1]; + dest[end - start] = '\0'; + + Sci_TextRange tr; + tr.chrg.cpMin = static_cast(start); + tr.chrg.cpMax = static_cast(end); + tr.lpstrText = dest; + + this->SendScintilla(SCI_GETTEXTRANGE, 0, &tr); + + QString text(dest); + + QStringList lineText = text.split("\n"); + QString selectConnect; + + for (int i = 0; i < lineText.size(); ++i) + { + const QString& t = lineText.at(i); + int pos = t.indexOf(": "); + if (pos != -1) + { + QString v = t.mid(pos + 2); + selectConnect.append(v); + selectConnect.append("\n"); + } + } + + QClipboard* clipboard = QApplication::clipboard(); + clipboard->setText(selectConnect); + + //CTipWin::showTips(this, tr("Copy to clipboard Finished!"), 1200, true); +} + +void FindResultView::on_clear() +{ + this->clear(); + m_resultWin->clear(); +} + +void FindResultView::on_close() +{ + m_resultWin->m_parent->close(); +} + +void FindResultView::on_warp() +{ + if (SC_WRAP_CHAR != wrapMode()) + { + this->setWrapMode(QsciScintilla::WrapCharacter); + } + else + { + this->setWrapMode(QsciScintilla::WrapNone); + } +} \ No newline at end of file diff --git a/src/findresultview.h b/src/findresultview.h new file mode 100755 index 0000000..1bbce7a --- /dev/null +++ b/src/findresultview.h @@ -0,0 +1,49 @@ +#pragma once +#include +#include +#include +#include + +extern const int MARGIN_VER_LINE; +extern const int STYLE_COLOUR_TITLE; +extern const int STYLE_COLOUR_DEST_FILE; +extern const int STYLE_COLOUR_KEYWORD_HIGH; +extern const int STYLE_COLOUR_KEYWORD_BACK_HIGH; +extern const int STYLE_DEEP_COLOUR_KEYWORD_HIGH; +extern const int STYLE_DEEP_COLOUR_DEST_FILE; + +class FindResultWin; + +class FindResultView : public QsciScintilla +{ + Q_OBJECT + +public: + FindResultView(QWidget* parent); + virtual ~FindResultView(); + + void setLineBackColorStyle(int line, int style); + void setLineColorStyle(int line, int pos, int length, int style); + +signals: + void lineDoubleClick(int line); + +public slots: + void on_foldAll(); +private slots: + + void on_expandAll(); + //void on_copySelect(); + void on_copySelectLine(); + void on_clear(); + void on_close(); + void on_warp(); + +protected: + void mouseDoubleClickEvent(QMouseEvent* e) override; + void contextUserDefineMenuEvent(QMenu* menu) override; + void setFoldColor(int margin, QColor fgClack, QColor bkColor, QColor foreActive); + +private: + FindResultWin* m_resultWin; +}; diff --git a/src/findresultwin.cpp b/src/findresultwin.cpp index 75af255..8c6391e 100755 --- a/src/findresultwin.cpp +++ b/src/findresultwin.cpp @@ -3,19 +3,20 @@ #include "common.h" #include "styleset.h" #include "nddsetting.h" +#include "findresultview.h" -#include -#include -#include -#include -#include -#include +#include +#include + +//#include +//#include +//#include +//#include +//#include +//#include #include #include #include - -#include "ndstyleditemdelegate.h" - //目前可以高亮,使用富文本进行了高亮设置。但是有个问题:富文本与html有一些冲突,在<>存在时,可能导致乱。这是一个问题。20220609 //使用Html的转义解决了该问题 @@ -23,51 +24,8 @@ FindResultWin::FindResultWin(QWidget *parent) : QWidget(parent), m_menu(nullptr), m_parent(parent),m_defaultFontSize(14), m_defFontSizeChange(false) { ui.setupUi(this); - - //设置左边的缩起来按钮为加号,而不是箭头 - ui.resultTreeView->setStyle(QStyleFactory::create("windows")); - ui.resultTreeView->header()->hide(); + connect(ui.displayView, &FindResultView::lineDoubleClick, this, &FindResultWin::on_lineDoubleClick); - m_model = new QStandardItemModel(ui.resultTreeView); - m_delegate = new NdStyledItemDelegate(ui.resultTreeView); - ui.resultTreeView->setModel(m_model); - ui.resultTreeView->setItemDelegate(m_delegate); - ui.resultTreeView->setEditTriggers(QAbstractItemView::NoEditTriggers); - ui.resultTreeView->setSelectionMode(QAbstractItemView::ExtendedSelection); - -//#if defined (Q_OS_MAC) -// QString qss = "QTreeView::item:selected{ \ -// background:#e8e8ff; \ -// } \ -// QTreeView::item{ \ -// height:18px; \ -// }"; -//#else -// QString qss = "QTreeView::item:selected{ \ -// background:#e8e8ff; \ -// }"; -//#endif -// ui.resultTreeView->setStyleSheet(qss); - - connect(ui.resultTreeView, &QTreeView::doubleClicked, this, &FindResultWin::itemDoubleClicked); - - connect(ui.resultTreeView, SIGNAL(pressed(QModelIndex)), this, SLOT(slot_treeView_pressed(QModelIndex))); - connect(ui.resultTreeView, SIGNAL(expanded(QModelIndex)), this, SLOT(slot_treeView_pressed(QModelIndex))); - - ui.resultTreeView->verticalScrollBar()->setStyle(QStyleFactory::create("vis")); - ui.resultTreeView->horizontalScrollBar()->setStyle(QStyleFactory::create("vis")); - - int defFontSize = NddSetting::getKeyValueFromNumSets(FIND_RESULT_FONT_SIZE); - if (defFontSize >= 8) - { - m_defaultFontSize = defFontSize; - - QFont curFt = ui.resultTreeView->font(); - curFt.setPointSize(m_defaultFontSize); - ui.resultTreeView->setFont(curFt); - - m_delegate->setFontSize(m_defaultFontSize); -} } FindResultWin::~FindResultWin() @@ -75,311 +33,32 @@ FindResultWin::~FindResultWin() if (m_defFontSizeChange) { NddSetting::updataKeyValueFromNumSets(FIND_RESULT_FONT_SIZE, m_defaultFontSize); -} + } + + clear(); } -void FindResultWin::slot_treeView_pressed(QModelIndex modeIndex) +void FindResultWin::clear() { - ui.resultTreeView->resizeColumnToContents(modeIndex.column()); -} - -void FindResultWin::contextMenuEvent(QContextMenuEvent *) -{ - if (m_menu == nullptr) + for (int i = 0; i < m_resultLineFilePath.size(); ++i) { - m_menu = new QMenu(this); - m_menu->addAction(tr("clear this find result"), this, &FindResultWin::slot_clearContents); - m_menu->addAction(tr("clear all find result"), this, &FindResultWin::slot_clearAllContents); - - m_menu->addSeparator(); - m_pSelectSectonAct = m_menu->addAction(tr("select section"), this, &FindResultWin::slot_selectSection); - m_menu->addAction(tr("select all item"), this, &FindResultWin::slot_selectAll); - - m_menu->addSeparator(); - - m_menu->addAction(tr("copy select item (Ctrl Muli)"), this, &FindResultWin::slot_copyItemContents); - m_menu->addAction(tr("copy select Line (Ctrl Muli)"), this, &FindResultWin::slot_copyContents); - - m_menu->addSeparator(); - m_menu->addAction(tr("Zoom In"), this, &FindResultWin::slot_fontZoomIn); - m_menu->addAction(tr("Zoom Out"), this, &FindResultWin::slot_fontZoomOut); - m_menu->addAction(tr("close"), m_parent, &QWidget::close); - + delete m_resultLineFilePath.at(i); } - m_menu->move(cursor().pos()); //让菜单显示的位置在鼠标的坐标上 - m_menu->show(); - - QModelIndex curSelItem = ui.resultTreeView->currentIndex(); - - if (!curSelItem.data(ResultItemRoot).isNull()) - { - //是根不能选择section - m_pSelectSectonAct->setEnabled(false); -} - else if (!curSelItem.data(ResultItemEditor).isNull()) - { - m_pSelectSectonAct->setEnabled(true); - } - else if (!curSelItem.data(ResultItemPos).isNull()) - { - m_pSelectSectonAct->setEnabled(true); - } -} - -void FindResultWin::slot_clearContents() -{ - QModelIndex curSelItem = ui.resultTreeView->currentIndex(); - - if (!curSelItem.data(ResultItemRoot).isNull()) - { - //是根可以直接删除 - m_model->removeRow(curSelItem.row()); - } - else if (!curSelItem.data(ResultItemEditor).isNull()) - { - //需要找到上一个父节点,即根 - QModelIndex rootItem = curSelItem.parent(); - - if (rootItem.isValid()) - { - m_model->removeRow(curSelItem.row(), rootItem); - - if (0 == m_model->rowCount(rootItem)) - { - m_model->removeRow(rootItem.row()); - } - } - } - else if (!curSelItem.data(ResultItemPos).isNull()) - { - //需要找到上两个父节点,即根 - QModelIndex itemEditor = curSelItem.parent(); - if (itemEditor.isValid()) - { - QModelIndex rootItem = itemEditor.parent(); - if (rootItem.isValid()) - { - m_model->removeRow(itemEditor.row(), rootItem); - if (0 == m_model->rowCount(rootItem)) - { - m_model->removeRow(rootItem.row()); - } - } - } - } -} - -//全选 -void FindResultWin::slot_selectAll() -{ - - QModelIndex root = ui.resultTreeView->rootIndex(); - - QModelIndex curSelItem = ui.resultTreeView->currentIndex(); - QModelIndex firstRootItem; - //先找到根节点 - while (curSelItem.isValid()) - { - QModelIndex pMi = curSelItem.parent(); - if (pMi.isValid()) - { - curSelItem = pMi; -} - else - { - break; - } - } - - //找到第一个兄弟根节点 - if (curSelItem.row() != 0) - { - firstRootItem = curSelItem.siblingAtRow(0); - } - else - { - firstRootItem = curSelItem; - } - - auto selectSection = [this](QModelIndex& sectionItem)->int{ - //遍历其下面的所有子节点 - ui.resultTreeView->selectionModel()->select(sectionItem, QItemSelectionModel::Select); - - //遍历下面的子节点 - int i = 0; - QModelIndex childMi; - childMi = sectionItem.child(i, 0); - while (childMi.isValid()) - { - ++i; - ui.resultTreeView->selectionModel()->select(childMi, QItemSelectionModel::Select); - childMi = sectionItem.child(i, 0); - } - return i+1; - }; - - QModelIndex rootItem = firstRootItem; - int j = 0; - int selectCount = 0; - while (rootItem.isValid()) - { - //遍历根节点下面每一个section - { - int i = 0; - QModelIndex section = rootItem.child(i, 0); - while (section.isValid() && !section.data(ResultItemEditor).isNull()) - { - ++i; - selectCount += selectSection(section); - section = firstRootItem.child(i, 0); - } - } - - //切换到下一个查找的根节点 - j++; - rootItem = firstRootItem.siblingAtRow(j); - } - - QString msg = tr("%1 rows selected !").arg(selectCount); - emit showMsg(msg); -} - -void FindResultWin::slot_selectSection() -{ - QModelIndex curSelItem = ui.resultTreeView->currentIndex(); - - auto selectSection = [this](QModelIndex& sectionItem)->int { - //遍历其下面的所有子节点 - ui.resultTreeView->selectionModel()->select(sectionItem, QItemSelectionModel::Select); - - //遍历下面的子节点 - int i = 0; - QModelIndex childMi; - childMi = sectionItem.child(i, 0); - while (childMi.isValid()) - { - ++i; - ui.resultTreeView->selectionModel()->select(childMi, QItemSelectionModel::Select); - childMi = sectionItem.child(i, 0); - } - return i+1; - }; - - int selectCount = 0; - - if (!curSelItem.data(ResultItemRoot).isNull()) - { - //啥也不做。不能选择多个section - } - else if (!curSelItem.data(ResultItemEditor).isNull()) - { - selectCount = selectSection(curSelItem); - - } - else if (!curSelItem.data(ResultItemPos).isNull()) - { - //其父节点 - QModelIndex sectionItem = curSelItem.parent(); - if (!sectionItem.data(ResultItemEditor).isNull()) - { - selectCount = selectSection(sectionItem); - } - } - - QString msg = tr("%1 rows selected !").arg(selectCount); - emit showMsg(msg); -} - -//拷贝item的行,不进行过滤,全部拷贝 -void FindResultWin::slot_copyItemContents() -{ - QModelIndexList selectList; - - ui.resultTreeView->getSelectedIndexes(selectList); - - QString selectConnect; - - for (int i = 0, s = selectList.size(); i < s; ++i) - { - - QModelIndex curSelItem = selectList.at(i); - - QString text = m_model->itemData(curSelItem).values()[0].toString(); - - QTextEdit t(this); - t.setAcceptRichText(true); - t.setText(text); - text = t.toPlainText(); - - selectConnect.append(text); - selectConnect.append("\n"); - } - - QClipboard *clip = QApplication::clipboard(); - clip->setText(selectConnect); - - QString msg = tr("%1 items have been copied to the clipboard !").arg(selectList.size()); - emit showMsg(msg); -} - -void FindResultWin::slot_copyContents() -{ - QModelIndexList selectList; - - //std::sort(selectList.begin(), selectList.end(), [](QModelIndex& a, QModelIndex& b) { - // return a.row() < b.row(); - //}); - - ui.resultTreeView->getSelectedIndexes(selectList); - - QString selectConnect; - - int copyTimes = 0; - - for (int i = 0, s = selectList.size(); i < s; ++i) - { - QModelIndex curSelItem = selectList.at(i); - - //只拷贝真正的行内容 - if (curSelItem.data(ResultItemPos).isNull()) - { - continue; - } - - copyTimes++; - - QString text = m_model->itemData(curSelItem).values()[0].toString(); - - QTextEdit t(this); - t.setAcceptRichText(true); - t.setText(text); - text = t.toPlainText(); - - int pos = text.indexOf(": "); - if (pos != -1) - { - text = text.mid(pos + 2); - } - - selectConnect.append(text); - selectConnect.append("\n"); - } - - QClipboard *clip = QApplication::clipboard(); - clip->setText(selectConnect); - - QString msg = tr("%1 lines have been copied to the clipboard !").arg(copyTimes); - emit showMsg(msg); + m_resultLineFilePath.clear(); + m_resultLineInfo.clear(); } void FindResultWin::slot_clearAllContents() { - m_model->clear(); + clear(); + ui.displayView->clear(); } +#if 0 //老的机制,暂时屏蔽,后续可删除 //高亮查找的关键字文本。Index表示是第几次出现,前面的要跳过 void FindResultWin::highlightFindText(int index, QString &srcText, QString &findText, Qt::CaseSensitivity cs) { +#if 0 int pos = 0; int findPos = 0; @@ -403,14 +82,18 @@ void FindResultWin::highlightFindText(int index, QString &srcText, QString &find index--; } srcText.replace(pos, lens, QString("%1").arg(srcText.mid(pos,lens))); +#endif } +#endif const int MAX_HEAD_LENTGH = 20; const int MAX_TAIL_LENGTH = 80; +#if 0 //更复杂的高亮:在全词语匹配,大小写敏感,甚至正则表达式情况下,上面的highlightFindText是不够的。需要精确定位 QString FindResultWin::highlightFindText(FindRecord& record) { +#if 0 QByteArray utf8bytes = record.lineContents.toUtf8(); int lineLens = utf8bytes.length(); @@ -438,9 +121,9 @@ QString FindResultWin::highlightFindText(FindRecord& record) head = QString("%1").arg(QString(utf8bytes.mid(0, targetStart)).toHtmlEscaped()); src = QString("%1").arg(QString(utf8bytes.mid(targetStart, targetLens)).toHtmlEscaped()); tail = QString("%1").arg(QString(utf8bytes.mid(tailStart)).toHtmlEscaped()); - } - else - { + } + else + { head = QString(utf8bytes.mid(0, targetStart)); if (head.size() > MAX_HEAD_LENTGH) { @@ -471,7 +154,7 @@ QString FindResultWin::highlightFindText(FindRecord& record) head = QString("%1").arg(QString(utf8bytes.mid(0, targetStart)).toHtmlEscaped()); src = QString("%1").arg(QString(utf8bytes.mid(targetStart, targetLens)).toHtmlEscaped()); tail = QString("%1").arg(QString(utf8bytes.mid(tailStart)).toHtmlEscaped()); - } + } else { QString headContens = QString(utf8bytes.mid(0, targetStart)); @@ -501,36 +184,68 @@ QString FindResultWin::highlightFindText(FindRecord& record) } return QString("%1%2%3").arg(head).arg(src).arg(tail); +#endif + return ""; } + +//在当前文件查找字段,结果是一个单一的FindRecords void FindResultWin::appendResultsToShow(FindRecords* record) { +#if 0 if (record == nullptr) { return; } + FindResultView* pDisplay = ui.displayView; + + QString findTitle = tr("Search \"%1\" (%2 hits)\n").arg(record->findText).arg(record->records.size()); + + //pDisplay->append(findTitle); + + pDisplay->insertAt(findTitle,0,0); + + pDisplay->SendScintilla(SCI_SETFOLDLEVEL, 0, (long)(0|SC_FOLDLEVELHEADERFLAG)); + + QStringList contents; + + for (int i = 0; i < record->records.size(); ++i) + { + FindRecord v = record->records.at(i); + + const QString & richText = v.lineContents; + + QString text; + if (!StyleSet::isCurrentDeepStyle()) + { + text = tr("Line %1 : %2\n").arg(v.lineNum + 1).arg(richText); + } + else + { + text = tr("Line %1 : %2\n").arg(v.lineNum + 1).arg(richText); + } + + contents.append(text); + } + + pDisplay->insertAt(contents.join(""), 1, 0); + + for (int i = 0; i < record->records.size(); ++i) + { + pDisplay->SendScintilla(SCI_SETFOLDLEVEL, i+1, 1); + } +#endif + +#if 0 + QString findTitle; - //if (!StyleSet::isCurrentDeepStyle()) - //{ - findTitle = tr("Search \"%1\" (%2 hits)").arg(record->findText.toHtmlEscaped()).arg(record->records.size()); - /*} - else - { - findTitle = tr("Search \"%1\" (%2 hits)").arg(record->findText.toHtmlEscaped()).arg(record->records.size()); - }*/ + findTitle = tr("Search \"%1\" (%2 hits)").arg(record->findText.toHtmlEscaped()).arg(record->records.size()); QStandardItem* titleItem = new QStandardItem(findTitle); - - //if (!StyleSet::isCurrentDeepStyle()) - //{ - setItemBackground(titleItem, QColor(0xbbbbff)); - //} - //else - //{ - // setItemBackground(titleItem, QColor(0x423328));//0xd5ffd5 - //} + setItemBackground(titleItem, QColor(0xbbbbff)); + m_model->insertRow(0, titleItem); titleItem->setData(QVariant(true), ResultItemRoot); @@ -579,8 +294,6 @@ void FindResultWin::appendResultsToShow(FindRecords* record) //描述行双击不响应 descItem->setData(QVariant(true), ResultItemDesc); - //int lastLineNum = -1; - //int occurTimes = 0; for (int i =0 ; i < record->records.size(); ++i) { @@ -600,14 +313,18 @@ void FindResultWin::appendResultsToShow(FindRecords* record) QStandardItem* childItem = new QStandardItem(text); childItem->setData(QVariant(v.pos), ResultItemPos); childItem->setData(QVariant(v.end - v.pos), ResultItemLen); +#if defined(Q_OS_MAC) + childItem->setTextAlignment(Qt::AlignVCenter); +#endif descItem->appendRow(childItem); } if (!record->records.isEmpty()) { ui.resultTreeView->expand(m_model->index(0, 0, m_model->index(0, 0))); } - +#endif } +#endif void FindResultWin::appendResultsToShow(QVector* record, int hits, QString whatFind) { @@ -616,146 +333,149 @@ void FindResultWin::appendResultsToShow(QVector* record, int hits, return; } - QString findTitle = tr("Search \"%1\" (%2 hits in %3 files)").arg(whatFind.toHtmlEscaped()).arg(hits).arg(record->size()); - QStandardItem* titleItem = new QStandardItem(findTitle); - setItemBackground(titleItem, QColor(0xbbbbff)); - titleItem->setData(QVariant(true), ResultItemRoot); - - //总是把结果插在最上面一行 - m_model->insertRow(0, titleItem); - - int rowNum = m_model->rowCount(); - - //把其余的行收起来 - for (int i = 1; i < rowNum; ++i) + if (this->isHidden()) { - ui.resultTreeView->collapse(m_model->index(i, 0)); + this->setVisible(true); } - ui.resultTreeView->expand(m_model->index(0, 0)); + + ResultLineInfo lineInfo; + + QString findTitle = tr("Search \"%1\" (%2 hits in %3 files)\n").arg(whatFind).arg(hits).arg(record->size()); + + FindResultView* pDisplay = ui.displayView; + pDisplay->on_foldAll(); + + pDisplay->insertAt(findTitle, 0, 0); + + lineInfo.level = 0; + m_resultLineInfo.insert(0,lineInfo); + + pDisplay->SendScintilla(SCI_SETFOLDLEVEL, 0, (long)(0 | SC_FOLDLEVELHEADERFLAG)); if (record->size() == 0) { return; } + QStringList contents; + + QList keyworkOffsetPos; + QString text; + QString linePrefix; - for (int i = 0,count= record->size(); i < count; ++i) + int insertIndex = 1; + for (int i = 0, count = record->size(); i < count; ++i) { FindRecords* pr = record->at(i); + QString* pFilePath = new QString(pr->findFilePath); QString desc; if (!StyleSet::isCurrentDeepStyle()) { - desc = tr("%1 (%2 hits)").arg(pr->findFilePath.toHtmlEscaped()).arg(pr->records.size()); + desc = tr(" %1 (%2 hits)\n").arg(pr->findFilePath).arg(pr->records.size()); } else { - desc = tr("%1 (%2 hits)").arg(pr->findFilePath.toHtmlEscaped()).arg(pr->records.size()); + desc = tr(" %1 (%2 hits)\n").arg(pr->findFilePath).arg(pr->records.size()); } + contents.append(desc); + m_resultLineFilePath.append(pFilePath); - QStandardItem* descItem = new QStandardItem(desc); + lineInfo.level = 1; + m_resultLineInfo.insert(insertIndex, lineInfo); + ++insertIndex; - if (!StyleSet::isCurrentDeepStyle()) + for (int j = 0; j < pr->records.size(); ++j) { - setItemBackground(descItem, QColor(0xd5ffd5)); - } - else - { - setItemBackground(descItem, QColor(0x484848)); - } + FindRecord v = pr->records.at(j); + QString richText = v.lineContents; - titleItem->insertRow(0,descItem); + linePrefix = tr(" Line %1: ").arg(v.lineNum + 1); - //默认全部收起来 - if (count > 10) - { - ui.resultTreeView->collapse(m_model->index(0, 0, m_model->index(0, 0))); - } - - descItem->setData(QVariant((qlonglong)pr->pEdit), ResultItemEditor); - descItem->setData(QVariant(pr->findFilePath), ResultItemEditorFilePath); - descItem->setData(QVariant(pr->findText), ResultWhatFind); - - //描述行双击不响应 - descItem->setData(QVariant(true), ResultItemDesc); - - for (int i = 0; i < pr->records.size(); ++i) - { - FindRecord v = pr->records.at(i); - QString richText = highlightFindText(v); - - QString text; if (!StyleSet::isCurrentDeepStyle()) { - text = tr("Line %1 : %2").arg(v.lineNum + 1).arg(richText); + text = tr("%1%2\n").arg(linePrefix).arg(richText); } else { - text = tr("Line %1 : %2").arg(v.lineNum + 1).arg(richText); + text = tr("%1%2\n").arg(linePrefix).arg(richText); } - QStandardItem* childItem = new QStandardItem(text); - childItem->setData(QVariant(v.pos), ResultItemPos); - childItem->setData(QVariant(v.end - v.pos), ResultItemLen); - descItem->appendRow(childItem); + contents.append(text); + keyworkOffsetPos.append(linePrefix.toUtf8().size()); + lineInfo.level = 2; + lineInfo.resultPos = v.pos; + lineInfo.resultEnd = v.end; + lineInfo.pFilePath = pFilePath; + m_resultLineInfo.insert(insertIndex, lineInfo); + ++insertIndex; QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents); } - if (count <= 10 && !pr->records.isEmpty()) + } + + pDisplay->insertAt(contents.join(""), 1, 0); + + int lineNum = 1; + + QList destFileLineNum; + + for (int i = 0, count = record->size(); i < count; ++i) + { + FindRecords* pr = record->at(i); + + pDisplay->SendScintilla(SCI_SETFOLDLEVEL, lineNum, (long)(1 | SC_FOLDLEVELHEADERFLAG)); + destFileLineNum.append(lineNum); + ++lineNum; + + for (int j = 0; j < pr->records.size(); ++j) { - ui.resultTreeView->expand(m_model->index(0, 0, m_model->index(0, 0))); + pDisplay->SendScintilla(SCI_SETFOLDLEVEL, lineNum, (long)2| SC_FOLDLEVELBASE); + + ++lineNum; } } - ui.resultTreeView->expand(m_model->index(0, 0, m_model->index(0, 0))); -} -void FindResultWin::setItemBackground(QStandardItem* item, const QColor& color) -{ - QBrush b(color); - item->setBackground(b); -} + //着色 + pDisplay->setLineBackColorStyle(0, STYLE_COLOUR_TITLE); -void FindResultWin::setItemForeground(QStandardItem* item, const QColor& color) -{ - QBrush b(color); - item->setForeground(b); -} - -//查找结果框的字体变大 -void FindResultWin::slot_fontZoomIn() -{ - QFont curFt = ui.resultTreeView->font(); - - int s = curFt.pointSize(); - s += 2; - curFt.setPointSize(s); - - m_defaultFontSize += 2; - - ui.resultTreeView->setFont(curFt); - - m_delegate->setFontSize(m_defaultFontSize); - - m_defFontSizeChange = true; -} - -void FindResultWin::slot_fontZoomOut() -{ - QFont curFt = ui.resultTreeView->font(); - - int s = curFt.pointSize(); - s -= 2; - - if (s >= 8) + for (int i = 0, count = destFileLineNum.size(); i < count; ++i) { - m_defFontSizeChange = true; - m_defaultFontSize -= 2; - curFt.setPointSize(s); - ui.resultTreeView->setFont(curFt); - m_delegate->setFontSize(m_defaultFontSize); + pDisplay->setLineBackColorStyle(destFileLineNum.at(i), (StyleSet::isCurrentDeepStyle()? STYLE_DEEP_COLOUR_DEST_FILE:STYLE_COLOUR_DEST_FILE)); } + + //关键字高亮 + //高亮的开始、结束位置 + int targetStart = 0; + int targetLens = 0; + lineNum = 1; + + int lineOffsetPosIndex = 0; + int lineOffsetPos = 0; + + QString lineNumStr = tr(" Line "); + int skipLineNumOffset = lineNumStr.toUtf8().size(); + + for (int i = 0, count = record->size(); i < count; ++i) + { + FindRecords* pr = record->at(i); + ++lineNum; + for (int j = 0; j < pr->records.size(); ++j) + { + lineOffsetPos = keyworkOffsetPos.at(lineOffsetPosIndex); + const FindRecord &v = pr->records.at(j); + targetStart = v.pos - v.lineStartPos + lineOffsetPos; + targetLens = v.end - v.pos; + pDisplay->setLineColorStyle(lineNum, skipLineNumOffset, lineOffsetPos-skipLineNumOffset-2, STYLE_COLOUR_KEYWORD_HIGH); + pDisplay->setLineColorStyle(lineNum, targetStart, targetLens, (StyleSet::isCurrentDeepStyle()? STYLE_DEEP_COLOUR_KEYWORD_HIGH:STYLE_COLOUR_KEYWORD_BACK_HIGH)); + ++lineNum; + ++lineOffsetPosIndex; + } + } + pDisplay->SendScintilla(SCI_GOTOLINE, 0); } + int FindResultWin::getDefaultFontSize() { return m_defaultFontSize; @@ -765,3 +485,21 @@ void FindResultWin::setDefaultFontSize(int defSize) { m_defaultFontSize = defSize; } + +void FindResultWin::on_lineDoubleClick(int lineNum) +{ + if (lineNum < m_resultLineInfo.size()) + { + const ResultLineInfo& lineInfo = m_resultLineInfo.at(lineNum); + + if (lineInfo.level == 2) + { + //文件定位到行 + emit lineDoubleClicked(lineInfo.pFilePath, lineInfo.resultPos, lineInfo.resultEnd); + } + else if ((lineInfo.level == 0) || (lineInfo.level == 1)) + { + ui.displayView->SendScintilla(SCI_FOLDLINE, lineNum, SC_FOLDACTION_TOGGLE); + } + } +} \ No newline at end of file diff --git a/src/findresultwin.h b/src/findresultwin.h index 408c101..e6f6150 100755 --- a/src/findresultwin.h +++ b/src/findresultwin.h @@ -6,57 +6,54 @@ #include "ui_findresultwin.h" class FindRecords; -class QStandardItem; -class NdStyledItemDelegate; -class QStandardItemModel; struct FindRecord; +struct ResultLineInfo { + int level;//Ëõ½øÀàÐ͡£0 1 2¡£0:title 1 filepath desc 2 result¡£ + int resultPos;//½á¹û×ֶεĿªʼoffset¡£0ºÍ1ÊÇûÓÐÕâ¸ö×ֶεġ£ + int resultEnd;//³¤¶È + QString* pFilePath; +}; + class FindResultWin : public QWidget { Q_OBJECT public: + friend class FindResultView; FindResultWin(QWidget *parent = Q_NULLPTR); ~FindResultWin(); - void appendResultsToShow(FindRecords * record); void appendResultsToShow(QVector* record, int hits, QString whatFind); int getDefaultFontSize(); void setDefaultFontSize(int defSize); + void clear(); signals: void itemDoubleClicked(const QModelIndex &index); void showMsg(QString &msg); + void lineDoubleClicked(QString* pFilePath, int pos, int end); private slots: - void slot_clearContents(); - void slot_selectAll(); - void slot_copyContents(); - void slot_copyItemContents(); - void slot_selectSection(); - void slot_treeView_pressed(QModelIndex modeIndex); - void slot_fontZoomIn(); - void slot_fontZoomOut(); + void on_lineDoubleClick(int line); public slots: void slot_clearAllContents(); -protected: - void contextMenuEvent(QContextMenuEvent * event); - private: +#if 0 void setItemBackground(QStandardItem* item, const QColor& color); void setItemForeground(QStandardItem * item, const QColor & color); void highlightFindText(int index, QString & srcText, QString & findText, Qt::CaseSensitivity cs); QString highlightFindText(FindRecord& record); +#endif private: Ui::FindResultWin ui; QMenu *m_menu; - QAction* m_pSelectSectonAct; - - QStandardItemModel* m_model; - NdStyledItemDelegate* m_delegate; - QWidget* m_parent; + + QList m_resultLineInfo; + QList m_resultLineFilePath; + int m_defaultFontSize; bool m_defFontSizeChange; }; diff --git a/src/findresultwin.ui b/src/findresultwin.ui index d7152e0..623eed8 100755 --- a/src/findresultwin.ui +++ b/src/findresultwin.ui @@ -39,31 +39,13 @@ 0 - - - - Microsoft YaHei - 10 - - + - QFrame::Panel + QFrame::StyledPanel - - 1 + + QFrame::Raised - - Qt::ScrollBarAsNeeded - - - QAbstractItemView::DoubleClicked - - - true - - - true - @@ -71,9 +53,10 @@ - MyTreeView - QTreeView -
mytreeview.h
+ FindResultView + QFrame +
findresultview.h
+ 1
diff --git a/src/findwin.cpp b/src/findwin.cpp index 14aad6c..c850bde 100755 --- a/src/findwin.cpp +++ b/src/findwin.cpp @@ -5,6 +5,7 @@ #include "doctypelistview.h" #include "filemanager.h" #include "ccnotepad.h" +#include "nddsetting.h" #include #include @@ -12,6 +13,7 @@ #include #include #include +#include #include enum TAB_TYPES { @@ -77,7 +79,7 @@ FindWin::~FindWin() { delete pEditTemp; pEditTemp = nullptr; -} + } } void FindWin::slot_tabIndexChange(int index) @@ -87,6 +89,7 @@ void FindWin::slot_tabIndexChange(int index) if (RELPACE_TYPE == type) { ui.replaceTextBox->setFocus(); + ui.replaceTextBox->lineEdit()->selectAll(); if (ui.replaceTextBox->currentText().isEmpty() && !ui.findComboBox->currentText().isEmpty()) { @@ -99,6 +102,7 @@ void FindWin::slot_tabIndexChange(int index) else if(FIND_TYPE == type) { ui.findComboBox->setFocus(); + ui.findComboBox->lineEdit()->selectAll(); if (ui.findComboBox->currentText().isEmpty() && !ui.replaceTextBox->currentText().isEmpty()) { @@ -111,10 +115,12 @@ void FindWin::slot_tabIndexChange(int index) else if (DIR_FIND_TYPE == type) { ui.dirFindWhat->setFocus(); + ui.dirFindWhat->lineEdit()->selectAll(); } else if (MARK_TYPE == type) { ui.markTextBox->setFocus(); + ui.markTextBox->lineEdit()->selectAll(); } m_isFindFirst = true; @@ -123,13 +129,20 @@ void FindWin::slot_tabIndexChange(int index) { return; } -} + } void FindWin::slot_dealFileTypeChange(int state) { if (state == Qt::Checked) { ui.fileType->setEnabled(true); + + if (ui.fileType->text().isEmpty()) + { + ui.fileType->setText(ui.fileType->placeholderText()); + } + ui.fileType->setFocus(); + ui.fileType->selectAll(); } else { @@ -142,6 +155,13 @@ void FindWin::slot_skipDirChange(int state) if (state == Qt::Checked) { ui.skipDirNames->setEnabled(true); + + if (ui.skipDirNames->text().isEmpty()) + { + ui.skipDirNames->setText(ui.skipDirNames->placeholderText()); + } + ui.skipDirNames->setFocus(); + ui.skipDirNames->selectAll(); } else { @@ -169,10 +189,12 @@ void FindWin::setCurrentTab(FindTabIndex index) if (FIND_TAB == index) { ui.findComboBox->setFocus(); + ui.findComboBox->lineEdit()->selectAll(); } else if(REPLACE_TAB == index) { ui.replaceTextBox->setFocus(); + ui.replaceTextBox->lineEdit()->selectAll(); } raise(); @@ -189,6 +211,32 @@ void FindWin::setFindText(QString &text) addFindHistory(text); } +void FindWin::keywordWinGetFouse(FindTabIndex tabIndex) +{ + switch (tabIndex) + { + case FIND_TAB: + this->setFocus(); + ui.findComboBox->setFocus(); + ui.findComboBox->lineEdit()->selectAll(); + break; + case REPLACE_TAB: + ui.replaceTextBox->setFocus(); + ui.replaceTextBox->lineEdit()->selectAll(); + break; + case DIR_FIND_TAB: + ui.dirFindWhat->setFocus(); + ui.dirFindWhat->lineEdit()->selectAll(); + break; + case MARK_TAB: + ui.markTextBox->setFocus(); + ui.markTextBox->lineEdit()->selectAll(); + break; + default: + break; + } +} + void FindWin::setReplaceFindText(QString& text) { ui.replaceTextBox->setEditText(text); @@ -201,6 +249,13 @@ void FindWin::setDirFindText(QString& text) addFindHistory(text); } +void FindWin::setMarkFindText(QString& text) +{ + ui.markTextBox->setEditText(text); + addFindHistory(text); +} + + void FindWin::disableReplace() { ui.tab_replace->setEnabled(false); @@ -223,6 +278,20 @@ void FindWin::setFindHistory(QList* findHistory) } } +void FindWin::setReplaceHistory(QList* replaceHistory) +{ + m_replaceHistory = replaceHistory; + + if ((m_replaceHistory != nullptr) && !m_replaceHistory->isEmpty()) + { + ui.replaceWithBox->addItems(*m_replaceHistory); + ui.replaceWithBox->clearEditText(); + ui.dirReplaceWhat->addItems(*m_replaceHistory); + ui.dirReplaceWhat->clearEditText(); + + } +} + //标记高亮所有word单词 int FindWin::markAllWord(QString & word) { @@ -258,7 +327,7 @@ void FindWin::removeLineHeadEndBlank(int mode) { ui.replaceTextBox->setCurrentText("[ ]+$"); } - ui.replaceWithBox->setText(""); + ui.replaceWithBox->setEditText(""); ui.replaceModeRegularBt->setChecked(true); @@ -412,9 +481,9 @@ void FindWin::updateParameterFromUI() m_isFindFirst = true; } - if (m_replaceWithText != ui.replaceWithBox->text()) + if (m_replaceWithText != ui.replaceWithBox->currentText()) { - m_replaceWithText = ui.replaceWithBox->text(); + m_replaceWithText = ui.replaceWithBox->currentText(); m_isFindFirst = true; } @@ -474,9 +543,9 @@ void FindWin::updateParameterFromUI() m_isFindFirst = true; } - if (m_replaceWithText != ui.dirReplaceWhat->text()) + if (m_replaceWithText != ui.dirReplaceWhat->currentText()) { - m_replaceWithText = ui.dirReplaceWhat->text(); + m_replaceWithText = ui.dirReplaceWhat->currentText(); m_isFindFirst = true; } @@ -575,8 +644,20 @@ void FindWin::updateParameterFromUI() if (ui.findinfilesTab->currentIndex() == 0) { m_forward = (m_isReverseFind ? !m_forward : m_forward); + } } + +#if 0 +//开始做了历史记录重复删除的,后面发现时序有问题,暂时不做 +void findItemAndRemove(QComboBox* pCombox, QString& text) +{ + int index = pCombox->findText(text); + if (index != -1) + { + pCombox->removeItem(index); + } } +#endif void FindWin::addFindHistory(QString &text) { @@ -585,19 +666,104 @@ void FindWin::addFindHistory(QString &text) { return; } - if ((m_findHistory != nullptr) && (-1 == m_findHistory->indexOf(text))) + + if (m_findHistory != nullptr) { - m_findHistory->push_front(text); + int index = m_findHistory->indexOf(text,0); + //已经是最上面一个了,直接返回 + if (0 == index) + { + return; + } + //没有直接添加到最前面。不做查找删除重复,一是慢,而是删除会引起信号逻辑时许有误 + if (-1 == index) + { + m_findHistory->push_front(text); + ui.findComboBox->insertItem(0, text); + ui.replaceTextBox->insertItem(0, text); + ui.dirFindWhat->insertItem(0, text); + ui.markTextBox->insertItem(0, text); + } + else + { + //有了怎么办,删除旧的,加新的 + m_findHistory->removeAt(index); + m_findHistory->push_front(text); + + //发现不能只删除旧的,有bug,一旦删除后,查找框乱了,被切换到下一个。 + ui.findComboBox->removeItem(index); + ui.replaceTextBox->removeItem(index); + ui.dirFindWhat->removeItem(index); + ui.markTextBox->removeItem(index); + + ui.findComboBox->insertItem(0, text); + ui.replaceTextBox->insertItem(0, text); + ui.dirFindWhat->insertItem(0, text); + ui.markTextBox->insertItem(0, text); + + //发现不能只删除旧的,有bug,一旦删除后,查找框乱了,被切换到下一个。 + //必须重新设置一下,否则查找框里面字段乱跳到下一个去了 + ui.findComboBox->setCurrentIndex(0); + ui.replaceTextBox->setCurrentIndex(0); + ui.dirFindWhat->setCurrentIndex(0); + ui.markTextBox->setCurrentIndex(0); + } + + if (m_findHistory->size() >= 15) { m_findHistory->takeLast(); } + } +} - ui.findComboBox->insertItem(0, text); - ui.replaceTextBox->insertItem(0, text); - ui.dirFindWhat->insertItem(0,text); - ui.markTextBox->insertItem(0, text); +void FindWin::addReplaceHistory(QString& text) +{ + //太长会导致看起来很杂乱,也不记录 + if (text.isEmpty() || text.size() >= MAX_RECORD_KEY_LENGTH) + { + return; + } + + if (m_replaceHistory != nullptr) + { + int index = m_replaceHistory->indexOf(text, 0); + //已经是最上面一个了,直接返回 + if (0 == index) + { + return; + } + //没有直接添加到最前面。不做查找删除重复,一是慢,而是删除会引起信号逻辑时序有误 + if (-1 == index) + { + m_replaceHistory->push_front(text); + ui.replaceWithBox->insertItem(0, text); + ui.dirReplaceWhat->insertItem(0, text); + } + else + { + //有了怎么办,删除旧的,加新的 + m_replaceHistory->removeAt(index); + m_replaceHistory->push_front(text); + + //发现不能只删除旧的,有bug,一旦删除后,查找框乱了,被切换到下一个。 + ui.replaceWithBox->removeItem(index); + ui.dirReplaceWhat->removeItem(index); + ui.replaceWithBox->insertItem(0, text); + ui.dirReplaceWhat->insertItem(0, text); + //发现不能只删除旧的,有bug,一旦删除后,查找框乱了,被切换到下一个。 + //必须重新设置一下,否则查找框里面字段乱跳到下一个去了 + ui.replaceWithBox->setCurrentIndex(0); + ui.dirReplaceWhat->setCurrentIndex(0); + } + + + + if (m_replaceHistory->size() >= 15) + { + m_replaceHistory->takeLast(); + } } } @@ -774,7 +940,7 @@ void FindWin::removeEmptyLine(bool isBlankContained) { ui.replaceTextBox->setCurrentText("^$(\\r\\n|\\r|\\n)"); } - ui.replaceWithBox->setText(""); + ui.replaceWithBox->setEditText(""); ui.replaceModeRegularBt->setChecked(true); @@ -867,8 +1033,6 @@ void FindWin::dofindNext() updateParameterFromUI(); QWidget* pw = autoAdjustCurrentEditWin(); - - QsciScintilla* pEdit = dynamic_cast(pw); //第一次查找 @@ -993,7 +1157,7 @@ void FindWin::slot_findCount() //这里的forward一定要是true。回环一定是false if (!pEdit->findFirst(whatFind, m_re, m_cs, m_wo, false, true, FINDNEXTTYPE_FINDNEXT, 0, 0,false)) { - ui.statusbar->showMessage(tr("count %1 times with \'%2\'").arg(countNums).arg(m_expr), 8000); + ui.statusbar->showMessage(tr("count %1 times with \'%2\'").arg(countNums).arg(m_expr)); QApplication::beep(); m_isFindFirst = true; @@ -1017,11 +1181,11 @@ void FindWin::slot_findCount() pEdit->execute(SCI_GOTOPOS, srcPostion); pEdit->execute(SCI_SETFIRSTVISIBLELINE, firstDisLineNum); - pEdit->execute(SCI_SETXOFFSET, 0); + //pEdit->execute(SCI_SETXOFFSET, 0); //全部替换后,下次查找,必须算第一次查找 m_isFindFirst = true; - ui.statusbar->showMessage(tr("count %1 times with \'%2\'").arg(countNums).arg(m_expr), 8000); + ui.statusbar->showMessage(tr("count %1 times with \'%2\'").arg(countNums).arg(m_expr)); } else { @@ -1048,10 +1212,11 @@ static QString trimmedEnd(QString lineText) return lineText; } -void FindWin::addCurFindRecord(ScintillaEditView* pEdit, FindRecords& recordRet,bool isMark) +//getResult:是否提取结果目标字符串。在正则查找时,还是有用的 +QString FindWin::addCurFindRecord(ScintillaEditView* pEdit, FindRecords& recordRet,bool isMark, bool getResult) { FindRecord aRecord; - + QString ret; //看了源码,当前查找到的结果,是会被选中的。所以可通过选中范围,来记录当前被查找中的结果 //光标在选择词的尾部下一个位置 #if 0 @@ -1062,58 +1227,63 @@ void FindWin::addCurFindRecord(ScintillaEditView* pEdit, FindRecords& recordRet, FindState& state = pEdit->getLastFindState(); aRecord.pos = state.targstart; aRecord.end = state.targend; + aRecord.lineNum = state.linenum; //mark模式不需要这么多信息,可直接返回 if (!isMark) { - aRecord.lineNum = pEdit->execute(SCI_LINEFROMPOSITION, aRecord.pos); - aRecord.lineStartPos = pEdit->execute(SCI_POSITIONFROMLINE, aRecord.lineNum); - int lineLens = pEdit->execute(SCI_LINELENGTH, aRecord.lineNum); + //静默查找,在后台批量查找时,不会返回这个state.linenum。需要手动获取一下 + if (aRecord.lineNum == -1) + { + aRecord.lineNum = pEdit->execute(SCI_LINEFROMPOSITION, aRecord.pos); + } + aRecord.lineStartPos = pEdit->execute(SCI_POSITIONFROMLINE, aRecord.lineNum); + int lineLens = pEdit->execute(SCI_LINELENGTH, aRecord.lineNum); - if (lineLens <= 0) - { - return; - } + if (lineLens <= 0) + { + return ret; + } - char* lineText = new char[lineLens + 1]; - memset(lineText, 0, lineLens + 1); + char* lineText = new char[lineLens + 1]; + memset(lineText, 0, lineLens + 1); - //这里有个bug,是qscint的,查找最后一行,会漏掉最后一个字符 - pEdit->execute(SCI_GETLINE, aRecord.lineNum, reinterpret_cast(lineText)); + //这里有个bug,是qscint的,查找最后一行,会漏掉最后一个字符 + pEdit->execute(SCI_GETLINE, aRecord.lineNum, reinterpret_cast(lineText)); - //务必要去掉行位的换行,否则显示结果列表会显示换行 - aRecord.lineContents = trimmedEnd(QString(lineText)); + //务必要去掉行位的换行,否则显示结果列表会显示换行 + aRecord.lineContents = trimmedEnd(QString(lineText)); + delete[]lineText; - delete[]lineText; + //如果需要结果,再把结果提取一下 + if (getResult && (state.targend - state.targstart > 0)) + { + Sci_TextRange lineText; + lineText.chrg.cpMin = static_cast(state.targstart); + lineText.chrg.cpMax = static_cast(state.targend); + + QByteArray result; + result.resize(state.targend - state.targstart); + lineText.lpstrText = result.data(); + //获取原始行的内容 + pEdit->SendScintilla(SCI_GETTEXTRANGE, 0, &lineText); + + ret = QString(result); + } } recordRet.records.append(aRecord); + + return ret; } -//在后台查找 -int FindWin::findAtBack(QString keyword) +//在后台批量查找 +int FindWin::findAtBack(QStringList& keyword) { - this->setCurrentTab(FIND_TAB); - ui.findComboBox->setCurrentText(keyword); - ui.findBackwardBox->setChecked(false); - ui.findMatchCaseBox->setChecked(true); - ui.findWrapBox->setChecked(false); - ui.findMatchWholeBox->setChecked(false); - ui.findModeNormalBt->setChecked(true); - - m_isStatic = true; - int times = findAllInCurDoc(); - m_isStatic = false; - - return times; -} - -//在后台替换 -int FindWin::replaceAtBack(QStringList& keyword, QStringList& replace) -{ - assert(keyword.size() == replace.size()); - - this->setCurrentTab(REPLACE_TAB); + if (keyword.isEmpty()) + { + return 0; + } QWidget* pw = autoAdjustCurrentEditWin(); ScintillaEditView* pEdit = dynamic_cast(pw); @@ -1127,49 +1297,148 @@ int FindWin::replaceAtBack(QStringList& keyword, QStringList& replace) } } - ui.replaceBackwardBox->setChecked(false); - ui.replaceMatchWholeBox->setChecked(false); - ui.replaceMatchCaseBox->setChecked(true); - ui.replaceWrapBox->setChecked(false); - ui.replaceModeNormalBox->setChecked(true); + m_isStatic = true; + int times = 0; + + ProgressWin* loadFileProcessWin = nullptr; + + if (keyword.size() > 1000) + { + loadFileProcessWin = new ProgressWin(this); + + loadFileProcessWin->setWindowModality(Qt::WindowModal); + + loadFileProcessWin->info(tr("total %1 keyword, please wait ...").arg(keyword.size())); + + loadFileProcessWin->setTotalSteps(keyword.size() / 100); + + loadFileProcessWin->show(); + } + + QString text = pEdit->text(); + + QByteArray bytes = text.toUtf8(); + + QByteArray findBytes; + int keyLens = 0; + + int index = 0; + + for (int i = 0; i < keyword.size(); ++i) + { + if ((loadFileProcessWin != nullptr) && loadFileProcessWin->isCancel()) + { + break; + } + index = 0; + + //20230223 不走老的逻辑了,批量替换太慢。直接把文件读取处理,在内存中一次性处理完毕。 + //但是这样就不知道到底有多少字符串被替换了 + findBytes = keyword.at(i).toUtf8(); + keyLens = findBytes.size(); + + while (true) + { + index = bytes.indexOf(findBytes,index); + + if (index == -1) + { + break; + } + ++times; + index += keyLens; + } + + if ((loadFileProcessWin != nullptr)&& ((i % 100) == 0)) + { + loadFileProcessWin->moveStep(); + QCoreApplication::processEvents(); + } + } + + if (loadFileProcessWin != nullptr) + { + delete loadFileProcessWin; + } + + return times; +} + +//在后台批量替换 +int FindWin::replaceAtBack(QStringList& keyword, QStringList& replace) +{ + assert(keyword.size() == replace.size()); + + //this->setCurrentTab(REPLACE_TAB); + if (keyword.isEmpty()) + { + return 0; + } + + QWidget* pw = autoAdjustCurrentEditWin(); + ScintillaEditView* pEdit = dynamic_cast(pw); + if (pEdit != nullptr) + { + if (pEdit->isReadOnly()) + { + ui.statusbar->showMessage(tr("The ReadOnly document does not allow replacement."), 8000); + QApplication::beep(); + return 0; + } + } m_isStatic = true; int times = 0; pEdit->execute(SCI_BEGINUNDOACTION); - ProgressWin* loadFileProcessWin = new ProgressWin(this); + ProgressWin* loadFileProcessWin = nullptr; - loadFileProcessWin->setWindowModality(Qt::WindowModal); + if (keyword.size() > 1000) + { + loadFileProcessWin = new ProgressWin(this); - loadFileProcessWin->info(tr("total %1 keyword, please wait ...").arg(keyword.size())); + loadFileProcessWin->setWindowModality(Qt::WindowModal); - loadFileProcessWin->setTotalSteps(keyword.size()); + loadFileProcessWin->info(tr("total %1 keyword, please wait ...").arg(keyword.size())); - loadFileProcessWin->show(); + loadFileProcessWin->setTotalSteps(keyword.size() / 10); + + loadFileProcessWin->show(); + } + + QString text = pEdit->text(); for (int i = 0; i < keyword.size(); ++i) { - if (loadFileProcessWin->isCancel()) + if ((loadFileProcessWin!=nullptr) && loadFileProcessWin->isCancel()) { break; } + //20230223 不走老的逻辑了,批量替换太慢。直接把文件读取处理,在内存中一次性处理完毕。 + //但是这样就不知道到底有多少字符串被替换了 + text.replace(keyword.at(i), replace.at(i)); - ui.replaceTextBox->setCurrentText(keyword.at(i)); - ui.replaceWithBox->setText(replace.at(i)); + if ((loadFileProcessWin != nullptr) && ((i % 10) == 0)) + { + loadFileProcessWin->moveStep(); + QCoreApplication::processEvents(); + } + } + //替换外部后,一次性整体替换 - updateParameterFromUI(); + int selectionEnd = pEdit->length(); - QString whatFind = ui.replaceTextBox->currentText(); - QString replaceText = ui.replaceWithBox->text(); + pEdit->execute(SCI_SETTARGETRANGE, 0, selectionEnd); - times += doReplaceAll(pEdit, whatFind, replaceText, false); + QByteArray bytes = text.toUtf8(); - loadFileProcessWin->moveStep(); + pEdit->execute(SCI_REPLACETARGET, bytes.size(), reinterpret_cast(bytes.data())); - QCoreApplication::processEvents(); + if (loadFileProcessWin != nullptr) + { + delete loadFileProcessWin; } - delete loadFileProcessWin; pEdit->execute(SCI_ENDUNDOACTION); @@ -1178,7 +1447,121 @@ int FindWin::replaceAtBack(QStringList& keyword, QStringList& replace) return times; } -int FindWin::findAllInCurDoc() +//在后台批量高亮 +int FindWin::markAtBack(QStringList& keyword) +{ + if (keyword.isEmpty()) + { + return 0; + } + + QWidget* pw = autoAdjustCurrentEditWin(); + ScintillaEditView* pEdit = dynamic_cast(pw); + if (pEdit != nullptr) + { + if (pEdit->isReadOnly()) + { + ui.statusbar->showMessage(tr("The ReadOnly document does not allow replacement."), 8000); + QApplication::beep(); + return 0; + } + } + + m_isStatic = true; + int times = 0; + + ProgressWin* loadFileProcessWin = nullptr; + + if (keyword.size() > 1000) + { + loadFileProcessWin = new ProgressWin(this); + + loadFileProcessWin->setWindowModality(Qt::WindowModal); + + loadFileProcessWin->info(tr("total %1 keyword, please wait ...").arg(keyword.size())); + + loadFileProcessWin->setTotalSteps(keyword.size() / 100); + + loadFileProcessWin->show(); + } + + QString text = pEdit->text(); + + QByteArray bytes = text.toUtf8(); + + QByteArray findBytes; + int keyLens = 0; + + int index = 0; + + QMap* > keyPos; + + for (int i = 0; i < keyword.size(); ++i) + { + if ((loadFileProcessWin != nullptr) && loadFileProcessWin->isCancel()) + { + break; + } + index = 0; + + //20230223 不走老的逻辑了,批量替换太慢。直接把文件读取处理,在内存中一次性处理完毕。 + //但是这样就不知道到底有多少字符串被替换了 + findBytes = keyword.at(i).toUtf8(); + keyLens = findBytes.size(); + + if (keyLens == 0) + { + continue; + } + + QVector* vec = new QVector(); + vec->reserve(128); + keyPos.insert(findBytes, vec); + + while (true) + { + index = bytes.indexOf(findBytes, index); + + if (index == -1) + { + break; + } + ++times; + vec->append(index); + + index += keyLens; + } + + if ((loadFileProcessWin != nullptr) && ((i % 100) == 0)) + { + loadFileProcessWin->moveStep(); + QCoreApplication::processEvents(); + } + } + + //把结果高亮起来。 + for (QMap* >::iterator it = keyPos.begin(); it != keyPos.end(); ++it) + { + int foundTextLen = it.key().size(); + QVector* pVect = (*it); + for (int i = 0, s = pVect->size(); i < s; ++i) + { + pEdit->execute(SCI_SETINDICATORCURRENT, CCNotePad::s_curMarkColorId); + pEdit->execute(SCI_INDICATORFILLRANGE, pVect->at(i), foundTextLen); + + } + delete pVect; + } + + if (loadFileProcessWin != nullptr) + { + delete loadFileProcessWin; + } + + return times; +} + +int FindWin::findAllInCurDoc(QStringList* reResult) { if (ui.findComboBox->currentText().isEmpty()) { @@ -1201,6 +1584,8 @@ int FindWin::findAllInCurDoc() return 0; } + QString resultDestStr; + int askAbortTimes = 0; FindRecords results; results.pEdit = pEdit; @@ -1208,10 +1593,13 @@ int FindWin::findAllInCurDoc() updateParameterFromUI(); + //正则模式下面,拷贝所有结果到剪切板 + bool isNeedResult(m_re && (reResult != nullptr)); + int srcPostion = pEdit->execute(SCI_GETCURRENTPOS); int firstDisLineNum = pEdit->execute(SCI_GETFIRSTVISIBLELINE); - int replaceNums = 0; + int findNums = 0; //无条件进行第一次查找,从0行0列开始查找,而且不回环。如果没有找到,则替换完毕 QString whatFind = ui.findComboBox->currentText(); @@ -1245,30 +1633,63 @@ int FindWin::findAllInCurDoc() dealWithZeroFound(pEdit); } - addCurFindRecord(pEdit, results); + resultDestStr = addCurFindRecord(pEdit, results, false, isNeedResult); - ++replaceNums; + //正则模式下面,拷贝所有结果到剪切板 + if (isNeedResult) + { + reResult->append(resultDestStr); + } + + ++findNums; //找到了,把结果收集起来 while (pEdit->findNext()) { - addCurFindRecord(pEdit, results); - ++replaceNums; + resultDestStr = addCurFindRecord(pEdit, results, false, isNeedResult); + ++findNums; + + //正则模式下面,拷贝所有结果到剪切板 + if (isNeedResult) + { + reResult->append(resultDestStr); + } dealWithZeroFound(pEdit); + + //2000 和 4000时各询问一次,避免查询结果过大 + if (((askAbortTimes == 0) && findNums > 2000) || ((askAbortTimes == 1) && findNums > 4000)) + { + int ret = QMessageBox::question(this, tr("Continue Find ?"), tr("The search results have been greater than %1 times in %2 files, and more may be slow. Continue to search?").arg(findNums).arg(1), tr("Yes"), tr("Abort")); + if (ret == 1) + { + break; + } + ++askAbortTimes; + } } pEdit->execute(SCI_GOTOPOS, srcPostion); pEdit->execute(SCI_SETFIRSTVISIBLELINE, firstDisLineNum); - pEdit->execute(SCI_SETXOFFSET, 0); + //pEdit->execute(SCI_SETXOFFSET, 0); //全部替换后,下次查找,必须算第一次查找 m_isFindFirst = true; - ui.statusbar->showMessage(tr("find finished, total %1 found!").arg(replaceNums), 10000); + + if (!isNeedResult) + { + ui.statusbar->showMessage(tr("find finished, total %1 found!").arg(findNums), 10000); + } + else + { + ui.statusbar->showMessage(tr("find finished, total %1 found! Result in clipboard.").arg(findNums), 10000); + } emit sign_findAllInCurDoc(&results); - return replaceNums; + + + return findNums; } else { @@ -1283,11 +1704,110 @@ int FindWin::findAllInCurDoc() void FindWin::slot_findAllInCurDoc() { - findAllInCurDoc(); + //findAllInCurDoc(); + + int index = m_editTabWidget->currentIndex(); + + if (index >= 0) + { + findAllInOpenDoc(index); + } +} + +void FindWin::findAllInOpenDoc(int index) +{ + if (ui.findComboBox->currentText().isEmpty()) + { + ui.statusbar->showMessage(tr("what find is null !"), 8000); + QApplication::beep(); + return; + } + + QString whatFind = ui.findComboBox->currentText(); + QString originWhatFine = whatFind; + + if (m_extend) + { + QString extendFind; + convertExtendedToString(whatFind, extendFind); + whatFind = extendFind; + } + + int replaceNums = 0; + QVector* allOpenFileRecord = new QVector(); + + for (int i = 0; i < m_editTabWidget->count(); ++i) + { + //是否只查找一个文档 + if ((index != -1) && (i != index)) + { + continue; + } + QWidget* pw = m_editTabWidget->widget(i); + ScintillaEditView* pEdit = dynamic_cast(pw); + if (pEdit != nullptr) + { + if (pEdit->isReadOnly()) + { + continue; + } + + FindRecords* results = new FindRecords(); + results->pEdit = pEdit; + + results->findFilePath = pw->property("filePath").toString(); + + updateParameterFromUI(); + + //无条件进行第一次查找,从0行0列开始查找,而且不回环。如果没有找到,则替换完毕 + //results->findText要是有原来的值,因为扩展模式下\r\n不会转义,直接输出会换行显示 + results->findText = originWhatFine; + if (!pEdit->findFirst(whatFind, m_re, m_cs, m_wo, false, true, FINDNEXTTYPE_FINDNEXT, 0, 0)) + { + delete results; + continue; + } + else + { + dealWithZeroFound(pEdit); + } + addCurFindRecord(pEdit, *results); + + ++replaceNums; + + //找到了,把结果收集起来 + while (pEdit->findNext()) + { + addCurFindRecord(pEdit, *results); + ++replaceNums; + dealWithZeroFound(pEdit); + } + + allOpenFileRecord->append(results); + } + } + + //全部替换后,下次查找,必须算第一次查找 + m_isFindFirst = true; + ui.statusbar->showMessage(tr("find finished, total %1 found!").arg(replaceNums), 10000); + + emit sign_findAllInOpenDoc(allOpenFileRecord, replaceNums, whatFind); + + //释放元素 + for (int i = 0; i < allOpenFileRecord->size(); ++i) + { + delete allOpenFileRecord->at(i); + } + + delete allOpenFileRecord; + } void FindWin::slot_findAllInOpenDoc() { + findAllInOpenDoc(-1); + +#if 0 if (ui.findComboBox->currentText().isEmpty()) { ui.statusbar->showMessage(tr("what find is null !"), 8000); @@ -1367,7 +1887,7 @@ void FindWin::slot_findAllInOpenDoc() } delete allOpenFileRecord; - +#endif } //返回是否查找得到内容 @@ -1385,6 +1905,9 @@ bool FindWin::replaceFindNext(QsciScintilla* pEdit, bool showZeroFindTip) addFindHistory(whatFind); + QString replaceWith = ui.replaceWithBox->currentText(); + addReplaceHistory(replaceWith); + if (m_extend) { QString extendFind; @@ -1461,7 +1984,7 @@ bool FindWin::replace(ScintillaEditView* pEdit) } QString findText = ui.replaceTextBox->currentText(); - QString replaceText = ui.replaceWithBox->text(); + QString replaceText = ui.replaceWithBox->currentText(); if (m_extend) { @@ -1724,7 +2247,7 @@ int FindWin::doReplaceAll(ScintillaEditView* pEdit, QString &whatFind, QString& if (isCombineUndo) { - pEdit->execute(SCI_BEGINUNDOACTION); + pEdit->execute(SCI_BEGINUNDOACTION); } int flags = buildSearchFlags(m_re, m_cs, m_wo, false, true, FINDNEXTTYPE_REPLACENEXT, 0, 0); @@ -1788,14 +2311,12 @@ int FindWin::doReplaceAll(ScintillaEditView* pEdit, QString &whatFind, QString& if (isCombineUndo) { - pEdit->execute(SCI_ENDUNDOACTION); + pEdit->execute(SCI_ENDUNDOACTION); } pEdit->execute(SCI_GOTOPOS, srcPostion); pEdit->execute(SCI_SETFIRSTVISIBLELINE, firstDisLineNum); - pEdit->execute(SCI_SETXOFFSET, 0); - - + //pEdit->execute(SCI_SETXOFFSET, 0); return replaceNums; } @@ -1827,7 +2348,7 @@ int FindWin::replaceAll() updateParameterFromUI(); QString whatFind = ui.replaceTextBox->currentText(); - QString replaceText = ui.replaceWithBox->text(); + QString replaceText = ui.replaceWithBox->currentText(); if (m_extend) { @@ -1931,7 +2452,7 @@ void FindWin::slot_replaceAllInOpenDoc() ui.statusbar->showMessage(tr("Replace in Opened Files: %1 occurrences were replaced.").arg(replaceNums), 10000); } -int FindWin::markAll() +int FindWin::markAll(QSet* outLineNum) { if (ui.markTextBox->currentText().isEmpty()) { @@ -2008,6 +2529,11 @@ int FindWin::markAll() pEdit->execute(SCI_SETINDICATORCURRENT, CCNotePad::s_curMarkColorId); pEdit->execute(SCI_INDICATORFILLRANGE, rs.pos, foundTextLen); } + + if (outLineNum != nullptr) + { + outLineNum->insert(rs.lineNum); + } } if (!results->records.isEmpty()) @@ -2015,15 +2541,15 @@ int FindWin::markAll() pEdit->appendMarkRecord(results); } - - pEdit->execute(SCI_SETFIRSTVISIBLELINE, firstDisLineNum); pEdit->execute(SCI_GOTOPOS, srcPostion); - pEdit->execute(SCI_SETXOFFSET, 0); + pEdit->execute(SCI_SETFIRSTVISIBLELINE, firstDisLineNum); + //pEdit->execute(SCI_SETXOFFSET, 0); //全部替换后,下次查找,必须算第一次查找 m_isFindFirst = true; ui.statusbar->showMessage(tr("mark finished, total %1 found!").arg(replaceNums), 10000); + return replaceNums; } else @@ -2072,6 +2598,10 @@ void FindWin::slot_dirSelectDest() QString curDirPath = ui.destFindDir->text(); if (curDirPath.isEmpty()) { + if (CCNotePad::s_lastOpenDirPath.isEmpty()) + { + CCNotePad::s_lastOpenDirPath = NddSetting::getKeyValueFromDelaySets(LAST_OPEN_DIR); + } curDirPath = CCNotePad::s_lastOpenDirPath; } @@ -2158,31 +2688,15 @@ bool FindWin::replaceTextInFile(QString &filePath, int &replaceNums, QVectorfindFirst(find, m_re, m_cs, m_wo, false, m_forward, FINDNEXTTYPE_REPLACENEXT,0, 0,false)) + if (modifyTimes > 0) { - return false; + replaceNums += modifyTimes; + //如果进行过替换,则必须要保存一下;否则不能保存,不然文件被修改。 + emit sign_replaceSaveFile(filePath, pEditTemp); } - pEditTemp->replace(replace); - dealWithZeroFound(pEditTemp); - - ++replaceNums; - - //找到了,则自动进行全部替换 - while (pEditTemp->findNext()) - { - pEditTemp->replace(replace); - ++replaceNums; - dealWithZeroFound(pEditTemp); - } -#endif - - //必须要保存一下 - emit sign_replaceSaveFile(filePath, pEditTemp); - return true; } @@ -2365,7 +2879,7 @@ int FindWin::walkDirfile(QString path, int &foundTimes, bool isSkipBinary, bool { loadFileProcessWin->setCancel(); break; - } + } else { if (canAbort && (hitFileNums > 100 || foundTimes > 1000)) @@ -2494,7 +3008,7 @@ void FindWin::slot_dirFindAll() if (pEditTemp == nullptr) { - pEditTemp = new ScintillaEditView(nullptr); + pEditTemp = ScintillaEditView::createEditForSearch(); } int foundNums = 0; @@ -2506,7 +3020,7 @@ void FindWin::slot_dirFindAll() //全部替换后,下次查找,必须算第一次查找 m_isFindFirst = true; - ui.statusbar->showMessage(tr("find finished, total %1 found in %2 file!").arg(foundNums).arg(filesNum), 10000); + ui.statusbar->showMessage(tr("find finished, walk %1 files, total %2 found in %3 file!").arg(filesNum).arg(foundNums).arg(allfileInDirRecord->size())); //复用了这个信号函数,没有新做消息,要注意 emit sign_findAllInOpenDoc(allfileInDirRecord, foundNums, whatFind); @@ -2528,7 +3042,7 @@ void FindWin::slot_dirReplaceAll() { QString dirPath = ui.destFindDir->text(); QString whatFind = ui.dirFindWhat->currentText(); - QString dirReplaceWhat = ui.dirReplaceWhat->text(); + QString dirReplaceWhat = ui.dirReplaceWhat->currentText(); if (dirPath.isEmpty()) { @@ -2610,12 +3124,15 @@ void FindWin::slot_dirReplaceAll() int skipMaxSize = (ui.skipFileMaxSize->isChecked()) ? ui.maxFileSizeSpinBox->value() * 1024 * 1024 : 0; bool isSkipChildDir = ui.skipChildDirs->isChecked(); + addReplaceHistory(dirReplaceWhat); + updateParameterFromUI(); if (pEditTemp == nullptr) { - pEditTemp = new ScintillaEditView(nullptr); + pEditTemp = ScintillaEditView::createEditForSearch(); } + int replaceNums = 0; std::function* allfileInDirRecord)> foundCallBack = std::bind(&FindWin::replaceTextInFile, this, std::placeholders::_1, std::placeholders::_2, nullptr); @@ -2624,6 +3141,40 @@ void FindWin::slot_dirReplaceAll() //全部替换后,下次查找,必须算第一次查找 m_isFindFirst = true; - ui.statusbar->showMessage(tr("replace finished, total %1 replace in %2 file!").arg(replaceNums).arg(filesNum), 10000); + ui.statusbar->showMessage(tr("replace finished, walk %1 files, total %2 replace !").arg(filesNum).arg(replaceNums)); } + +//把正则查找的结果,拷贝到剪切板 +void FindWin::on_copyReFindResult() +{ + if (!ui.findModeRegularBt->isChecked()) + { + ui.statusbar->showMessage(tr("Only regular lookup mode can be used!"),10000); + return; + } + QStringList reResult; + + findAllInCurDoc(&reResult); + + if (!reResult.isEmpty()) + { + QClipboard* clipboard = QApplication::clipboard(); + clipboard->setText(reResult.join("\n")); + } +} + +void FindWin::on_markAndBook() +{ + QSet outLineNum; + markAll(&outLineNum); + + QWidget* pw = autoAdjustCurrentEditWin(); + ScintillaEditView* pEdit = dynamic_cast(pw); + + if (pEdit != nullptr) + { + pEdit->bookmarkAdd(outLineNum); + } + +} \ No newline at end of file diff --git a/src/findwin.h b/src/findwin.h index 6eebf1f..b29473a 100755 --- a/src/findwin.h +++ b/src/findwin.h @@ -63,10 +63,13 @@ public: void setCurrentTab(FindTabIndex index); void setTabWidget(QTabWidget * editTabWidget); void setFindText(QString & text); + void keywordWinGetFouse(FindTabIndex tabIndex); void setReplaceFindText(QString& text); void setDirFindText(QString& text); + void setMarkFindText(QString& text); void disableReplace(); void setFindHistory(QList* findHistory); + void setReplaceHistory(QList* replaceHistory); int markAllWord(QString& word); void removeLineHeadEndBlank(int mode); static void showCallTip(QsciScintilla * pEdit, int pos); @@ -74,11 +77,10 @@ public: void findNext(); void findPrev(); void setFindBackward(bool isBackward); - int findAtBack(QString keyword); + + int findAtBack(QStringList& keyword); + int markAtBack(QStringList& keyword); int replaceAtBack(QStringList& keyword, QStringList& replace); - - - protected: virtual void focusInEvent(QFocusEvent *ev); @@ -96,8 +98,10 @@ signals: private: void updateParameterFromUI(); void addFindHistory(QString & text); + void addReplaceHistory(QString& text); bool isFirstFind(); - void addCurFindRecord(ScintillaEditView * pEdit, FindRecords & recordRet, bool isMark=false); + + QString addCurFindRecord(ScintillaEditView * pEdit, FindRecords & recordRet, bool isMark=false, bool getResult=false); bool findTextInFile(QString & filePath, int & findNums, QVector* allfileInDirRecord); @@ -123,9 +127,11 @@ private: int replaceAll(); - int markAll(); + int markAll(QSet* outLineNum=nullptr); - int findAllInCurDoc(); + int findAllInCurDoc(QStringList * reResult=nullptr); + + void findAllInOpenDoc(int index = -1); private slots: @@ -169,6 +175,10 @@ private slots: void slot_tabIndexChange(int index); + void on_copyReFindResult(); + + void on_markAndBook(); + private: Ui::FindWin ui; @@ -212,6 +222,8 @@ private: QList* m_findHistory; + QList* m_replaceHistory; + ScintillaEditView* pEditTemp; QWidget* m_curEditWin; diff --git a/src/findwin.ui b/src/findwin.ui index 28b310f..485a7fa 100755 --- a/src/findwin.ui +++ b/src/findwin.ui @@ -286,6 +286,13 @@ + + + + Copy Regular Result + + + @@ -396,13 +403,7 @@ - - - - 0 - 0 - - + 300 @@ -415,6 +416,12 @@ 16777215 + + true + + + 512 + @@ -752,48 +759,7 @@ - - - - false - - - - 0 - 0 - - - - - 300 - 0 - - - - - 350 - 16777215 - - - - *.c:*.cpp:*.h - - - - - - - 0 - 0 - - - - File Type : - - - - @@ -806,20 +772,7 @@ - - - - - 0 - 0 - - - - Skip Dir Name : - - - - + false @@ -847,8 +800,24 @@ - - + + + + + 0 + 0 + + + + Skip Dir Name : + + + + + + + false + 0 @@ -867,6 +836,35 @@ 16777215 + + *.c:*.cpp:*.h + + + + + + + + 0 + 0 + + + + File Type : + + + + + + + + 300 + 0 + + + + true + @@ -1305,6 +1303,25 @@ + + + + + 0 + 0 + + + + + 200 + 28 + + + + Mark & Bookmark + + + @@ -1403,7 +1420,6 @@ findModeExtendBt findModeRegularBt replaceTextBox - replaceWithBox replaceFindNextBox replaceBt replaceAllBt @@ -1418,7 +1434,6 @@ replaceModeRegularBt destFindDir dirFindWhat - dirReplaceWhat selectDir dirFindAll dirReplaceAll @@ -1476,8 +1491,8 @@ close() - 572 - 251 + 672 + 291 169 @@ -1524,8 +1539,8 @@ slot_replaceFindNext() - 94 - 60 + 458 + 61 588 @@ -1540,8 +1555,8 @@ close() - 94 - 45 + 458 + 198 588 @@ -1556,8 +1571,8 @@ slot_replace() - 94 - 64 + 458 + 95 588 @@ -1572,8 +1587,8 @@ slot_replaceAll() - 94 - 67 + 458 + 129 588 @@ -1588,8 +1603,8 @@ slot_replaceAllInOpenDoc() - 94 - 76 + 458 + 169 588 @@ -1620,8 +1635,8 @@ slot_clearMark() - 489 - 84 + 672 + 129 588 @@ -1636,8 +1651,8 @@ close() - 572 - 162 + 672 + 197 404 @@ -1748,8 +1763,8 @@ slot_clearAllMark() - 538 - 112 + 672 + 163 574 @@ -1757,6 +1772,38 @@ + + copyReResultBt + clicked() + FindWin + on_copyReFindResult() + + + 534 + 222 + + + 344 + 191 + + + + + pushButton + clicked() + FindWin + on_markAndBook() + + + 565 + 77 + + + 434 + 386 + + + slot_findNext() @@ -1775,5 +1822,7 @@ sign_clearResult() slot_findPrev() slot_clearAllMark() + on_copyReFindResult() + on_markAndBook() diff --git a/src/installer/newinstall_dync.iss b/src/installer/newinstall_dync.iss index 0d5bcf4..4f2f608 100755 --- a/src/installer/newinstall_dync.iss +++ b/src/installer/newinstall_dync.iss @@ -2,7 +2,8 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "Notepad--" -#define MyAppVersion "1.22.0" +#define MyAppVersion "1.23.2" +#define MyAppDesc MyAppName + MyAppVersion + "(NddÖ÷³ÌÐò)" #define MyAppPublisher "ndd¿ªԴ×é֯" #define MyAppURL "https://gitee.com/cxasm/notepad--" #define MyAppExeName "Notepad--.exe" @@ -10,6 +11,20 @@ #define MyAppAssocExt ".txt" #define MyAppAssocKey StringChange(MyAppAssocName, " ", "") + MyAppAssocExt +#define MyAppAssocExt1 ".ini" +#define MyAppAssocExt2 ".log" +#define MyAppAssocExt3 ".sh" +#define MyAppAssocExt4 ".h" +#define MyAppAssocExt5 ".c" +#define MyAppAssocExt6 ".cpp" +#define MyAppAssocExt7 ".py" +#define MyAppAssocExt8 ".xml" +#define MyAppAssocExt9 ".def" +#define MyAppAssocExt10 ".json" +#define MyAppAssocExt11 ".pro" +#define MyAppAssocExt12 ".csv" + + [Setup] ; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications. ; (To generate a new GUID, click Tools | Generate GUID inside the IDE.) @@ -35,6 +50,7 @@ Compression=lzma SolidCompression=yes WizardStyle=modern + [Languages] Name: "ChineseSimplified"; MessagesFile: "compiler:Languages\ChineseSimplified.isl" @@ -47,14 +63,35 @@ Source: "D:\CCNotePad\x64\Release\*"; DestDir: "{app}"; Flags: ignoreversion rec ; NOTE: Don't use "Flags: ignoreversion" on any shared system files [Registry] -Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue -Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey -Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0" -Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1""" -Root: HKA; Subkey: "Software\Classes\Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".myp"; ValueData: "" -Root: HKA; Subkey: "Software\Classes\*\shell\Notepad--"; ValueType: string; ValueName: ""; ValueData: "Edit with Notepad--"; Flags: uninsdeletekey -Root: HKA; Subkey: "Software\Classes\*\shell\Notepad--"; ValueType: string; ValueName: "Icon"; ValueData: """{app}\{#MyAppExeName}""" -Root: HKA; Subkey: "Software\Classes\*\shell\Notepad--\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1""" ; +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: main +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt1}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue ; Components: ass +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt2}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: ass +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt3}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: ass +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt4}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: ass +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt5}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: ass +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt6}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: ass +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt7}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: ass +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt8}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: ass +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt9}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: ass +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt10}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: ass +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocExt11}\OpenWithProgids"; ValueType: string; ValueName: "{#MyAppAssocKey}"; ValueData: ""; Flags: uninsdeletevalue; Components: ass + +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}"; ValueType: string; ValueName: ""; ValueData: "{#MyAppAssocName}"; Flags: uninsdeletekey; Components: main +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\DefaultIcon"; ValueType: string; ValueName: ""; ValueData: "{app}\{#MyAppExeName},0"; Components: main +Root: HKA; Subkey: "Software\Classes\{#MyAppAssocKey}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Components: main + +Root: HKA; Subkey: "Software\Classes\Applications\{#MyAppExeName}"; ValueType: string; ValueName: ""; ValueData: ""; Flags: uninsdeletekey; Components: main +Root: HKA; Subkey: "Software\Classes\Applications\{#MyAppExeName}\SupportedTypes"; ValueType: string; ValueName: ".myp"; ValueData: ""; Flags: uninsdeletekey; Components: main +;Root: HKA; Subkey: "Software\Classes\Applications\{#MyAppExeName}\shell\open\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1"""; Flags: uninsdeletekey; Components: main +Root: HKA; Subkey: "Software\Classes\*\shell\Notepad--"; ValueType: string; ValueName: ""; ValueData: "Edit with Notepad--"; Flags: uninsdeletekey; Components: main +Root: HKA; Subkey: "Software\Classes\*\shell\Notepad--"; ValueType: string; ValueName: "Icon"; ValueData: """{app}\{#MyAppExeName}""" ; Components: main +Root: HKA; Subkey: "Software\Classes\*\shell\Notepad--\command"; ValueType: string; ValueName: ""; ValueData: """{app}\{#MyAppExeName}"" ""%1""" ; Components: main + + + +[Components] +Name: "main"; Description: "{#MyAppDesc}"; Types: full compact custom; Flags: fixed +Name: "ass"; Description: "¹ØÁª´򿪳£¼ûÎı¾ÀàÐÍ"; Types: full [Icons] diff --git a/src/linux/usr/share/applications/io.gitee.cxasm.notepad--.desktop b/src/linux/usr/share/applications/io.gitee.cxasm.notepad--.desktop index 333cc68..3e50291 100755 --- a/src/linux/usr/share/applications/io.gitee.cxasm.notepad--.desktop +++ b/src/linux/usr/share/applications/io.gitee.cxasm.notepad--.desktop @@ -4,7 +4,7 @@ Name=Notepad-- Name[zh_CN]=Notepad-- Comment=Notepad-- 是一个国产跨平台、简单的文本编辑器。 Type=Application -Exec=NotePad-- %F +Exec=notepad-- %F Icon=notepad-- Categories=Development;Office; Terminal=false diff --git a/src/main.cpp b/src/main.cpp index 5d94509..e59aeb2 100755 --- a/src/main.cpp +++ b/src/main.cpp @@ -40,7 +40,7 @@ const QString c_strTitle = "Ndd"; #ifdef Q_OS_UNIX #if defined(Q_OS_MAC) -QSharedMemory shared("CCNotebook122");;//mac下面后面带一个版本号,避免新的打不开 +QSharedMemory shared("CCNotebook123");;//mac下面后面带一个版本号,避免新的打不开 #else QSharedMemory shared("CCNotebook"); #endif @@ -120,8 +120,12 @@ class MyApplication : public QApplication int main(int argc, char *argv[]) { - //可以防止某些屏幕下的字体拥挤重叠问题 - QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + //可以防止某些屏幕下的字体拥挤重叠问题。暂时屏蔽,不使用qt方法,使用windows自带方案 + // 发现windows自带方案模糊。//发现下面打开后,在win10上反而效果不好,界面会变得很大,默认还是不开启的好。 + //QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); + //QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); + //QApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::RoundPreferFloor); + #ifdef Q_OS_MAC MyApplication a(argc, argv); #else diff --git a/src/markdownview.cpp b/src/markdownview.cpp new file mode 100755 index 0000000..18cd647 --- /dev/null +++ b/src/markdownview.cpp @@ -0,0 +1,18 @@ +#include "markdownview.h" + +MarkdownView::MarkdownView(QWidget *parent) + : QMainWindow(parent) +{ + ui.setupUi(this); +} + +MarkdownView::~MarkdownView() +{ + +} + + +void MarkdownView::viewMarkdown(QString& text) +{ + ui.textEdit->setMarkdown(text); +} \ No newline at end of file diff --git a/src/markdownview.h b/src/markdownview.h new file mode 100755 index 0000000..1041271 --- /dev/null +++ b/src/markdownview.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include "ui_markdownview.h" + +class MarkdownView : public QMainWindow +{ + Q_OBJECT + +public: + MarkdownView(QWidget *parent = nullptr); + ~MarkdownView(); + void viewMarkdown(QString& text); + +private: + Ui::MarkdownViewClass ui; +}; diff --git a/src/markdownview.ui b/src/markdownview.ui new file mode 100755 index 0000000..0ecc018 --- /dev/null +++ b/src/markdownview.ui @@ -0,0 +1,65 @@ + + + MarkdownViewClass + + + + 0 + 0 + 1134 + 712 + + + + MarkdownView + + + + + 3 + + + 3 + + + 3 + + + 3 + + + 3 + + + + + true + + + + + + + + + 0 + 0 + 1134 + 23 + + + + + + TopToolBarArea + + + false + + + + + + + + diff --git a/src/md5hash.cpp b/src/md5hash.cpp new file mode 100755 index 0000000..ee00dfb --- /dev/null +++ b/src/md5hash.cpp @@ -0,0 +1,153 @@ +#include "md5hash.h" +#include "ccnotepad.h" +#include "ctipwin.h" + +#include +#include +#include +#include + +Md5hash::Md5hash(QWidget *parent) + : QWidget(parent), m_isFile(false) +{ + ui.setupUi(this); + + + m_btGroup.addButton(ui.md4RadioBt, 0); + m_btGroup.addButton(ui.md5RadioBt, 1); + m_btGroup.addButton(ui.sha1RadioBt, 2); + m_btGroup.addButton(ui.sha256RadioBt, 4); + m_btGroup.addButton(ui.sha3RadioBt, 12); + m_btGroup.addButton(ui.kec256RadioBt, 8); + +#if (QT_VERSION <= QT_VERSION_CHECK(5,15,0)) + connect(&m_btGroup, QOverload::of(&QButtonGroup::buttonClicked), this, &Md5hash::on_methodIdChange); +#else + connect(&m_btGroup, &QButtonGroup::idClicked, this, &Md5hash::on_methodIdChange); +#endif + + connect(ui.srcTextEdit,&QPlainTextEdit::textChanged,this,&Md5hash::on_hash); +} + +Md5hash::~Md5hash() +{} + +void Md5hash::slot_select() +{ + QFileDialog fd(this, QString(), CCNotePad::s_lastOpenDirPath); + fd.setFileMode(QFileDialog::ExistingFile); + m_fileList.clear(); + + if (fd.exec() == QDialog::Accepted) //Èç¹û³ɹ¦µÄִÐÐ + { + m_fileList = fd.selectedFiles(); //·µ»ØÎļþÁбíµÄÃû³Æ + + if (!m_fileList.isEmpty()) + { + m_isFile = true; + ui.srcTextEdit->setPlainText(m_fileList.join("\n")); + } + + } + else + { + fd.close(); + } +} + +void Md5hash::on_methodIdChange(int id) +{ + on_hash(); +} + +void Md5hash::on_hash() +{ + QCryptographicHash::Algorithm method = QCryptographicHash::Md5; + + if (ui.md5RadioBt->isChecked()) + { + method = QCryptographicHash::Md5; + } + else if (ui.md4RadioBt->isChecked()) + { + method = QCryptographicHash::Md4; + } + else if (ui.sha1RadioBt->isChecked()) + { + method = QCryptographicHash::Sha1; + } + else if (ui.sha256RadioBt->isChecked()) + { + method = QCryptographicHash::Sha256; + } + else if (ui.sha3RadioBt->isChecked()) + { + method = QCryptographicHash::Sha3_256; + } + else if (ui.kec256RadioBt->isChecked()) + { + method = QCryptographicHash::Keccak_256; + } + + //Èç¹ûÊÇÎı¾ + if (!m_isFile) + { + QString text = ui.srcTextEdit->toPlainText(); + + QByteArray data = text.toUtf8(); + + if (!text.isEmpty()) + { + QByteArray result = QCryptographicHash::hash(data, method); + ui.hashTextEdit->setPlainText(result.toHex()); + } + } + else + { + QCryptographicHash fileHash(method); + QByteArray rs; + + QList result; + + for (int i = 0; i < m_fileList.size(); ++i) + { + rs.clear(); + QFile file(m_fileList.at(i)); + if (file.open(QIODevice::ReadOnly)) + { + if (fileHash.addData(&file)) + { + rs = fileHash.result(); + result.append(rs.toHex()); + } + else + { + result.append("Error Null"); + } + file.close(); + } + else + { + result.append("Error Null"); + } + + } + for (int i = 0; i < result.size(); ++i) + { + QString info = QString("File %1 cyp hash is \n%2").arg(m_fileList.at(i)).arg(QString(result.at(i))); + ui.hashTextEdit->appendPlainText(info); + } + m_isFile = false; + } +} + +void Md5hash::on_copyClipboard() +{ + if (!ui.hashTextEdit->toPlainText().isEmpty()) + { + QClipboard* clipboard = QApplication::clipboard(); + clipboard->setText(ui.hashTextEdit->toPlainText()); + + CTipWin::showTips(this, tr("Copy to clipboard Finished!"), 1200); + } +} \ No newline at end of file diff --git a/src/md5hash.h b/src/md5hash.h new file mode 100755 index 0000000..be12f80 --- /dev/null +++ b/src/md5hash.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include "ui_md5hash.h" + +class Md5hash : public QWidget +{ + Q_OBJECT + +public: + Md5hash(QWidget *parent = nullptr); + ~Md5hash(); + +private slots: + void slot_select(); + void on_hash(); + void on_methodIdChange(int id); + void on_copyClipboard(); + +private: + Ui::Md5hashClass ui; + QButtonGroup m_btGroup; + QStringList m_fileList; + bool m_isFile; +}; diff --git a/src/md5hash.ui b/src/md5hash.ui new file mode 100755 index 0000000..a004d64 --- /dev/null +++ b/src/md5hash.ui @@ -0,0 +1,203 @@ + + + Md5hashClass + + + + 0 + 0 + 560 + 436 + + + + Md5hash + + + + 3 + + + 3 + + + + + + + Copy Text Or Select File + + + + + + + select + + + + + + + + + + + + Algorithm + + + + + + Md4 + + + + + + + Sha1 + + + + + + + Sha3_256 + + + + + + + Md5 + + + true + + + + + + + Sha256 + + + + + + + Keccak_256 + + + + + + + + + + + 0 + 0 + + + + + 16777215 + 80 + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Copy to Clipboard + + + + + + + Close + + + + + + + + + + + + toolButton + clicked() + Md5hashClass + slot_select() + + + 534 + 19 + + + 552 + 239 + + + + + cancelBt + clicked() + Md5hashClass + close() + + + 503 + 412 + + + 338 + 430 + + + + + pushButton + clicked() + Md5hashClass + on_copyClipboard() + + + 393 + 415 + + + 539 + 430 + + + + + + slot_select() + on_copyClipboard() + + diff --git a/src/nddpluginapi.cpp b/src/nddpluginapi.cpp new file mode 100755 index 0000000..3df7179 --- /dev/null +++ b/src/nddpluginapi.cpp @@ -0,0 +1,25 @@ +#include "nddpluginapi.h" +#include "ccnotepad.h" + +NddPluginApi::NddPluginApi(QObject *parent) + : QObject(parent) +{} + +NddPluginApi::~NddPluginApi() +{} + +void NddPluginApi::setMainNotePad(QWidget * pWidget) +{ + m_mainNotePad = pWidget; +} + +//עÒâÕâÀïʵ¼ʷµ»صÄÊÇScintillaEditView +QsciScintilla* NddPluginApi::getCurrentEidtHandle() +{ + CCNotePad* pNotepad = dynamic_cast(m_mainNotePad); + if (pNotepad != nullptr) + { + return pNotepad->getCurEditView(); + } + return nullptr; +} diff --git a/src/nddpluginapi.h b/src/nddpluginapi.h new file mode 100755 index 0000000..93e89a4 --- /dev/null +++ b/src/nddpluginapi.h @@ -0,0 +1,37 @@ +#pragma once + +#include +#include +#include + +//Õâ¸öÀ๩²å¼þÖе÷Óã¬Îñ±ØҪ±£֤¸ÃÀàµÄABI¼æÈÝÐԡ£ +//ÕâÒâζ×ţ¬²»ÄÜËæÒâÔö¼Óɾ³ý¸ÃÀàÖеĺ¯ÊýºͳÉԱ±äÁ¿;·ñÔò»ᵼÖ²å¼þÎ޷¨¼æÈݡ£ +//²»ʹÓóýÐ麯Êý֮ÍâµÄÈκÎÐ麯Êý +//ÀíÂÛÉÏ×îºÃһ¸ö²å¼þ£¬¶ÔӦһ¸ö¸öÔÏó¡£ÕâÑù²»»á³åͻ¡£ + +class QsciScintilla; + +class NddPluginApi : public QObject +{ + Q_OBJECT + +public: + NddPluginApi(QObject *parent); + ~NddPluginApi(); + + //»ñȡµ±ǰ±༭¿òµĶÔÏóÕâ¸öһ¶¨Ҫÿ´ζ¯̬»ñȡ¡£ÕâÀïҲÓÐÎÊÌ⣬һµ©QsciScintillaÐ޸쬻¹ÊDz»ÄÜÆðµ½ABI¼æÈݡ£ + //¾¡Á¿ÒÀÀµ²»ÐèҪ¸Ķ¯µIJ¿·֡£ + + void setMainNotePad(QWidget* pWidget); + + //ÓÐÁËÕâ¸öµ±ǰ±༭¿òº󣬾ͿÉÒԶ¯̬×öÐí¶àÊÂÇéÁˡ£µ«ÊÇǰÌáÊÇQsciScintilla»ùÀ಻ÄÜËæÒâÐ޸ġ£ + QsciScintilla* getCurrentEidtHandle(); + + + + //Õâ¸öÀïÃæµijÉԱº¯ÊýҪÌرðСÐģ¬һµ©¸ø¶¨£¬Ôò˳ÐòºͲÎÊý²»ÄÜËæÒâÐ޸ġ£ֻÄÜÒÀ´ÎÍùºóÔö¼ӡ¢²»ÄÜɾ³ý¡£ +public: + //ʹÓö¯̬²ÎÊý½øÐвÎÊýµĴ«µݡ£ʹÓÃpublic´«µݳÉԱ²ÎÊý + QMap m_parameter; + QWidget* m_mainNotePad; +}; diff --git a/src/nddsetting.cpp b/src/nddsetting.cpp index 24fd83d..c224fb1 100755 --- a/src/nddsetting.cpp +++ b/src/nddsetting.cpp @@ -1,4 +1,4 @@ -#include "nddsetting.h" +#include "nddsetting.h" #include #include #include @@ -7,20 +7,20 @@ #include #include -static short version_num = 29; //1.22.0 ÊÇ29 -//ÅäÖÃÎļþÊǷñ´æÔڡ£Èç¹û³õʼ»¯ʧ°ܣ¬Ô򲻴æÔÚ +static short version_num = 29; //1.22.0 是29 +//配置文件是否存在。如果初始化失败,则不存在 bool NddSetting::s_isExistDb = false; int NddSetting::s_reference = 0; bool NddSetting::s_isContentChanged = false; QSettings* NddSetting::s_nddSet = nullptr; -QSettings* NddSetting::s_winPosSet = nullptr; +QSettings* NddSetting::s_nddDelaySet = nullptr; -//Èç¹ûkey²»´æÔڣ¬ÔòÐÂÔökey-value¡£´æÔڣº·µ»Øtrue +//如果key不存在,则新增key-value。存在:返回true bool NddSetting::checkNoExistAdd(QString key, QVariant& value) { - //ÿ´ÎмÓ×ֶκó£¬ÕâÀïҪ¼ì²éһÏ£¬²»´æÔÚÔòÐÂÔö + //每次新加字段后,这里要检查一下,不存在则新增 if (!s_nddSet->contains(key)) { s_nddSet->setValue(key, value); @@ -34,13 +34,13 @@ bool NddSetting::checkNoExistAdd(QString key, QVariant& value) return true; } -//20220402ÕâÀïÒþº¬ÁËһ¸öǰÖÃÌõ¼þ£ºÊý¾ݿâ¾ä±úÊÇÔÚÖ÷Ï̴߳´½¨µģ¬×îºò»ҪÔÚ×ÓÏ߳ÌÖе÷Óᣠ-//±ÜÃâÒòΪ¿çÏ̷߳ÃÎʺͶàÏ̳߳åͻ·ÃÎÊÒý·¢µÄÉÁÍËÎÊÌ⡣ËùÒÔ×îºÃÅäÖÃÎļþµĶÁд¶¼ÔÚÖ÷Ï߳ÌÖнøÐÐ +//20220402这里隐含了一个前置条件:数据库句柄是在主线程创建的,最好不要在子线程中调用。 +//避免因为跨线程访问和多线程冲突访问引发的闪退问题。所以最好配置文件的读写都在主线程中进行 void NddSetting::init() { ++s_reference; - //Èç¹ûÒѾ­³õʼ»¯¹ýÁˣ¬Ôòֱ½ӷµ»Ø + //如果已经初始化过了,则直接返回 if (s_isExistDb) { return; @@ -56,47 +56,47 @@ void NddSetting::init() auto initNddSet = []() { QString key = "signdate"; //QString date = QDate::currentDate().toString(QString("yyyy/M/d")); - //²»д½ñÌìµÄʱ¼䣬·ñÔòµÚһ´ÎÔËÐУ¬ÎÞÌõ¼þ²»»ᷢËÍÐÄÌø¡£ - //ֱ½Óдһ¸ö¹ýȥµÄʱ¼䣬ÈõÚһ´ÎÔËÐУ¬×ÜÊÇҪǩµ½ + //不写今天的时间,否则第一次运行,无条件不会发送心跳。 + //直接写一个过去的时间,让第一次运行,总是要签到 addKeyValueToSets(key, "2022/2/20"); QString str; - //tabµij¤¶ȣ¬ĬÈÏΪ4 + //tab的长度,默认为4 addKeyValueToNumSets("tablens", 4); - //space replace tab¿ոñÌ滻tab£¬ĬÈÏ0, 1Ϊtrue,0Ϊfalse + //space replace tab空格替换tab,默认0, 1为true,0为false addKeyValueToNumSets("tabnouse", 0); addKeyValueToSets("mac", "0"); addKeyValueToNumSets("padtimes", 0); addKeyValueToNumSets("serverip", 0); - //ÊǷñ¸ßÁÁ²»ͬ´¦±³¾° + //是否高亮不同处背景 addKeyValueToNumSets("hexhigh", 1); addKeyValueToNumSets(VERSION, version_num); - //Ƥ·ôid + //皮肤id addKeyValueToNumSets(SKIN_KEY, 0); - //ÓïÑÔindex 0:×Զ¯ѡÔñ 1:ÖÐÎÄ 2 ӢÎÄ + //语言index 0:自动选择 1:中文 2 英文 addKeyValueToNumSets(LANGS_KEY, 0); - //¿ªÆô×Զ¯»»ÐÐ + //开启自动换行 addKeyValueToNumSets(AUTOWARP_KEY, 0); - //¿ªÆô×Զ¯Ëõ½ø + //开启自动缩进 addKeyValueToNumSets(INDENT_KEY, 0); - //ÏÔʾ¿հ× + //显示空白。0都不显示 1 单显示空格 2 单显示行尾 3 都显示 addKeyValueToNumSets(SHOWSPACE_KEY, 0); - //×î´óÎı¾ÎļþµÄÃÅÏޡ£ĬÈÏ100M.(50-300) + //最大文本文件的门限。默认100M.(50-600) addKeyValueToNumSets(MAX_BIG_TEXT, 100); addKeyValueToSets(SOFT_KEY, "0"); - addKeyValueToSets(RESTORE_CLOSE_FILE, "1"); + addKeyValueToNumSets(RESTORE_CLOSE_FILE, 1); //0 24 1 36 2 48 addKeyValueToNumSets(ICON_SIZE, 1); @@ -107,22 +107,22 @@ void NddSetting::init() addKeyValueToNumSets(FILELISTPOS, Qt::LeftDockWidgetArea); - //ĬÈÏ0²»ÏÔʾ + //默认0不显示 addKeyValueToNumSets(FILELISTSHOW, 0); - //ĬÈÏÏÔʾ¹¤¾ßÀ¸ + //默认显示工具栏 addKeyValueToNumSets(TOOLBARSHOW, 1); - //´ò¿ªÍøҳ£¬ĬÈϲ»¹´ѡ£¬×ÊԴºķѶà + //打开网页,默认不勾选,资源耗费多 addKeyValueToNumSets(SHOWWEBADDR, 0); - //²éÕҽá¹û¿òµÄĬÈÏ×ÖÌå´óС + //查找结果框的默认字体大小 addKeyValueToNumSets(FIND_RESULT_FONT_SIZE, 14); }; if (!s_nddSet->contains(VERSION)) { - //²»´æÔÚ×߳õʼ»¯Á÷³Ì + //不存在走初始化流程 initNddSet(); s_isContentChanged = true; } @@ -133,7 +133,7 @@ void NddSetting::init() QVariant v(VERSION); if (checkNoExistAdd(VERSION, v)) { - //Èç¹û´æÔڣ¬¶øÇҰ汾ÊÇ×îÐÂ,²»ÐèҪ×ߺóÃæ×Զ¯¼ì²éÁ÷³ÌÁË + //如果存在,而且版本是最新,不需要走后面自动检查流程了 int curVersion = s_nddSet->value(VERSION).toInt(); if (curVersion == version_num) { @@ -141,12 +141,12 @@ void NddSetting::init() } else if (curVersion < version_num) { - //¸üа汾µ½×îР+ //更新版本到最新 updataKeyValueFromNumSets(VERSION, version_num); } } } - //ÿ´ÎмÓ×ֶκó£¬ÕâÀïҪ¼ì²éһÏ£¬²»´æÔÚÔòÐÂÔö + //每次新加字段后,这里要检查一下,不存在则新增 { QVariant v(1); checkNoExistAdd(SKIN_KEY, v); @@ -227,6 +227,10 @@ void NddSetting::init() QVariant v(14); checkNoExistAdd(FIND_RESULT_FONT_SIZE, v); } + { + QVariant v(0); + checkNoExistAdd(LAST_ACTION_TAB_INDEX, v); + } } while (false); } @@ -237,7 +241,7 @@ void NddSetting::init() -//дһ¸ö×ܵĻñȡÅäÖõĽӿڣ¬±ÜÃâÒԺóÿ¸ö×ֶζ¼ÐèҪдһ¸ö¶Áд½ӿÚ +//写一个总的获取配置的接口,避免以后每个字段都需要写一个读写接口 QString NddSetting::getKeyValueFromSets(QString key) { return s_nddSet->value(key,"").toString(); @@ -250,7 +254,7 @@ bool NddSetting::updataKeyValueFromSets(QString key, QString value) return true; } -//дһ¸ö×ܵĻñȡÅäÖõĽӿڣ¬±ÜÃâÒԺóÿ¸ö×ֶζ¼ÐèҪдһ¸ö¶Áд½ӿÚ +//写一个总的获取配置的接口,避免以后每个字段都需要写一个读写接口 QByteArray NddSetting::getKeyByteArrayValue(QString key) { return s_nddSet->value(key, "").toByteArray(); @@ -262,14 +266,14 @@ void NddSetting::updataKeyByteArrayValue(QString key, QByteArray& value) s_isContentChanged = true; } -//µÚһ´μÓһÌõ¼Ç¼£¬ÓÃÓڳõʼ»¯ +//第一次加一条记录,用于初始化 void NddSetting::addKeyValueToSets(QString key, QString value) { s_nddSet->setValue(key, QVariant(value)); } -//дһ¸ö×ܵĻñȡÅäÖõĽӿڣ¬±ÜÃâÒԺóÿ¸ö×ֶζ¼ÐèҪдһ¸ö¶Áд½ӿÚ.0×öĬÈÏֵ£¬Íⲿ×îºò»ÓÃ0×ö³õʼ»¯ֵ +//写一个总的获取配置的接口,避免以后每个字段都需要写一个读写接口.0做默认值,外部最好不用0做初始化值 int NddSetting::getKeyValueFromNumSets(const QString key) { QVariant v = s_nddSet->value(key, QVariant(0)); @@ -283,7 +287,7 @@ bool NddSetting::updataKeyValueFromNumSets(const QString key, int value) } -//µÚһ´μÓһÌõ¼Ç¼£¬ÓÃÓڳõʼ»¯ +//第一次加一条记录,用于初始化 void NddSetting::addKeyValueToNumSets(QString key, int value) { s_nddSet->setValue(key, QVariant(value)); @@ -300,7 +304,7 @@ void NddSetting::close() { s_isExistDb = false; - //×öһ´ÎÕæÕýµı£´æ + //做一次真正的保存 if (s_isContentChanged) { s_nddSet->sync(); @@ -309,38 +313,69 @@ void NddSetting::close() s_isContentChanged = false; } - //ÔÚÕâÀﱣ´æһÏÂ×Ӵ°¿ڵÄλÖᣲ»ÅųýÓпÉÄÜ×Ӵ°¿ڻ¹Ôڣ¬Ö÷´°¿ÚÒѾ­Í˳öµÄÇé¿ö£¬²»¹ýÎÊÌⲻ´ó¡£ - if (s_winPosSet != nullptr) + //在这里保存一下子窗口的位置。不排除有可能子窗口还在,主窗口已经退出的情况,不过问题不大。 + if (s_nddDelaySet != nullptr) { - s_winPosSet->sync(); - s_winPosSet = nullptr; + s_nddDelaySet->sync(); + s_nddDelaySet = nullptr; } } } } -//×Ӵ°¿ڵÄλÖ㬵¥¶À·ÅÔÚһ¸öwinpos.iniÎļþÖУ¬¶øÇÒÆô¶¯³ÌÐòʱ£¬²»ÐèҪ¶Áȡ£¬¿ɱÜÃâÆô¶¯ʱÍÏÂýËٶÈ +//子窗口的位置,单独放在一个winpos.ini文件中,而且启动程序时,不需要读取,可避免启动时拖慢速度 QByteArray NddSetting::getWinPos(QString key) { - winPosInit(); - return s_winPosSet->value(key, "").toByteArray(); + nddDelaySetInit(); + return s_nddDelaySet->value(key, "").toByteArray(); } void NddSetting::updataWinPos(QString key, QByteArray& value) { - winPosInit(); - s_winPosSet->setValue(key, QVariant(value)); + nddDelaySetInit(); + s_nddDelaySet->setValue(key, QVariant(value)); } -void NddSetting::winPosInit() +void NddSetting::nddDelaySetInit() { - if (s_winPosSet == nullptr) + if (s_nddDelaySet == nullptr) { QString settingDir = QString("notepad/delayset"); QSettings qs(QSettings::IniFormat, QSettings::UserScope, settingDir); QString qsSetPath = qs.fileName(); - s_winPosSet = new QSettings(QSettings::IniFormat, QSettings::UserScope, settingDir); - s_winPosSet->setIniCodec("UTF-8"); + s_nddDelaySet = new QSettings(QSettings::IniFormat, QSettings::UserScope, settingDir); + s_nddDelaySet->setIniCodec("UTF-8"); } } + + +//写一个总的获取配置的接口,避免以后每个字段都需要写一个读写接口 +QString NddSetting::getKeyValueFromDelaySets(QString key) +{ + nddDelaySetInit(); + return s_nddDelaySet->value(key, "").toString(); +} + +bool NddSetting::updataKeyValueFromDelaySets(QString key, QString value) +{ + nddDelaySetInit(); + s_nddDelaySet->setValue(key, value); + s_isContentChanged = true; + return true; +} + +//写一个总的获取配置的接口,避免以后每个字段都需要写一个读写接口 +int NddSetting::getKeyValueFromDelayNumSets(QString key) +{ + nddDelaySetInit(); + return s_nddDelaySet->value(key, "").toInt(); +} + +bool NddSetting::updataKeyValueFromDelayNumSets(QString key, int value) +{ + nddDelaySetInit(); + s_nddDelaySet->setValue(key, value); + s_isContentChanged = true; + return true; +} diff --git a/src/nddsetting.h b/src/nddsetting.h index 2fc34d8..6a65690 100755 --- a/src/nddsetting.h +++ b/src/nddsetting.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -10,24 +10,29 @@ static QString SHOWSPACE_KEY = "blank"; static QString MAX_BIG_TEXT = "maxtsize"; static QString SOFT_STATUS = "rstatus"; static QString SOFT_KEY = "rkey"; -static QString RESTORE_CLOSE_FILE = "restore"; //»ָ´¹رÕʱ´򿪵ÄÎļþ -static QString PRO_DIR = "prodir";//·ÅÖÃÅäÖÃÎļþµÄ·¾¶ -//static QString RESTORE_SIZE = "rsize";//±£´æ¹رÕʱµĴóС -static QString WIN_POS = "pos";//±£´æ¹رÕÊǵĴóС -static QString ICON_SIZE = "iconsize";//ͼ±ê´óС -static QString ZOOMVALUE = "zoom"; //·Ŵó±¶Êý -static QString VERSION = "version";//µ±ǰ°汾 -static QString FINDRESULTPOS = "findpos";//²éÕҴ°¿ÚÐü¸¡µÄλÖà -static QString FILELISTPOS = "filepos";//ÎļþÁбíÐü¸¡¿òµÄλÖà -static QString FILELISTSHOW = "showfilelist"; //ÎļþÁбí¿òÊǷñÏÔʾ -static QString TOOLBARSHOW = "showbar"; //ÊǷñÏÔʾ¹¤¾ßÀ¸ -static QString FINDWINSIZE = "findwinsize";//±£´æ²éÕҿòµĴóС¡£150%·Ŵóʱ½çÃæÓÀ¾á£±£Áô±ÜÃâÿ´ÎÊֶ¯µ÷Õû -static QString SHOWWEBADDR = "showweb";//¸ßÁÁwebµØַ£¬˫»÷Íøҳ´ò¿ª -static QString FIND_RESULT_FONT_SIZE = "frfs";//²éÕҽá¹ûµÄĬÈÏ×ÖÌå´óС£¬ĬÈÏΪ14 +static QString RESTORE_CLOSE_FILE = "restore"; //恢复关闭时打开的文件 +static QString PRO_DIR = "prodir";//放置配置文件的路径 +//static QString RESTORE_SIZE = "rsize";//保存关闭时的大小 +static QString WIN_POS = "pos";//保存关闭是的大小 +static QString ICON_SIZE = "iconsize";//图标大小 +static QString ZOOMVALUE = "zoom"; //放大倍数 +static QString VERSION = "version";//当前版本 +static QString FINDRESULTPOS = "findpos";//查找窗口悬浮的位置 +static QString FILELISTPOS = "filepos";//文件列表悬浮框的位置 +static QString FILELISTSHOW = "showfilelist"; //文件列表框是否显示 +static QString TOOLBARSHOW = "showbar"; //是否显示工具栏 +static QString FINDWINSIZE = "findwinsize";//保存查找框的大小。150%放大时界面永久。保留避免每次手动调整 +static QString SHOWWEBADDR = "showweb";//高亮web地址,双击网页打开 +static QString FIND_RESULT_FONT_SIZE = "frfs";//查找结果的默认字体大小,默认为14 +static QString LAST_ACTION_TAB_INDEX = "lati";//上次关闭时,当前激活的tab标签页序号 + +static QString RECENT_OPEN_FILE = "recentopenfile"; +static QString LAST_OPEN_DIR = "lastdir"; +static QString CLEAR_OPENFILE_ON_CLOSE = "clearopenfile"; //关闭时清空历史文件 -//ÏÂÃæÕâ¸öÊÇwinpos.iniÖеÄkey£¬±ÜÃⵥ¸öÎļþ̫´ó£¬ÍÏÂýÆô¶¯ËٶÈ -static QString BATCH_FIND_REPLACE_POS = "bfpos";//ÅúÁ¿²éÕÒÌ滻´°¿ڵĴóС +//下面这个是winpos.ini中的key,避免单个文件太大,拖慢启动速度 +static QString BATCH_FIND_REPLACE_POS = "bfpos";//批量查找替换窗口的大小 class NddSetting { @@ -58,14 +63,20 @@ public: static void updataWinPos(QString key, QByteArray& value); - + static QString getKeyValueFromDelaySets(QString key); + + static bool updataKeyValueFromDelaySets(QString key, QString value); + + static int getKeyValueFromDelayNumSets(QString key); + + static bool updataKeyValueFromDelayNumSets(QString key, int value); static bool isDbExist() { return s_isExistDb; } private: - static void winPosInit(); + static void nddDelaySetInit(); private: static bool s_isExistDb; @@ -74,5 +85,7 @@ private: static QSettings* s_nddSet; - static QSettings* s_winPosSet; + //基本和s_nddSet一样,不过在启动的时候,不需要读取该文件。加快启动速度 + //启动完毕后,其他操作触发加载该文件 + static QSettings* s_nddDelaySet; }; diff --git a/src/notepad/tailf.png b/src/notepad/tailf.png new file mode 100755 index 0000000..83e6106 Binary files /dev/null and b/src/notepad/tailf.png differ diff --git a/src/plugin.h b/src/plugin.h index 57e920e..4e84343 100755 --- a/src/plugin.h +++ b/src/plugin.h @@ -1,10 +1,10 @@ -#pragma once +#pragma once #include "pluginGl.h" #include class QMenu; class QsciScintilla; class QWidget; -typedef int (*NDD_PROC_MAIN_CALLBACK)(QWidget* parent, const QString& strFileName, std::functiongetCurEdit, NDD_PROC_DATA* procData); +typedef int (*NDD_PROC_MAIN_CALLBACK)(QWidget* parent, const QString& strFileName, std::functiongetCurEdit, std::function, NDD_PROC_DATA* procData); int loadProc(const QString& strDirOut, std::function funcallback, QMenu* pUserData); diff --git a/src/plugin/helloworld/helloworld.pro b/src/plugin/helloworld/helloworld.pro index ec08b04..7a5abfa 100755 --- a/src/plugin/helloworld/helloworld.pro +++ b/src/plugin/helloworld/helloworld.pro @@ -1,7 +1,7 @@ TEMPLATE = lib LANGUAGE = C++ -CONFIG += qt warn_on +CONFIG += qt warn_on Release QT += core gui widgets HEADERS += *.h diff --git a/src/plugin/helloworld/helloworldexport.cpp b/src/plugin/helloworld/helloworldexport.cpp index 28bc0ff..6b1d299 100755 --- a/src/plugin/helloworld/helloworldexport.cpp +++ b/src/plugin/helloworld/helloworldexport.cpp @@ -1,9 +1,12 @@ -#include +#include #include #include #include #include #include "qttestclass.h" +#ifdef WIN32 +#include +#endif #define NDD_EXPORTDLL @@ -22,7 +25,7 @@ #endif NDD_EXPORT bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData); - NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::functiongetCurEdit, NDD_PROC_DATA* procData); + NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::functiongetCurEdit, std::function pluginCallBack, NDD_PROC_DATA* procData); #ifdef __cplusplus @@ -32,6 +35,7 @@ static NDD_PROC_DATA s_procData; static QWidget* s_pMainNotepad = nullptr; std::function s_getCurEdit; +std::function s_invokeMainFun; bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData) { @@ -40,7 +44,7 @@ bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData) return false; } pProcData->m_strPlugName = QObject::tr("Hello World Plug"); - pProcData->m_strComment = QObject::tr("char to Upper."); + pProcData->m_strComment = QObject::tr(u8"不需要创建二级菜单的插件例子"); pProcData->m_version = QString("v1.0"); pProcData->m_auther = QString("zuowei.yin"); @@ -54,9 +58,10 @@ bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData) //pNotepad:就是CCNotepad的主界面指针 //strFileName:当前插件DLL的全路径,如果不关心,则可以不使用 //getCurEdit:从NDD主程序传递过来的仿函数,通过该函数获取当前编辑框操作对象QsciScintilla +//s_invokeMainFun: 可以回调NDD主程序中的功能函数,比如创建新文件功能等,根据需要可实时扩展。 //pProcData:如果pProcData->m_menuType = 0 ,则该指针为空;如果pProcData->m_menuType = 1,则该指针有值。目前需要关心s_procData.m_rootMenu //开发者可以在该菜单下面,自行创建二级菜单 -int NDD_PROC_MAIN(QWidget* pNotepad, const QString &strFileName, std::functiongetCurEdit, NDD_PROC_DATA* pProcData) +int NDD_PROC_MAIN(QWidget* pNotepad, const QString &strFileName, std::functiongetCurEdit, std::function pluginCallBack, NDD_PROC_DATA* pProcData) { QsciScintilla* pEdit = getCurEdit(); if (pEdit == nullptr) @@ -72,6 +77,7 @@ int NDD_PROC_MAIN(QWidget* pNotepad, const QString &strFileName, std::functionm_menuType = 1;是自己要创建二级菜单的场景。则通过s_procData.m_rootMenu 获取该插件的菜单根节点。 //插件开发者自行在s_procData.m_rootMenu下添加新的二级菜单项目 @@ -85,3 +91,26 @@ int NDD_PROC_MAIN(QWidget* pNotepad, const QString &strFileName, std::function +#include #include #include #include #include #include +#ifdef WIN32 +#include +#endif #define NDD_EXPORTDLL @@ -22,7 +25,7 @@ #endif NDD_EXPORT bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData); - NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::functiongetCurEdit, NDD_PROC_DATA* procData); + NDD_EXPORT int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::functiongetCurEdit, std::function pluginCallBack, NDD_PROC_DATA* procData); #ifdef __cplusplus } @@ -31,6 +34,7 @@ static NDD_PROC_DATA s_procData; static QWidget* s_pMainNotepad = nullptr; std::function s_getCurEdit; +std::function s_invokeMainFun; bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData) { @@ -38,8 +42,8 @@ bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData) { return false; } - pProcData->m_strPlugName = QObject::tr("Test Plug"); - pProcData->m_strComment = QObject::tr("char to lower."); + pProcData->m_strPlugName = QObject::tr("Create Second Menu Plug"); + pProcData->m_strComment = QObject::tr(u8"创建二级菜单的插件例子"); pProcData->m_version = QString("v1.0"); pProcData->m_auther = QString("zuowei.yin"); @@ -53,8 +57,9 @@ bool NDD_PROC_IDENTIFY(NDD_PROC_DATA* pProcData) //strFileName:当前插件DLL的全路径,如果不关心,则可以不使用 //getCurEdit:从NDD主程序传递过来的仿函数,通过该函数获取当前编辑框操作对象QsciScintilla //pProcData:如果pProcData->m_menuType = 0 ,则该指针为空;如果pProcData->m_menuType = 1,则该指针有值。目前需要关心s_procData.m_rootMenu -//开发者可以在该菜单下面,自行创建二级菜单 -int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::functiongetCurEdit, NDD_PROC_DATA* pProcData) +//s_invokeMainFun: 可以回调NDD主程序中的功能函数,比如创建新文件功能等,根据需要可实时扩展。 +//开发者可以在该菜单下面,自行创建二级菜单.更详细的例子,请见jstool min插件。 +int NDD_PROC_MAIN(QWidget* pNotepad, const QString& strFileName, std::functiongetCurEdit, std::function pluginCallBack, NDD_PROC_DATA* pProcData) { //务必拷贝一份pProcData,在外面会释放。 diff --git a/src/pluginmgr.cpp b/src/pluginmgr.cpp index 6ba10e1..7cbd786 100755 --- a/src/pluginmgr.cpp +++ b/src/pluginmgr.cpp @@ -1,4 +1,4 @@ -#include "pluginmgr.h" +#include "pluginmgr.h" #include "rcglobal.h" @@ -7,6 +7,10 @@ PluginMgr::PluginMgr(QWidget *parent, QList& pluginList) { ui.setupUi(this); + ui.pluginTable->horizontalHeader()->setStretchLastSection(true); + ui.pluginTable->horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents); + ui.pluginTable->horizontalHeader()->setSectionResizeMode(3, QHeaderView::ResizeToContents); + //ui.pluginTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch); init(pluginList); } diff --git a/src/qscint/scintilla/src/EditView.cpp b/src/qscint/scintilla/src/EditView.cpp index 9e31596..31e0442 100755 --- a/src/qscint/scintilla/src/EditView.cpp +++ b/src/qscint/scintilla/src/EditView.cpp @@ -1,4 +1,4 @@ -// Scintilla source code edit control +// Scintilla source code edit control /** @file EditView.cxx ** Defines the appearance of the main text area of the editor window. **/ @@ -833,7 +833,13 @@ static void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle r PRectangle rcChar = rcCChar; rcChar.left++; rcChar.right--; - surface->DrawTextClipped(rcChar, ctrlCharsFont, + // In the original Scintilla code this was a call to DrawTextClipped(). + // This caused the clipping to be incorrect (triggered when EOLs are + // visible) causing text to overwrite the margins when scrolling. The + // change is consistent with the alternative code paths to where + // DrawTextBlob() is called bu tthe root cause maybe in PlatQt.cpp or in Qt + // itself. + surface->DrawTextNoClip(rcChar, ctrlCharsFont, rcSegment.top + vsDraw.maxAscent, s, static_cast(s ? strlen(s) : 0), textBack, textFore); } diff --git a/src/qscint/scintilla/src/Editor.cpp b/src/qscint/scintilla/src/Editor.cpp index 0174286..86590fd 100755 --- a/src/qscint/scintilla/src/Editor.cpp +++ b/src/qscint/scintilla/src/Editor.cpp @@ -5622,7 +5622,7 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam vs.styles[wParam].back = ColourDesired(static_cast(lParam)); break; case SCI_STYLESETBOLD: - vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL; + vs.styles[wParam].weight = ((lParam != 0) ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL); break; case SCI_STYLESETWEIGHT: vs.styles[wParam].weight = static_cast(lParam); diff --git a/src/qscint/src/InputMethod.cpp b/src/qscint/src/InputMethod.cpp index 8f90180..41400b2 100755 --- a/src/qscint/src/InputMethod.cpp +++ b/src/qscint/src/InputMethod.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // Copyright (c) 2011 Archaeopteryx Software, Inc. // Copyright (c) 1990-2011, Scientific Toolworks, Inc. // @@ -137,44 +137,45 @@ void QsciScintillaBase::inputMethodEvent(QInputMethodEvent *event) return; } + bool initialCompose = false; if (sci->pdoc->TentativeActive()) { sci->pdoc->TentativeUndo(); } else { // No tentative undo means start of this composition so // Fill in any virtual spaces. - sci->ClearBeforeTentativeStart(); + initialCompose = true; } sci->view.imeCaretBlockOverride = false; if (!event->commitString().isEmpty()) { const QString commitStr = event->commitString(); - const unsigned int commitStrLen = commitStr.length(); + const int commitStrLen = commitStr.length(); - for (unsigned int i = 0; i < commitStrLen;) { - const unsigned int ucWidth = commitStr.at(i).isHighSurrogate() ? 2 : 1; + for (int i = 0; i < commitStrLen;) { + const int ucWidth = commitStr.at(i).isHighSurrogate() ? 2 : 1; const QString oneCharUTF16 = commitStr.mid(i, ucWidth); const QByteArray oneChar = textAsBytes(oneCharUTF16); const int oneCharLen = oneChar.length(); - sci->AddCharUTF(oneChar.data(), oneCharLen); + sci->AddCharUTF(oneChar.data(), oneChar.length()); i += ucWidth; } } else if (!event->preeditString().isEmpty()) { const QString preeditStr = event->preeditString(); - const unsigned int preeditStrLen = preeditStr.length(); - if ((preeditStrLen == 0) || (preeditStrLen > MAXLENINPUTIME)) { + const int preeditStrLen = preeditStr.length(); + if (preeditStrLen == 0) { sci->ShowCaretAtCurrentPosition(); return; } + if (initialCompose) + sci->ClearBeforeTentativeStart(); sci->pdoc->TentativeStart(); // TentativeActive() from now on. std::vector imeIndicator = MapImeIndicators(event); - const bool recording = sci->recordingMacro; - sci->recordingMacro = false; for (unsigned int i = 0; i < preeditStrLen;) { const unsigned int ucWidth = preeditStr.at(i).isHighSurrogate() ? 2 : 1; const QString oneCharUTF16 = preeditStr.mid(i, ucWidth); @@ -186,7 +187,6 @@ void QsciScintillaBase::inputMethodEvent(QInputMethodEvent *event) DrawImeIndicator(sci, imeIndicator[i], oneCharLen); i += ucWidth; } - sci->recordingMacro = recording; // Move IME carets. int imeCaretPos = GetImeCaretPos(event); diff --git a/src/qscint/src/ListBoxQt.cpp b/src/qscint/src/ListBoxQt.cpp index aa74e40..f67e581 100755 --- a/src/qscint/src/ListBoxQt.cpp +++ b/src/qscint/src/ListBoxQt.cpp @@ -1,7 +1,7 @@ // This module implements the specialisation of QListBox that handles the // Scintilla double-click callback. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/ListBoxQt.h b/src/qscint/src/ListBoxQt.h index c3d5a2c..ffcc17a 100755 --- a/src/qscint/src/ListBoxQt.h +++ b/src/qscint/src/ListBoxQt.h @@ -1,7 +1,7 @@ // This defines the specialisation of QListBox that handles the Scintilla // double-click callback. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/MacPasteboardMime.cpp b/src/qscint/src/MacPasteboardMime.cpp index 1839c64..bea06b5 100755 --- a/src/qscint/src/MacPasteboardMime.cpp +++ b/src/qscint/src/MacPasteboardMime.cpp @@ -2,7 +2,7 @@ // macOS. It is a separate file to avoid clashes between macOS and Scintilla // data types. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/PlatQt.cpp b/src/qscint/src/PlatQt.cpp index 59c4c98..e15bfb7 100755 --- a/src/qscint/src/PlatQt.cpp +++ b/src/qscint/src/PlatQt.cpp @@ -1,6 +1,6 @@ -// This module implements the portability layer for the Qt port of Scintilla. +// This module implements the portability layer for the Qt port of Scintilla. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qsciabstractapis.h b/src/qscint/src/Qsci/qsciabstractapis.h index dfa877c..76e2a34 100755 --- a/src/qscint/src/Qsci/qsciabstractapis.h +++ b/src/qscint/src/Qsci/qsciabstractapis.h @@ -1,6 +1,6 @@ // This module defines interface to the QsciAbstractAPIs class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qsciapis.h b/src/qscint/src/Qsci/qsciapis.h index 1f92002..bc1eb68 100755 --- a/src/qscint/src/Qsci/qsciapis.h +++ b/src/qscint/src/Qsci/qsciapis.h @@ -1,6 +1,6 @@ // This module defines interface to the QsciAPIs class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscicommand.h b/src/qscint/src/Qsci/qscicommand.h index 94f12c3..16c4e26 100755 --- a/src/qscint/src/Qsci/qscicommand.h +++ b/src/qscint/src/Qsci/qscicommand.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciCommand class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscicommandset.h b/src/qscint/src/Qsci/qscicommandset.h index 43dff82..85bb2bc 100755 --- a/src/qscint/src/Qsci/qscicommandset.h +++ b/src/qscint/src/Qsci/qscicommandset.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciCommandSet class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscidocument.h b/src/qscint/src/Qsci/qscidocument.h index f55e219..965ebb0 100755 --- a/src/qscint/src/Qsci/qscidocument.h +++ b/src/qscint/src/Qsci/qscidocument.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciDocument class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qsciglobal.h b/src/qscint/src/Qsci/qsciglobal.h index 89e404b..cdcf295 100755 --- a/src/qscint/src/Qsci/qsciglobal.h +++ b/src/qscint/src/Qsci/qsciglobal.h @@ -1,6 +1,6 @@ // This module defines various things common to all of the Scintilla Qt port. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // @@ -37,7 +37,11 @@ // Define QSCINTILLA_MAKE_DLL to create a QScintilla shared library, or // define QSCINTILLA_DLL to link against a QScintilla shared library, or define // neither to either build or link against a static QScintilla library. -#define QSCINTILLA_DLL +#ifdef QSCINTILLA_DLL +#undef QSCINTILLA_DLL +#endif + +//#define QSCINTILLA_DLL #if defined(QSCINTILLA_DLL) #define QSCINTILLA_EXPORT Q_DECL_IMPORT diff --git a/src/qscint/src/Qsci/qscilexer.h b/src/qscint/src/Qsci/qscilexer.h index 862f818..0316c91 100755 --- a/src/qscint/src/Qsci/qscilexer.h +++ b/src/qscint/src/Qsci/qscilexer.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexer class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerasm.h b/src/qscint/src/Qsci/qscilexerasm.h index 4ab60c9..eec4734 100755 --- a/src/qscint/src/Qsci/qscilexerasm.h +++ b/src/qscint/src/Qsci/qscilexerasm.h @@ -1,7 +1,7 @@ #pragma once // This defines the interface to the QsciLexerAsm class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexeravs.h b/src/qscint/src/Qsci/qscilexeravs.h index 7da30e5..9a28283 100755 --- a/src/qscint/src/Qsci/qscilexeravs.h +++ b/src/qscint/src/Qsci/qscilexeravs.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerAVS class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerbash.h b/src/qscint/src/Qsci/qscilexerbash.h index 9948796..92d3e54 100755 --- a/src/qscint/src/Qsci/qscilexerbash.h +++ b/src/qscint/src/Qsci/qscilexerbash.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerBash class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerbatch.h b/src/qscint/src/Qsci/qscilexerbatch.h index 62e4969..ed2c920 100755 --- a/src/qscint/src/Qsci/qscilexerbatch.h +++ b/src/qscint/src/Qsci/qscilexerbatch.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerBatch class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexercmake.h b/src/qscint/src/Qsci/qscilexercmake.h index 5b128cb..78e3168 100755 --- a/src/qscint/src/Qsci/qscilexercmake.h +++ b/src/qscint/src/Qsci/qscilexercmake.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerCMake class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexercoffeescript.h b/src/qscint/src/Qsci/qscilexercoffeescript.h index 3bae77d..b443d3d 100755 --- a/src/qscint/src/Qsci/qscilexercoffeescript.h +++ b/src/qscint/src/Qsci/qscilexercoffeescript.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerCoffeeScript class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexercpp.h b/src/qscint/src/Qsci/qscilexercpp.h index 13777e5..962c811 100755 --- a/src/qscint/src/Qsci/qscilexercpp.h +++ b/src/qscint/src/Qsci/qscilexercpp.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerCPP class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexercsharp.h b/src/qscint/src/Qsci/qscilexercsharp.h index adf4fa5..d91b0d5 100755 --- a/src/qscint/src/Qsci/qscilexercsharp.h +++ b/src/qscint/src/Qsci/qscilexercsharp.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerCSharp class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexercss.h b/src/qscint/src/Qsci/qscilexercss.h index 72675aa..04a76f1 100755 --- a/src/qscint/src/Qsci/qscilexercss.h +++ b/src/qscint/src/Qsci/qscilexercss.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerCSS class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexercustom.h b/src/qscint/src/Qsci/qscilexercustom.h index d166f86..d1ba17b 100755 --- a/src/qscint/src/Qsci/qscilexercustom.h +++ b/src/qscint/src/Qsci/qscilexercustom.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerCustom class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerd.h b/src/qscint/src/Qsci/qscilexerd.h index a444122..4099169 100755 --- a/src/qscint/src/Qsci/qscilexerd.h +++ b/src/qscint/src/Qsci/qscilexerd.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerD class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerdiff.h b/src/qscint/src/Qsci/qscilexerdiff.h index cfa7405..43b67e9 100755 --- a/src/qscint/src/Qsci/qscilexerdiff.h +++ b/src/qscint/src/Qsci/qscilexerdiff.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerDiff class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexeredifact.h b/src/qscint/src/Qsci/qscilexeredifact.h index 973fcdf..548fa09 100755 --- a/src/qscint/src/Qsci/qscilexeredifact.h +++ b/src/qscint/src/Qsci/qscilexeredifact.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerEDIFACT class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerfortran.h b/src/qscint/src/Qsci/qscilexerfortran.h index 5ca55ef..787502e 100755 --- a/src/qscint/src/Qsci/qscilexerfortran.h +++ b/src/qscint/src/Qsci/qscilexerfortran.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerFortran class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerfortran77.h b/src/qscint/src/Qsci/qscilexerfortran77.h index 8aebb5e..69db10a 100755 --- a/src/qscint/src/Qsci/qscilexerfortran77.h +++ b/src/qscint/src/Qsci/qscilexerfortran77.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerFortran77 class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexergo.h b/src/qscint/src/Qsci/qscilexergo.h index 97bb6aa..2466e7c 100755 --- a/src/qscint/src/Qsci/qscilexergo.h +++ b/src/qscint/src/Qsci/qscilexergo.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerGO class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerhtml.h b/src/qscint/src/Qsci/qscilexerhtml.h index b167f6a..924eb94 100755 --- a/src/qscint/src/Qsci/qscilexerhtml.h +++ b/src/qscint/src/Qsci/qscilexerhtml.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerHTML class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexeridl.h b/src/qscint/src/Qsci/qscilexeridl.h index 6ada0f6..ba79c66 100755 --- a/src/qscint/src/Qsci/qscilexeridl.h +++ b/src/qscint/src/Qsci/qscilexeridl.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerIDL class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerjava.h b/src/qscint/src/Qsci/qscilexerjava.h index 30e15c5..8cc738a 100755 --- a/src/qscint/src/Qsci/qscilexerjava.h +++ b/src/qscint/src/Qsci/qscilexerjava.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerJava class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerjavascript.h b/src/qscint/src/Qsci/qscilexerjavascript.h index e9f8b2c..496c4d6 100755 --- a/src/qscint/src/Qsci/qscilexerjavascript.h +++ b/src/qscint/src/Qsci/qscilexerjavascript.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerJavaScript class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerjson.h b/src/qscint/src/Qsci/qscilexerjson.h index 9c0c5b6..a2146c8 100755 --- a/src/qscint/src/Qsci/qscilexerjson.h +++ b/src/qscint/src/Qsci/qscilexerjson.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerJSON class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerlua.h b/src/qscint/src/Qsci/qscilexerlua.h index 482c471..223865f 100755 --- a/src/qscint/src/Qsci/qscilexerlua.h +++ b/src/qscint/src/Qsci/qscilexerlua.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerLua class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexermakefile.h b/src/qscint/src/Qsci/qscilexermakefile.h index cb24707..76c1bbc 100755 --- a/src/qscint/src/Qsci/qscilexermakefile.h +++ b/src/qscint/src/Qsci/qscilexermakefile.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerMakefile class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexermarkdown.h b/src/qscint/src/Qsci/qscilexermarkdown.h index 48dfcfb..dc25715 100755 --- a/src/qscint/src/Qsci/qscilexermarkdown.h +++ b/src/qscint/src/Qsci/qscilexermarkdown.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerMarkdown class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexermatlab.h b/src/qscint/src/Qsci/qscilexermatlab.h index 2b085de..fb274f2 100755 --- a/src/qscint/src/Qsci/qscilexermatlab.h +++ b/src/qscint/src/Qsci/qscilexermatlab.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerMatlab class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexeroctave.h b/src/qscint/src/Qsci/qscilexeroctave.h index 8ac9a85..b8c4f90 100755 --- a/src/qscint/src/Qsci/qscilexeroctave.h +++ b/src/qscint/src/Qsci/qscilexeroctave.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerOctave class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerpascal.h b/src/qscint/src/Qsci/qscilexerpascal.h index 548e14d..9e09563 100755 --- a/src/qscint/src/Qsci/qscilexerpascal.h +++ b/src/qscint/src/Qsci/qscilexerpascal.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerPascal class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerperl.h b/src/qscint/src/Qsci/qscilexerperl.h index fe98a34..658a809 100755 --- a/src/qscint/src/Qsci/qscilexerperl.h +++ b/src/qscint/src/Qsci/qscilexerperl.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerPerl class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerpo.h b/src/qscint/src/Qsci/qscilexerpo.h index be5f72e..083308f 100755 --- a/src/qscint/src/Qsci/qscilexerpo.h +++ b/src/qscint/src/Qsci/qscilexerpo.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerPO class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerpostscript.h b/src/qscint/src/Qsci/qscilexerpostscript.h index c88c611..a569dcc 100755 --- a/src/qscint/src/Qsci/qscilexerpostscript.h +++ b/src/qscint/src/Qsci/qscilexerpostscript.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerPostScript class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerpov.h b/src/qscint/src/Qsci/qscilexerpov.h index 0161cd7..8057b5e 100755 --- a/src/qscint/src/Qsci/qscilexerpov.h +++ b/src/qscint/src/Qsci/qscilexerpov.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerPOV class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerproperties.h b/src/qscint/src/Qsci/qscilexerproperties.h index c68d27f..547de60 100755 --- a/src/qscint/src/Qsci/qscilexerproperties.h +++ b/src/qscint/src/Qsci/qscilexerproperties.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerProperties class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerpython.h b/src/qscint/src/Qsci/qscilexerpython.h index 1662c05..2212794 100755 --- a/src/qscint/src/Qsci/qscilexerpython.h +++ b/src/qscint/src/Qsci/qscilexerpython.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerPython class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerr.h b/src/qscint/src/Qsci/qscilexerr.h index b3a7cf8..89aa9ab 100755 --- a/src/qscint/src/Qsci/qscilexerr.h +++ b/src/qscint/src/Qsci/qscilexerr.h @@ -2,7 +2,7 @@ #pragma once // This defines the interface to the QsciLexerR class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerruby.h b/src/qscint/src/Qsci/qscilexerruby.h index 632d220..4d2e485 100755 --- a/src/qscint/src/Qsci/qscilexerruby.h +++ b/src/qscint/src/Qsci/qscilexerruby.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerRuby class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerspice.h b/src/qscint/src/Qsci/qscilexerspice.h index 6ba4f91..6be18bd 100755 --- a/src/qscint/src/Qsci/qscilexerspice.h +++ b/src/qscint/src/Qsci/qscilexerspice.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerSpice class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexersql.h b/src/qscint/src/Qsci/qscilexersql.h index 4eeda31..0b9e6f1 100755 --- a/src/qscint/src/Qsci/qscilexersql.h +++ b/src/qscint/src/Qsci/qscilexersql.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerSQL class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexertcl.h b/src/qscint/src/Qsci/qscilexertcl.h index af744f6..8810d06 100755 --- a/src/qscint/src/Qsci/qscilexertcl.h +++ b/src/qscint/src/Qsci/qscilexertcl.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerTCL class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexertex.h b/src/qscint/src/Qsci/qscilexertex.h index 5c04f45..cd8274f 100755 --- a/src/qscint/src/Qsci/qscilexertex.h +++ b/src/qscint/src/Qsci/qscilexertex.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerTeX class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerverilog.h b/src/qscint/src/Qsci/qscilexerverilog.h index 5131a5b..243db7c 100755 --- a/src/qscint/src/Qsci/qscilexerverilog.h +++ b/src/qscint/src/Qsci/qscilexerverilog.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerVerilog class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexervhdl.h b/src/qscint/src/Qsci/qscilexervhdl.h index 64020d2..6f121fb 100755 --- a/src/qscint/src/Qsci/qscilexervhdl.h +++ b/src/qscint/src/Qsci/qscilexervhdl.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerVHDL class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexerxml.h b/src/qscint/src/Qsci/qscilexerxml.h index 2efcf84..ab8b767 100755 --- a/src/qscint/src/Qsci/qscilexerxml.h +++ b/src/qscint/src/Qsci/qscilexerxml.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerXML class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscilexeryaml.h b/src/qscint/src/Qsci/qscilexeryaml.h index 609e465..c30847b 100755 --- a/src/qscint/src/Qsci/qscilexeryaml.h +++ b/src/qscint/src/Qsci/qscilexeryaml.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciLexerYAML class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscimacro.h b/src/qscint/src/Qsci/qscimacro.h index 45f3649..89610a5 100755 --- a/src/qscint/src/Qsci/qscimacro.h +++ b/src/qscint/src/Qsci/qscimacro.h @@ -1,6 +1,6 @@ // This defines the interface to the QsciMacro class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qsciprinter.h b/src/qscint/src/Qsci/qsciprinter.h index 5cbf785..869a8ed 100755 --- a/src/qscint/src/Qsci/qsciprinter.h +++ b/src/qscint/src/Qsci/qsciprinter.h @@ -1,6 +1,6 @@ // This module defines interface to the QsciPrinter class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qsciscintilla.h b/src/qscint/src/Qsci/qsciscintilla.h index 1420d7e..e339c0b 100755 --- a/src/qscint/src/Qsci/qsciscintilla.h +++ b/src/qscint/src/Qsci/qsciscintilla.h @@ -1,7 +1,7 @@ // This module defines the "official" high-level API of the Qt port of // Scintilla. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qsciscintillabase.h b/src/qscint/src/Qsci/qsciscintillabase.h index a1172e9..963dd38 100755 --- a/src/qscint/src/Qsci/qsciscintillabase.h +++ b/src/qscint/src/Qsci/qsciscintillabase.h @@ -1,6 +1,6 @@ // This class defines the "official" low-level API. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscistyle.h b/src/qscint/src/Qsci/qscistyle.h index 3fae62a..c6eb7ed 100755 --- a/src/qscint/src/Qsci/qscistyle.h +++ b/src/qscint/src/Qsci/qscistyle.h @@ -1,6 +1,6 @@ // This module defines interface to the QsciStyle class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/Qsci/qscistyledtext.h b/src/qscint/src/Qsci/qscistyledtext.h index c28cda5..4298f2b 100755 --- a/src/qscint/src/Qsci/qscistyledtext.h +++ b/src/qscint/src/Qsci/qscistyledtext.h @@ -1,6 +1,6 @@ // This module defines interface to the QsciStyledText class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/SciAccessibility.cpp b/src/qscint/src/SciAccessibility.cpp index 0c0e049..447eb86 100755 --- a/src/qscint/src/SciAccessibility.cpp +++ b/src/qscint/src/SciAccessibility.cpp @@ -1,6 +1,6 @@ -// The implementation of the class that implements accessibility support. +// The implementation of the class that implements accessibility support. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/SciAccessibility.h b/src/qscint/src/SciAccessibility.h index 181f5c8..7dc2e77 100755 --- a/src/qscint/src/SciAccessibility.h +++ b/src/qscint/src/SciAccessibility.h @@ -1,6 +1,6 @@ // The definition of the class that implements accessibility support. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/SciClasses.cpp b/src/qscint/src/SciClasses.cpp index 7393332..438965a 100755 --- a/src/qscint/src/SciClasses.cpp +++ b/src/qscint/src/SciClasses.cpp @@ -1,7 +1,7 @@ // The implementation of various Qt version independent classes used by the // rest of the port. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/SciClasses.h b/src/qscint/src/SciClasses.h index cabda20..d5e9e08 100755 --- a/src/qscint/src/SciClasses.h +++ b/src/qscint/src/SciClasses.h @@ -1,7 +1,7 @@ // The definition of various Qt version independent classes used by the rest of // the port. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/ScintillaQt.cpp b/src/qscint/src/ScintillaQt.cpp index c9ca654..4efb1dd 100755 --- a/src/qscint/src/ScintillaQt.cpp +++ b/src/qscint/src/ScintillaQt.cpp @@ -1,6 +1,6 @@ // The implementation of the Qt specific subclass of ScintillaBase. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/ScintillaQt.h b/src/qscint/src/ScintillaQt.h index e522167..2bc53ba 100755 --- a/src/qscint/src/ScintillaQt.h +++ b/src/qscint/src/ScintillaQt.h @@ -1,6 +1,6 @@ // The definition of the Qt specific subclass of ScintillaBase. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qsciabstractapis.cpp b/src/qscint/src/qsciabstractapis.cpp index 3a5a37f..6f17d6e 100755 --- a/src/qscint/src/qsciabstractapis.cpp +++ b/src/qscint/src/qsciabstractapis.cpp @@ -1,6 +1,6 @@ // This module implements the QsciAbstractAPIs class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qsciapis.cpp b/src/qscint/src/qsciapis.cpp index f8b100f..d4abccc 100755 --- a/src/qscint/src/qsciapis.cpp +++ b/src/qscint/src/qsciapis.cpp @@ -1,6 +1,6 @@ // This module implements the QsciAPIs class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscicommand.cpp b/src/qscint/src/qscicommand.cpp index 079f375..840c3bc 100755 --- a/src/qscint/src/qscicommand.cpp +++ b/src/qscint/src/qscicommand.cpp @@ -1,6 +1,6 @@ // This module implements the QsciCommand class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscicommandset.cpp b/src/qscint/src/qscicommandset.cpp index 1945a56..e06181f 100755 --- a/src/qscint/src/qscicommandset.cpp +++ b/src/qscint/src/qscicommandset.cpp @@ -1,6 +1,6 @@ // This module implements the QsciCommandSet class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // @@ -47,7 +47,9 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) const char *desc; }; + //20230216 屏蔽一些生僻的命令,加宽速度,让出快捷键 static struct sci_cmd cmd_table[] = { + { QsciCommand::LineDown, Qt::Key_Down, @@ -58,6 +60,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) #endif QT_TRANSLATE_NOOP("QsciCommand", "Move down one line") }, + { QsciCommand::LineDownExtend, Qt::Key_Down | Qt::SHIFT, @@ -122,12 +125,13 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Scroll view up one line") }, +#if 0 { QsciCommand::ScrollToStart, #if defined(USING_OSX_KEYS) Qt::Key_Home, #else - 0, + Qt::Key_Home | Qt::CTRL, #endif 0, QT_TRANSLATE_NOOP("QsciCommand", "Scroll to start of document") @@ -137,11 +141,13 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) #if defined(USING_OSX_KEYS) Qt::Key_End, #else - 0, + Qt::Key_End | Qt::CTRL, #endif 0, QT_TRANSLATE_NOOP("QsciCommand", "Scroll to end of document") }, +#endif +#if 0 { QsciCommand::VerticalCentreCaret, #if defined(USING_OSX_KEYS) @@ -159,6 +165,10 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Move down one paragraph") }, +#endif + +#if 0 + //测试无效 { QsciCommand::ParaDownExtend, Qt::Key_BracketRight | Qt::CTRL | Qt::SHIFT, @@ -166,12 +176,15 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend selection down one paragraph") }, +#endif { QsciCommand::ParaUp, Qt::Key_BracketLeft | Qt::CTRL, 0, QT_TRANSLATE_NOOP("QsciCommand", "Move up one paragraph") }, + +#if 0 { QsciCommand::ParaUpExtend, Qt::Key_BracketLeft | Qt::CTRL | Qt::SHIFT, @@ -179,6 +192,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend selection up one paragraph") }, +#endif { QsciCommand::CharLeft, Qt::Key_Left, @@ -189,6 +203,8 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) #endif QT_TRANSLATE_NOOP("QsciCommand", "Move left one character") }, + + { QsciCommand::CharLeftExtend, Qt::Key_Left | Qt::SHIFT, @@ -200,6 +216,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend selection left one character") }, + { QsciCommand::CharLeftRectExtend, Qt::Key_Left | Qt::ALT | Qt::SHIFT, @@ -243,6 +260,8 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend rectangular selection right one character") }, + +#if 0 { QsciCommand::WordLeft, #if defined(USING_OSX_KEYS) @@ -253,6 +272,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Move left one word") }, +#endif { QsciCommand::WordLeftExtend, #if defined(USING_OSX_KEYS) @@ -263,6 +283,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Extend selection left one word") }, +#if 0 { QsciCommand::WordRight, #if defined(USING_OSX_KEYS) @@ -273,12 +294,16 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Move right one word") }, +#endif +#if 0 { QsciCommand::WordRightExtend, Qt::Key_Right | Qt::CTRL | Qt::SHIFT, 0, QT_TRANSLATE_NOOP("QsciCommand", "Extend selection right one word") }, +#endif +#if 0 { QsciCommand::WordLeftEnd, 0, @@ -313,6 +338,8 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend selection to end of next word") }, +#endif +#if 0 { QsciCommand::WordPartLeft, Qt::Key_Slash | Qt::CTRL, @@ -339,6 +366,8 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend selection right one word part") }, +#endif +#if 0 { QsciCommand::Home, #if defined(USING_OSX_KEYS) @@ -371,6 +400,8 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend rectangular selection to start of document line") }, +#endif +#if 0 { QsciCommand::HomeDisplay, #if defined(USING_OSX_KEYS) @@ -406,6 +437,8 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend selection to start of display or document line") }, +#endif + { QsciCommand::VCHome, #if defined(USING_OSX_KEYS) @@ -417,6 +450,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Move to first visible character in document line") }, + { QsciCommand::VCHomeExtend, #if defined(USING_OSX_KEYS) @@ -428,6 +462,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend selection to first visible character in document line") }, +#if 0 { QsciCommand::VCHomeRectExtend, #if defined(USING_OSX_KEYS) @@ -453,6 +488,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend selection to first visible character in display or document line") }, +#endif { QsciCommand::LineEnd, #if defined(USING_OSX_KEYS) @@ -463,6 +499,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Move to end of document line") }, + { QsciCommand::LineEndExtend, #if defined(USING_OSX_KEYS) @@ -474,6 +511,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend selection to end of document line") }, +#if 0 { QsciCommand::LineEndRectExtend, #if defined(USING_OSX_KEYS) @@ -485,6 +523,8 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend rectangular selection to end of document line") }, +#endif +#if 0 { QsciCommand::LineEndDisplay, #if defined(USING_OSX_KEYS) @@ -495,6 +535,8 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Move to end of display line") }, +#endif +#if 0 { QsciCommand::LineEndDisplayExtend, #if defined(USING_OSX_KEYS) @@ -520,6 +562,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Extend selection to end of display or document line") }, +#endif { QsciCommand::DocumentStart, #if defined(USING_OSX_KEYS) @@ -568,7 +611,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Move up one page") }, - { + /* { QsciCommand::PageUpExtend, Qt::Key_PageUp | Qt::SHIFT, 0, @@ -580,7 +623,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Extend rectangular selection up one page") - }, + },*/ { QsciCommand::PageDown, Qt::Key_PageDown, @@ -591,7 +634,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) #endif QT_TRANSLATE_NOOP("QsciCommand", "Move down one page") }, - { + /*{ QsciCommand::PageDownExtend, Qt::Key_PageDown | Qt::SHIFT, #if defined(USING_OSX_KEYS) @@ -611,7 +654,8 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) #endif QT_TRANSLATE_NOOP("QsciCommand", "Extend rectangular selection down one page") - }, + },*/ +#if 0 { QsciCommand::StutteredPageUp, 0, @@ -638,6 +682,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Stuttered extend selection down one page") }, +#endif { QsciCommand::Delete, Qt::Key_Delete, @@ -658,6 +703,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) #endif QT_TRANSLATE_NOOP("QsciCommand", "Delete previous character") }, +#if 0 { QsciCommand::DeleteBackNotLine, 0, @@ -677,6 +723,8 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Delete word to right") }, +#endif +#if 0 { QsciCommand::DeleteWordRightEnd, #if defined(USING_OSX_KEYS) @@ -688,6 +736,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Delete right to end of next word") }, +#endif { QsciCommand::DeleteLineLeft, Qt::Key_Backspace | Qt::CTRL | Qt::SHIFT, @@ -729,18 +778,21 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Transpose current and previous lines") },*/ +#if 0 { QsciCommand::LineDuplicate, 0, 0, QT_TRANSLATE_NOOP("QsciCommand", "Duplicate the current line") }, +#endif { QsciCommand::SelectAll, Qt::Key_A | Qt::CTRL, 0, QT_TRANSLATE_NOOP("QsciCommand", "Select all") }, +#if 0 { QsciCommand::MoveSelectedLinesUp, 0, @@ -754,12 +806,15 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) QT_TRANSLATE_NOOP("QsciCommand", "Move selected lines down one line") }, +#endif +#if 0 { QsciCommand::SelectionDuplicate, Qt::Key_D | Qt::CTRL, 0, QT_TRANSLATE_NOOP("QsciCommand", "Duplicate selection") }, +#endif { QsciCommand::SelectionLowerCase, Qt::Key_U | Qt::CTRL, @@ -802,18 +857,21 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) Qt::Key_Return | Qt::SHIFT, QT_TRANSLATE_NOOP("QsciCommand", "Insert newline") }, +#if 0 { QsciCommand::Formfeed, 0, 0, QT_TRANSLATE_NOOP("QsciCommand", "Formfeed") }, +#endif { QsciCommand::Tab, Qt::Key_Tab, 0, QT_TRANSLATE_NOOP("QsciCommand", "Indent one level") }, +#if 0 { QsciCommand::Backtab, Qt::Key_Tab | Qt::SHIFT, @@ -826,6 +884,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Cancel") }, +#endif { QsciCommand::Undo, Qt::Key_Z | Qt::CTRL, @@ -842,9 +901,10 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Redo last command") }, +#if 1 { QsciCommand::ZoomIn, - Qt::Key_Plus | Qt::CTRL, + Qt::Key_Equal | Qt::CTRL, 0, QT_TRANSLATE_NOOP("QsciCommand", "Zoom in") }, @@ -853,7 +913,9 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) Qt::Key_Minus | Qt::CTRL, 0, QT_TRANSLATE_NOOP("QsciCommand", "Zoom out") - }, + }, +#endif +#if 0 { QsciCommand::MoveLineUp, Qt::Key_Up | Qt::CTRL | Qt::SHIFT, @@ -867,6 +929,7 @@ QsciCommandSet::QsciCommandSet(QsciScintilla *qs) : qsci(qs) 0, QT_TRANSLATE_NOOP("QsciCommand", "Move Line down") }, +#endif }; // Clear the default map. diff --git a/src/qscint/src/qscidocument.cpp b/src/qscint/src/qscidocument.cpp index 2eb5841..895ed34 100755 --- a/src/qscint/src/qscidocument.cpp +++ b/src/qscint/src/qscidocument.cpp @@ -1,6 +1,6 @@ // This module implements the QsciDocument class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexer.cpp b/src/qscint/src/qscilexer.cpp index 070a4a6..5a20922 100755 --- a/src/qscint/src/qscilexer.cpp +++ b/src/qscint/src/qscilexer.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexer class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerasm.cpp b/src/qscint/src/qscilexerasm.cpp index fdb2851..1da5608 100755 --- a/src/qscint/src/qscilexerasm.cpp +++ b/src/qscint/src/qscilexerasm.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerAsm class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexeravs.cpp b/src/qscint/src/qscilexeravs.cpp index 79468e8..7abd21b 100755 --- a/src/qscint/src/qscilexeravs.cpp +++ b/src/qscint/src/qscilexeravs.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerAVS class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerbash.cpp b/src/qscint/src/qscilexerbash.cpp index 0c049ee..24546ef 100755 --- a/src/qscint/src/qscilexerbash.cpp +++ b/src/qscint/src/qscilexerbash.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerBash class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerbatch.cpp b/src/qscint/src/qscilexerbatch.cpp index 9682fc3..92c28eb 100755 --- a/src/qscint/src/qscilexerbatch.cpp +++ b/src/qscint/src/qscilexerbatch.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerBatch class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexercmake.cpp b/src/qscint/src/qscilexercmake.cpp index d850444..e1c580c 100755 --- a/src/qscint/src/qscilexercmake.cpp +++ b/src/qscint/src/qscilexercmake.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerCMake class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexercoffeescript.cpp b/src/qscint/src/qscilexercoffeescript.cpp index b718d70..355e27b 100755 --- a/src/qscint/src/qscilexercoffeescript.cpp +++ b/src/qscint/src/qscilexercoffeescript.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerCoffeeScript class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexercpp.cpp b/src/qscint/src/qscilexercpp.cpp index c7a3007..bb59df7 100755 --- a/src/qscint/src/qscilexercpp.cpp +++ b/src/qscint/src/qscilexercpp.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerCPP class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexercsharp.cpp b/src/qscint/src/qscilexercsharp.cpp index 22427eb..66241df 100755 --- a/src/qscint/src/qscilexercsharp.cpp +++ b/src/qscint/src/qscilexercsharp.cpp @@ -1,7 +1,7 @@ #include "Qsci/qscilexercsharp.h" // This module implements the QsciLexerCSharp class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexercss.cpp b/src/qscint/src/qscilexercss.cpp index f3cc026..9023767 100755 --- a/src/qscint/src/qscilexercss.cpp +++ b/src/qscint/src/qscilexercss.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerCSS class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexercustom.cpp b/src/qscint/src/qscilexercustom.cpp index e1bbda4..490c154 100755 --- a/src/qscint/src/qscilexercustom.cpp +++ b/src/qscint/src/qscilexercustom.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerCustom class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerd.cpp b/src/qscint/src/qscilexerd.cpp index 61eec64..7ee2b86 100755 --- a/src/qscint/src/qscilexerd.cpp +++ b/src/qscint/src/qscilexerd.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerD class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerdiff.cpp b/src/qscint/src/qscilexerdiff.cpp index 4e27267..f22f59b 100755 --- a/src/qscint/src/qscilexerdiff.cpp +++ b/src/qscint/src/qscilexerdiff.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerDiff class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexeredifact.cpp b/src/qscint/src/qscilexeredifact.cpp index 1a9d4c9..5bf09df 100755 --- a/src/qscint/src/qscilexeredifact.cpp +++ b/src/qscint/src/qscilexeredifact.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerEDIFACT class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerfortran.cpp b/src/qscint/src/qscilexerfortran.cpp index fd940a2..eeaae3a 100755 --- a/src/qscint/src/qscilexerfortran.cpp +++ b/src/qscint/src/qscilexerfortran.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerFortran class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerfortran77.cpp b/src/qscint/src/qscilexerfortran77.cpp index 130cda7..16aca01 100755 --- a/src/qscint/src/qscilexerfortran77.cpp +++ b/src/qscint/src/qscilexerfortran77.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerFortran77 class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerglobal.cpp b/src/qscint/src/qscilexerglobal.cpp index 0ac42e3..d24c97b 100755 --- a/src/qscint/src/qscilexerglobal.cpp +++ b/src/qscint/src/qscilexerglobal.cpp @@ -147,9 +147,11 @@ QFont QsciLexerGlobal::defaultFont(int style) const return f; case LINE_NUMBER_MARGIN: + { //这个对应STYLE_LINENUMBER的默认大小为10 - f.setPointSize(12); - return f; + QFont linefont("Courier New", 10); + return linefont; + } default: break; } @@ -163,7 +165,7 @@ QColor QsciLexerGlobal::defaultColor(int style) const switch (style) { case GLOBAL_OVERRIDE: - return QColor(0xFFFF80); + return QColor(Qt::black); case DEFAULT_STYLE: return QColor(Qt::black); @@ -328,7 +330,7 @@ QColor QsciLexerGlobal::defaultPaper(int style) const switch (style) { case GLOBAL_OVERRIDE: - return QColor(0xFF8000); + return QColor(0xFFFFFF); case DEFAULT_STYLE: return QColor(0xFFFFFF); @@ -346,7 +348,7 @@ QColor QsciLexerGlobal::defaultPaper(int style) const return QColor(0xE8E8FF); case SELECT_TEXT_COLOR: - return QColor(0xC0C0C0); + return QColor(0xffff00); case CARET_COLOUR: return QColor(0x919994); diff --git a/src/qscint/src/qscilexergo.cpp b/src/qscint/src/qscilexergo.cpp index bc56423..96f28a8 100755 --- a/src/qscint/src/qscilexergo.cpp +++ b/src/qscint/src/qscilexergo.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerGO class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerhtml.cpp b/src/qscint/src/qscilexerhtml.cpp index da7b6fa..c30e1d6 100755 --- a/src/qscint/src/qscilexerhtml.cpp +++ b/src/qscint/src/qscilexerhtml.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerHTML class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // @@ -312,21 +312,21 @@ QFont QsciLexerHTML::defaultFont(int style) const case Default: case Entity: #if defined(Q_OS_WIN) - f = QFont("Courier New",13); + f = QFont("Courier New", QsciLexer::s_defaultFontSize); #elif defined(Q_OS_MAC) - f = QFont("Courier New", 13); + f = QFont("Courier New", QsciLexer::s_defaultFontSize); #else - f = QFont("Bitstream Charter",10); + f = QFont("Bitstream Charter", QsciLexer::s_defaultFontSize); #endif break; case HTMLComment: #if defined(Q_OS_WIN) - f = QFont("Courier New",9); + f = QFont("Courier New", QsciLexer::s_defaultFontSize); #elif defined(Q_OS_MAC) - f = QFont("Verdana", 12); + f = QFont("Verdana", QsciLexer::s_defaultFontSize); #else - f = QFont("Bitstream Vera Sans",8); + f = QFont("Bitstream Vera Sans", QsciLexer::s_defaultFontSize); #endif break; @@ -354,9 +354,9 @@ QFont QsciLexerHTML::defaultFont(int style) const #if defined(Q_OS_WIN) f = QFont("Courier New",QsciLexer::s_defaultFontSize); #elif defined(Q_OS_MAC) - f = QFont("Comic Sans MS", 12); + f = QFont("Comic Sans MS", QsciLexer::s_defaultFontSize); #else - f = QFont("Bitstream Vera Serif",9); + f = QFont("Bitstream Vera Serif", QsciLexer::s_defaultFontSize); #endif f.setBold(true); break; @@ -381,9 +381,9 @@ QFont QsciLexerHTML::defaultFont(int style) const #if defined(Q_OS_WIN) f = QFont("Courier New",QsciLexer::s_defaultFontSize); #elif defined(Q_OS_MAC) - f = QFont("Comic Sans MS", 12); + f = QFont("Comic Sans MS", QsciLexer::s_defaultFontSize); #else - f = QFont("Bitstream Vera Serif",9); + f = QFont("Bitstream Vera Serif", QsciLexer::s_defaultFontSize); #endif break; @@ -400,9 +400,9 @@ QFont QsciLexerHTML::defaultFont(int style) const #if defined(Q_OS_WIN) f = QFont("Courier New",QsciLexer::s_defaultFontSize); #elif defined(Q_OS_MAC) - f = QFont("Lucida Grande", 12); + f = QFont("Lucida Grande", QsciLexer::s_defaultFontSize); #else - f = QFont("Bitstream Vera Serif",9); + f = QFont("Bitstream Vera Serif", QsciLexer::s_defaultFontSize); #endif break; @@ -411,9 +411,9 @@ QFont QsciLexerHTML::defaultFont(int style) const #if defined(Q_OS_WIN) f = QFont("Courier New",QsciLexer::s_defaultFontSize); #elif defined(Q_OS_MAC) - f = QFont("Lucida Grande", 12); + f = QFont("Lucida Grande", QsciLexer::s_defaultFontSize); #else - f = QFont("Bitstream Vera Serif",9); + f = QFont("Bitstream Vera Serif", QsciLexer::s_defaultFontSize); #endif f.setBold(false); break; @@ -425,9 +425,9 @@ QFont QsciLexerHTML::defaultFont(int style) const #if defined(Q_OS_WIN) f = QFont("Courier New",QsciLexer::s_defaultFontSize); #elif defined(Q_OS_MAC) - f = QFont("Courier New", 12); + f = QFont("Courier New", QsciLexer::s_defaultFontSize); #else - f = QFont("Bitstream Vera Sans Mono",9); + f = QFont("Bitstream Vera Sans Mono", QsciLexer::s_defaultFontSize); #endif break; @@ -442,9 +442,9 @@ QFont QsciLexerHTML::defaultFont(int style) const #if defined(Q_OS_WIN) f = QFont("Courier New",QsciLexer::s_defaultFontSize); #elif defined(Q_OS_MAC) - f = QFont("Comic Sans MS", 12); + f = QFont("Comic Sans MS", QsciLexer::s_defaultFontSize); #else - f = QFont("Bitstream Vera Serif",9); + f = QFont("Bitstream Vera Serif", QsciLexer::s_defaultFontSize); #endif f.setItalic(true); break; diff --git a/src/qscint/src/qscilexeridl.cpp b/src/qscint/src/qscilexeridl.cpp index cd903de..e9acf73 100755 --- a/src/qscint/src/qscilexeridl.cpp +++ b/src/qscint/src/qscilexeridl.cpp @@ -1,7 +1,7 @@ #include "Qsci/qscilexeridl.h" // This module implements the QsciLexerIDL class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerjava.cpp b/src/qscint/src/qscilexerjava.cpp index d0a314d..57789eb 100755 --- a/src/qscint/src/qscilexerjava.cpp +++ b/src/qscint/src/qscilexerjava.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerJava class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerjavascript.cpp b/src/qscint/src/qscilexerjavascript.cpp index a49b4ba..00ebf28 100755 --- a/src/qscint/src/qscilexerjavascript.cpp +++ b/src/qscint/src/qscilexerjavascript.cpp @@ -1,7 +1,7 @@ #include "Qsci/qscilexerjavascript.h" // This module implements the QsciLexerJavaScript class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerjson.cpp b/src/qscint/src/qscilexerjson.cpp index 03d0a68..5ff45ce 100755 --- a/src/qscint/src/qscilexerjson.cpp +++ b/src/qscint/src/qscilexerjson.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerJSON class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerlua.cpp b/src/qscint/src/qscilexerlua.cpp index 870b37b..8cef78b 100755 --- a/src/qscint/src/qscilexerlua.cpp +++ b/src/qscint/src/qscilexerlua.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerLua class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexermakefile.cpp b/src/qscint/src/qscilexermakefile.cpp index f1418db..0604ca3 100755 --- a/src/qscint/src/qscilexermakefile.cpp +++ b/src/qscint/src/qscilexermakefile.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerMakefile class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexermarkdown.cpp b/src/qscint/src/qscilexermarkdown.cpp index d850e19..965f3d2 100755 --- a/src/qscint/src/qscilexermarkdown.cpp +++ b/src/qscint/src/qscilexermarkdown.cpp @@ -1,6 +1,6 @@ -// This module implements the QsciLexerMarkdown class. +// This module implements the QsciLexerMarkdown class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // @@ -189,8 +189,8 @@ QColor QsciLexerMarkdown::defaultPaper(int style) const case UnorderedListItem: return QColor(0xde, 0xd8, 0xc3); - case OrderedListItem: - return QColor(0xb8, 0xc3, 0xe1); + /*case OrderedListItem: + return QColor(0xb8, 0xc3, 0xe1);*/ case BlockQuote: return QColor(0xcb, 0xdc, 0xcb); diff --git a/src/qscint/src/qscilexermatlab.cpp b/src/qscint/src/qscilexermatlab.cpp index d817d73..56cc478 100755 --- a/src/qscint/src/qscilexermatlab.cpp +++ b/src/qscint/src/qscilexermatlab.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerMatlab class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexeroctave.cpp b/src/qscint/src/qscilexeroctave.cpp index 31ae12b..44e5f30 100755 --- a/src/qscint/src/qscilexeroctave.cpp +++ b/src/qscint/src/qscilexeroctave.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerOctave class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerpascal.cpp b/src/qscint/src/qscilexerpascal.cpp index 38d2daf..772522e 100755 --- a/src/qscint/src/qscilexerpascal.cpp +++ b/src/qscint/src/qscilexerpascal.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerPascal class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerperl.cpp b/src/qscint/src/qscilexerperl.cpp index 27b6be6..c69428f 100755 --- a/src/qscint/src/qscilexerperl.cpp +++ b/src/qscint/src/qscilexerperl.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerPerl class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerpo.cpp b/src/qscint/src/qscilexerpo.cpp index 8cc1c7b..8519259 100755 --- a/src/qscint/src/qscilexerpo.cpp +++ b/src/qscint/src/qscilexerpo.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerPO class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerpostscript.cpp b/src/qscint/src/qscilexerpostscript.cpp index 804451b..bb1eec3 100755 --- a/src/qscint/src/qscilexerpostscript.cpp +++ b/src/qscint/src/qscilexerpostscript.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerPostScript class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerpov.cpp b/src/qscint/src/qscilexerpov.cpp index f7fb926..1a8f686 100755 --- a/src/qscint/src/qscilexerpov.cpp +++ b/src/qscint/src/qscilexerpov.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerPOV class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerproperties.cpp b/src/qscint/src/qscilexerproperties.cpp index ae00c9c..e72b5ea 100755 --- a/src/qscint/src/qscilexerproperties.cpp +++ b/src/qscint/src/qscilexerproperties.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerProperties class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerpython.cpp b/src/qscint/src/qscilexerpython.cpp index fd06ddc..b1025f2 100755 --- a/src/qscint/src/qscilexerpython.cpp +++ b/src/qscint/src/qscilexerpython.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerPython class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerr.cpp b/src/qscint/src/qscilexerr.cpp index 1de7014..4b50985 100755 --- a/src/qscint/src/qscilexerr.cpp +++ b/src/qscint/src/qscilexerr.cpp @@ -1,5 +1,5 @@ -#include "Qsci/qsciLexerr.h" +#include "Qsci/qscilexerr.h" #include #include diff --git a/src/qscint/src/qscilexerruby.cpp b/src/qscint/src/qscilexerruby.cpp index 25c6ca4..c24fca1 100755 --- a/src/qscint/src/qscilexerruby.cpp +++ b/src/qscint/src/qscilexerruby.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerRuby class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerspice.cpp b/src/qscint/src/qscilexerspice.cpp index fc458b9..e3d039f 100755 --- a/src/qscint/src/qscilexerspice.cpp +++ b/src/qscint/src/qscilexerspice.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerSpice class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexersql.cpp b/src/qscint/src/qscilexersql.cpp index 1f4b93d..5a3203b 100755 --- a/src/qscint/src/qscilexersql.cpp +++ b/src/qscint/src/qscilexersql.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerSQL class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // @@ -305,7 +305,7 @@ QString QsciLexerSQL::description(int style) const return tr("SQL*Plus comment"); case CommentLineHash: - return tr("# comment line"); + return tr("comment line"); case CommentDocKeyword: return tr("JavaDoc keyword"); diff --git a/src/qscint/src/qscilexertcl.cpp b/src/qscint/src/qscilexertcl.cpp index 1d06660..d4f4bfb 100755 --- a/src/qscint/src/qscilexertcl.cpp +++ b/src/qscint/src/qscilexertcl.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerTCL class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexertex.cpp b/src/qscint/src/qscilexertex.cpp index 51c562d..c9a3f38 100755 --- a/src/qscint/src/qscilexertex.cpp +++ b/src/qscint/src/qscilexertex.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerTeX class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexertext.cpp b/src/qscint/src/qscilexertext.cpp index 87dfa92..0fa4c49 100755 --- a/src/qscint/src/qscilexertext.cpp +++ b/src/qscint/src/qscilexertext.cpp @@ -72,23 +72,10 @@ QFont QsciLexerText::defaultFont(int style) const switch (style) { case Default: -#if defined(Q_OS_WIN) return s_defaultTxtFont; -#elif defined(Q_OS_MAC) - //return QFont("Courier", 12); - return s_defaultTxtFont; -#else - return s_defaultTxtFont;//sQFont("Bitstream Vera Sans Mono", 9); -#endif break; case Ascii: -#if defined(Q_OS_WIN) - return QFont("Courier New", 12); -#elif defined(Q_OS_MAC) - return QFont("Courier New", 14); -#else return s_defaultTxtFont; -#endif break; case Keyword: #if defined(Q_OS_WIN) diff --git a/src/qscint/src/qscilexerverilog.cpp b/src/qscint/src/qscilexerverilog.cpp index d1c36d7..4c25fe7 100755 --- a/src/qscint/src/qscilexerverilog.cpp +++ b/src/qscint/src/qscilexerverilog.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerVerilog class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexervhdl.cpp b/src/qscint/src/qscilexervhdl.cpp index 68cabe0..5bc3742 100755 --- a/src/qscint/src/qscilexervhdl.cpp +++ b/src/qscint/src/qscilexervhdl.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerVHDL class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexerxml.cpp b/src/qscint/src/qscilexerxml.cpp index 24976e9..986a52a 100755 --- a/src/qscint/src/qscilexerxml.cpp +++ b/src/qscint/src/qscilexerxml.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerXML class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscilexeryaml.cpp b/src/qscint/src/qscilexeryaml.cpp index f15c758..505eab6 100755 --- a/src/qscint/src/qscilexeryaml.cpp +++ b/src/qscint/src/qscilexeryaml.cpp @@ -1,6 +1,6 @@ // This module implements the QsciLexerYAML class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscimacro.cpp b/src/qscint/src/qscimacro.cpp index 01507b6..c216cae 100755 --- a/src/qscint/src/qscimacro.cpp +++ b/src/qscint/src/qscimacro.cpp @@ -1,6 +1,6 @@ // This module implements the QsciMacro class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscintilla.pro b/src/qscint/src/qscintilla.pro index eb7089f..8cab273 100755 --- a/src/qscint/src/qscintilla.pro +++ b/src/qscint/src/qscintilla.pro @@ -21,7 +21,7 @@ !win32:VERSION = 15.1.0 TEMPLATE = lib -CONFIG += qt warn_off thread exceptions hide_symbols staticlib +CONFIG += qt warn_off thread exceptions hide_symbols release staticlib CONFIG(debug, debug|release) { mac: { diff --git a/src/qscint/src/qscintilla_ch.ts b/src/qscint/src/qscintilla_ch.ts index e35c088..0b427da 100755 --- a/src/qscint/src/qscintilla_ch.ts +++ b/src/qscint/src/qscintilla_ch.ts @@ -1,519 +1,636 @@ - + QsciCommand + Move down one line + Extend selection down one line + Extend rectangular selection down one line + Scroll view down one line + Move up one line + Extend selection up one line + Extend rectangular selection up one line + Scroll view up one line + Scroll to start of document + Scroll to end of document + Scroll vertically to centre current line + Move down one paragraph + Extend selection down one paragraph + Move up one paragraph + Extend selection up one paragraph + Move left one character + Extend selection left one character + Extend rectangular selection left one character + Move right one character + Extend selection right one character + Extend rectangular selection right one character + Move left one word + Extend selection left one word + Move right one word + Extend selection right one word + Move to end of previous word + Extend selection to end of previous word + Move to end of next word + Extend selection to end of next word + Move left one word part + Extend selection left one word part + Move right one word part + Extend selection right one word part + Move to start of document line + Extend selection to start of document line + Extend rectangular selection to start of document line + Move to start of display line + Extend selection to start of display line + Move to start of display or document line + Extend selection to start of display or document line + Move to first visible character in document line + Extend selection to first visible character in document line + Extend rectangular selection to first visible character in document line + Move to first visible character of display in document line + Extend selection to first visible character in display or document line + Move to end of document line + Extend selection to end of document line + Extend rectangular selection to end of document line + Move to end of display line + Extend selection to end of display line + Move to end of display or document line + Extend selection to end of display or document line + Move to start of document + Extend selection to start of document + Move to end of document + Extend selection to end of document + Move up one page - Extend selection up one page - - - - Extend rectangular selection up one page - - - + Move down one page - Extend selection down one page - - - - Extend rectangular selection down one page - - - + Stuttered move up one page + Stuttered extend selection up one page + Stuttered move down one page + Stuttered extend selection down one page + Delete current character + Delete previous character + Delete previous character if not at start of line + Delete word to left + Delete word to right + Delete right to end of next word + Delete line to left + Delete line to right + Delete current line + Cut current line + Copy current line - Transpose current and previous lines - - - + Duplicate the current line + Select all + Move selected lines up one line + Move selected lines down one line + Duplicate selection + Convert selection to lower case + Convert selection to upper case + Cut selection + Copy selection + Paste + Toggle insert/overtype + Insert newline + Formfeed + Indent one level + De-indent one level + Cancel + Undo last command + Redo last command + Zoom in + Zoom out + + + Move Line up + + + + + Move Line down + + - QsciLexerAVS + QsciLexerAsm + Default - Block comment - - - - Nested block comment - - - - Line comment + + Comment + Number + + String + + + + Operator + Identifier - Double-quoted string + + Keyword (Cpu instruction) - Triple double-quoted string + + Math instruction - Keyword + + Register - Filter + + Directive - Plugin + + Directive Operand - Function + + Comment Block - Clip property + + Character - User defined + + String eol + + + + + Extinstruction + + + + + Comment Directive QsciLexerBash + Default + Error + Comment + Number + Keyword + Double-quoted string + Single-quoted string + Operator + Identifier + Scalar + Parameter expansion + Backticks + Here document delimiter + Single-quoted here document @@ -521,34 +638,42 @@ QsciLexerBatch + Default + Comment + Keyword + Label + Hide command character + External command + Variable + Operator @@ -556,62 +681,77 @@ QsciLexerCMake + Default + Comment + String + Left quoted string + Right quoted string + Function + Variable + Label + User defined + WHILE block + FOREACH block + IF block + MACRO block + Variable within a string + Number @@ -619,226 +759,282 @@ QsciLexerCPP + Default + Inactive default + C comment + Inactive C comment + C++ comment + Inactive C++ comment + JavaDoc style C comment + Inactive JavaDoc style C comment + Number + Inactive number + Keyword + Inactive keyword + Double-quoted string + Inactive double-quoted string + Single-quoted string + Inactive single-quoted string + IDL UUID + Inactive IDL UUID + Pre-processor block + Inactive pre-processor block + Operator + Inactive operator + Identifier + Inactive identifier + Unclosed string + Inactive unclosed string + C# verbatim string + Inactive C# verbatim string + JavaScript regular expression + Inactive JavaScript regular expression + JavaDoc style C++ comment + Inactive JavaDoc style C++ comment + Secondary keywords and identifiers + Inactive secondary keywords and identifiers + JavaDoc keyword + Inactive JavaDoc keyword + JavaDoc keyword error + Inactive JavaDoc keyword error + Global classes and typedefs + Inactive global classes and typedefs + C++ raw string + Inactive C++ raw string + Vala triple-quoted verbatim string + Inactive Vala triple-quoted verbatim string + Pike hash-quoted string + Inactive Pike hash-quoted string + Pre-processor C comment + Inactive pre-processor C comment + JavaDoc style pre-processor comment + Inactive JavaDoc style pre-processor comment + User-defined literal + Inactive user-defined literal + Task marker + Inactive task marker + Escape sequence + Inactive escape sequence @@ -846,98 +1042,122 @@ QsciLexerCSS + Default + Tag + Class selector + Pseudo-class + Unknown pseudo-class + Operator + CSS1 property + Unknown property + Value + Comment + ID selector + Important + @-rule + Double-quoted string + Single-quoted string + CSS2 property + Attribute + CSS3 property + Pseudo-element + Extended CSS property + Extended pseudo-class + Extended pseudo-element + Media rule + Variable @@ -945,6 +1165,7 @@ QsciLexerCSharp + Verbatim string @@ -952,98 +1173,122 @@ QsciLexerCoffeeScript + Default + C-style comment + C++-style comment + JavaDoc C-style comment + Number + Keyword + Double-quoted string + Single-quoted string + IDL UUID + Pre-processor block + Operator + Identifier + Unclosed string + C# verbatim string + Regular expression + JavaDoc C++-style comment + Secondary keywords and identifiers + JavaDoc keyword + JavaDoc keyword error + Global classes + Block comment + Block regular expression + Block regular expression comment + Instance property @@ -1051,94 +1296,117 @@ QsciLexerD + Default + Block comment + Line comment + DDoc style block comment + Nesting comment + Number + Keyword + Secondary keyword + Documentation keyword + Type definition + String + Unclosed string + Character + Operator + Identifier + DDoc style line comment + DDoc keyword + DDoc keyword error + Backquoted string + Raw string + User defined 1 + User defined 2 + User defined 3 @@ -1146,50 +1414,62 @@ QsciLexerDiff + Default + Comment + Command + Header + Position + Removed line + Added line + Changed line + Added adding patch + Removed adding patch + Added removing patch + Removed removing patch @@ -1197,38 +1477,47 @@ QsciLexerEDIFACT + Default + Segment start + Segment end + Element separator + Composite separator + Release separator + UNA segment header + UNH segment header + Badly formed segment @@ -1236,62 +1525,77 @@ QsciLexerFortran77 + Default + Comment + Number + Single-quoted string + Double-quoted string + Unclosed string + Operator + Identifier + Keyword + Intrinsic function + Extended function + Pre-processor block + Dotted operator + Label + Continuation @@ -1299,445 +1603,688 @@ QsciLexerGO + Verbatim string + + QsciLexerGlobal + + + Global override + + + + + Default + + + + + Indent guideline style + + + + + Brace highlight style + + + + + Bad brace colour + + + + + Current line background colour + + + + + Select text colour + + + + + Caret colour + + + + + Edge colour + + + + + Line number margin + + + + + Bookmark margin + + + + + Fold + + + + + Fold active + + + + + Fold margin + + + + + White space symbol + + + + + Smart HighLighting + + + + + Find Mark Style + + + + + Mark Style 1 + + + + + Mark Style 2 + + + + + Mark Style 3 + + + + + Mark Style 4 + + + + + Mark Style 5 + + + + + Incremental highlight + + + + + Tags match highlight + + + + + Tags attribute + + + + + URL hovered + + + QsciLexerHTML - HTML default + + Default + Tag + Unknown tag + Attribute + Unknown attribute + HTML number + HTML double-quoted string + HTML single-quoted string + Other text in a tag + HTML comment + Entity + End of a tag + Start of an XML fragment + End of an XML fragment + Script tag + Start of an ASP fragment with @ + Start of an ASP fragment + CDATA + Start of a PHP fragment + Unquoted HTML value + ASP X-Code comment + SGML default + SGML command + First parameter of an SGML command + SGML double-quoted string + SGML single-quoted string + SGML error + SGML special entity + SGML comment + First parameter comment of an SGML command + SGML block default + Start of a JavaScript fragment + JavaScript default + JavaScript comment + JavaScript line comment + JavaDoc style JavaScript comment + JavaScript number + JavaScript word + JavaScript keyword + JavaScript double-quoted string + JavaScript single-quoted string + JavaScript symbol + JavaScript unclosed string + JavaScript regular expression + Start of an ASP JavaScript fragment + ASP JavaScript default + ASP JavaScript comment + ASP JavaScript line comment + JavaDoc style ASP JavaScript comment + ASP JavaScript number + ASP JavaScript word + ASP JavaScript keyword + ASP JavaScript double-quoted string + ASP JavaScript single-quoted string + ASP JavaScript symbol + ASP JavaScript unclosed string + ASP JavaScript regular expression + Start of a VBScript fragment + VBScript default + VBScript comment + VBScript number + VBScript keyword + VBScript string + VBScript identifier + VBScript unclosed string + Start of an ASP VBScript fragment + ASP VBScript default + ASP VBScript comment + ASP VBScript number + ASP VBScript keyword + ASP VBScript string + ASP VBScript identifier + ASP VBScript unclosed string + Start of a Python fragment + Python default + Python comment + Python number + Python double-quoted string + Python single-quoted string + Python keyword + Python triple double-quoted string + Python triple single-quoted string + Python class name + Python function or method name + Python operator + Python identifier + Start of an ASP Python fragment + ASP Python default + ASP Python comment + ASP Python number + ASP Python double-quoted string + ASP Python single-quoted string + ASP Python keyword + ASP Python triple double-quoted string + ASP Python triple single-quoted string + ASP Python class name + ASP Python function or method name + ASP Python operator + ASP Python identifier + PHP default + PHP double-quoted string + PHP single-quoted string + PHP keyword + PHP number + PHP variable + PHP comment + PHP line comment + PHP double-quoted variable + PHP operator @@ -1745,6 +2292,7 @@ QsciLexerIDL + UUID @@ -1752,58 +2300,72 @@ QsciLexerJSON + Default + Number + String + Unclosed string + Property + Escape sequence + Line comment + Block comment + Operator + IRI + JSON-LD compact IRI + JSON keyword + JSON-LD keyword + Parsing error @@ -1811,6 +2373,7 @@ QsciLexerJavaScript + Regular expression @@ -1818,82 +2381,102 @@ QsciLexerLua + Default + Comment + Line comment + Number + Keyword + String + Character + Literal string + Preprocessor + Operator + Identifier + Unclosed string + Basic functions + String, table and maths functions + Coroutines, i/o and system facilities + User defined 1 + User defined 2 + User defined 3 + User defined 4 + Label @@ -1901,30 +2484,37 @@ QsciLexerMakefile + Default + Comment + Preprocessor + Variable + Operator + Target + Error @@ -1932,90 +2522,112 @@ QsciLexerMarkdown + Default + Special + Strong emphasis using double asterisks + Strong emphasis using double underscores + Emphasis using single asterisks + Emphasis using single underscores + Level 1 header + Level 2 header + Level 3 header + Level 4 header + Level 5 header + Level 6 header + Pre-char + Unordered list item + Ordered list item + Block quote + Strike out + Horizontal rule + Link + Code between backticks + Code between double backticks + Code block @@ -2023,101 +2635,223 @@ QsciLexerMatlab + Default + Comment + Command + Number + Keyword + Single-quoted string + Operator + Identifier + Double-quoted string + + QsciLexerNsis + + + Default + + + + + COMMENT + + + + + STRING DOUBLE QUOTE + + + + + STRING LEFT QUOTE + + + + + STRING RIGHT QUOTE + + + + + FUNCTION + + + + + VARIABLE + + + + + LABEL + + + + + USEREFINED + + + + + SECTION + + + + + SUB SECTION + + + + + IF DEFINE + + + + + MACRO + + + + + STRING VAR + + + + + NUMBER + + + + + SECTION GROUP + + + + + PAGE EX + + + + + FUNCTION DEFINE + + + + + COMMENT BOX + + + QsciLexerPO + Default + Comment + Message identifier + Message identifier text + Message string + Message string text + Message context + Message context text + Fuzzy flag + Programmer comment + Reference + Flags + Message identifier text end-of-line + Message string text end-of-line + Message context text end-of-line @@ -2125,70 +2859,87 @@ QsciLexerPOV + Default + Comment + Comment line + Number + Operator + Identifier + String + Unclosed string + Directive + Bad directive + Objects, CSG and appearance + Types, modifiers and items + Predefined identifiers + Predefined functions + User defined 1 + User defined 2 + User defined 3 @@ -2196,62 +2947,77 @@ QsciLexerPascal + Default + Identifier + '{ ... }' style comment + '(* ... *)' style comment + Line comment + '{$ ... }' style pre-processor block + '(*$ ... *)' style pre-processor block + Number + Hexadecimal number + Keyword + Single-quoted string + Unclosed string + Character + Operator + Inline asm @@ -2259,166 +3025,207 @@ QsciLexerPerl + Default + Error + Comment + POD + Number + Keyword + Double-quoted string + Single-quoted string + Operator + Identifier + Scalar + Array + Hash + Symbol table + Regular expression + Substitution + Backticks + Data section + Here document delimiter + Single-quoted here document + Double-quoted here document + Backtick here document + Quoted string (q) + Quoted string (qq) + Quoted string (qx) + Quoted string (qr) + Quoted string (qw) + POD verbatim + Subroutine prototype + Format identifier + Format body + Double-quoted string (interpolated variable) + Translation + Regular expression (interpolated variable) + Substitution (interpolated variable) + Backticks (interpolated variable) + Double-quoted here document (interpolated variable) + Backtick here document (interpolated variable) + Quoted string (qq, interpolated variable) + Quoted string (qx, interpolated variable) + Quoted string (qr, interpolated variable) @@ -2426,66 +3233,82 @@ QsciLexerPostScript + Default + Comment + DSC comment + DSC comment value + Number + Name + Keyword + Literal + Immediately evaluated literal + Array parenthesis + Dictionary parenthesis + Procedure parenthesis + Text + Hexadecimal string + Base85 string + Bad string character @@ -2493,26 +3316,32 @@ QsciLexerProperties + Default + Comment + Section + Assignment + Default value + Key @@ -2520,209 +3349,323 @@ QsciLexerPython + Default + Comment + Number + Double-quoted string + Single-quoted string + Keyword + Triple single-quoted string + Triple double-quoted string + Class name + Function or method name + Operator + Identifier + Comment block + Unclosed string + Highlighted identifier + Decorator + Double-quoted f-string + Single-quoted f-string + Triple single-quoted f-string + Triple double-quoted f-string + + QsciLexerR + + + Default + + + + + Comment + + + + + Kword + + + + + Basekword + + + + + OtherKeyWord + + + + + Number + + + + + String + + + + + String2 + + + + + Operator + + + + + Identifier + + + + + Infix + + + + + Infix Eol + + + QsciLexerRuby + Default + Error + Comment + POD + Number + Keyword + Double-quoted string + Single-quoted string + Class name + Function or method name + Operator + Identifier + Regular expression + Global + Symbol + Module name + Instance variable + Class variable + Backticks + Data section + Here document delimiter + Here document + %q string + %Q string + %x string + %r string + %w string + Demoted keyword + stdin + stdout + stderr @@ -2730,90 +3673,113 @@ QsciLexerSQL + Default + Comment + Comment line + JavaDoc style comment + Number + Keyword + Double-quoted string + Single-quoted string + SQL*Plus keyword + SQL*Plus prompt + Operator + Identifier + SQL*Plus comment - # comment line + + comment line + # comment line + JavaDoc keyword + JavaDoc keyword error + User defined 1 + User defined 2 + User defined 3 + User defined 4 + Quoted identifier + Quoted operator @@ -2821,38 +3787,47 @@ QsciLexerSpice + Default + Identifier + Command + Function + Parameter + Number + Delimiter + Value + Comment @@ -2860,90 +3835,112 @@ QsciLexerTCL + Default + Comment + Comment line + Number + Quoted keyword + Quoted string + Operator + Identifier + Substitution + Brace substitution + Modifier + Expand keyword + TCL keyword + Tk keyword + iTCL keyword + Tk command + User defined 1 + User defined 2 + User defined 3 + User defined 4 + Comment box + Comment block @@ -2951,26 +3948,32 @@ QsciLexerTeX + Default + Special + Group + Symbol + Command + Text @@ -2978,77 +3981,100 @@ QsciLexerText + Chinese And Others - 中文字符及其它 + + Ascii - 英文字符 + + + + + Keyword + QsciLexerVHDL + Default + Comment + Comment line + Number + String + Operator + Identifier + Unclosed string + Keyword + Standard operator + Attribute + Standard function + Standard package + Standard type + User defined + Comment block @@ -3056,154 +4082,192 @@ QsciLexerVerilog + Default + Inactive default + Comment + Inactive comment + Line comment + Inactive line comment + Bang comment + Inactive bang comment + Number + Inactive number + Primary keywords and identifiers + Inactive primary keywords and identifiers + String + Inactive string + Secondary keywords and identifiers + Inactive secondary keywords and identifiers + System task + Inactive system task + Preprocessor block + Inactive preprocessor block + Operator + Inactive operator + Identifier + Inactive identifier + Unclosed string + Inactive unclosed string + User defined tasks and identifiers + Inactive user defined tasks and identifiers + Keyword comment + Inactive keyword comment + Input port declaration + Inactive input port declaration + Output port declaration + Inactive output port declaration + Input/output port declaration + Inactive input/output port declaration + Port connection + Inactive port connection @@ -3211,42 +4275,52 @@ QsciLexerYAML + Default + Comment + Identifier + Keyword + Number + Reference + Document delimiter + Text block marker + Syntax error marker + Operator @@ -3254,24 +4328,29 @@ QsciScintilla + &Cut - 剪切 + + &Copy - 复制 + + &Paste - 拷贝 + + Delete - 删除 + + Select All - 全选 + diff --git a/src/qscint/src/qsciprinter.cpp b/src/qscint/src/qsciprinter.cpp index 4c64bed..7f40fde 100755 --- a/src/qscint/src/qsciprinter.cpp +++ b/src/qscint/src/qsciprinter.cpp @@ -1,6 +1,6 @@ // This module implements the QsciPrinter class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qsciscintilla.cpp b/src/qscint/src/qsciscintilla.cpp index 0a00e64..c74ab43 100755 --- a/src/qscint/src/qsciscintilla.cpp +++ b/src/qscint/src/qsciscintilla.cpp @@ -1,2472 +1,2474 @@ -// This module implements the "official" high-level API of the Qt port of -// Scintilla. It is modelled on QTextEdit - a method of the same name should -// behave in the same way. -// -// Copyright (c) 2021 Riverbank Computing Limited -// -// This file is part of QScintilla. -// -// This file may be used under the terms of the GNU General Public License -// version 3.0 as published by the Free Software Foundation and appearing in -// the file LICENSE included in the packaging of this file. Please review the -// following information to ensure the GNU General Public License version 3.0 -// requirements will be met: http://www.gnu.org/copyleft/gpl.html. -// -// If you do not wish to use this file under the terms of the GPL version 3.0 -// then you may purchase a commercial license. For more information contact -// info@riverbankcomputing.com. -// -// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE -// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. - - -#include "Qsci/qsciscintilla.h" - -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "Qsci/qsciabstractapis.h" -#include "Qsci/qscicommandset.h" -#include "Qsci/qscilexer.h" -#include "Qsci/qscistyle.h" -#include "Qsci/qscistyledtext.h" -#include "xmlMatchedTagsHighlighter.h" -#include "BoostRegexSearch.h" - - -// Make sure these match the values in Scintilla.h. We don't #include that -// file because it just causes more clashes. -#define KEYWORDSET_MAX 8 -#define MARKER_MAX 31 - -// The list separators for auto-completion and user lists. -const char acSeparator = '\x03'; -const char userSeparator = '\x04'; - -// The default fold margin width. -static const int defaultFoldMarginWidth = 14; - -// The default set of characters that make up a word. -static const char *defaultWordChars = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; - -// Forward declarations. -static QColor asQColor(long sci_colour); - - -// The ctor. -QsciScintilla::QsciScintilla(QWidget *parent) - : QsciScintillaBase(parent), - allocatedMarkers(0), allocatedIndicators(7), oldPos(-1), oldLine(-1), selText(false), - fold(NoFoldStyle), foldmargin(2), autoInd(false), - braceMode(NoBraceMatch), acSource(AcsNone), acThresh(-1), - wchars(defaultWordChars), call_tips_position(CallTipsBelowText), - call_tips_style(CallTipsNoContext), maxCallTips(-1), - use_single(AcusNever), explicit_fillups(""), fillups_enabled(false), isIndentGuide(false), isHtmlHighLightTag(false) -{ - connect(this,SIGNAL(SCN_MODIFYATTEMPTRO()), - SIGNAL(modificationAttempted())); - - connect(this,SIGNAL(SCN_MODIFIED(int,int,const char *,int,int,int,int,int,int,int)), - SLOT(handleModified(int,int,const char *,int,int,int,int,int,int,int))); - connect(this,SIGNAL(SCN_CALLTIPCLICK(int)), - SLOT(handleCallTipClick(int))); - connect(this,SIGNAL(SCN_CHARADDED(int)), - SLOT(handleCharAdded(int))); - connect(this,SIGNAL(SCN_INDICATORCLICK(int,int)), - SLOT(handleIndicatorClick(int,int))); - connect(this,SIGNAL(SCN_INDICATORRELEASE(int,int)), - SLOT(handleIndicatorRelease(int,int))); - connect(this,SIGNAL(SCN_MARGINCLICK(int,int,int)), - SLOT(handleMarginClick(int,int,int))); - connect(this,SIGNAL(SCN_MARGINRIGHTCLICK(int,int,int)), - SLOT(handleMarginRightClick(int,int,int))); - connect(this,SIGNAL(SCN_SAVEPOINTREACHED()), - SLOT(handleSavePointReached())); - connect(this,SIGNAL(SCN_SAVEPOINTLEFT()), - SLOT(handleSavePointLeft())); - connect(this,SIGNAL(SCN_UPDATEUI(int)), - SLOT(handleUpdateUI(int))); - connect(this,SIGNAL(QSCN_SELCHANGED(bool)), - SLOT(handleSelectionChanged(bool))); - connect(this,SIGNAL(SCN_AUTOCSELECTION(const char *,int)), - SLOT(handleAutoCompletionSelection())); - connect(this,SIGNAL(SCN_USERLISTSELECTION(const char *,int)), - SLOT(handleUserListSelection(const char *,int))); - - // Set the default font. - setFont(QApplication::font()); - - // Set the default fore and background colours. - QPalette pal = QApplication::palette(); - setColor(pal.text().color()); - setPaper(pal.base().color()); - setSelectionForegroundColor(pal.highlightedText().color()); - setSelectionBackgroundColor(pal.highlight().color()); - -#if defined(Q_OS_WIN) - setEolMode(EolWindows); -#else - // Note that EolMac is pre-OS/X. - setEolMode(EolUnix); -#endif - - // Capturing the mouse seems to cause problems on multi-head systems. Qt - // should do the right thing anyway. - SendScintilla(SCI_SETMOUSEDOWNCAPTURES, 0UL); - - setMatchedBraceForegroundColor(Qt::blue); - setUnmatchedBraceForegroundColor(Qt::red); - - //下面这个不能随意放开,否则在一个长行的情况下,进行替换操作将非常慢 - //20221123用户反馈替换非常慢,对比ndd后查找得到的问题。 - setAnnotationDisplay(AnnotationHidden); - setLexer(); - - // Set the visible policy. These are the same as SciTE's defaults - // which, presumably, are sensible. - SendScintilla(SCI_SETVISIBLEPOLICY, VISIBLE_STRICT | VISIBLE_SLOP, 4); - - // The default behaviour is unexpected. - SendScintilla(SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR, - SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE); - - // Create the standard command set. - stdCmds = new QsciCommandSet(this); - - doc.display(this,0); -} - - -// The dtor. -QsciScintilla::~QsciScintilla() -{ - // Detach any current lexer. - detachLexer(); - - doc.undisplay(this); - delete stdCmds; -} - - -// Return the current text colour. -QColor QsciScintilla::color() const -{ - return nl_text_colour; -} - - -// Set the text colour. -void QsciScintilla::setColor(const QColor &c) -{ - if (lex.isNull()) - { - // Assume style 0 applies to everything so that we don't need to use - // SCI_STYLECLEARALL which clears everything. - SendScintilla(SCI_STYLESETFORE, 0, c); - nl_text_colour = c; - } -} - - -// Return the overwrite mode. -bool QsciScintilla::overwriteMode() const -{ - return SendScintilla(SCI_GETOVERTYPE); -} - - -// Set the overwrite mode. -void QsciScintilla::setOverwriteMode(bool overwrite) -{ - SendScintilla(SCI_SETOVERTYPE, overwrite); -} - - -// Return the current paper colour. -QColor QsciScintilla::paper() const -{ - return nl_paper_colour; -} - - -// Set the paper colour. -void QsciScintilla::setPaper(const QColor &c) -{ - if (lex.isNull()) - { - // Assume style 0 applies to everything so that we don't need to use - // SCI_STYLECLEARALL which clears everything. We still have to set the - // default style as well for the background without any text. - SendScintilla(SCI_STYLESETBACK, 0, c); - SendScintilla(SCI_STYLESETBACK, STYLE_DEFAULT, c); - nl_paper_colour = c; - } -} - - -// Set the default font. -void QsciScintilla::setFont(const QFont &f) -{ - if (lex.isNull()) - { - // Assume style 0 applies to everything so that we don't need to use - // SCI_STYLECLEARALL which clears everything. - setStylesFont(f, 0); - QWidget::setFont(f); - } -} - - -// Enable/disable auto-indent. -void QsciScintilla::setAutoIndent(bool autoindent) -{ - autoInd = autoindent; -} - - -// Set the brace matching mode. -void QsciScintilla::setBraceMatching(BraceMatch bm) -{ - braceMode = bm; -} - - -// Handle the addition of a character. -void QsciScintilla::handleCharAdded(int ch) -{ - // Ignore if there is a selection. - long pos = SendScintilla(SCI_GETSELECTIONSTART); - - if (pos != SendScintilla(SCI_GETSELECTIONEND) || pos == 0) - return; - - // If auto-completion is already active then see if this character is a - // start character. If it is then create a new list which will be a subset - // of the current one. The case where it isn't a start character seems to - // be handled correctly elsewhere. - if (isListActive() && isStartChar(ch)) - { - cancelList(); - startAutoCompletion(acSource, false, use_single == AcusAlways); - - return; - } - - // Handle call tips. - if (call_tips_style != CallTipsNone && !lex.isNull() && strchr("(),", ch) != NULL) - callTip(); - - // Handle auto-indentation. - if (autoInd) - { - if (lex.isNull() || (lex->autoIndentStyle() & AiMaintain)) - maintainIndentation(ch, pos); - else - autoIndentation(ch, pos); - } - - // See if we might want to start auto-completion. - if (!isCallTipActive() && acSource != AcsNone) - { - if (isStartChar(ch)) - startAutoCompletion(acSource, false, use_single == AcusAlways); - else if (acThresh >= 1 && isWordCharacter(ch)) - startAutoCompletion(acSource, true, use_single == AcusAlways); - } -} - - -// See if a call tip is active. -bool QsciScintilla::isCallTipActive() const -{ - return SendScintilla(SCI_CALLTIPACTIVE); -} - - -// Handle a possible change to any current call tip. -void QsciScintilla::callTip() -{ - QsciAbstractAPIs *apis = lex->apis(); - - if (!apis) - return; - - int pos, commas = 0; - bool found = false; - char ch; - - pos = SendScintilla(SCI_GETCURRENTPOS); - - // Move backwards through the line looking for the start of the current - // call tip and working out which argument it is. - while ((ch = getCharacter(pos)) != '\0') - { - if (ch == ',') - ++commas; - else if (ch == ')') - { - int depth = 1; - - // Ignore everything back to the start of the corresponding - // parenthesis. - while ((ch = getCharacter(pos)) != '\0') - { - if (ch == ')') - ++depth; - else if (ch == '(' && --depth == 0) - break; - } - } - else if (ch == '(') - { - found = true; - break; - } - } - - // Cancel any existing call tip. - SendScintilla(SCI_CALLTIPCANCEL); - - // Done if there is no new call tip to set. - if (!found) - return; - - QStringList context = apiContext(pos, pos, ctPos); - - if (context.isEmpty()) - return; - - // The last word is complete, not partial. - context << QString(); - - ct_cursor = 0; - ct_shifts.clear(); - ct_entries = apis->callTips(context, commas, call_tips_style, ct_shifts); - - int nr_entries = ct_entries.count(); - - if (nr_entries == 0) - return; - - if (maxCallTips > 0 && maxCallTips < nr_entries) - { - ct_entries = ct_entries.mid(0, maxCallTips); - nr_entries = maxCallTips; - } - - int shift; - QString ct; - - int nr_shifts = ct_shifts.count(); - - if (maxCallTips < 0 && nr_entries > 1) - { - shift = (nr_shifts > 0 ? ct_shifts.first() : 0); - ct = ct_entries[0]; - ct.prepend('\002'); - } - else - { - if (nr_shifts > nr_entries) - nr_shifts = nr_entries; - - // Find the biggest shift. - shift = 0; - - for (int i = 0; i < nr_shifts; ++i) - { - int sh = ct_shifts[i]; - - if (shift < sh) - shift = sh; - } - - ct = ct_entries.join("\n"); - } - - ScintillaBytes ct_bytes = textAsBytes(ct); - const char *cts = ScintillaBytesConstData(ct_bytes); - - SendScintilla(SCI_CALLTIPSHOW, adjustedCallTipPosition(shift), cts); - - // Done if there is more than one call tip. - if (nr_entries > 1) - return; - - // Highlight the current argument. - const char *astart; - - if (commas == 0) - astart = strchr(cts, '('); - else - for (astart = strchr(cts, ','); astart && --commas > 0; astart = strchr(astart + 1, ',')) - ; - - if (!astart || !*++astart) - return; - - // The end is at the next comma or unmatched closing parenthesis. - const char *aend; - int depth = 0; - - for (aend = astart; *aend; ++aend) - { - char ch = *aend; - - if (ch == ',' && depth == 0) - break; - else if (ch == '(') - ++depth; - else if (ch == ')') - { - if (depth == 0) - break; - - --depth; - } - } - - if (astart != aend) - SendScintilla(SCI_CALLTIPSETHLT, astart - cts, aend - cts); -} - - -// Handle a call tip click. -void QsciScintilla::handleCallTipClick(int dir) -{ - int nr_entries = ct_entries.count(); - - // Move the cursor while bounds checking. - if (dir == 1) - { - if (ct_cursor - 1 < 0) - return; - - --ct_cursor; - } - else if (dir == 2) - { - if (ct_cursor + 1 >= nr_entries) - return; - - ++ct_cursor; - } - else - return; - - int shift = (ct_shifts.count() > ct_cursor ? ct_shifts[ct_cursor] : 0); - QString ct = ct_entries[ct_cursor]; - - // Add the arrows. - if (ct_cursor < nr_entries - 1) - ct.prepend('\002'); - - if (ct_cursor > 0) - ct.prepend('\001'); - - ScintillaBytes ct_bytes = textAsBytes(ct); - const char *cts = ScintillaBytesConstData(ct_bytes); - - SendScintilla(SCI_CALLTIPSHOW, adjustedCallTipPosition(shift), cts); -} - - -// Shift the position of the call tip (to take any context into account) but -// don't go before the start of the line. -int QsciScintilla::adjustedCallTipPosition(int ctshift) const -{ - int ct = ctPos; - - if (ctshift) - { - int ctmin = SendScintilla(SCI_POSITIONFROMLINE, SendScintilla(SCI_LINEFROMPOSITION, ct)); - - if (ct - ctshift < ctmin) - ct = ctmin; - } - - return ct; -} - - -// Return the list of words that make up the context preceding the given -// position. The list will only have more than one element if there is a lexer -// set and it defines start strings. If so, then the last element might be -// empty if a start string has just been typed. On return pos is at the start -// of the context. -QStringList QsciScintilla::apiContext(int pos, int &context_start, - int &last_word_start) -{ - enum { - Either, - Separator, - Word - }; - - QStringList words; - int good_pos = pos, expecting = Either; - - last_word_start = -1; - - while (pos > 0) - { - if (getSeparator(pos)) - { - if (expecting == Either) - words.prepend(QString()); - else if (expecting == Word) - break; - - good_pos = pos; - expecting = Word; - } - else - { - QString word = getWord(pos); - - if (word.isEmpty() || expecting == Separator) - break; - - words.prepend(word); - good_pos = pos; - expecting = Separator; - - // Return the position of the start of the last word if required. - if (last_word_start < 0) - last_word_start = pos; - } - - // Strip any preceding spaces (mainly around operators). - char ch; - - while ((ch = getCharacter(pos)) != '\0') - { - // This is the same definition of space that Scintilla uses. - if (ch != ' ' && (ch < 0x09 || ch > 0x0d)) - { - ++pos; - break; - } - } - } - - // A valid sequence always starts with a word and so should be expecting a - // separator. - if (expecting != Separator) - words.clear(); - - context_start = good_pos; - - return words; -} - - -// Try and get a lexer's word separator from the text before the current -// position. Return true if one was found and adjust the position accordingly. -bool QsciScintilla::getSeparator(int &pos) const -{ - int opos = pos; - - // Go through each separator. - for (int i = 0; i < wseps.count(); ++i) - { - const QString &ws = wseps[i]; - - // Work backwards. - uint l; - - for (l = ws.length(); l; --l) - { - char ch = getCharacter(pos); - - if (ch == '\0' || ws.at(l - 1) != ch) - break; - } - - if (!l) - return true; - - // Reset for the next separator. - pos = opos; - } - - return false; -} - - -// Try and get a word from the text before the current position. Return the -// word if one was found and adjust the position accordingly. -QString QsciScintilla::getWord(int &pos) const -{ - QString word; - bool numeric = true; - char ch; - - while ((ch = getCharacter(pos)) != '\0') - { - if (!isWordCharacter(ch)) - { - ++pos; - break; - } - - if (ch < '0' || ch > '9') - numeric = false; - - word.prepend(ch); - } - - // We don't auto-complete numbers. - if (numeric) - word.truncate(0); - - return word; -} - - -// Get the "next" character (ie. the one before the current position) in the -// current line. The character will be '\0' if there are no more. -char QsciScintilla::getCharacter(int &pos) const -{ - if (pos <= 0) - return '\0'; - - char ch = SendScintilla(SCI_GETCHARAT, --pos); - - // Don't go past the end of the previous line. - if (ch == '\n' || ch == '\r') - { - ++pos; - return '\0'; - } - - return ch; -} - - -// See if a character is an auto-completion start character, ie. the last -// character of a word separator. -bool QsciScintilla::isStartChar(char ch) const -{ - QString s = QChar(ch); - - for (int i = 0; i < wseps.count(); ++i) - if (wseps[i].endsWith(s)) - return true; - - return false; -} - - -// Possibly start auto-completion. -void QsciScintilla::startAutoCompletion(AutoCompletionSource acs, - bool checkThresh, bool choose_single) -{ - int start, ignore; - QStringList context = apiContext(SendScintilla(SCI_GETCURRENTPOS), start, - ignore); - - if (context.isEmpty()) - return; - - // Get the last word's raw data and length. - ScintillaBytes s = textAsBytes(context.last()); - const char *last_data = ScintillaBytesConstData(s); - int last_len = s.length(); - - if (checkThresh && last_len < acThresh) - return; - - // Generate the string representing the valid words to select from. - QStringList wlist; - - if ((acs == AcsAll || acs == AcsAPIs) && !lex.isNull()) - { - QsciAbstractAPIs *apis = lex->apis(); - - if (apis) - apis->updateAutoCompletionList(context, wlist); - } - - if (acs == AcsAll || acs == AcsDocument) - { - int sflags = SCFIND_WORDSTART; - - if (!SendScintilla(SCI_AUTOCGETIGNORECASE)) - sflags |= SCFIND_MATCHCASE; - - SendScintilla(SCI_SETSEARCHFLAGS, sflags); - - int pos = 0; - int dlen = SendScintilla(SCI_GETLENGTH); - int caret = SendScintilla(SCI_GETCURRENTPOS); - int clen = caret - start; - char *orig_context = new char[clen + 1]; - - SendScintilla(SCI_GETTEXTRANGE, start, caret, orig_context); - - for (;;) - { - int fstart; - - SendScintilla(SCI_SETTARGETSTART, pos); - SendScintilla(SCI_SETTARGETEND, dlen); - - if ((fstart = SendScintilla(SCI_SEARCHINTARGET, clen, orig_context)) < 0) - break; - - // Move past the root part. - pos = fstart + clen; - - // Skip if this is the context we are auto-completing. - if (pos == caret) - continue; - - // Get the rest of this word. - QString w = last_data; - - while (pos < dlen) - { - char ch = SendScintilla(SCI_GETCHARAT, pos); - - if (!isWordCharacter(ch)) - break; - - w += ch; - ++pos; - } - - // Add the word if it isn't already there. - if (!w.isEmpty()) - { - bool keep; - - // If there are APIs then check if the word is already present - // as an API word (i.e. with a trailing space). - if (acs == AcsAll) - { - QString api_w = w; - api_w.append(' '); - - keep = !wlist.contains(api_w); - } - else - { - keep = true; - } - - if (keep && !wlist.contains(w)) - wlist.append(w); - } - } - - delete []orig_context; - } - - if (wlist.isEmpty()) - return; - - wlist.sort(); - - SendScintilla(SCI_AUTOCSETCHOOSESINGLE, choose_single); - SendScintilla(SCI_AUTOCSETSEPARATOR, acSeparator); - - ScintillaBytes wlist_s = textAsBytes(wlist.join(QChar(acSeparator))); - SendScintilla(SCI_AUTOCSHOW, last_len, ScintillaBytesConstData(wlist_s)); -} - - -// Maintain the indentation of the previous line. -void QsciScintilla::maintainIndentation(char ch, long pos) -{ - if (ch != '\r' && ch != '\n') - return; - - int curr_line = SendScintilla(SCI_LINEFROMPOSITION, pos); - - // Get the indentation of the preceding non-zero length line. - int ind = 0; - - for (int line = curr_line - 1; line >= 0; --line) - { - if (SendScintilla(SCI_GETLINEENDPOSITION, line) > - SendScintilla(SCI_POSITIONFROMLINE, line)) - { - ind = indentation(line); - break; - } - } - - if (ind > 0) - autoIndentLine(pos, curr_line, ind); -} - - -// Implement auto-indentation. -void QsciScintilla::autoIndentation(char ch, long pos) -{ - int curr_line = SendScintilla(SCI_LINEFROMPOSITION, pos); - int ind_width = indentWidth(); - long curr_line_start = SendScintilla(SCI_POSITIONFROMLINE, curr_line); - - const char *block_start = lex->blockStart(); - bool start_single = (block_start && qstrlen(block_start) == 1); - - const char *block_end = lex->blockEnd(); - bool end_single = (block_end && qstrlen(block_end) == 1); - - if (end_single && block_end[0] == ch) - { - if (!(lex->autoIndentStyle() & AiClosing) && rangeIsWhitespace(curr_line_start, pos - 1)) - autoIndentLine(pos, curr_line, blockIndent(curr_line - 1) - ind_width); - } - else if (start_single && block_start[0] == ch) - { - // De-indent if we have already indented because the previous line was - // a start of block keyword. - if (!(lex->autoIndentStyle() & AiOpening) && curr_line > 0 && getIndentState(curr_line - 1) == isKeywordStart && rangeIsWhitespace(curr_line_start, pos - 1)) - autoIndentLine(pos, curr_line, blockIndent(curr_line - 1) - ind_width); - } - else if (ch == '\r' || ch == '\n') - { - // Don't auto-indent the line (ie. preserve its existing indentation) - // if we have inserted a new line above by pressing return at the start - // of this line - in other words, if the previous line is empty. - long prev_line_length = SendScintilla(SCI_GETLINEENDPOSITION, curr_line - 1) - SendScintilla(SCI_POSITIONFROMLINE, curr_line - 1); - - if (prev_line_length != 0) - autoIndentLine(pos, curr_line, blockIndent(curr_line - 1)); - } -} - - -// Set the indentation for a line. -void QsciScintilla::autoIndentLine(long pos, int line, int indent) -{ - if (indent < 0) - return; - - long pos_before = SendScintilla(SCI_GETLINEINDENTPOSITION, line); - SendScintilla(SCI_SETLINEINDENTATION, line, indent); - long pos_after = SendScintilla(SCI_GETLINEINDENTPOSITION, line); - long new_pos = -1; - - if (pos_after > pos_before) - { - new_pos = pos + (pos_after - pos_before); - } - else if (pos_after < pos_before && pos >= pos_after) - { - if (pos >= pos_before) - new_pos = pos + (pos_after - pos_before); - else - new_pos = pos_after; - } - - if (new_pos >= 0) - SendScintilla(SCI_SETSEL, new_pos, new_pos); -} - - -// Return the indentation of the block defined by the given line (or something -// significant before). -int QsciScintilla::blockIndent(int line) -{ - if (line < 0) - return 0; - - // Handle the trvial case. - if (!lex->blockStartKeyword() && !lex->blockStart() && !lex->blockEnd()) - return indentation(line); - - int line_limit = line - lex->blockLookback(); - - if (line_limit < 0) - line_limit = 0; - - for (int l = line; l >= line_limit; --l) - { - IndentState istate = getIndentState(l); - - if (istate != isNone) - { - int ind_width = indentWidth(); - int ind = indentation(l); - - if (istate == isBlockStart) - { - if (!(lex -> autoIndentStyle() & AiOpening)) - ind += ind_width; - } - else if (istate == isBlockEnd) - { - if (lex -> autoIndentStyle() & AiClosing) - ind -= ind_width; - - if (ind < 0) - ind = 0; - } - else if (line == l) - ind += ind_width; - - return ind; - } - } - - return indentation(line); -} - - -// Return true if all characters starting at spos up to, but not including -// epos, are spaces or tabs. -bool QsciScintilla::rangeIsWhitespace(long spos, long epos) -{ - while (spos < epos) - { - char ch = SendScintilla(SCI_GETCHARAT, spos); - - if (ch != ' ' && ch != '\t') - return false; - - ++spos; - } - - return true; -} - - -// Returns the indentation state of a line. -QsciScintilla::IndentState QsciScintilla::getIndentState(int line) -{ - IndentState istate; - - // Get the styled text. - long spos = SendScintilla(SCI_POSITIONFROMLINE, line); - long epos = SendScintilla(SCI_POSITIONFROMLINE, line + 1); - - char *text = new char[(epos - spos + 1) * 2]; - - SendScintilla(SCI_GETSTYLEDTEXT, spos, epos, text); - - int style, bstart_off, bend_off; - - // Block start/end takes precedence over keywords. - const char *bstart_words = lex->blockStart(&style); - bstart_off = findStyledWord(text, style, bstart_words); - - const char *bend_words = lex->blockEnd(&style); - bend_off = findStyledWord(text, style, bend_words); - - // If there is a block start but no block end characters then ignore it - // unless the block start is the last significant thing on the line, ie. - // assume Python-like blocking. - if (bstart_off >= 0 && !bend_words) - for (int i = bstart_off * 2; text[i] != '\0'; i += 2) - if (!QChar(text[i]).isSpace()) - return isNone; - - if (bstart_off > bend_off) - istate = isBlockStart; - else if (bend_off > bstart_off) - istate = isBlockEnd; - else - { - const char *words = lex->blockStartKeyword(&style); - - istate = (findStyledWord(text,style,words) >= 0) ? isKeywordStart : isNone; - } - - delete[] text; - - return istate; -} - - -// text is a pointer to some styled text (ie. a character byte followed by a -// style byte). style is a style number. words is a space separated list of -// words. Returns the position in the text immediately after the last one of -// the words with the style. The reason we are after the last, and not the -// first, occurance is that we are looking for words that start and end a block -// where the latest one is the most significant. -int QsciScintilla::findStyledWord(const char *text, int style, - const char *words) -{ - if (!words) - return -1; - - // Find the range of text with the style we are looking for. - const char *stext; - - for (stext = text; stext[1] != style; stext += 2) - if (stext[0] == '\0') - return -1; - - // Move to the last character. - const char *etext = stext; - - while (etext[2] != '\0') - etext += 2; - - // Backtrack until we find the style. There will be one. - while (etext[1] != style) - etext -= 2; - - // Look for each word in turn. - while (words[0] != '\0') - { - // Find the end of the word. - const char *eword = words; - - while (eword[1] != ' ' && eword[1] != '\0') - ++eword; - - // Now search the text backwards. - const char *wp = eword; - - for (const char *tp = etext; tp >= stext; tp -= 2) - { - if (tp[0] != wp[0] || tp[1] != style) - { - // Reset the search. - wp = eword; - continue; - } - - // See if all the word has matched. - if (wp-- == words) - return ((tp - text) / 2) + (eword - words) + 1; - } - - // Move to the start of the next word if there is one. - words = eword + 1; - - if (words[0] == ' ') - ++words; - } - - return -1; -} - - -// Return true if the code page is UTF8. -bool QsciScintilla::isUtf8() const -{ - return (SendScintilla(SCI_GETCODEPAGE) == SC_CP_UTF8); -} - - -// Set the code page. -void QsciScintilla::setUtf8(bool cp) -{ - SendScintilla(SCI_SETCODEPAGE, (cp ? SC_CP_UTF8 : 0)); -} - - -// Return the end-of-line mode. -QsciScintilla::EolMode QsciScintilla::eolMode() const -{ - return (EolMode)SendScintilla(SCI_GETEOLMODE); -} - - -// Set the end-of-line mode. -void QsciScintilla::setEolMode(EolMode mode) -{ - SendScintilla(SCI_SETEOLMODE, mode); -} - - -// Convert the end-of-lines to a particular mode. -void QsciScintilla::convertEols(EolMode mode) -{ - SendScintilla(SCI_CONVERTEOLS, mode); -} - - -// Add an edge column. -void QsciScintilla::addEdgeColumn(int colnr, const QColor &col) -{ - SendScintilla(SCI_MULTIEDGEADDLINE, colnr, col); -} - - -// Clear all multi-edge columns. -void QsciScintilla::clearEdgeColumns() -{ - SendScintilla(SCI_MULTIEDGECLEARALL); -} - - -// Return the edge colour. -QColor QsciScintilla::edgeColor() const -{ - return asQColor(SendScintilla(SCI_GETEDGECOLOUR)); -} - - -// Set the edge colour. -void QsciScintilla::setEdgeColor(const QColor &col) -{ - SendScintilla(SCI_SETEDGECOLOUR, col); -} - - -// Return the edge column. -int QsciScintilla::edgeColumn() const -{ - return SendScintilla(SCI_GETEDGECOLUMN); -} - - -// Set the edge column. -void QsciScintilla::setEdgeColumn(int colnr) -{ - SendScintilla(SCI_SETEDGECOLUMN, colnr); -} - - -// Return the edge mode. -QsciScintilla::EdgeMode QsciScintilla::edgeMode() const -{ - return (EdgeMode)SendScintilla(SCI_GETEDGEMODE); -} - - -// Set the edge mode. -void QsciScintilla::setEdgeMode(EdgeMode mode) -{ - SendScintilla(SCI_SETEDGEMODE, mode); -} - - -// Return the end-of-line visibility. -bool QsciScintilla::eolVisibility() const -{ - return SendScintilla(SCI_GETVIEWEOL); -} - - -// Set the end-of-line visibility. -void QsciScintilla::setEolVisibility(bool visible) -{ - SendScintilla(SCI_SETVIEWEOL, visible); -} - - -// Return the extra ascent. -int QsciScintilla::extraAscent() const -{ - return SendScintilla(SCI_GETEXTRAASCENT); -} - - -// Set the extra ascent. -void QsciScintilla::setExtraAscent(int extra) -{ - SendScintilla(SCI_SETEXTRAASCENT, extra); -} - - -// Return the extra descent. -int QsciScintilla::extraDescent() const -{ - return SendScintilla(SCI_GETEXTRADESCENT); -} - - -// Set the extra descent. -void QsciScintilla::setExtraDescent(int extra) -{ - SendScintilla(SCI_SETEXTRADESCENT, extra); -} - - -// Return the whitespace size. -int QsciScintilla::whitespaceSize() const -{ - return SendScintilla(SCI_GETWHITESPACESIZE); -} - - -// Set the whitespace size. -void QsciScintilla::setWhitespaceSize(int size) -{ - SendScintilla(SCI_SETWHITESPACESIZE, size); -} - - -// Set the whitespace background colour. -void QsciScintilla::setWhitespaceBackgroundColor(const QColor &col) -{ - SendScintilla(SCI_SETWHITESPACEBACK, col.isValid(), col); -} - - -// Set the whitespace foreground colour. -void QsciScintilla::setWhitespaceForegroundColor(const QColor &col) -{ - SendScintilla(SCI_SETWHITESPACEFORE, col.isValid(), col); -} - - -// Return the whitespace visibility. -QsciScintilla::WhitespaceVisibility QsciScintilla::whitespaceVisibility() const -{ - return (WhitespaceVisibility)SendScintilla(SCI_GETVIEWWS); -} - - -// Set the whitespace visibility. -void QsciScintilla::setWhitespaceVisibility(WhitespaceVisibility mode) -{ - SendScintilla(SCI_SETVIEWWS, mode); -} - - -// Return the tab draw mode. -QsciScintilla::TabDrawMode QsciScintilla::tabDrawMode() const -{ - return (TabDrawMode)SendScintilla(SCI_GETTABDRAWMODE); -} - - -// Set the tab draw mode. -void QsciScintilla::setTabDrawMode(TabDrawMode mode) -{ - SendScintilla(SCI_SETTABDRAWMODE, mode); -} - - -// Return the line wrap mode. -QsciScintilla::WrapMode QsciScintilla::wrapMode() const -{ - return (WrapMode)SendScintilla(SCI_GETWRAPMODE); -} - - -// Set the line wrap mode. -void QsciScintilla::setWrapMode(WrapMode mode) -{ - SendScintilla(SCI_SETLAYOUTCACHE, - (mode == WrapNone ? SC_CACHE_CARET : SC_CACHE_DOCUMENT)); - SendScintilla(SCI_SETWRAPMODE, mode); -} - - -// Return the line wrap indent mode. -QsciScintilla::WrapIndentMode QsciScintilla::wrapIndentMode() const -{ - return (WrapIndentMode)SendScintilla(SCI_GETWRAPINDENTMODE); -} - - -// Set the line wrap indent mode. -void QsciScintilla::setWrapIndentMode(WrapIndentMode mode) -{ - SendScintilla(SCI_SETWRAPINDENTMODE, mode); -} - - -// Set the line wrap visual flags. -void QsciScintilla::setWrapVisualFlags(WrapVisualFlag endFlag, - WrapVisualFlag startFlag, int indent) -{ - int flags = SC_WRAPVISUALFLAG_NONE; - int loc = SC_WRAPVISUALFLAGLOC_DEFAULT; - - switch (endFlag) - { - case WrapFlagNone: - break; - - case WrapFlagByText: - flags |= SC_WRAPVISUALFLAG_END; - loc |= SC_WRAPVISUALFLAGLOC_END_BY_TEXT; - break; - - case WrapFlagByBorder: - flags |= SC_WRAPVISUALFLAG_END; - break; - - case WrapFlagInMargin: - flags |= SC_WRAPVISUALFLAG_MARGIN; - break; - } - - switch (startFlag) - { - case WrapFlagNone: - break; - - case WrapFlagByText: - flags |= SC_WRAPVISUALFLAG_START; - loc |= SC_WRAPVISUALFLAGLOC_START_BY_TEXT; - break; - - case WrapFlagByBorder: - flags |= SC_WRAPVISUALFLAG_START; - break; - - case WrapFlagInMargin: - flags |= SC_WRAPVISUALFLAG_MARGIN; - break; - } - - SendScintilla(SCI_SETWRAPVISUALFLAGS, flags); - SendScintilla(SCI_SETWRAPVISUALFLAGSLOCATION, loc); - SendScintilla(SCI_SETWRAPSTARTINDENT, indent); -} - - -// Set the folding style. -void QsciScintilla::setFolding(FoldStyle folding, int margin) -{ - fold = folding; - foldmargin = margin; - - if (folding == NoFoldStyle) - { - SendScintilla(SCI_SETMARGINWIDTHN, margin, 0L); - return; - } - - int mask = SendScintilla(SCI_GETMODEVENTMASK); - SendScintilla(SCI_SETMODEVENTMASK, mask | SC_MOD_CHANGEFOLD); - - SendScintilla(SCI_SETFOLDFLAGS, SC_FOLDFLAG_LINEAFTER_CONTRACTED); - - SendScintilla(SCI_SETMARGINTYPEN, margin, (long)SC_MARGIN_SYMBOL); - SendScintilla(SCI_SETMARGINMASKN, margin, SC_MASK_FOLDERS); - SendScintilla(SCI_SETMARGINSENSITIVEN, margin, 1); - - // Set the marker symbols to use. - switch (folding) - { - case NoFoldStyle: - break; - - case PlainFoldStyle: - setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS); - setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_PLUS); - setFoldMarker(SC_MARKNUM_FOLDERSUB); - setFoldMarker(SC_MARKNUM_FOLDERTAIL); - setFoldMarker(SC_MARKNUM_FOLDEREND); - setFoldMarker(SC_MARKNUM_FOLDEROPENMID); - setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL); - break; - - case CircledFoldStyle: - setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_CIRCLEMINUS); - setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_CIRCLEPLUS); - setFoldMarker(SC_MARKNUM_FOLDERSUB); - setFoldMarker(SC_MARKNUM_FOLDERTAIL); - setFoldMarker(SC_MARKNUM_FOLDEREND); - setFoldMarker(SC_MARKNUM_FOLDEROPENMID); - setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL); - break; - - case BoxedFoldStyle: - setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS); - setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS); - setFoldMarker(SC_MARKNUM_FOLDERSUB); - setFoldMarker(SC_MARKNUM_FOLDERTAIL); - setFoldMarker(SC_MARKNUM_FOLDEREND); - setFoldMarker(SC_MARKNUM_FOLDEROPENMID); - setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL); - break; - - case CircledTreeFoldStyle: - setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_CIRCLEMINUS); - setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_CIRCLEPLUS); - setFoldMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE); - setFoldMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNERCURVE); - setFoldMarker(SC_MARKNUM_FOLDEREND, SC_MARK_CIRCLEPLUSCONNECTED); - setFoldMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_CIRCLEMINUSCONNECTED); - setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNERCURVE); - break; - - case BoxedTreeFoldStyle: - setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS); - setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS); - setFoldMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE); - setFoldMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNER); - setFoldMarker(SC_MARKNUM_FOLDEREND, SC_MARK_BOXPLUSCONNECTED); - setFoldMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_BOXMINUSCONNECTED); - setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNER); - break; - } - - SendScintilla(SCI_SETMARGINWIDTHN, margin, defaultFoldMarginWidth); -} - - -// Clear all current folds. -void QsciScintilla::clearFolds() -{ - recolor(); - - int maxLine = SendScintilla(SCI_GETLINECOUNT); - - for (int line = 0; line < maxLine; line++) - { - int level = SendScintilla(SCI_GETFOLDLEVEL, line); - - if (level & SC_FOLDLEVELHEADERFLAG) - { - SendScintilla(SCI_SETFOLDEXPANDED, line, 1); - foldExpand(line, true, false, 0, level); - line--; - } - } -} - - -// Set up a folder marker. -void QsciScintilla::setFoldMarker(int marknr, int mark) -{ - SendScintilla(SCI_MARKERDEFINE, marknr, mark); - - if (mark != SC_MARK_EMPTY) - { - SendScintilla(SCI_MARKERSETFORE, marknr, QColor(Qt::white)); - SendScintilla(SCI_MARKERSETBACK, marknr, QColor(128,128,128)); - } -} - - -// Handle a click in the fold margin. This is mostly taken from SciTE. -void QsciScintilla::foldClick(int lineClick, int bstate) -{ - bool shift = bstate & Qt::ShiftModifier; - bool ctrl = bstate & Qt::ControlModifier; - - if (shift && ctrl) - { - foldAll(); - return; - } - - int levelClick = SendScintilla(SCI_GETFOLDLEVEL, lineClick); - - if (levelClick & SC_FOLDLEVELHEADERFLAG) - { - if (shift) - { - // Ensure all children are visible. - SendScintilla(SCI_SETFOLDEXPANDED, lineClick, 1); - foldExpand(lineClick, true, true, 100, levelClick); - } - else if (ctrl) - { - if (SendScintilla(SCI_GETFOLDEXPANDED, lineClick)) - { - // Contract this line and all its children. - SendScintilla(SCI_SETFOLDEXPANDED, lineClick, 0L); - foldExpand(lineClick, false, true, 0, levelClick); - } - else - { - // Expand this line and all its children. - SendScintilla(SCI_SETFOLDEXPANDED, lineClick, 1); - foldExpand(lineClick, true, true, 100, levelClick); - } - } - else - { - // Toggle this line. - SendScintilla(SCI_TOGGLEFOLD, lineClick); - } - } -} - - -// Do the hard work of hiding and showing lines. This is mostly taken from -// SciTE. -void QsciScintilla::foldExpand(int &line, bool doExpand, bool force, - int visLevels, int level) -{ - int lineMaxSubord = SendScintilla(SCI_GETLASTCHILD, line, - level & SC_FOLDLEVELNUMBERMASK); - - line++; - - while (line <= lineMaxSubord) - { - if (force) - { - if (visLevels > 0) - SendScintilla(SCI_SHOWLINES, line, line); - else - SendScintilla(SCI_HIDELINES, line, line); - } - else if (doExpand) - SendScintilla(SCI_SHOWLINES, line, line); - - int levelLine = level; - - if (levelLine == -1) - levelLine = SendScintilla(SCI_GETFOLDLEVEL, line); - - if (levelLine & SC_FOLDLEVELHEADERFLAG) - { - if (force) - { - if (visLevels > 1) - SendScintilla(SCI_SETFOLDEXPANDED, line, 1); - else - SendScintilla(SCI_SETFOLDEXPANDED, line, 0L); - - foldExpand(line, doExpand, force, visLevels - 1); - } - else if (doExpand) - { - if (!SendScintilla(SCI_GETFOLDEXPANDED, line)) - SendScintilla(SCI_SETFOLDEXPANDED, line, 1); - - foldExpand(line, true, force, visLevels - 1); - } - else - foldExpand(line, false, force, visLevels - 1); - } - else - line++; - } -} - - -// Fully expand (if there is any line currently folded) all text. Otherwise, -// fold all text. This is mostly taken from SciTE. -void QsciScintilla::foldAll(bool children) -{ - recolor(); - - int maxLine = SendScintilla(SCI_GETLINECOUNT); - bool expanding = true; - - for (int lineSeek = 0; lineSeek < maxLine; lineSeek++) - { - if (SendScintilla(SCI_GETFOLDLEVEL,lineSeek) & SC_FOLDLEVELHEADERFLAG) - { - expanding = !SendScintilla(SCI_GETFOLDEXPANDED, lineSeek); - break; - } - } - - for (int line = 0; line < maxLine; line++) - { - int level = SendScintilla(SCI_GETFOLDLEVEL, line); - - if (!(level & SC_FOLDLEVELHEADERFLAG)) - continue; - - if (children || - (SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK))) - { - if (expanding) - { - SendScintilla(SCI_SETFOLDEXPANDED, line, 1); - foldExpand(line, true, false, 0, level); - line--; - } - else - { - int lineMaxSubord = SendScintilla(SCI_GETLASTCHILD, line, -1); - - SendScintilla(SCI_SETFOLDEXPANDED, line, 0L); - - if (lineMaxSubord > line) - SendScintilla(SCI_HIDELINES, line + 1, lineMaxSubord); - } - } - } -} - - -// Handle a fold change. This is mostly taken from SciTE. -void QsciScintilla::foldChanged(int line,int levelNow,int levelPrev) -{ - if (levelNow & SC_FOLDLEVELHEADERFLAG) - { - if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) - SendScintilla(SCI_SETFOLDEXPANDED, line, 1); - } - else if (levelPrev & SC_FOLDLEVELHEADERFLAG) - { - if (!SendScintilla(SCI_GETFOLDEXPANDED, line)) - { - // Removing the fold from one that has been contracted so should - // expand. Otherwise lines are left invisible with no way to make - // them visible. - foldExpand(line, true, false, 0, levelPrev); - } - } -} - - -// Toggle the fold for a line if it contains a fold marker. -void QsciScintilla::foldLine(int line) -{ - SendScintilla(SCI_TOGGLEFOLD, line); -} - - -// Return the list of folded lines. -QList QsciScintilla::contractedFolds() const -{ - QList folds; - int linenr = 0, fold_line; - - while ((fold_line = SendScintilla(SCI_CONTRACTEDFOLDNEXT, linenr)) >= 0) - { - folds.append(fold_line); - linenr = fold_line + 1; - } - - return folds; -} - - -// Set the fold state from a list. -void QsciScintilla::setContractedFolds(const QList &folds) -{ - for (int i = 0; i < folds.count(); ++i) - { - int line = folds[i]; - int last_line = SendScintilla(SCI_GETLASTCHILD, line, -1); - - SendScintilla(SCI_SETFOLDEXPANDED, line, 0L); - SendScintilla(SCI_HIDELINES, line + 1, last_line); - } -} - - -// Handle the SCN_MODIFIED notification. -void QsciScintilla::handleModified(int pos, int mtype, const char *text, - int len, int added, int line, int foldNow, int foldPrev, int token, - int annotationLinesAdded) -{ - Q_UNUSED(pos); - Q_UNUSED(text); - Q_UNUSED(len); - Q_UNUSED(token); - Q_UNUSED(annotationLinesAdded); - - if (mtype & SC_MOD_CHANGEFOLD) - { - if (fold) - foldChanged(line, foldNow, foldPrev); - } - - if (mtype & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) - { - emit textChanged(); - - if (added != 0) - emit linesChanged(); - } -} - - -// Zoom in a number of points. -void QsciScintilla::zoomIn(int range) -{ - zoomTo(SendScintilla(SCI_GETZOOM) + range); -} - - -// Zoom in a single point. -void QsciScintilla::zoomIn() -{ - SendScintilla(SCI_ZOOMIN); -} - - -// Zoom out a number of points. -void QsciScintilla::zoomOut(int range) -{ - zoomTo(SendScintilla(SCI_GETZOOM) - range); -} - - -// Zoom out a single point. -void QsciScintilla::zoomOut() -{ - SendScintilla(SCI_ZOOMOUT); -} - - -// Set the zoom to a number of points. -void QsciScintilla::zoomTo(int size) -{ - if (size < -10) - size = -10; - else if (size > 20) - size = 20; - - SendScintilla(SCI_SETZOOM, size); -} - -FindState& QsciScintilla::getLastFindState() -{ - return findState; -} - - -// Find the first occurrence of a string. -//show:会保证找到的自动,在当前屏幕上可见,这个默认是true,注意该操作非常耗时。 -//在批量查找或者替换的时候,如果不需要可见,最好修改为不可见。否则在替换一个长行,长行中存在几百个的情况,速度会非常慢。 -//本来只需要2s的操作,结果会需要30s。 -bool QsciScintilla::findFirst(const QString &expr, bool re, bool cs, bool wo, - bool wrap, bool forward, FindNextType findNextType, int line, int index, bool show, bool posix, - bool cxx11) -{ - if (expr.isEmpty()) - { - findState.status = FindState::Idle; - return false; - } - - findState.status = FindState::Finding; - findState.expr = expr; - findState.wrap = wrap; - findState.forward = forward; - - findState.flags = - (cs ? SCFIND_MATCHCASE : 0) | - (wo ? SCFIND_WHOLEWORD : 0) | - (re ? SCFIND_REGEXP : 0) | - (posix ? SCFIND_POSIX : 0) | - (cxx11 ? SCFIND_CXX11REGEX : 0); - - switch (findNextType) - { - case FINDNEXTTYPE_FINDNEXT: - findState.flags |= SCFIND_REGEXP_EMPTYMATCH_ALL | SCFIND_REGEXP_SKIPCRLFASONE; - break; - - case FINDNEXTTYPE_REPLACENEXT: - findState.flags |= SCFIND_REGEXP_EMPTYMATCH_NOTAFTERMATCH | SCFIND_REGEXP_SKIPCRLFASONE; - break; - - case FINDNEXTTYPE_FINDNEXTFORREPLACE: - findState.flags |= SCFIND_REGEXP_EMPTYMATCH_ALL | SCFIND_REGEXP_EMPTYMATCH_ALLOWATSTART | SCFIND_REGEXP_SKIPCRLFASONE; - break; - } - - if (line < 0 || index < 0) - findState.startpos = SendScintilla(SCI_GETCURRENTPOS); - else - findState.startpos = positionFromLineIndex(line, index); - - if (forward) - findState.endpos = SendScintilla(SCI_GETLENGTH); - else - findState.endpos = 0; - - findState.show = show; - - return doFind(); -} - - -// Find the first occurrence of a string in the current selection. -bool QsciScintilla::findFirstInSelection(const QString &expr, bool re, bool cs, - bool wo, bool forward, bool show, bool posix, bool cxx11) -{ - if (expr.isEmpty()) - { - findState.status = FindState::Idle; - return false; - } - - findState.status = FindState::FindingInSelection; - findState.expr = expr; - findState.wrap = false; - findState.forward = forward; - - findState.flags = - (cs ? SCFIND_MATCHCASE : 0) | - (wo ? SCFIND_WHOLEWORD : 0) | - (re ? SCFIND_REGEXP : 0) | - (posix ? SCFIND_POSIX : 0) | - (cxx11 ? SCFIND_CXX11REGEX : 0); - - findState.startpos_orig = SendScintilla(SCI_GETSELECTIONSTART); - findState.endpos_orig = SendScintilla(SCI_GETSELECTIONEND); - - if (forward) - { - findState.startpos = findState.startpos_orig; - findState.endpos = findState.endpos_orig; - } - else - { - findState.startpos = findState.endpos_orig; - findState.endpos = findState.startpos_orig; - } - - findState.show = show; - - return doFind(); -} - - -// Cancel any current search. -void QsciScintilla::cancelFind() -{ - findState.status = FindState::Idle; -} - - -// Find the next occurrence of a string. -bool QsciScintilla::findNext() -{ - if (findState.status == FindState::Idle) - return false; - - return doFind(); -} - - -// Do the hard work of the find methods. -bool QsciScintilla::doFind() -{ - SendScintilla(SCI_SETSEARCHFLAGS, findState.flags); - - int pos = simpleFind(); - - // See if it was found. If not and wraparound is wanted, try again. - if (pos == -1 && findState.wrap) - { - if (findState.forward) - { - findState.startpos = 0; - findState.endpos = SendScintilla(SCI_GETLENGTH); - } - else - { - findState.startpos = SendScintilla(SCI_GETLENGTH); - findState.endpos = 0; - } - - pos = simpleFind(); - } - - //替换boost正则库后,返回值不只有-1,可能-2-3,负数都是错误 - if (pos < 0) - { - // Restore the original selection. - if (findState.status == FindState::FindingInSelection) - SendScintilla(SCI_SETSEL, findState.startpos_orig, - findState.endpos_orig); - - findState.status = FindState::Idle; - return false; - } - - // It was found. - long targstart = SendScintilla(SCI_GETTARGETSTART); - long targend = SendScintilla(SCI_GETTARGETEND); - - // Ensure the text found is visible if required. - if (findState.show) - { - int startLine = SendScintilla(SCI_LINEFROMPOSITION, targstart); - int endLine = SendScintilla(SCI_LINEFROMPOSITION, targend); - findState.linenum = startLine; - - for (int i = startLine; i <= endLine; ++i) - SendScintilla(SCI_ENSUREVISIBLEENFORCEPOLICY, i); - } - else - { - findState.linenum = -1; - } - - // Now set the selection. - SendScintilla(SCI_SETSEL, targstart, targend); - - /* 把查找到的结构返回出去,新增的,外面需要使用 */ - findState.targstart = targstart; - findState.targend = targend; - - // Finally adjust the start position so that we don't find the same one - // again. - if (findState.forward) - findState.startpos = targend; - else if ((findState.startpos = targstart - 1) < 0) - findState.startpos = 0; - - return true; -} - - -// Do a simple find between the start and end positions. -int QsciScintilla::simpleFind() -{ - /*这里是会大于的,因为我在外面会零长查找时,会增加startPos的值。如果是向前,才这样处理*/ - - if (findState.forward && (findState.startpos >= findState.endpos)) { - return -1; - } - else if (!findState.forward && (findState.startpos == findState.endpos)) - { - //如果是往后,则按照原来的逻辑进行处理。 - return -1; - } - - SendScintilla(SCI_SETTARGETSTART, findState.startpos); - SendScintilla(SCI_SETTARGETEND, findState.endpos); - - ScintillaBytes s = textAsBytes(findState.expr); - - return SendScintilla(SCI_SEARCHINTARGET, s.length(), - ScintillaBytesConstData(s)); -} - - -// Replace the text found with the previous find method. -void QsciScintilla::replace(const QString &replaceStr) -{ - if (findState.status == FindState::Idle) - return; - - long start = SendScintilla(SCI_GETSELECTIONSTART); - long orig_len = SendScintilla(SCI_GETSELECTIONEND) - start; - - /*类似查找,当零长替换时,orig_len是0 */ - findState.targstart = start; - findState.targend = start + orig_len; - - SendScintilla(SCI_TARGETFROMSELECTION); - - int cmd = (findState.flags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; - - ScintillaBytes s = textAsBytes(replaceStr); - long len = SendScintilla(cmd, -1, ScintillaBytesConstData(s)); - - // Reset the selection. - SendScintilla(SCI_SETSELECTIONSTART, start); - SendScintilla(SCI_SETSELECTIONEND, start + len); - - // Fix the original selection. - findState.endpos_orig += (len - orig_len); - - if (findState.forward) - { - findState.startpos = start + len; - findState.endpos += (len - orig_len); -} -} - - -// Query the modified state. -bool QsciScintilla::isModified() const -{ - return doc.isModified(); -} - - -// Set the modified state. -void QsciScintilla::setModified(bool m) -{ - if (!m) - SendScintilla(SCI_SETSAVEPOINT); -} - - -// Handle the SCN_INDICATORCLICK notification. -void QsciScintilla::handleIndicatorClick(int pos, int modifiers) -{ - int state = mapModifiers(modifiers); - int line, index; - - lineIndexFromPosition(pos, &line, &index); - - emit indicatorClicked(line, index, Qt::KeyboardModifiers(state)); -} - - -// Handle the SCN_INDICATORRELEASE notification. -void QsciScintilla::handleIndicatorRelease(int pos, int modifiers) -{ - int state = mapModifiers(modifiers); - int line, index; - - lineIndexFromPosition(pos, &line, &index); - - emit indicatorReleased(line, index, Qt::KeyboardModifiers(state)); -} - - -// Handle the SCN_MARGINCLICK notification. -void QsciScintilla::handleMarginClick(int pos, int modifiers, int margin) -{ - int state = mapModifiers(modifiers); - int line = SendScintilla(SCI_LINEFROMPOSITION, pos); - - if (fold && margin == foldmargin) - foldClick(line, state); - else - emit marginClicked(margin, line, Qt::KeyboardModifiers(state)); -} - - -// Handle the SCN_MARGINRIGHTCLICK notification. -void QsciScintilla::handleMarginRightClick(int pos, int modifiers, int margin) -{ - int state = mapModifiers(modifiers); - int line = SendScintilla(SCI_LINEFROMPOSITION, pos); - - emit marginRightClicked(margin, line, Qt::KeyboardModifiers(state)); -} - - -// Handle the SCN_SAVEPOINTREACHED notification. -void QsciScintilla::handleSavePointReached() -{ - doc.setModified(false); - emit modificationChanged(false); -} - - -// Handle the SCN_SAVEPOINTLEFT notification. -void QsciScintilla::handleSavePointLeft() -{ - doc.setModified(true); - emit modificationChanged(true); -} - - -// Handle the QSCN_SELCHANGED signal. -void QsciScintilla::handleSelectionChanged(bool yes) -{ - selText = yes; - - emit copyAvailable(yes); - emit selectionChanged(); -} - - -// Get the current selection. -void QsciScintilla::getSelection(int *lineFrom, int *indexFrom, int *lineTo, - int *indexTo) const -{ - if (selText) - { - lineIndexFromPosition(SendScintilla(SCI_GETSELECTIONSTART), lineFrom, - indexFrom); - lineIndexFromPosition(SendScintilla(SCI_GETSELECTIONEND), lineTo, - indexTo); - } - else - *lineFrom = *indexFrom = *lineTo = *indexTo = -1; -} - - -// Sets the current selection. -void QsciScintilla::setSelection(int lineFrom, int indexFrom, int lineTo, - int indexTo) -{ - SendScintilla(SCI_SETSEL, positionFromLineIndex(lineFrom, indexFrom), - positionFromLineIndex(lineTo, indexTo)); -} - - -// Set the background colour of selected text. -void QsciScintilla::setSelectionBackgroundColor(const QColor &col) -{ - int alpha = col.alpha(); - - if (alpha == 255) - alpha = SC_ALPHA_NOALPHA; - - SendScintilla(SCI_SETSELBACK, 1, col); - SendScintilla(SCI_SETSELALPHA, alpha); -} - - -// Set the foreground colour of selected text. -void QsciScintilla::setSelectionForegroundColor(const QColor &col) -{ - SendScintilla(SCI_SETSELFORE, 1, col); -} - - -// Reset the background colour of selected text to the default. -void QsciScintilla::resetSelectionBackgroundColor() -{ - SendScintilla(SCI_SETSELALPHA, SC_ALPHA_NOALPHA); - SendScintilla(SCI_SETSELBACK, 0UL); -} - - -// Reset the foreground colour of selected text to the default. -void QsciScintilla::resetSelectionForegroundColor() -{ - SendScintilla(SCI_SETSELFORE, 0UL); -} - - -// Set the fill to the end-of-line for the selection. -void QsciScintilla::setSelectionToEol(bool filled) -{ - SendScintilla(SCI_SETSELEOLFILLED, filled); -} - - -// Return the fill to the end-of-line for the selection. -bool QsciScintilla::selectionToEol() const -{ - return SendScintilla(SCI_GETSELEOLFILLED); -} - - -// Set the width of the caret. -void QsciScintilla::setCaretWidth(int width) -{ - SendScintilla(SCI_SETCARETWIDTH, width); -} - - -// Set the width of the frame of the line containing the caret. -void QsciScintilla::setCaretLineFrameWidth(int width) -{ - SendScintilla(SCI_SETCARETLINEFRAME, width); -} - - -// Set the foreground colour of the caret. -void QsciScintilla::setCaretForegroundColor(const QColor &col) -{ - SendScintilla(SCI_SETCARETFORE, col); -} - - -// Set the background colour of the line containing the caret. -void QsciScintilla::setCaretLineBackgroundColor(const QColor &col) -{ - int alpha = col.alpha(); - - if (alpha == 255) - alpha = SC_ALPHA_NOALPHA; - - SendScintilla(SCI_SETCARETLINEBACK, col); - SendScintilla(SCI_SETCARETLINEBACKALPHA, alpha); -} - - -// Set the state of the background colour of the line containing the caret. -void QsciScintilla::setCaretLineVisible(bool enable) -{ - SendScintilla(SCI_SETCARETLINEVISIBLE, enable); -} - - -// Set the background colour of a hotspot area. -void QsciScintilla::setHotspotBackgroundColor(const QColor &col) -{ - SendScintilla(SCI_SETHOTSPOTACTIVEBACK, 1, col); -} - - -// Set the foreground colour of a hotspot area. -void QsciScintilla::setHotspotForegroundColor(const QColor &col) -{ - SendScintilla(SCI_SETHOTSPOTACTIVEFORE, 1, col); -} - - -// Reset the background colour of a hotspot area to the default. -void QsciScintilla::resetHotspotBackgroundColor() -{ - SendScintilla(SCI_SETHOTSPOTACTIVEBACK, 0UL); -} - - -// Reset the foreground colour of a hotspot area to the default. -void QsciScintilla::resetHotspotForegroundColor() -{ - SendScintilla(SCI_SETHOTSPOTACTIVEFORE, 0UL); -} - - -// Set the underline of a hotspot area. -void QsciScintilla::setHotspotUnderline(bool enable) -{ - SendScintilla(SCI_SETHOTSPOTACTIVEUNDERLINE, enable); -} - - -// Set the wrapping of a hotspot area. -void QsciScintilla::setHotspotWrap(bool enable) -{ - SendScintilla(SCI_SETHOTSPOTSINGLELINE, !enable); -} - - -// Query the read-only state. -bool QsciScintilla::isReadOnly() const -{ - return SendScintilla(SCI_GETREADONLY); -} - - -// Set the read-only state. -void QsciScintilla::setReadOnly(bool ro) -{ - setAttribute(Qt::WA_InputMethodEnabled, !ro); - SendScintilla(SCI_SETREADONLY, ro); -} - - -// Append the given text. -void QsciScintilla::append(const QString &text) -{ - bool ro = ensureRW(); - - ScintillaBytes s = textAsBytes(text); - SendScintilla(SCI_APPENDTEXT, s.length(), ScintillaBytesConstData(s)); - - SendScintilla(SCI_EMPTYUNDOBUFFER); - - setReadOnly(ro); -} - - -// Insert the given text at the current position. -void QsciScintilla::insert(const QString &text) -{ - insertAtPos(text, -1); -} - - -// Insert the given text at the given line and offset. -void QsciScintilla::insertAt(const QString &text, int line, int index) -{ - insertAtPos(text, positionFromLineIndex(line, index)); -} - - -// Insert the given text at the given position. -void QsciScintilla::insertAtPos(const QString &text, int pos) -{ - bool ro = ensureRW(); - - SendScintilla(SCI_BEGINUNDOACTION); - SendScintilla(SCI_INSERTTEXT, pos, - ScintillaBytesConstData(textAsBytes(text))); - SendScintilla(SCI_ENDUNDOACTION); - - setReadOnly(ro); -} - - -// Begin a sequence of undoable actions. -void QsciScintilla::beginUndoAction() -{ - SendScintilla(SCI_BEGINUNDOACTION); -} - - -// End a sequence of undoable actions. -void QsciScintilla::endUndoAction() -{ - SendScintilla(SCI_ENDUNDOACTION); -} - - -// Redo a sequence of actions. -void QsciScintilla::redo() -{ - SendScintilla(SCI_REDO); -} - - -// Undo a sequence of actions. -void QsciScintilla::undo() -{ - SendScintilla(SCI_UNDO); -} - - -// See if there is something to redo. -bool QsciScintilla::isRedoAvailable() const -{ - return SendScintilla(SCI_CANREDO); -} - - -// See if there is something to undo. -bool QsciScintilla::isUndoAvailable() const -{ - return SendScintilla(SCI_CANUNDO); -} - - -// Return the number of lines. -int QsciScintilla::lines() const -{ - return SendScintilla(SCI_GETLINECOUNT); -} - - -// Return the line at a position. -int QsciScintilla::lineAt(const QPoint &pos) const -{ - long chpos = SendScintilla(SCI_POSITIONFROMPOINTCLOSE, pos.x(), pos.y()); - - if (chpos < 0) - return -1; - - return SendScintilla(SCI_LINEFROMPOSITION, chpos); -} - - -// Return the length of a line. -int QsciScintilla::lineLength(int line) const -{ - if (line < 0 || line >= SendScintilla(SCI_GETLINECOUNT)) - return -1; - - return SendScintilla(SCI_LINELENGTH, line); -} - - -// Return the length of the current text. -int QsciScintilla::length() const -{ - return SendScintilla(SCI_GETTEXTLENGTH); -} - - -// Remove any selected text. -void QsciScintilla::removeSelectedText() -{ - SendScintilla(SCI_REPLACESEL, ""); -} - - -// Replace any selected text. -void QsciScintilla::replaceSelectedText(const QString &text) -{ - SendScintilla(SCI_REPLACESEL, ScintillaBytesConstData(textAsBytes(text))); -} - - -// Return the current selected text. -QString QsciScintilla::selectedText() const -{ - if (!selText) - return QString(); - - char *buf = new char[SendScintilla(SCI_GETSELECTIONEND) - SendScintilla(SCI_GETSELECTIONSTART) + 1]; - - SendScintilla(SCI_GETSELTEXT, buf); - - QString qs = bytesAsText(buf); - delete[] buf; - - return qs; -} - - -// Return the current text. -QString QsciScintilla::text() const -{ - int buflen = length() + 1; - char *buf = new char[buflen]; - - SendScintilla(SCI_GETTEXT, buflen, buf); - - QString qs = bytesAsText(buf,buflen-1); - delete[] buf; - - return qs; -} - - -// Return the text of a line. -QString QsciScintilla::text(int line) const -{ - int line_len = lineLength(line); - - if (line_len < 1) - return QString(); - - char *buf = new char[line_len + 1]; - - SendScintilla(SCI_GETLINE, line, buf); - buf[line_len] = '\0'; - - QString qs = bytesAsText(buf); - delete[] buf; - - return qs; -} - - -// Return the text between two positions. -QString QsciScintilla::text(int start, int end) const -{ - char *buf = new char[end - start + 1]; - SendScintilla(SCI_GETTEXTRANGE, start, end, buf); - QString text = bytesAsText(buf); - delete[] buf; - - return text; -} - - -// Return the text as encoded bytes between two positions. -QByteArray QsciScintilla::bytes(int start, int end) const -{ - QByteArray bytes(end - start + 1, '\0'); - - SendScintilla(SCI_GETTEXTRANGE, start, end, bytes.data()); - - return bytes; -} - - -// Set the given text. -void QsciScintilla::setText(const QString &text) -{ -#if 0 - bool ro = ensureRW(); - - SendScintilla(SCI_SETTEXT, ScintillaBytesConstData(textAsBytes(text))); - SendScintilla(SCI_EMPTYUNDOBUFFER); - - setReadOnly(ro); -#endif - //0 正常 1 只读模式。 - bool ro = ensureRW(); - - ScintillaBytes temp = textAsBytes(text); - const char *data = ScintillaBytesConstData(temp); - SendScintilla(SCI_SET_UTF8_TEXT, temp.length(), data); - SendScintilla(SCI_EMPTYUNDOBUFFER); - - setReadOnly(ro); - -} - +// This module implements the "official" high-level API of the Qt port of +// Scintilla. It is modelled on QTextEdit - a method of the same name should +// behave in the same way. +// +// Copyright (c) 2023 Riverbank Computing Limited +// +// This file is part of QScintilla. +// +// This file may be used under the terms of the GNU General Public License +// version 3.0 as published by the Free Software Foundation and appearing in +// the file LICENSE included in the packaging of this file. Please review the +// following information to ensure the GNU General Public License version 3.0 +// requirements will be met: http://www.gnu.org/copyleft/gpl.html. +// +// If you do not wish to use this file under the terms of the GPL version 3.0 +// then you may purchase a commercial license. For more information contact +// info@riverbankcomputing.com. +// +// This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +// WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. + + +#include "Qsci/qsciscintilla.h" + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Qsci/qsciabstractapis.h" +#include "Qsci/qscicommandset.h" +#include "Qsci/qscilexer.h" +#include "Qsci/qscistyle.h" +#include "Qsci/qscistyledtext.h" +#include "xmlMatchedTagsHighlighter.h" +#include "BoostRegexSearch.h" + + +// Make sure these match the values in Scintilla.h. We don't #include that +// file because it just causes more clashes. +#define KEYWORDSET_MAX 8 +#define MARKER_MAX 31 + +// The list separators for auto-completion and user lists. +const char acSeparator = '\x03'; +const char userSeparator = '\x04'; + +// The default fold margin width. +static const int defaultFoldMarginWidth = 14; + +// The default set of characters that make up a word. +static const char *defaultWordChars = "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +// Forward declarations. +static QColor asQColor(long sci_colour); + + +// The ctor. +QsciScintilla::QsciScintilla(QWidget *parent) + : QsciScintillaBase(parent), + allocatedMarkers(0), allocatedIndicators(7), oldPos(-1), oldLine(-1), selText(false), + fold(NoFoldStyle), foldmargin(2), autoInd(false), + braceMode(NoBraceMatch), acSource(AcsNone), acThresh(-1), + wchars(defaultWordChars), call_tips_position(CallTipsBelowText), + call_tips_style(CallTipsNoContext), maxCallTips(-1), + use_single(AcusNever), explicit_fillups(""), fillups_enabled(false), isIndentGuide(false), isHtmlHighLightTag(false) +{ + connect(this,SIGNAL(SCN_MODIFYATTEMPTRO()), + SIGNAL(modificationAttempted())); + + connect(this,SIGNAL(SCN_MODIFIED(int,int,const char *,int,int,int,int,int,int,int)), + SLOT(handleModified(int,int,const char *,int,int,int,int,int,int,int))); + connect(this,SIGNAL(SCN_CALLTIPCLICK(int)), + SLOT(handleCallTipClick(int))); + connect(this,SIGNAL(SCN_CHARADDED(int)), + SLOT(handleCharAdded(int))); + connect(this,SIGNAL(SCN_INDICATORCLICK(int,int)), + SLOT(handleIndicatorClick(int,int))); + connect(this,SIGNAL(SCN_INDICATORRELEASE(int,int)), + SLOT(handleIndicatorRelease(int,int))); + connect(this,SIGNAL(SCN_MARGINCLICK(int,int,int)), + SLOT(handleMarginClick(int,int,int))); + connect(this,SIGNAL(SCN_MARGINRIGHTCLICK(int,int,int)), + SLOT(handleMarginRightClick(int,int,int))); + connect(this,SIGNAL(SCN_SAVEPOINTREACHED()), + SLOT(handleSavePointReached())); + connect(this,SIGNAL(SCN_SAVEPOINTLEFT()), + SLOT(handleSavePointLeft())); + connect(this,SIGNAL(SCN_UPDATEUI(int)), + SLOT(handleUpdateUI(int))); + connect(this,SIGNAL(QSCN_SELCHANGED(bool)), + SLOT(handleSelectionChanged(bool))); + connect(this,SIGNAL(SCN_AUTOCSELECTION(const char *,int)), + SLOT(handleAutoCompletionSelection())); + connect(this,SIGNAL(SCN_USERLISTSELECTION(const char *,int)), + SLOT(handleUserListSelection(const char *,int))); + + // Set the default font. + setFont(QApplication::font()); + + // Set the default fore and background colours. + QPalette pal = QApplication::palette(); + setColor(pal.text().color()); + setPaper(pal.base().color()); + setSelectionForegroundColor(pal.highlightedText().color()); + setSelectionBackgroundColor(pal.highlight().color()); + +#if defined(Q_OS_WIN) + setEolMode(EolWindows); +#else + // Note that EolMac is pre-OS/X. + setEolMode(EolUnix); +#endif + + // Capturing the mouse seems to cause problems on multi-head systems. Qt + // should do the right thing anyway. + SendScintilla(SCI_SETMOUSEDOWNCAPTURES, 0UL); + + setMatchedBraceForegroundColor(Qt::blue); + setUnmatchedBraceForegroundColor(Qt::red); + + //下面这个不能随意放开,否则在一个长行的情况下,进行替换操作将非常慢 + //20221123用户反馈替换非常慢,对比ndd后查找得到的问题。 + setAnnotationDisplay(AnnotationHidden); + setLexer(); + + // Set the visible policy. These are the same as SciTE's defaults + // which, presumably, are sensible. + SendScintilla(SCI_SETVISIBLEPOLICY, VISIBLE_STRICT | VISIBLE_SLOP, 4); + + // The default behaviour is unexpected. + SendScintilla(SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR, + SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE); + + // Create the standard command set. + stdCmds = new QsciCommandSet(this); + + doc.display(this,0); +} + + +// The dtor. +QsciScintilla::~QsciScintilla() +{ + // Detach any current lexer. + detachLexer(); + + doc.undisplay(this); + delete stdCmds; +} + + +// Return the current text colour. +QColor QsciScintilla::color() const +{ + return nl_text_colour; +} + + +// Set the text colour. +void QsciScintilla::setColor(const QColor &c) +{ + if (lex.isNull()) + { + // Assume style 0 applies to everything so that we don't need to use + // SCI_STYLECLEARALL which clears everything. + SendScintilla(SCI_STYLESETFORE, 0, c); + nl_text_colour = c; + } +} + + +// Return the overwrite mode. +bool QsciScintilla::overwriteMode() const +{ + return SendScintilla(SCI_GETOVERTYPE); +} + + +// Set the overwrite mode. +void QsciScintilla::setOverwriteMode(bool overwrite) +{ + SendScintilla(SCI_SETOVERTYPE, overwrite); +} + + +// Return the current paper colour. +QColor QsciScintilla::paper() const +{ + return nl_paper_colour; +} + + +// Set the paper colour. +void QsciScintilla::setPaper(const QColor &c) +{ + if (lex.isNull()) + { + // Assume style 0 applies to everything so that we don't need to use + // SCI_STYLECLEARALL which clears everything. We still have to set the + // default style as well for the background without any text. + SendScintilla(SCI_STYLESETBACK, 0, c); + SendScintilla(SCI_STYLESETBACK, STYLE_DEFAULT, c); + nl_paper_colour = c; + } +} + + +// Set the default font. +void QsciScintilla::setFont(const QFont &f) +{ + if (lex.isNull()) + { + // Assume style 0 applies to everything so that we don't need to use + // SCI_STYLECLEARALL which clears everything. + setStylesFont(f, 0); + QWidget::setFont(f); + } +} + + +// Enable/disable auto-indent. +void QsciScintilla::setAutoIndent(bool autoindent) +{ + autoInd = autoindent; +} + + +// Set the brace matching mode. +void QsciScintilla::setBraceMatching(BraceMatch bm) +{ + braceMode = bm; +} + + +// Handle the addition of a character. +void QsciScintilla::handleCharAdded(int ch) +{ + // Ignore if there is a selection. + long pos = SendScintilla(SCI_GETSELECTIONSTART); + + if (pos != SendScintilla(SCI_GETSELECTIONEND) || pos == 0) + return; + + // If auto-completion is already active then see if this character is a + // start character. If it is then create a new list which will be a subset + // of the current one. The case where it isn't a start character seems to + // be handled correctly elsewhere. + if (isListActive() && isStartChar(ch)) + { + cancelList(); + startAutoCompletion(acSource, false, use_single == AcusAlways); + + return; + } + + // Handle call tips. + if (call_tips_style != CallTipsNone && !lex.isNull() && strchr("(),", ch) != NULL) + callTip(); + + // Handle auto-indentation. + if (autoInd) + { + if (lex.isNull() || (lex->autoIndentStyle() & AiMaintain)) + maintainIndentation(ch, pos); + else + autoIndentation(ch, pos); + } + + // See if we might want to start auto-completion. + if (!isCallTipActive() && acSource != AcsNone) + { + if (isStartChar(ch)) + startAutoCompletion(acSource, false, use_single == AcusAlways); + else if (acThresh >= 1 && isWordCharacter(ch)) + startAutoCompletion(acSource, true, use_single == AcusAlways); + } +} + + +// See if a call tip is active. +bool QsciScintilla::isCallTipActive() const +{ + return SendScintilla(SCI_CALLTIPACTIVE); +} + + +// Handle a possible change to any current call tip. +void QsciScintilla::callTip() +{ + QsciAbstractAPIs *apis = lex->apis(); + + if (!apis) + return; + + int pos, commas = 0; + bool found = false; + char ch; + + pos = SendScintilla(SCI_GETCURRENTPOS); + + // Move backwards through the line looking for the start of the current + // call tip and working out which argument it is. + while ((ch = getCharacter(pos)) != '\0') + { + if (ch == ',') + ++commas; + else if (ch == ')') + { + int depth = 1; + + // Ignore everything back to the start of the corresponding + // parenthesis. + while ((ch = getCharacter(pos)) != '\0') + { + if (ch == ')') + ++depth; + else if (ch == '(' && --depth == 0) + break; + } + } + else if (ch == '(') + { + found = true; + break; + } + } + + // Cancel any existing call tip. + SendScintilla(SCI_CALLTIPCANCEL); + + // Done if there is no new call tip to set. + if (!found) + return; + + QStringList context = apiContext(pos, pos, ctPos); + + if (context.isEmpty()) + return; + + // The last word is complete, not partial. + context << QString(); + + ct_cursor = 0; + ct_shifts.clear(); + ct_entries = apis->callTips(context, commas, call_tips_style, ct_shifts); + + int nr_entries = ct_entries.count(); + + if (nr_entries == 0) + return; + + if (maxCallTips > 0 && maxCallTips < nr_entries) + { + ct_entries = ct_entries.mid(0, maxCallTips); + nr_entries = maxCallTips; + } + + int shift; + QString ct; + + int nr_shifts = ct_shifts.count(); + + if (maxCallTips < 0 && nr_entries > 1) + { + shift = (nr_shifts > 0 ? ct_shifts.first() : 0); + ct = ct_entries[0]; + ct.prepend('\002'); + } + else + { + if (nr_shifts > nr_entries) + nr_shifts = nr_entries; + + // Find the biggest shift. + shift = 0; + + for (int i = 0; i < nr_shifts; ++i) + { + int sh = ct_shifts[i]; + + if (shift < sh) + shift = sh; + } + + ct = ct_entries.join("\n"); + } + + ScintillaBytes ct_bytes = textAsBytes(ct); + const char *cts = ScintillaBytesConstData(ct_bytes); + + SendScintilla(SCI_CALLTIPSHOW, adjustedCallTipPosition(shift), cts); + + // Done if there is more than one call tip. + if (nr_entries > 1) + return; + + // Highlight the current argument. + const char *astart; + + if (commas == 0) + astart = strchr(cts, '('); + else + for (astart = strchr(cts, ','); astart && --commas > 0; astart = strchr(astart + 1, ',')) + ; + + if (!astart || !*++astart) + return; + + // The end is at the next comma or unmatched closing parenthesis. + const char *aend; + int depth = 0; + + for (aend = astart; *aend; ++aend) + { + char ch = *aend; + + if (ch == ',' && depth == 0) + break; + else if (ch == '(') + ++depth; + else if (ch == ')') + { + if (depth == 0) + break; + + --depth; + } + } + + if (astart != aend) + SendScintilla(SCI_CALLTIPSETHLT, astart - cts, aend - cts); +} + + +// Handle a call tip click. +void QsciScintilla::handleCallTipClick(int dir) +{ + int nr_entries = ct_entries.count(); + + // Move the cursor while bounds checking. + if (dir == 1) + { + if (ct_cursor - 1 < 0) + return; + + --ct_cursor; + } + else if (dir == 2) + { + if (ct_cursor + 1 >= nr_entries) + return; + + ++ct_cursor; + } + else + return; + + int shift = (ct_shifts.count() > ct_cursor ? ct_shifts[ct_cursor] : 0); + QString ct = ct_entries[ct_cursor]; + + // Add the arrows. + if (ct_cursor < nr_entries - 1) + ct.prepend('\002'); + + if (ct_cursor > 0) + ct.prepend('\001'); + + ScintillaBytes ct_bytes = textAsBytes(ct); + const char *cts = ScintillaBytesConstData(ct_bytes); + + SendScintilla(SCI_CALLTIPSHOW, adjustedCallTipPosition(shift), cts); +} + + +// Shift the position of the call tip (to take any context into account) but +// don't go before the start of the line. +int QsciScintilla::adjustedCallTipPosition(int ctshift) const +{ + int ct = ctPos; + + if (ctshift) + { + int ctmin = SendScintilla(SCI_POSITIONFROMLINE, SendScintilla(SCI_LINEFROMPOSITION, ct)); + + if (ct - ctshift < ctmin) + ct = ctmin; + } + + return ct; +} + + +// Return the list of words that make up the context preceding the given +// position. The list will only have more than one element if there is a lexer +// set and it defines start strings. If so, then the last element might be +// empty if a start string has just been typed. On return pos is at the start +// of the context. +QStringList QsciScintilla::apiContext(int pos, int &context_start, + int &last_word_start) +{ + enum { + Either, + Separator, + Word + }; + + QStringList words; + int good_pos = pos, expecting = Either; + + last_word_start = -1; + + while (pos > 0) + { + if (getSeparator(pos)) + { + if (expecting == Either) + words.prepend(QString()); + else if (expecting == Word) + break; + + good_pos = pos; + expecting = Word; + } + else + { + QString word = getWord(pos); + + if (word.isEmpty() || expecting == Separator) + break; + + words.prepend(word); + good_pos = pos; + expecting = Separator; + + // Return the position of the start of the last word if required. + if (last_word_start < 0) + last_word_start = pos; + } + + // Strip any preceding spaces (mainly around operators). + char ch; + + while ((ch = getCharacter(pos)) != '\0') + { + // This is the same definition of space that Scintilla uses. + if (ch != ' ' && (ch < 0x09 || ch > 0x0d)) + { + ++pos; + break; + } + } + } + + // A valid sequence always starts with a word and so should be expecting a + // separator. + if (expecting != Separator) + words.clear(); + + context_start = good_pos; + + return words; +} + + +// Try and get a lexer's word separator from the text before the current +// position. Return true if one was found and adjust the position accordingly. +bool QsciScintilla::getSeparator(int &pos) const +{ + int opos = pos; + + // Go through each separator. + for (int i = 0; i < wseps.count(); ++i) + { + const QString &ws = wseps[i]; + + // Work backwards. + uint l; + + for (l = ws.length(); l; --l) + { + char ch = getCharacter(pos); + + if (ch == '\0' || ws.at(l - 1) != ch) + break; + } + + if (!l) + return true; + + // Reset for the next separator. + pos = opos; + } + + return false; +} + + +// Try and get a word from the text before the current position. Return the +// word if one was found and adjust the position accordingly. +QString QsciScintilla::getWord(int &pos) const +{ + QString word; + bool numeric = true; + char ch; + + while ((ch = getCharacter(pos)) != '\0') + { + if (!isWordCharacter(ch)) + { + ++pos; + break; + } + + if (ch < '0' || ch > '9') + numeric = false; + + word.prepend(ch); + } + + // We don't auto-complete numbers. + if (numeric) + word.truncate(0); + + return word; +} + + +// Get the "next" character (ie. the one before the current position) in the +// current line. The character will be '\0' if there are no more. +char QsciScintilla::getCharacter(int &pos) const +{ + if (pos <= 0) + return '\0'; + + char ch = SendScintilla(SCI_GETCHARAT, --pos); + + // Don't go past the end of the previous line. + if (ch == '\n' || ch == '\r') + { + ++pos; + return '\0'; + } + + return ch; +} + + +// See if a character is an auto-completion start character, ie. the last +// character of a word separator. +bool QsciScintilla::isStartChar(char ch) const +{ + QString s = QChar(ch); + + for (int i = 0; i < wseps.count(); ++i) + if (wseps[i].endsWith(s)) + return true; + + return false; +} + + +// Possibly start auto-completion. +void QsciScintilla::startAutoCompletion(AutoCompletionSource acs, + bool checkThresh, bool choose_single) +{ + int start, ignore; + QStringList context = apiContext(SendScintilla(SCI_GETCURRENTPOS), start, + ignore); + + if (context.isEmpty()) + return; + + // Get the last word's raw data and length. + ScintillaBytes s = textAsBytes(context.last()); + const char *last_data = ScintillaBytesConstData(s); + int last_len = s.length(); + + if (checkThresh && last_len < acThresh) + return; + + // Generate the string representing the valid words to select from. + QStringList wlist; + + if ((acs == AcsAll || acs == AcsAPIs) && !lex.isNull()) + { + QsciAbstractAPIs *apis = lex->apis(); + + if (apis) + apis->updateAutoCompletionList(context, wlist); + } + + if (acs == AcsAll || acs == AcsDocument) + { + int sflags = SCFIND_WORDSTART; + + if (!SendScintilla(SCI_AUTOCGETIGNORECASE)) + sflags |= SCFIND_MATCHCASE; + + SendScintilla(SCI_SETSEARCHFLAGS, sflags); + + int pos = 0; + int dlen = SendScintilla(SCI_GETLENGTH); + int caret = SendScintilla(SCI_GETCURRENTPOS); + int clen = caret - start; + char *orig_context = new char[clen + 1]; + + SendScintilla(SCI_GETTEXTRANGE, start, caret, orig_context); + + for (;;) + { + int fstart; + + SendScintilla(SCI_SETTARGETSTART, pos); + SendScintilla(SCI_SETTARGETEND, dlen); + + if ((fstart = SendScintilla(SCI_SEARCHINTARGET, clen, orig_context)) < 0) + break; + + // Move past the root part. + pos = fstart + clen; + + // Skip if this is the context we are auto-completing. + if (pos == caret) + continue; + + // Get the rest of this word. + QString w = last_data; + + while (pos < dlen) + { + char ch = SendScintilla(SCI_GETCHARAT, pos); + + if (!isWordCharacter(ch)) + break; + + w += ch; + ++pos; + } + + // Add the word if it isn't already there. + if (!w.isEmpty()) + { + bool keep; + + // If there are APIs then check if the word is already present + // as an API word (i.e. with a trailing space). + if (acs == AcsAll) + { + QString api_w = w; + api_w.append(' '); + + keep = !wlist.contains(api_w); + } + else + { + keep = true; + } + + if (keep && !wlist.contains(w)) + wlist.append(w); + } + } + + delete []orig_context; + } + + if (wlist.isEmpty()) + return; + + wlist.sort(); + + SendScintilla(SCI_AUTOCSETCHOOSESINGLE, choose_single); + SendScintilla(SCI_AUTOCSETSEPARATOR, acSeparator); + + ScintillaBytes wlist_s = textAsBytes(wlist.join(QChar(acSeparator))); + SendScintilla(SCI_AUTOCSHOW, last_len, ScintillaBytesConstData(wlist_s)); +} + + +// Maintain the indentation of the previous line. +void QsciScintilla::maintainIndentation(char ch, long pos) +{ + if (ch != '\r' && ch != '\n') + return; + + int curr_line = SendScintilla(SCI_LINEFROMPOSITION, pos); + + // Get the indentation of the preceding non-zero length line. + int ind = 0; + + for (int line = curr_line - 1; line >= 0; --line) + { + if (SendScintilla(SCI_GETLINEENDPOSITION, line) > + SendScintilla(SCI_POSITIONFROMLINE, line)) + { + ind = indentation(line); + break; + } + } + + if (ind > 0) + autoIndentLine(pos, curr_line, ind); +} + + +// Implement auto-indentation. +void QsciScintilla::autoIndentation(char ch, long pos) +{ + int curr_line = SendScintilla(SCI_LINEFROMPOSITION, pos); + int ind_width = indentWidth(); + long curr_line_start = SendScintilla(SCI_POSITIONFROMLINE, curr_line); + + const char *block_start = lex->blockStart(); + bool start_single = (block_start && qstrlen(block_start) == 1); + + const char *block_end = lex->blockEnd(); + bool end_single = (block_end && qstrlen(block_end) == 1); + + if (end_single && block_end[0] == ch) + { + if (!(lex->autoIndentStyle() & AiClosing) && rangeIsWhitespace(curr_line_start, pos - 1)) + autoIndentLine(pos, curr_line, blockIndent(curr_line - 1) - ind_width); + } + else if (start_single && block_start[0] == ch) + { + // De-indent if we have already indented because the previous line was + // a start of block keyword. + if (!(lex->autoIndentStyle() & AiOpening) && curr_line > 0 && getIndentState(curr_line - 1) == isKeywordStart && rangeIsWhitespace(curr_line_start, pos - 1)) + autoIndentLine(pos, curr_line, blockIndent(curr_line - 1) - ind_width); + } + else if (ch == '\r' || ch == '\n') + { + // Don't auto-indent the line (ie. preserve its existing indentation) + // if we have inserted a new line above by pressing return at the start + // of this line - in other words, if the previous line is empty. + long prev_line_length = SendScintilla(SCI_GETLINEENDPOSITION, curr_line - 1) - SendScintilla(SCI_POSITIONFROMLINE, curr_line - 1); + + if (prev_line_length != 0) + autoIndentLine(pos, curr_line, blockIndent(curr_line - 1)); + } +} + + +// Set the indentation for a line. +void QsciScintilla::autoIndentLine(long pos, int line, int indent) +{ + if (indent < 0) + return; + + long pos_before = SendScintilla(SCI_GETLINEINDENTPOSITION, line); + SendScintilla(SCI_SETLINEINDENTATION, line, indent); + long pos_after = SendScintilla(SCI_GETLINEINDENTPOSITION, line); + long new_pos = -1; + + if (pos_after > pos_before) + { + new_pos = pos + (pos_after - pos_before); + } + else if (pos_after < pos_before && pos >= pos_after) + { + if (pos >= pos_before) + new_pos = pos + (pos_after - pos_before); + else + new_pos = pos_after; + } + + if (new_pos >= 0) + SendScintilla(SCI_SETSEL, new_pos, new_pos); +} + + +// Return the indentation of the block defined by the given line (or something +// significant before). +int QsciScintilla::blockIndent(int line) +{ + if (line < 0) + return 0; + + // Handle the trvial case. + if (!lex->blockStartKeyword() && !lex->blockStart() && !lex->blockEnd()) + return indentation(line); + + int line_limit = line - lex->blockLookback(); + + if (line_limit < 0) + line_limit = 0; + + for (int l = line; l >= line_limit; --l) + { + IndentState istate = getIndentState(l); + + if (istate != isNone) + { + int ind_width = indentWidth(); + int ind = indentation(l); + + if (istate == isBlockStart) + { + if (!(lex -> autoIndentStyle() & AiOpening)) + ind += ind_width; + } + else if (istate == isBlockEnd) + { + if (lex -> autoIndentStyle() & AiClosing) + ind -= ind_width; + + if (ind < 0) + ind = 0; + } + else if (line == l) + ind += ind_width; + + return ind; + } + } + + return indentation(line); +} + + +// Return true if all characters starting at spos up to, but not including +// epos, are spaces or tabs. +bool QsciScintilla::rangeIsWhitespace(long spos, long epos) +{ + while (spos < epos) + { + char ch = SendScintilla(SCI_GETCHARAT, spos); + + if (ch != ' ' && ch != '\t') + return false; + + ++spos; + } + + return true; +} + + +// Returns the indentation state of a line. +QsciScintilla::IndentState QsciScintilla::getIndentState(int line) +{ + IndentState istate; + + // Get the styled text. + long spos = SendScintilla(SCI_POSITIONFROMLINE, line); + long epos = SendScintilla(SCI_POSITIONFROMLINE, line + 1); + + char *text = new char[(epos - spos + 1) * 2]; + + SendScintilla(SCI_GETSTYLEDTEXT, spos, epos, text); + + int style, bstart_off, bend_off; + + // Block start/end takes precedence over keywords. + const char *bstart_words = lex->blockStart(&style); + bstart_off = findStyledWord(text, style, bstart_words); + + const char *bend_words = lex->blockEnd(&style); + bend_off = findStyledWord(text, style, bend_words); + + // If there is a block start but no block end characters then ignore it + // unless the block start is the last significant thing on the line, ie. + // assume Python-like blocking. + if (bstart_off >= 0 && !bend_words) + for (int i = bstart_off * 2; text[i] != '\0'; i += 2) + if (!QChar(text[i]).isSpace()) + return isNone; + + if (bstart_off > bend_off) + istate = isBlockStart; + else if (bend_off > bstart_off) + istate = isBlockEnd; + else + { + const char *words = lex->blockStartKeyword(&style); + + istate = (findStyledWord(text,style,words) >= 0) ? isKeywordStart : isNone; + } + + delete[] text; + + return istate; +} + + +// text is a pointer to some styled text (ie. a character byte followed by a +// style byte). style is a style number. words is a space separated list of +// words. Returns the position in the text immediately after the last one of +// the words with the style. The reason we are after the last, and not the +// first, occurance is that we are looking for words that start and end a block +// where the latest one is the most significant. +int QsciScintilla::findStyledWord(const char *text, int style, + const char *words) +{ + if (!words) + return -1; + + // Find the range of text with the style we are looking for. + const char *stext; + + for (stext = text; stext[1] != style; stext += 2) + if (stext[0] == '\0') + return -1; + + // Move to the last character. + const char *etext = stext; + + while (etext[2] != '\0') + etext += 2; + + // Backtrack until we find the style. There will be one. + while (etext[1] != style) + etext -= 2; + + // Look for each word in turn. + while (words[0] != '\0') + { + // Find the end of the word. + const char *eword = words; + + while (eword[1] != ' ' && eword[1] != '\0') + ++eword; + + // Now search the text backwards. + const char *wp = eword; + + for (const char *tp = etext; tp >= stext; tp -= 2) + { + if (tp[0] != wp[0] || tp[1] != style) + { + // Reset the search. + wp = eword; + continue; + } + + // See if all the word has matched. + if (wp-- == words) + return ((tp - text) / 2) + (eword - words) + 1; + } + + // Move to the start of the next word if there is one. + words = eword + 1; + + if (words[0] == ' ') + ++words; + } + + return -1; +} + + +// Return true if the code page is UTF8. +bool QsciScintilla::isUtf8() const +{ + return (SendScintilla(SCI_GETCODEPAGE) == SC_CP_UTF8); +} + + +// Set the code page. +void QsciScintilla::setUtf8(bool cp) +{ + SendScintilla(SCI_SETCODEPAGE, (cp ? SC_CP_UTF8 : 0)); +} + + +// Return the end-of-line mode. +QsciScintilla::EolMode QsciScintilla::eolMode() const +{ + return (EolMode)SendScintilla(SCI_GETEOLMODE); +} + + +// Set the end-of-line mode. +void QsciScintilla::setEolMode(EolMode mode) +{ + SendScintilla(SCI_SETEOLMODE, mode); +} + + +// Convert the end-of-lines to a particular mode. +void QsciScintilla::convertEols(EolMode mode) +{ + SendScintilla(SCI_CONVERTEOLS, mode); +} + + +// Add an edge column. +void QsciScintilla::addEdgeColumn(int colnr, const QColor &col) +{ + SendScintilla(SCI_MULTIEDGEADDLINE, colnr, col); +} + + +// Clear all multi-edge columns. +void QsciScintilla::clearEdgeColumns() +{ + SendScintilla(SCI_MULTIEDGECLEARALL); +} + + +// Return the edge colour. +QColor QsciScintilla::edgeColor() const +{ + return asQColor(SendScintilla(SCI_GETEDGECOLOUR)); +} + + +// Set the edge colour. +void QsciScintilla::setEdgeColor(const QColor &col) +{ + SendScintilla(SCI_SETEDGECOLOUR, col); +} + + +// Return the edge column. +int QsciScintilla::edgeColumn() const +{ + return SendScintilla(SCI_GETEDGECOLUMN); +} + + +// Set the edge column. +void QsciScintilla::setEdgeColumn(int colnr) +{ + SendScintilla(SCI_SETEDGECOLUMN, colnr); +} + + +// Return the edge mode. +QsciScintilla::EdgeMode QsciScintilla::edgeMode() const +{ + return (EdgeMode)SendScintilla(SCI_GETEDGEMODE); +} + + +// Set the edge mode. +void QsciScintilla::setEdgeMode(EdgeMode mode) +{ + SendScintilla(SCI_SETEDGEMODE, mode); +} + + +// Return the end-of-line visibility. +bool QsciScintilla::eolVisibility() const +{ + return SendScintilla(SCI_GETVIEWEOL); +} + + +// Set the end-of-line visibility. +void QsciScintilla::setEolVisibility(bool visible) +{ + SendScintilla(SCI_SETVIEWEOL, visible); +} + + +// Return the extra ascent. +int QsciScintilla::extraAscent() const +{ + return SendScintilla(SCI_GETEXTRAASCENT); +} + + +// Set the extra ascent. +void QsciScintilla::setExtraAscent(int extra) +{ + SendScintilla(SCI_SETEXTRAASCENT, extra); +} + + +// Return the extra descent. +int QsciScintilla::extraDescent() const +{ + return SendScintilla(SCI_GETEXTRADESCENT); +} + + +// Set the extra descent. +void QsciScintilla::setExtraDescent(int extra) +{ + SendScintilla(SCI_SETEXTRADESCENT, extra); +} + + +// Return the whitespace size. +int QsciScintilla::whitespaceSize() const +{ + return SendScintilla(SCI_GETWHITESPACESIZE); +} + + +// Set the whitespace size. +void QsciScintilla::setWhitespaceSize(int size) +{ + SendScintilla(SCI_SETWHITESPACESIZE, size); +} + + +// Set the whitespace background colour. +void QsciScintilla::setWhitespaceBackgroundColor(const QColor &col) +{ + SendScintilla(SCI_SETWHITESPACEBACK, col.isValid(), col); +} + + +// Set the whitespace foreground colour. +void QsciScintilla::setWhitespaceForegroundColor(const QColor &col) +{ + SendScintilla(SCI_SETWHITESPACEFORE, col.isValid(), col); +} + + +// Return the whitespace visibility. +QsciScintilla::WhitespaceVisibility QsciScintilla::whitespaceVisibility() const +{ + return (WhitespaceVisibility)SendScintilla(SCI_GETVIEWWS); +} + + +// Set the whitespace visibility. +void QsciScintilla::setWhitespaceVisibility(WhitespaceVisibility mode) +{ + SendScintilla(SCI_SETVIEWWS, mode); +} + + +// Return the tab draw mode. +QsciScintilla::TabDrawMode QsciScintilla::tabDrawMode() const +{ + return (TabDrawMode)SendScintilla(SCI_GETTABDRAWMODE); +} + + +// Set the tab draw mode. +void QsciScintilla::setTabDrawMode(TabDrawMode mode) +{ + SendScintilla(SCI_SETTABDRAWMODE, mode); +} + + +// Return the line wrap mode. +QsciScintilla::WrapMode QsciScintilla::wrapMode() const +{ + return (WrapMode)SendScintilla(SCI_GETWRAPMODE); +} + + +// Set the line wrap mode. +void QsciScintilla::setWrapMode(WrapMode mode) +{ + SendScintilla(SCI_SETLAYOUTCACHE, + (mode == WrapNone ? SC_CACHE_CARET : SC_CACHE_DOCUMENT)); + SendScintilla(SCI_SETWRAPMODE, mode); +} + + +// Return the line wrap indent mode. +QsciScintilla::WrapIndentMode QsciScintilla::wrapIndentMode() const +{ + return (WrapIndentMode)SendScintilla(SCI_GETWRAPINDENTMODE); +} + + +// Set the line wrap indent mode. +void QsciScintilla::setWrapIndentMode(WrapIndentMode mode) +{ + SendScintilla(SCI_SETWRAPINDENTMODE, mode); +} + + +// Set the line wrap visual flags. +void QsciScintilla::setWrapVisualFlags(WrapVisualFlag endFlag, + WrapVisualFlag startFlag, int indent) +{ + int flags = SC_WRAPVISUALFLAG_NONE; + int loc = SC_WRAPVISUALFLAGLOC_DEFAULT; + + switch (endFlag) + { + case WrapFlagNone: + break; + + case WrapFlagByText: + flags |= SC_WRAPVISUALFLAG_END; + loc |= SC_WRAPVISUALFLAGLOC_END_BY_TEXT; + break; + + case WrapFlagByBorder: + flags |= SC_WRAPVISUALFLAG_END; + break; + + case WrapFlagInMargin: + flags |= SC_WRAPVISUALFLAG_MARGIN; + break; + } + + switch (startFlag) + { + case WrapFlagNone: + break; + + case WrapFlagByText: + flags |= SC_WRAPVISUALFLAG_START; + loc |= SC_WRAPVISUALFLAGLOC_START_BY_TEXT; + break; + + case WrapFlagByBorder: + flags |= SC_WRAPVISUALFLAG_START; + break; + + case WrapFlagInMargin: + flags |= SC_WRAPVISUALFLAG_MARGIN; + break; + } + + SendScintilla(SCI_SETWRAPVISUALFLAGS, flags); + SendScintilla(SCI_SETWRAPVISUALFLAGSLOCATION, loc); + SendScintilla(SCI_SETWRAPSTARTINDENT, indent); +} + + +// Set the folding style. +void QsciScintilla::setFolding(FoldStyle folding, int margin) +{ + fold = folding; + foldmargin = margin; + + if (folding == NoFoldStyle) + { + SendScintilla(SCI_SETMARGINWIDTHN, margin, 0L); + return; + } + + int mask = SendScintilla(SCI_GETMODEVENTMASK); + SendScintilla(SCI_SETMODEVENTMASK, mask | SC_MOD_CHANGEFOLD); + + SendScintilla(SCI_SETFOLDFLAGS, SC_FOLDFLAG_LINEAFTER_CONTRACTED); + + SendScintilla(SCI_SETMARGINTYPEN, margin, (long)SC_MARGIN_SYMBOL); + SendScintilla(SCI_SETMARGINMASKN, margin, SC_MASK_FOLDERS); + SendScintilla(SCI_SETMARGINSENSITIVEN, margin, 1); + + // Set the marker symbols to use. + switch (folding) + { + case NoFoldStyle: + break; + + case PlainFoldStyle: + setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_MINUS); + setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_PLUS); + setFoldMarker(SC_MARKNUM_FOLDERSUB); + setFoldMarker(SC_MARKNUM_FOLDERTAIL); + setFoldMarker(SC_MARKNUM_FOLDEREND); + setFoldMarker(SC_MARKNUM_FOLDEROPENMID); + setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL); + break; + + case CircledFoldStyle: + setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_CIRCLEMINUS); + setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_CIRCLEPLUS); + setFoldMarker(SC_MARKNUM_FOLDERSUB); + setFoldMarker(SC_MARKNUM_FOLDERTAIL); + setFoldMarker(SC_MARKNUM_FOLDEREND); + setFoldMarker(SC_MARKNUM_FOLDEROPENMID); + setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL); + break; + + case BoxedFoldStyle: + setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS); + setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS); + setFoldMarker(SC_MARKNUM_FOLDERSUB); + setFoldMarker(SC_MARKNUM_FOLDERTAIL); + setFoldMarker(SC_MARKNUM_FOLDEREND); + setFoldMarker(SC_MARKNUM_FOLDEROPENMID); + setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL); + break; + + case CircledTreeFoldStyle: + setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_CIRCLEMINUS); + setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_CIRCLEPLUS); + setFoldMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE); + setFoldMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNERCURVE); + setFoldMarker(SC_MARKNUM_FOLDEREND, SC_MARK_CIRCLEPLUSCONNECTED); + setFoldMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_CIRCLEMINUSCONNECTED); + setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNERCURVE); + break; + + case BoxedTreeFoldStyle: + setFoldMarker(SC_MARKNUM_FOLDEROPEN, SC_MARK_BOXMINUS); + setFoldMarker(SC_MARKNUM_FOLDER, SC_MARK_BOXPLUS); + setFoldMarker(SC_MARKNUM_FOLDERSUB, SC_MARK_VLINE); + setFoldMarker(SC_MARKNUM_FOLDERTAIL, SC_MARK_LCORNER); + setFoldMarker(SC_MARKNUM_FOLDEREND, SC_MARK_BOXPLUSCONNECTED); + setFoldMarker(SC_MARKNUM_FOLDEROPENMID, SC_MARK_BOXMINUSCONNECTED); + setFoldMarker(SC_MARKNUM_FOLDERMIDTAIL, SC_MARK_TCORNER); + break; + } + + SendScintilla(SCI_SETMARGINWIDTHN, margin, defaultFoldMarginWidth); +} + + +// Clear all current folds. +void QsciScintilla::clearFolds() +{ + recolor(); + + int maxLine = SendScintilla(SCI_GETLINECOUNT); + + for (int line = 0; line < maxLine; line++) + { + int level = SendScintilla(SCI_GETFOLDLEVEL, line); + + if (level & SC_FOLDLEVELHEADERFLAG) + { + SendScintilla(SCI_SETFOLDEXPANDED, line, 1); + foldExpand(line, true, false, 0, level); + line--; + } + } +} + + +// Set up a folder marker. +void QsciScintilla::setFoldMarker(int marknr, int mark) +{ + SendScintilla(SCI_MARKERDEFINE, marknr, mark); + + if (mark != SC_MARK_EMPTY) + { + SendScintilla(SCI_MARKERSETFORE, marknr, QColor(Qt::white)); + SendScintilla(SCI_MARKERSETBACK, marknr, QColor(128,128,128)); + } +} + + +// Handle a click in the fold margin. This is mostly taken from SciTE. +void QsciScintilla::foldClick(int lineClick, int bstate) +{ + bool shift = bstate & Qt::ShiftModifier; + bool ctrl = bstate & Qt::ControlModifier; + + if (shift && ctrl) + { + foldAll(); + return; + } + + int levelClick = SendScintilla(SCI_GETFOLDLEVEL, lineClick); + + if (levelClick & SC_FOLDLEVELHEADERFLAG) + { + if (shift) + { + // Ensure all children are visible. + SendScintilla(SCI_SETFOLDEXPANDED, lineClick, 1); + foldExpand(lineClick, true, true, 100, levelClick); + } + else if (ctrl) + { + if (SendScintilla(SCI_GETFOLDEXPANDED, lineClick)) + { + // Contract this line and all its children. + SendScintilla(SCI_SETFOLDEXPANDED, lineClick, 0L); + foldExpand(lineClick, false, true, 0, levelClick); + } + else + { + // Expand this line and all its children. + SendScintilla(SCI_SETFOLDEXPANDED, lineClick, 1); + foldExpand(lineClick, true, true, 100, levelClick); + } + } + else + { + // Toggle this line. + SendScintilla(SCI_TOGGLEFOLD, lineClick); + } + } +} + + +// Do the hard work of hiding and showing lines. This is mostly taken from +// SciTE. +void QsciScintilla::foldExpand(int &line, bool doExpand, bool force, + int visLevels, int level) +{ + int lineMaxSubord = SendScintilla(SCI_GETLASTCHILD, line, + level & SC_FOLDLEVELNUMBERMASK); + + line++; + + while (line <= lineMaxSubord) + { + if (force) + { + if (visLevels > 0) + SendScintilla(SCI_SHOWLINES, line, line); + else + SendScintilla(SCI_HIDELINES, line, line); + } + else if (doExpand) + SendScintilla(SCI_SHOWLINES, line, line); + + int levelLine = level; + + if (levelLine == -1) + levelLine = SendScintilla(SCI_GETFOLDLEVEL, line); + + if (levelLine & SC_FOLDLEVELHEADERFLAG) + { + if (force) + { + if (visLevels > 1) + SendScintilla(SCI_SETFOLDEXPANDED, line, 1); + else + SendScintilla(SCI_SETFOLDEXPANDED, line, 0L); + + foldExpand(line, doExpand, force, visLevels - 1); + } + else if (doExpand) + { + if (!SendScintilla(SCI_GETFOLDEXPANDED, line)) + SendScintilla(SCI_SETFOLDEXPANDED, line, 1); + + foldExpand(line, true, force, visLevels - 1); + } + else + foldExpand(line, false, force, visLevels - 1); + } + else + line++; + } +} + + +// Fully expand (if there is any line currently folded) all text. Otherwise, +// fold all text. This is mostly taken from SciTE. +void QsciScintilla::foldAll(bool children) +{ + recolor(); + + int maxLine = SendScintilla(SCI_GETLINECOUNT); + bool expanding = true; + + for (int lineSeek = 0; lineSeek < maxLine; lineSeek++) + { + if (SendScintilla(SCI_GETFOLDLEVEL,lineSeek) & SC_FOLDLEVELHEADERFLAG) + { + expanding = !SendScintilla(SCI_GETFOLDEXPANDED, lineSeek); + break; + } + } + + for (int line = 0; line < maxLine; line++) + { + int level = SendScintilla(SCI_GETFOLDLEVEL, line); + + if (!(level & SC_FOLDLEVELHEADERFLAG)) + continue; + + if (children || + (SC_FOLDLEVELBASE == (level & SC_FOLDLEVELNUMBERMASK))) + { + if (expanding) + { + SendScintilla(SCI_SETFOLDEXPANDED, line, 1); + foldExpand(line, true, false, 0, level); + line--; + } + else + { + int lineMaxSubord = SendScintilla(SCI_GETLASTCHILD, line, -1); + + SendScintilla(SCI_SETFOLDEXPANDED, line, 0L); + + if (lineMaxSubord > line) + SendScintilla(SCI_HIDELINES, line + 1, lineMaxSubord); + } + } + } +} + + +// Handle a fold change. This is mostly taken from SciTE. +void QsciScintilla::foldChanged(int line,int levelNow,int levelPrev) +{ + if (levelNow & SC_FOLDLEVELHEADERFLAG) + { + if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) + SendScintilla(SCI_SETFOLDEXPANDED, line, 1); + } + else if (levelPrev & SC_FOLDLEVELHEADERFLAG) + { + if (!SendScintilla(SCI_GETFOLDEXPANDED, line)) + { + // Removing the fold from one that has been contracted so should + // expand. Otherwise lines are left invisible with no way to make + // them visible. + foldExpand(line, true, false, 0, levelPrev); + } + } +} + + +// Toggle the fold for a line if it contains a fold marker. +void QsciScintilla::foldLine(int line) +{ + SendScintilla(SCI_TOGGLEFOLD, line); +} + + +// Return the list of folded lines. +QList QsciScintilla::contractedFolds() const +{ + QList folds; + int linenr = 0, fold_line; + + while ((fold_line = SendScintilla(SCI_CONTRACTEDFOLDNEXT, linenr)) >= 0) + { + folds.append(fold_line); + linenr = fold_line + 1; + } + + return folds; +} + + +// Set the fold state from a list. +void QsciScintilla::setContractedFolds(const QList &folds) +{ + for (int i = 0; i < folds.count(); ++i) + { + int line = folds[i]; + int last_line = SendScintilla(SCI_GETLASTCHILD, line, -1); + + SendScintilla(SCI_SETFOLDEXPANDED, line, 0L); + SendScintilla(SCI_HIDELINES, line + 1, last_line); + } +} + + +// Handle the SCN_MODIFIED notification. +void QsciScintilla::handleModified(int pos, int mtype, const char *text, + int len, int added, int line, int foldNow, int foldPrev, int token, + int annotationLinesAdded) +{ + Q_UNUSED(pos); + Q_UNUSED(text); + Q_UNUSED(len); + Q_UNUSED(token); + Q_UNUSED(annotationLinesAdded); + + if (mtype & SC_MOD_CHANGEFOLD) + { + if (fold) + foldChanged(line, foldNow, foldPrev); + } + + if (mtype & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) + { + emit textChanged(); + + if (added != 0) + emit linesChanged(); + } +} + + +// Zoom in a number of points. +void QsciScintilla::zoomIn(int range) +{ + zoomTo(SendScintilla(SCI_GETZOOM) + range); +} + + +// Zoom in a single point. +void QsciScintilla::zoomIn() +{ + SendScintilla(SCI_ZOOMIN); +} + + +// Zoom out a number of points. +void QsciScintilla::zoomOut(int range) +{ + zoomTo(SendScintilla(SCI_GETZOOM) - range); +} + + +// Zoom out a single point. +void QsciScintilla::zoomOut() +{ + SendScintilla(SCI_ZOOMOUT); +} + + +// Set the zoom to a number of points. +void QsciScintilla::zoomTo(int size) +{ + if (size < -10) + size = -10; + else if (size > 20) + size = 20; + + SendScintilla(SCI_SETZOOM, size); +} + +FindState& QsciScintilla::getLastFindState() +{ + return findState; +} + + +// Find the first occurrence of a string. +//show:会保证找到的自动,在当前屏幕上可见,这个默认是true,注意该操作非常耗时。 +//在批量查找或者替换的时候,如果不需要可见,最好修改为不可见。否则在替换一个长行,长行中存在几百个的情况,速度会非常慢。 +//本来只需要2s的操作,结果会需要30s。 +bool QsciScintilla::findFirst(const QString &expr, bool re, bool cs, bool wo, + bool wrap, bool forward, FindNextType findNextType, int line, int index, bool show, bool posix, + bool cxx11) +{ + if (expr.isEmpty()) + { + findState.status = FindState::Idle; + return false; + } + + findState.status = FindState::Finding; + findState.expr = expr; + findState.wrap = wrap; + findState.forward = forward; + + findState.flags = + (cs ? SCFIND_MATCHCASE : 0) | + (wo ? SCFIND_WHOLEWORD : 0) | + (re ? SCFIND_REGEXP : 0) | + (posix ? SCFIND_POSIX : 0) | + (cxx11 ? SCFIND_CXX11REGEX : 0); + + switch (findNextType) + { + case FINDNEXTTYPE_FINDNEXT: + findState.flags |= SCFIND_REGEXP_EMPTYMATCH_ALL | SCFIND_REGEXP_SKIPCRLFASONE; + break; + + case FINDNEXTTYPE_REPLACENEXT: + findState.flags |= SCFIND_REGEXP_EMPTYMATCH_NOTAFTERMATCH | SCFIND_REGEXP_SKIPCRLFASONE; + break; + + case FINDNEXTTYPE_FINDNEXTFORREPLACE: + findState.flags |= SCFIND_REGEXP_EMPTYMATCH_ALL | SCFIND_REGEXP_EMPTYMATCH_ALLOWATSTART | SCFIND_REGEXP_SKIPCRLFASONE; + break; + } + + if (line < 0 || index < 0) + findState.startpos = SendScintilla(SCI_GETCURRENTPOS); + else + findState.startpos = positionFromLineIndex(line, index); + + if (forward) + findState.endpos = SendScintilla(SCI_GETLENGTH); + else + findState.endpos = 0; + + findState.show = show; + + return doFind(); +} + + +// Find the first occurrence of a string in the current selection. +bool QsciScintilla::findFirstInSelection(const QString &expr, bool re, bool cs, + bool wo, bool forward, bool show, bool posix, bool cxx11) +{ + if (expr.isEmpty()) + { + findState.status = FindState::Idle; + return false; + } + + findState.status = FindState::FindingInSelection; + findState.expr = expr; + findState.wrap = false; + findState.forward = forward; + + findState.flags = + (cs ? SCFIND_MATCHCASE : 0) | + (wo ? SCFIND_WHOLEWORD : 0) | + (re ? SCFIND_REGEXP : 0) | + (posix ? SCFIND_POSIX : 0) | + (cxx11 ? SCFIND_CXX11REGEX : 0); + + findState.startpos_orig = SendScintilla(SCI_GETSELECTIONSTART); + findState.endpos_orig = SendScintilla(SCI_GETSELECTIONEND); + + if (forward) + { + findState.startpos = findState.startpos_orig; + findState.endpos = findState.endpos_orig; + } + else + { + findState.startpos = findState.endpos_orig; + findState.endpos = findState.startpos_orig; + } + + findState.show = show; + + return doFind(); +} + + +// Cancel any current search. +void QsciScintilla::cancelFind() +{ + findState.status = FindState::Idle; +} + + +// Find the next occurrence of a string. +bool QsciScintilla::findNext() +{ + if (findState.status == FindState::Idle) + return false; + + return doFind(); +} + + +// Do the hard work of the find methods. +bool QsciScintilla::doFind() +{ + SendScintilla(SCI_SETSEARCHFLAGS, findState.flags); + + int pos = simpleFind(); + + // See if it was found. If not and wraparound is wanted, try again. + if (pos == -1 && findState.wrap) + { + if (findState.forward) + { + findState.startpos = 0; + findState.endpos = SendScintilla(SCI_GETLENGTH); + } + else + { + findState.startpos = SendScintilla(SCI_GETLENGTH); + findState.endpos = 0; + } + + pos = simpleFind(); + } + + //替换boost正则库后,返回值不只有-1,可能-2-3,负数都是错误 + if (pos < 0) + { + // Restore the original selection. + if (findState.status == FindState::FindingInSelection) + SendScintilla(SCI_SETSEL, findState.startpos_orig, + findState.endpos_orig); + + findState.status = FindState::Idle; + return false; + } + + // It was found. + long targstart = SendScintilla(SCI_GETTARGETSTART); + long targend = SendScintilla(SCI_GETTARGETEND); + + // Ensure the text found is visible if required. + if (findState.show) + { + int startLine = SendScintilla(SCI_LINEFROMPOSITION, targstart); + int endLine = SendScintilla(SCI_LINEFROMPOSITION, targend); + findState.linenum = startLine; + + for (int i = startLine; i <= endLine; ++i) + SendScintilla(SCI_ENSUREVISIBLEENFORCEPOLICY, i); + } + else + { + findState.linenum = -1; + } + + // Now set the selection. + SendScintilla(SCI_SETSEL, targstart, targend); + + /* 把查找到的结构返回出去,新增的,外面需要使用 */ + findState.targstart = targstart; + findState.targend = targend; + + // Finally adjust the start position so that we don't find the same one + // again. + if (findState.forward) + findState.startpos = targend; + else if ((findState.startpos = targstart - 1) < 0) + findState.startpos = 0; + + return true; +} + + +// Do a simple find between the start and end positions. +int QsciScintilla::simpleFind() +{ + /*这里是会大于的,因为我在外面会零长查找时,会增加startPos的值。如果是向前,才这样处理*/ + + if (findState.forward && (findState.startpos >= findState.endpos)) { + return -1; + } + else if (!findState.forward && (findState.startpos == findState.endpos)) + { + //如果是往后,则按照原来的逻辑进行处理。 + return -1; + } + + SendScintilla(SCI_SETTARGETSTART, findState.startpos); + SendScintilla(SCI_SETTARGETEND, findState.endpos); + + ScintillaBytes s = textAsBytes(findState.expr); + + return SendScintilla(SCI_SEARCHINTARGET, s.length(), + ScintillaBytesConstData(s)); +} + + +// Replace the text found with the previous find method. +void QsciScintilla::replace(const QString &replaceStr) +{ + if (findState.status == FindState::Idle) + return; + + long start = SendScintilla(SCI_GETSELECTIONSTART); + long orig_len = SendScintilla(SCI_GETSELECTIONEND) - start; + + /*类似查找,当零长替换时,orig_len是0 */ + findState.targstart = start; + findState.targend = start + orig_len; + + SendScintilla(SCI_TARGETFROMSELECTION); + + int cmd = (findState.flags & SCFIND_REGEXP) ? SCI_REPLACETARGETRE : SCI_REPLACETARGET; + + ScintillaBytes s = textAsBytes(replaceStr); + long len = SendScintilla(cmd, -1, ScintillaBytesConstData(s)); + + // Reset the selection. + SendScintilla(SCI_SETSELECTIONSTART, start); + SendScintilla(SCI_SETSELECTIONEND, start + len); + + // Fix the original selection. + findState.endpos_orig += (len - orig_len); + + if (findState.forward) + { + findState.startpos = start + len; + findState.endpos += (len - orig_len); +} +} + + +// Query the modified state. +bool QsciScintilla::isModified() const +{ + return doc.isModified(); +} + + +// Set the modified state. +void QsciScintilla::setModified(bool m) +{ + if (!m) + SendScintilla(SCI_SETSAVEPOINT); +} + + +// Handle the SCN_INDICATORCLICK notification. +void QsciScintilla::handleIndicatorClick(int pos, int modifiers) +{ + int state = mapModifiers(modifiers); + int line, index; + + lineIndexFromPosition(pos, &line, &index); + + emit indicatorClicked(line, index, Qt::KeyboardModifiers(state)); +} + + +// Handle the SCN_INDICATORRELEASE notification. +void QsciScintilla::handleIndicatorRelease(int pos, int modifiers) +{ + int state = mapModifiers(modifiers); + int line, index; + + lineIndexFromPosition(pos, &line, &index); + + emit indicatorReleased(line, index, Qt::KeyboardModifiers(state)); +} + + +// Handle the SCN_MARGINCLICK notification. +void QsciScintilla::handleMarginClick(int pos, int modifiers, int margin) +{ + int state = mapModifiers(modifiers); + int line = SendScintilla(SCI_LINEFROMPOSITION, pos); + + if (fold && margin == foldmargin) + foldClick(line, state); + else + emit marginClicked(margin, line, Qt::KeyboardModifiers(state)); +} + + +// Handle the SCN_MARGINRIGHTCLICK notification. +void QsciScintilla::handleMarginRightClick(int pos, int modifiers, int margin) +{ + int state = mapModifiers(modifiers); + int line = SendScintilla(SCI_LINEFROMPOSITION, pos); + + emit marginRightClicked(margin, line, Qt::KeyboardModifiers(state)); +} + + +// Handle the SCN_SAVEPOINTREACHED notification. +void QsciScintilla::handleSavePointReached() +{ + doc.setModified(false); + emit modificationChanged(false); +} + + +// Handle the SCN_SAVEPOINTLEFT notification. +void QsciScintilla::handleSavePointLeft() +{ + doc.setModified(true); + emit modificationChanged(true); +} + + +// Handle the QSCN_SELCHANGED signal. +void QsciScintilla::handleSelectionChanged(bool yes) +{ + selText = yes; + + emit copyAvailable(yes); + emit selectionChanged(); +} + + +// Get the current selection. +void QsciScintilla::getSelection(int *lineFrom, int *indexFrom, int *lineTo, + int *indexTo) const +{ + if (selText) + { + lineIndexFromPosition(SendScintilla(SCI_GETSELECTIONSTART), lineFrom, + indexFrom); + lineIndexFromPosition(SendScintilla(SCI_GETSELECTIONEND), lineTo, + indexTo); + } + else + *lineFrom = *indexFrom = *lineTo = *indexTo = -1; +} + + +// Sets the current selection. +void QsciScintilla::setSelection(int lineFrom, int indexFrom, int lineTo, + int indexTo) +{ + SendScintilla(SCI_SETSEL, positionFromLineIndex(lineFrom, indexFrom), + positionFromLineIndex(lineTo, indexTo)); +} + + +// Set the background colour of selected text. +void QsciScintilla::setSelectionBackgroundColor(const QColor &col) +{ + int alpha = col.alpha(); + + if (alpha == 255) + alpha = SC_ALPHA_NOALPHA; + + SendScintilla(SCI_SETSELBACK, 1, col); + SendScintilla(SCI_SETSELALPHA, alpha); +} + + +// Set the foreground colour of selected text. +void QsciScintilla::setSelectionForegroundColor(const QColor &col) +{ + SendScintilla(SCI_SETSELFORE, 1, col); +} + + +// Reset the background colour of selected text to the default. +void QsciScintilla::resetSelectionBackgroundColor() +{ + SendScintilla(SCI_SETSELALPHA, SC_ALPHA_NOALPHA); + SendScintilla(SCI_SETSELBACK, 0UL); +} + + +// Reset the foreground colour of selected text to the default. +void QsciScintilla::resetSelectionForegroundColor() +{ + SendScintilla(SCI_SETSELFORE, 0UL); +} + + +// Set the fill to the end-of-line for the selection. +void QsciScintilla::setSelectionToEol(bool filled) +{ + SendScintilla(SCI_SETSELEOLFILLED, filled); +} + + +// Return the fill to the end-of-line for the selection. +bool QsciScintilla::selectionToEol() const +{ + return SendScintilla(SCI_GETSELEOLFILLED); +} + + +// Set the width of the caret. +void QsciScintilla::setCaretWidth(int width) +{ + SendScintilla(SCI_SETCARETWIDTH, width); +} + + +// Set the width of the frame of the line containing the caret. +void QsciScintilla::setCaretLineFrameWidth(int width) +{ + SendScintilla(SCI_SETCARETLINEFRAME, width); +} + + +// Set the foreground colour of the caret. +void QsciScintilla::setCaretForegroundColor(const QColor &col) +{ + SendScintilla(SCI_SETCARETFORE, col); +} + + +// Set the background colour of the line containing the caret. +void QsciScintilla::setCaretLineBackgroundColor(const QColor &col) +{ + int alpha = col.alpha(); + + if (alpha == 255) + alpha = SC_ALPHA_NOALPHA; + + SendScintilla(SCI_SETCARETLINEBACK, col); + SendScintilla(SCI_SETCARETLINEBACKALPHA, alpha); +} + + +// Set the state of the background colour of the line containing the caret. +void QsciScintilla::setCaretLineVisible(bool enable) +{ + SendScintilla(SCI_SETCARETLINEVISIBLE, enable); +} + + +// Set the background colour of a hotspot area. +void QsciScintilla::setHotspotBackgroundColor(const QColor &col) +{ + SendScintilla(SCI_SETHOTSPOTACTIVEBACK, 1, col); +} + + +// Set the foreground colour of a hotspot area. +void QsciScintilla::setHotspotForegroundColor(const QColor &col) +{ + SendScintilla(SCI_SETHOTSPOTACTIVEFORE, 1, col); +} + + +// Reset the background colour of a hotspot area to the default. +void QsciScintilla::resetHotspotBackgroundColor() +{ + SendScintilla(SCI_SETHOTSPOTACTIVEBACK, 0UL); +} + + +// Reset the foreground colour of a hotspot area to the default. +void QsciScintilla::resetHotspotForegroundColor() +{ + SendScintilla(SCI_SETHOTSPOTACTIVEFORE, 0UL); +} + + +// Set the underline of a hotspot area. +void QsciScintilla::setHotspotUnderline(bool enable) +{ + SendScintilla(SCI_SETHOTSPOTACTIVEUNDERLINE, enable); +} + + +// Set the wrapping of a hotspot area. +void QsciScintilla::setHotspotWrap(bool enable) +{ + SendScintilla(SCI_SETHOTSPOTSINGLELINE, !enable); +} + + +// Query the read-only state. +bool QsciScintilla::isReadOnly() const +{ + return SendScintilla(SCI_GETREADONLY); +} + + +// Set the read-only state. +void QsciScintilla::setReadOnly(bool ro) +{ + setAttribute(Qt::WA_InputMethodEnabled, !ro); + SendScintilla(SCI_SETREADONLY, ro); +} + + +// Append the given text. +void QsciScintilla::append(const QString &text) +{ + bool ro = ensureRW(); + + ScintillaBytes s = textAsBytes(text); + SendScintilla(SCI_APPENDTEXT, s.length(), ScintillaBytesConstData(s)); + + SendScintilla(SCI_EMPTYUNDOBUFFER); + + setReadOnly(ro); +} + + +// Insert the given text at the current position. +void QsciScintilla::insert(const QString &text) +{ + insertAtPos(text, -1); +} + + +// Insert the given text at the given line and offset. +void QsciScintilla::insertAt(const QString &text, int line, int index) +{ + insertAtPos(text, positionFromLineIndex(line, index)); +} + + +// Insert the given text at the given position. +void QsciScintilla::insertAtPos(const QString &text, int pos) +{ + bool ro = ensureRW(); + + SendScintilla(SCI_BEGINUNDOACTION); + SendScintilla(SCI_INSERTTEXT, pos, + ScintillaBytesConstData(textAsBytes(text))); + SendScintilla(SCI_ENDUNDOACTION); + + setReadOnly(ro); +} + + +// Begin a sequence of undoable actions. +void QsciScintilla::beginUndoAction() +{ + SendScintilla(SCI_BEGINUNDOACTION); +} + + +// End a sequence of undoable actions. +void QsciScintilla::endUndoAction() +{ + SendScintilla(SCI_ENDUNDOACTION); +} + + +// Redo a sequence of actions. +void QsciScintilla::redo() +{ + SendScintilla(SCI_REDO); +} + + +// Undo a sequence of actions. +void QsciScintilla::undo() +{ + SendScintilla(SCI_UNDO); +} + + +// See if there is something to redo. +bool QsciScintilla::isRedoAvailable() const +{ + return SendScintilla(SCI_CANREDO); +} + + +// See if there is something to undo. +bool QsciScintilla::isUndoAvailable() const +{ + return SendScintilla(SCI_CANUNDO); +} + + +// Return the number of lines. +int QsciScintilla::lines() const +{ + return SendScintilla(SCI_GETLINECOUNT); +} + + +// Return the line at a position. +int QsciScintilla::lineAt(const QPoint &pos) const +{ + long chpos = SendScintilla(SCI_POSITIONFROMPOINTCLOSE, pos.x(), pos.y()); + + if (chpos < 0) + return -1; + + return SendScintilla(SCI_LINEFROMPOSITION, chpos); +} + + +// Return the length of a line. +int QsciScintilla::lineLength(int line) const +{ + if (line < 0 || line >= SendScintilla(SCI_GETLINECOUNT)) + return -1; + + return SendScintilla(SCI_LINELENGTH, line); +} + + +// Return the length of the current text. +int QsciScintilla::length() const +{ + return SendScintilla(SCI_GETTEXTLENGTH); +} + + +// Remove any selected text. +void QsciScintilla::removeSelectedText() +{ + SendScintilla(SCI_REPLACESEL, ""); +} + + +// Replace any selected text. +void QsciScintilla::replaceSelectedText(const QString &text) +{ + SendScintilla(SCI_REPLACESEL, ScintillaBytesConstData(textAsBytes(text))); +} + + +// Return the current selected text. +QString QsciScintilla::selectedText() const +{ + if (!selText) + return QString(); + + //char *buf = new char[SendScintilla(SCI_GETSELECTIONEND) - SendScintilla(SCI_GETSELECTIONSTART) + 1]; + int size = SendScintilla(SCI_GETSELTEXT, 0); + char* buf = new char[size]; + + SendScintilla(SCI_GETSELTEXT, buf); + + QString qs = bytesAsText(buf); + delete[] buf; + + return qs; +} + + +// Return the current text. +QString QsciScintilla::text() const +{ + int buflen = length() + 1; + char *buf = new char[buflen]; + + SendScintilla(SCI_GETTEXT, buflen, buf); + + QString qs = bytesAsText(buf,buflen-1); + delete[] buf; + + return qs; +} + + +// Return the text of a line. +QString QsciScintilla::text(int line) const +{ + int line_len = lineLength(line); + + if (line_len < 1) + return QString(); + + char *buf = new char[line_len + 1]; + + SendScintilla(SCI_GETLINE, line, buf); + buf[line_len] = '\0'; + + QString qs = bytesAsText(buf); + delete[] buf; + + return qs; +} + + +// Return the text between two positions. +QString QsciScintilla::text(int start, int end) const +{ + char *buf = new char[end - start + 1]; + SendScintilla(SCI_GETTEXTRANGE, start, end, buf); + QString text = bytesAsText(buf); + delete[] buf; + + return text; +} + + +// Return the text as encoded bytes between two positions. +QByteArray QsciScintilla::bytes(int start, int end) const +{ + QByteArray bytes(end - start + 1, '\0'); + + SendScintilla(SCI_GETTEXTRANGE, start, end, bytes.data()); + + return bytes; +} + + +// Set the given text. +void QsciScintilla::setText(const QString &text) +{ +#if 0 + bool ro = ensureRW(); + + SendScintilla(SCI_SETTEXT, ScintillaBytesConstData(textAsBytes(text))); + SendScintilla(SCI_EMPTYUNDOBUFFER); + + setReadOnly(ro); +#endif + //0 正常 1 只读模式。 + bool ro = ensureRW(); + + ScintillaBytes temp = textAsBytes(text); + const char *data = ScintillaBytesConstData(temp); + SendScintilla(SCI_SET_UTF8_TEXT, temp.length(), data); + SendScintilla(SCI_EMPTYUNDOBUFFER); + + setReadOnly(ro); + +} + /*Set the given text.注意setText底层会把text里面的值变成一个char*,遇到\0就会终止。而这个函数不会有该问题 *会把长度传递到底层中去。如果text里面的不是uft8,而是一个二进制文件强行以文本加载,则进入只读模式。 */ const int TEXT_SIZE = 50 * 1024; - + int QsciScintilla::setUtf8Text(const QString &text) { //0 正常 1 只读模式。 @@ -2505,2272 +2507,2273 @@ int QsciScintilla::setUtf8Text(const QString &text) return ret; } -int QsciScintilla::setUtf8Text(const char*data, int len) -{ - //0 正常 1 只读模式。 - int ret = 0; - bool ro = ensureRW(); - - /*在setText旧逻辑中,会只显示strlen(data)部分的内容。strlen会去掉\0后的逻辑。 - *下面那个加1其实是不准确的,因为结尾可能有多个\0。这种情况,说明该文件肯定不是text文本模式。 - *为保险起见,我们还是只有在二进制文件强行以文本打开的情况下,才调用setUtf8Text函数。其余逻辑还是走setText - */ - if ((strlen(data) + 1) < len) - { - ro = true; - ret = 1; - /*如果文件小于TEXT_SIZE,我们还是全部显示出来。不纠结了,最多显示500K - *如果显示的太多,会比较慢。没有必要 - */ - if (len <= TEXT_SIZE) - { - SendScintilla(SCI_SET_UTF8_TEXT, len, data); - } - else - { - SendScintilla(SCI_SET_UTF8_TEXT, TEXT_SIZE, data); - } - } - else - { - SendScintilla(SCI_SET_UTF8_TEXT, len, data); - } - - SendScintilla(SCI_EMPTYUNDOBUFFER); - setReadOnly(ro); - return ret; -} - -// Get the cursor position -void QsciScintilla::getCursorPosition(int *line, int *index) const -{ - lineIndexFromPosition(SendScintilla(SCI_GETCURRENTPOS), line, index); -} - - -// Set the cursor position -void QsciScintilla::setCursorPosition(int line, int index) -{ - SendScintilla(SCI_GOTOPOS, positionFromLineIndex(line, index)); -} - - -// Ensure the cursor is visible. -void QsciScintilla::ensureCursorVisible() -{ - SendScintilla(SCI_SCROLLCARET); -} - - -// Ensure a line is visible. -void QsciScintilla::ensureLineVisible(int line) -{ - SendScintilla(SCI_ENSUREVISIBLEENFORCEPOLICY, line); -} - - -// Copy text to the clipboard. -void QsciScintilla::copy() -{ - SendScintilla(SCI_COPY); -} - - -// Cut text to the clipboard. -void QsciScintilla::cut() -{ - SendScintilla(SCI_CUT); -} - - -// Paste text from the clipboard. -void QsciScintilla::paste() -{ - SendScintilla(SCI_PASTE); -} - - -// Select all text, or deselect any selected text. -void QsciScintilla::selectAll(bool select) -{ - if (select) - SendScintilla(SCI_SELECTALL); - else - SendScintilla(SCI_SETANCHOR, SendScintilla(SCI_GETCURRENTPOS)); -} - - -// Delete all text. -void QsciScintilla::clear() -{ - bool ro = ensureRW(); - - SendScintilla(SCI_CLEARALL); - SendScintilla(SCI_EMPTYUNDOBUFFER); - - setReadOnly(ro); -} - - -// Return the indentation of a line. -int QsciScintilla::indentation(int line) const -{ - return SendScintilla(SCI_GETLINEINDENTATION, line); -} - - -// Set the indentation of a line. -void QsciScintilla::setIndentation(int line, int indentation) -{ - SendScintilla(SCI_BEGINUNDOACTION); - SendScintilla(SCI_SETLINEINDENTATION, line, indentation); - SendScintilla(SCI_ENDUNDOACTION); -} - - -// Indent a line. -void QsciScintilla::indent(int line) -{ - setIndentation(line, indentation(line) + indentWidth()); -} - - -// Unindent a line. -void QsciScintilla::unindent(int line) -{ - int newIndent = indentation(line) - indentWidth(); - - if (newIndent < 0) - newIndent = 0; - - setIndentation(line, newIndent); -} - - -// Return the indentation of the current line. -int QsciScintilla::currentIndent() const -{ - return indentation(SendScintilla(SCI_LINEFROMPOSITION, - SendScintilla(SCI_GETCURRENTPOS))); -} - - -// Return the current indentation width. -int QsciScintilla::indentWidth() const -{ - int w = indentationWidth(); - - if (w == 0) - w = tabWidth(); - - return w; -} - - -// Return the state of indentation guides. -bool QsciScintilla::indentationGuides() const -{ - return (SendScintilla(SCI_GETINDENTATIONGUIDES) != SC_IV_NONE); -} - - -// Enable and disable indentation guides. -void QsciScintilla::setIndentationGuides(bool enable) -{ - int iv; - - if (!enable) - iv = SC_IV_NONE; - else if (lex.isNull()) - iv = SC_IV_REAL; - else - iv = lex->indentationGuideView(); - - SendScintilla(SCI_SETINDENTATIONGUIDES, iv); -} - - -// Set the background colour of indentation guides. -void QsciScintilla::setIndentationGuidesBackgroundColor(const QColor &col) -{ - SendScintilla(SCI_STYLESETBACK, STYLE_INDENTGUIDE, col); -} - - -// Set the foreground colour of indentation guides. -void QsciScintilla::setIndentationGuidesForegroundColor(const QColor &col) -{ - SendScintilla(SCI_STYLESETFORE, STYLE_INDENTGUIDE, col); -} - - -// Return the indentation width. -int QsciScintilla::indentationWidth() const -{ - return SendScintilla(SCI_GETINDENT); -} - - -// Set the indentation width. -void QsciScintilla::setIndentationWidth(int width) -{ - SendScintilla(SCI_SETINDENT, width); -} - - -// Return the tab width. -int QsciScintilla::tabWidth() const -{ - return SendScintilla(SCI_GETTABWIDTH); -} - - -// Set the tab width. -void QsciScintilla::setTabWidth(int width) -{ - SendScintilla(SCI_SETTABWIDTH, width); -} - - -// Return the effect of the backspace key. -bool QsciScintilla::backspaceUnindents() const -{ - return SendScintilla(SCI_GETBACKSPACEUNINDENTS); -} - - -// Set the effect of the backspace key. -void QsciScintilla::setBackspaceUnindents(bool unindents) -{ - SendScintilla(SCI_SETBACKSPACEUNINDENTS, unindents); -} - - -// Return the effect of the tab key. -bool QsciScintilla::tabIndents() const -{ - return SendScintilla(SCI_GETTABINDENTS); -} - - -// Set the effect of the tab key. -void QsciScintilla::setTabIndents(bool indents) -{ - SendScintilla(SCI_SETTABINDENTS, indents); -} - - -// Return the indentation use of tabs. -bool QsciScintilla::indentationsUseTabs() const -{ - return SendScintilla(SCI_GETUSETABS); -} - - -// Set the indentation use of tabs. -void QsciScintilla::setIndentationsUseTabs(bool tabs) -{ - SendScintilla(SCI_SETUSETABS, tabs); -} - - -// Return the number of margins. -int QsciScintilla::margins() const -{ - return SendScintilla(SCI_GETMARGINS); -} - - -// Set the number of margins. -void QsciScintilla::setMargins(int margins) -{ - SendScintilla(SCI_SETMARGINS, margins); -} - - -// Return the margin background colour. -QColor QsciScintilla::marginBackgroundColor(int margin) const -{ - return asQColor(SendScintilla(SCI_GETMARGINBACKN, margin)); -} - - -// Set the margin background colour. -void QsciScintilla::setMarginBackgroundColor(int margin, const QColor &col) -{ - SendScintilla(SCI_SETMARGINBACKN, margin, col); -} - - -// Return the margin options. -int QsciScintilla::marginOptions() const -{ - return SendScintilla(SCI_GETMARGINOPTIONS); -} - - -// Set the margin options. -void QsciScintilla::setMarginOptions(int options) -{ - SendScintilla(SCI_SETMARGINOPTIONS, options); -} - - -// Return the margin type. -QsciScintilla::MarginType QsciScintilla::marginType(int margin) const -{ - return (MarginType)SendScintilla(SCI_GETMARGINTYPEN, margin); -} - - -// Set the margin type. -void QsciScintilla::setMarginType(int margin, QsciScintilla::MarginType type) -{ - SendScintilla(SCI_SETMARGINTYPEN, margin, type); -} - - -// Clear margin text. -void QsciScintilla::clearMarginText(int line) -{ - if (line < 0) - SendScintilla(SCI_MARGINTEXTCLEARALL); - else - SendScintilla(SCI_MARGINSETTEXT, line, (const char *)0); -} - - -// Annotate a line. -void QsciScintilla::setMarginText(int line, const QString &text, int style) -{ - int style_offset = SendScintilla(SCI_MARGINGETSTYLEOFFSET); - - SendScintilla(SCI_MARGINSETTEXT, line, - ScintillaBytesConstData(textAsBytes(text))); - - SendScintilla(SCI_MARGINSETSTYLE, line, style - style_offset); -} - - -// Annotate a line. -void QsciScintilla::setMarginText(int line, const QString &text, const QsciStyle &style) -{ - style.apply(this); - - setMarginText(line, text, style.style()); -} - - -// Annotate a line. -void QsciScintilla::setMarginText(int line, const QsciStyledText &text) -{ - text.apply(this); - - setMarginText(line, text.text(), text.style()); -} - - -// Annotate a line. -void QsciScintilla::setMarginText(int line, const QList &text) -{ - char *styles; - ScintillaBytes styled_text = styleText(text, &styles, - SendScintilla(SCI_MARGINGETSTYLEOFFSET)); - - SendScintilla(SCI_MARGINSETTEXT, line, - ScintillaBytesConstData(styled_text)); - SendScintilla(SCI_MARGINSETSTYLES, line, styles); - - delete[] styles; -} - - -// Return the state of line numbers in a margin. -bool QsciScintilla::marginLineNumbers(int margin) const -{ - return SendScintilla(SCI_GETMARGINTYPEN, margin); -} - - -// Enable and disable line numbers in a margin. -void QsciScintilla::setMarginLineNumbers(int margin, bool lnrs) -{ - SendScintilla(SCI_SETMARGINTYPEN, margin, - lnrs ? SC_MARGIN_NUMBER : SC_MARGIN_SYMBOL); -} - - -// Return the marker mask of a margin. -int QsciScintilla::marginMarkerMask(int margin) const -{ - return SendScintilla(SCI_GETMARGINMASKN, margin); -} - - -// Set the marker mask of a margin. -void QsciScintilla::setMarginMarkerMask(int margin,int mask) -{ - SendScintilla(SCI_SETMARGINMASKN, margin, mask); -} - - -// Return the state of a margin's sensitivity. -bool QsciScintilla::marginSensitivity(int margin) const -{ - return SendScintilla(SCI_GETMARGINSENSITIVEN, margin); -} - - -// Enable and disable a margin's sensitivity. -void QsciScintilla::setMarginSensitivity(int margin,bool sens) -{ - SendScintilla(SCI_SETMARGINSENSITIVEN, margin, sens); -} - - -// Return the width of a margin. -int QsciScintilla::marginWidth(int margin) const -{ - return SendScintilla(SCI_GETMARGINWIDTHN, margin); -} - - -// Set the width of a margin. -void QsciScintilla::setMarginWidth(int margin, int width) -{ - SendScintilla(SCI_SETMARGINWIDTHN, margin, width); -} - - -// Set the width of a margin to the width of some text. -void QsciScintilla::setMarginWidth(int margin, const QString &s) -{ - int width = SendScintilla(SCI_TEXTWIDTH, STYLE_LINENUMBER, - ScintillaBytesConstData(textAsBytes(s))); - - setMarginWidth(margin, width); -} - - -// Set the background colour of all margins. -void QsciScintilla::setMarginsBackgroundColor(const QColor &col) -{ - handleStylePaperChange(col, STYLE_LINENUMBER); -} - - -// Set the foreground colour of all margins. -void QsciScintilla::setMarginsForegroundColor(const QColor &col) -{ - handleStyleColorChange(col, STYLE_LINENUMBER); -} - - -// Set the font of all margins. -void QsciScintilla::setMarginsFont(const QFont &f) -{ - setStylesFont(f, STYLE_LINENUMBER); -} - - -// Define an indicator. -int QsciScintilla::indicatorDefine(IndicatorStyle style, int indicatorNumber) -{ - checkIndicator(indicatorNumber); - - if (indicatorNumber >= 0) - SendScintilla(SCI_INDICSETSTYLE, indicatorNumber, - static_cast(style)); - - return indicatorNumber; -} - - -// Return the state of an indicator being drawn under the text. -bool QsciScintilla::indicatorDrawUnder(int indicatorNumber) const -{ - if (indicatorNumber < 0 || indicatorNumber >= INDIC_IME) - return false; - - return SendScintilla(SCI_INDICGETUNDER, indicatorNumber); -} - - -// Set the state of indicators being drawn under the text. -void QsciScintilla::setIndicatorDrawUnder(bool under, int indicatorNumber) -{ - if (indicatorNumber < INDIC_IME) - { - // We ignore allocatedIndicators to allow any indicators defined - // elsewhere (e.g. in lexers) to be set. - if (indicatorNumber < 0) - { - for (int i = 0; i < INDIC_IME; ++i) - SendScintilla(SCI_INDICSETUNDER, i, under); - } - else - { - SendScintilla(SCI_INDICSETUNDER, indicatorNumber, under); - } - } -} - - -// Set the indicator foreground colour. -void QsciScintilla::setIndicatorForegroundColor(const QColor &col, - int indicatorNumber) -{ - if (indicatorNumber < INDIC_IME) - { - int alpha = col.alpha(); - - // We ignore allocatedIndicators to allow any indicators defined - // elsewhere (e.g. in lexers) to be set. - if (indicatorNumber < 0) - { - for (int i = 0; i < INDIC_IME; ++i) - { - SendScintilla(SCI_INDICSETFORE, i, col); - SendScintilla(SCI_INDICSETALPHA, i, alpha); - } - } - else - { - SendScintilla(SCI_INDICSETFORE, indicatorNumber, col); - SendScintilla(SCI_INDICSETALPHA, indicatorNumber, alpha); - } - } -} - - -// Set the indicator hover foreground colour. -void QsciScintilla::setIndicatorHoverForegroundColor(const QColor &col, - int indicatorNumber) -{ - if (indicatorNumber < INDIC_IME) - { - // We ignore allocatedIndicators to allow any indicators defined - // elsewhere (e.g. in lexers) to be set. - if (indicatorNumber < 0) - { - for (int i = 0; i < INDIC_IME; ++i) - SendScintilla(SCI_INDICSETHOVERFORE, i, col); - } - else - { - SendScintilla(SCI_INDICSETHOVERFORE, indicatorNumber, col); - } - } -} - - -// Set the indicator hover style. -void QsciScintilla::setIndicatorHoverStyle(IndicatorStyle style, - int indicatorNumber) -{ - if (indicatorNumber < INDIC_IME) - { - // We ignore allocatedIndicators to allow any indicators defined - // elsewhere (e.g. in lexers) to be set. - if (indicatorNumber < 0) - { - for (int i = 0; i < INDIC_IME; ++i) - SendScintilla(SCI_INDICSETHOVERSTYLE, i, - static_cast(style)); - } - else - { - SendScintilla(SCI_INDICSETHOVERSTYLE, indicatorNumber, - static_cast(style)); - } - } -} - - -// Set the indicator outline colour. -void QsciScintilla::setIndicatorOutlineColor(const QColor &col, int indicatorNumber) -{ - if (indicatorNumber < INDIC_IME) - { - int alpha = col.alpha(); - - // We ignore allocatedIndicators to allow any indicators defined - // elsewhere (e.g. in lexers) to be set. - if (indicatorNumber < 0) - { - for (int i = 0; i < INDIC_IME; ++i) - SendScintilla(SCI_INDICSETOUTLINEALPHA, i, alpha); - } - else - { - SendScintilla(SCI_INDICSETOUTLINEALPHA, indicatorNumber, alpha); - } - } -} - - -// Fill a range with an indicator. -void QsciScintilla::fillIndicatorRange(int lineFrom, int indexFrom, - int lineTo, int indexTo, int indicatorNumber) -{ - if (indicatorNumber < INDIC_IME) - { - int start = positionFromLineIndex(lineFrom, indexFrom); - int finish = positionFromLineIndex(lineTo, indexTo); - - // We ignore allocatedIndicators to allow any indicators defined - // elsewhere (e.g. in lexers) to be set. - if (indicatorNumber < 0) - { - for (int i = 0; i < INDIC_IME; ++i) - { - SendScintilla(SCI_SETINDICATORCURRENT, i); - SendScintilla(SCI_INDICATORFILLRANGE, start, finish - start); - } - } - else - { - SendScintilla(SCI_SETINDICATORCURRENT, indicatorNumber); - SendScintilla(SCI_INDICATORFILLRANGE, start, finish - start); - } - } -} - - -// Clear a range with an indicator. -void QsciScintilla::clearIndicatorRange(int lineFrom, int indexFrom, - int lineTo, int indexTo, int indicatorNumber) -{ - if (indicatorNumber < INDIC_IME) - { - int start = positionFromLineIndex(lineFrom, indexFrom); - int finish = positionFromLineIndex(lineTo, indexTo); - - // We ignore allocatedIndicators to allow any indicators defined - // elsewhere (e.g. in lexers) to be set. - if (indicatorNumber < 0) - { - for (int i = 0; i < INDIC_IME; ++i) - { - SendScintilla(SCI_SETINDICATORCURRENT, i); - SendScintilla(SCI_INDICATORCLEARRANGE, start, finish - start); - } - } - else - { - SendScintilla(SCI_SETINDICATORCURRENT, indicatorNumber); - SendScintilla(SCI_INDICATORCLEARRANGE, start, finish - start); - } - } -} - - -// Define a marker based on a symbol. -int QsciScintilla::markerDefine(MarkerSymbol sym, int markerNumber) -{ - checkMarker(markerNumber); - - if (markerNumber >= 0) - SendScintilla(SCI_MARKERDEFINE, markerNumber, static_cast(sym)); - - return markerNumber; -} - - -// Define a marker based on a character. -int QsciScintilla::markerDefine(char ch, int markerNumber) -{ - checkMarker(markerNumber); - - if (markerNumber >= 0) - SendScintilla(SCI_MARKERDEFINE, markerNumber, - static_cast(SC_MARK_CHARACTER) + ch); - - return markerNumber; -} - - -// Define a marker based on a QPixmap. -int QsciScintilla::markerDefine(const QPixmap &pm, int markerNumber) -{ - checkMarker(markerNumber); - - if (markerNumber >= 0) - SendScintilla(SCI_MARKERDEFINEPIXMAP, markerNumber, pm); - - return markerNumber; -} - - -// Define a marker based on a QImage. -int QsciScintilla::markerDefine(const QImage &im, int markerNumber) -{ - checkMarker(markerNumber); - - if (markerNumber >= 0) - { - SendScintilla(SCI_RGBAIMAGESETHEIGHT, im.height()); - SendScintilla(SCI_RGBAIMAGESETWIDTH, im.width()); - SendScintilla(SCI_MARKERDEFINERGBAIMAGE, markerNumber, im); - } - - return markerNumber; -} - - -// Add a marker to a line. -int QsciScintilla::markerAdd(int linenr, int markerNumber) -{ - if (markerNumber < 0 || markerNumber > MARKER_MAX || (allocatedMarkers & (1 << markerNumber)) == 0) - return -1; - - return SendScintilla(SCI_MARKERADD, linenr, markerNumber); -} - - -// Get the marker mask for a line. -unsigned QsciScintilla::markersAtLine(int linenr) const -{ - return SendScintilla(SCI_MARKERGET, linenr); -} - - -// Delete a marker from a line. -void QsciScintilla::markerDelete(int linenr, int markerNumber) -{ - if (markerNumber <= MARKER_MAX) - { - if (markerNumber < 0) - { - unsigned am = allocatedMarkers; - - for (int m = 0; m <= MARKER_MAX; ++m) - { - if (am & 1) - SendScintilla(SCI_MARKERDELETE, linenr, m); - - am >>= 1; - } - } - else if (allocatedMarkers & (1 << markerNumber)) - SendScintilla(SCI_MARKERDELETE, linenr, markerNumber); - } -} - -//删除一行的全部marker -void QsciScintilla::markerDelete(int linenr) -{ - if (allocatedMarkers) - SendScintilla(SCI_LINE_MARKERDELETE_ALL, linenr); -} - -// Delete a marker from the text. -void QsciScintilla::markerDeleteAll(int markerNumber) -{ - if (markerNumber <= MARKER_MAX) - { - if (markerNumber < 0) - SendScintilla(SCI_MARKERDELETEALL, -1); - else if (allocatedMarkers & (1 << markerNumber)) - SendScintilla(SCI_MARKERDELETEALL, markerNumber); - } -} - - -// Delete a marker handle from the text. -void QsciScintilla::markerDeleteHandle(int mhandle) -{ - SendScintilla(SCI_MARKERDELETEHANDLE, mhandle); -} - - -// Return the line containing a marker instance. -int QsciScintilla::markerLine(int mhandle) const -{ - return SendScintilla(SCI_MARKERLINEFROMHANDLE, mhandle); -} - - -// Search forwards for a marker. -int QsciScintilla::markerFindNext(int linenr, unsigned mask) const -{ - return SendScintilla(SCI_MARKERNEXT, linenr, mask); -} - - -// Search backwards for a marker. -int QsciScintilla::markerFindPrevious(int linenr, unsigned mask) const -{ - return SendScintilla(SCI_MARKERPREVIOUS, linenr, mask); -} - - -// Set the marker background colour. -void QsciScintilla::setMarkerBackgroundColor(const QColor &col, int markerNumber) -{ - if (markerNumber <= MARKER_MAX) - { - int alpha = col.alpha(); - - // An opaque background would make the text invisible. - if (alpha == 255) - alpha = SC_ALPHA_NOALPHA; - - if (markerNumber < 0) - { - unsigned am = allocatedMarkers; - - for (int m = 0; m <= MARKER_MAX; ++m) - { - if (am & 1) - { - SendScintilla(SCI_MARKERSETBACK, m, col); - SendScintilla(SCI_MARKERSETALPHA, m, alpha); - } - - am >>= 1; - } - } - else if (allocatedMarkers & (1 << markerNumber)) - { - SendScintilla(SCI_MARKERSETBACK, markerNumber, col); - SendScintilla(SCI_MARKERSETALPHA, markerNumber, alpha); - } - } -} - - -// Set the marker foreground colour. -void QsciScintilla::setMarkerForegroundColor(const QColor &col, int markerNumber) -{ - if (markerNumber <= MARKER_MAX) - { - if (markerNumber < 0) - { - unsigned am = allocatedMarkers; - - for (int m = 0; m <= MARKER_MAX; ++m) - { - if (am & 1) - SendScintilla(SCI_MARKERSETFORE, m, col); - - am >>= 1; - } - } - else if (allocatedMarkers & (1 << markerNumber)) - { - SendScintilla(SCI_MARKERSETFORE, markerNumber, col); - } - } -} - - -// Check a marker, allocating a marker number if necessary. -void QsciScintilla::checkMarker(int &markerNumber) -{ - allocateId(markerNumber, allocatedMarkers, 0, MARKER_MAX); -} - - -// Check an indicator, allocating an indicator number if necessary. -void QsciScintilla::checkIndicator(int &indicatorNumber) -{ - allocateId(indicatorNumber, allocatedIndicators, INDIC_CONTAINER, - INDIC_IME - 1); -} - - -// Make sure an identifier is valid and allocate it if necessary. -void QsciScintilla::allocateId(int &id, unsigned &allocated, int min, int max) -{ - if (id >= 0) - { - // Note that we allow existing identifiers to be explicitly redefined. - if (id > max) - id = -1; - } - else - { - unsigned aids = allocated >> min; - - // Find the smallest unallocated identifier. - for (id = min; id <= max; ++id) - { - if ((aids & 1) == 0) - break; - - aids >>= 1; - } - } - - // Allocate the identifier if it is valid. - if (id >= 0) - allocated |= (1 << id); -} - - -// Reset the fold margin colours. -void QsciScintilla::resetFoldMarginColors() -{ - SendScintilla(SCI_SETFOLDMARGINHICOLOUR, 0, 0L); - SendScintilla(SCI_SETFOLDMARGINCOLOUR, 0, 0L); -} - - -// Set the fold margin colours. -void QsciScintilla::setFoldMarginColors(const QColor &fore, const QColor &back) -{ - SendScintilla(SCI_SETFOLDMARGINHICOLOUR, 1, fore); - SendScintilla(SCI_SETFOLDMARGINCOLOUR, 1, back); -} - - -// Set the call tips background colour. -void QsciScintilla::setCallTipsBackgroundColor(const QColor &col) -{ - SendScintilla(SCI_CALLTIPSETBACK, col); -} - - -// Set the call tips foreground colour. -void QsciScintilla::setCallTipsForegroundColor(const QColor &col) -{ - SendScintilla(SCI_CALLTIPSETFORE, col); -} - - -// Set the call tips highlight colour. -void QsciScintilla::setCallTipsHighlightColor(const QColor &col) -{ - SendScintilla(SCI_CALLTIPSETFOREHLT, col); -} - - -// Set the matched brace background colour. -void QsciScintilla::setMatchedBraceBackgroundColor(const QColor &col) -{ - SendScintilla(SCI_STYLESETBACK, STYLE_BRACELIGHT, col); -} - - -// Set the matched brace foreground colour. -void QsciScintilla::setMatchedBraceForegroundColor(const QColor &col) -{ - SendScintilla(SCI_STYLESETFORE, STYLE_BRACELIGHT, col); -} - - -// Set the matched brace indicator. -void QsciScintilla::setMatchedBraceIndicator(int indicatorNumber) -{ - SendScintilla(SCI_BRACEHIGHLIGHTINDICATOR, 1, indicatorNumber); -} - - -// Reset the matched brace indicator. -void QsciScintilla::resetMatchedBraceIndicator() -{ - SendScintilla(SCI_BRACEHIGHLIGHTINDICATOR, 0, 0L); -} - - -// Set the unmatched brace background colour. -void QsciScintilla::setUnmatchedBraceBackgroundColor(const QColor &col) -{ - SendScintilla(SCI_STYLESETBACK, STYLE_BRACEBAD, col); -} - - -// Set the unmatched brace foreground colour. -void QsciScintilla::setUnmatchedBraceForegroundColor(const QColor &col) -{ - SendScintilla(SCI_STYLESETFORE, STYLE_BRACEBAD, col); -} - - -// Set the unmatched brace indicator. -void QsciScintilla::setUnmatchedBraceIndicator(int indicatorNumber) -{ - SendScintilla(SCI_BRACEBADLIGHTINDICATOR, 1, indicatorNumber); -} - - -// Reset the unmatched brace indicator. -void QsciScintilla::resetUnmatchedBraceIndicator() -{ - SendScintilla(SCI_BRACEBADLIGHTINDICATOR, 0, 0L); -} - - -// Detach any lexer. -void QsciScintilla::detachLexer() -{ - if (!lex.isNull()) - { - lex->setEditor(0); - lex->disconnect(this); - - SendScintilla(SCI_STYLERESETDEFAULT); - SendScintilla(SCI_STYLECLEARALL); - } -} - - -// Set the lexer. -void QsciScintilla::setLexer(QsciLexer *lexer) -{ - // Detach any current lexer. - detachLexer(); - - // Connect up the new lexer. - lex = lexer; - - if (lex != nullptr) - { - SendScintilla(SCI_CLEARDOCUMENTSTYLE); - - if (lex->lexer()) - SendScintilla(SCI_SETLEXERLANGUAGE, lex->lexer()); - else - SendScintilla(SCI_SETLEXER, lex->lexerId()); - - lex->setEditor(this); - - connect(lex,SIGNAL(colorChanged(const QColor &, int)), - SLOT(handleStyleColorChange(const QColor &, int))); - connect(lex,SIGNAL(eolFillChanged(bool, int)), - SLOT(handleStyleEolFillChange(bool, int))); - connect(lex,SIGNAL(fontChanged(const QFont &, int)), - SLOT(handleStyleFontChange(const QFont &, int))); - connect(lex,SIGNAL(paperChanged(const QColor &, int)), - SLOT(handleStylePaperChange(const QColor &, int))); - connect(lex,SIGNAL(propertyChanged(const char *, const char *)), - SLOT(handlePropertyChange(const char *, const char *))); - - SendScintilla(SCI_SETPROPERTY, "fold", "1"); - SendScintilla(SCI_SETPROPERTY, "fold.html", "1"); - - // Set the keywords. Scintilla allows for sets numbered 0 to - // KEYWORDSET_MAX (although the lexers only seem to exploit 0 to - // KEYWORDSET_MAX - 1). We number from 1 in line with SciTE's property - // files. - for (int k = 0; k <= KEYWORDSET_MAX; ++k) - { - const char *kw = lex -> keywords(k + 1); - - if (!kw) - kw = ""; - - SendScintilla(SCI_SETKEYWORDS, k, kw); - } - - // Initialise each style. Do the default first so its (possibly - // incorrect) font setting gets reset when style 0 is set. - setLexerStyle(STYLE_DEFAULT); - - for (int s = 0; s <= STYLE_MAX; ++s) - if (!lex->description(s).isEmpty()) - setLexerStyle(s); - - // Initialise the properties. - lex->refreshProperties(); - - // Set the auto-completion fillups and word separators. - setAutoCompletionFillupsEnabled(fillups_enabled); - wseps = lex->autoCompletionWordSeparators(); - - wchars = lex->wordCharacters(); - - if (!wchars) - wchars = defaultWordChars; - - SendScintilla(SCI_AUTOCSETIGNORECASE, !lex->caseSensitive()); - - recolor(); - - int lang = lexer->lexerId(); - - if (lang == L_XML || lang == L_HTML || lang == L_PHP || lang == L_ASP || lang == L_JSP) - { - setHtmlHighLightTag(true); - } - else - { - setHtmlHighLightTag(false); - } - } - else - { - SendScintilla(SCI_SETLEXER, SCLEX_CONTAINER); - - setColor(nl_text_colour); - setPaper(nl_paper_colour); - - SendScintilla(SCI_AUTOCSETFILLUPS, ""); - SendScintilla(SCI_AUTOCSETIGNORECASE, false); - wseps.clear(); - wchars = defaultWordChars; - - setHtmlHighLightTag(false); - } -} - - -// Set a particular style of the current lexer. -void QsciScintilla::setLexerStyle(int style) -{ - handleStyleColorChange(lex->color(style), style); - handleStyleEolFillChange(lex->eolFill(style), style); - handleStyleFontChange(lex->font(style), style); - handleStylePaperChange(lex->paper(style), style); -} - - -// Get the current lexer. -QsciLexer *QsciScintilla::lexer() const -{ - return lex; -} - - -// Handle a change in lexer style foreground colour. -void QsciScintilla::handleStyleColorChange(const QColor &c, int style) -{ - SendScintilla(SCI_STYLESETFORE, style, c); -} - - -// Handle a change in lexer style end-of-line fill. -void QsciScintilla::handleStyleEolFillChange(bool eolfill, int style) -{ - SendScintilla(SCI_STYLESETEOLFILLED, style, eolfill); -} - - -// Handle a change in lexer style font. -void QsciScintilla::handleStyleFontChange(const QFont &f, int style) -{ - setStylesFont(f, style); - - if (style == lex->braceStyle()) - { - setStylesFont(f, STYLE_BRACELIGHT); - setStylesFont(f, STYLE_BRACEBAD); - } -} - - -// Set the font for a style. -void QsciScintilla::setStylesFont(const QFont &f, int style) -{ - //20220629这里是中文编码的一个bug - SendScintilla(SCI_STYLESETFONT, style, f.family().toUtf8().data()); - SendScintilla(SCI_STYLESETSIZEFRACTIONAL, style, - long(f.pointSizeF() * SC_FONT_SIZE_MULTIPLIER)); - - // Pass the Qt weight via the back door. - SendScintilla(SCI_STYLESETWEIGHT, style, -f.weight()); - - SendScintilla(SCI_STYLESETITALIC, style, f.italic()); - SendScintilla(SCI_STYLESETUNDERLINE, style, f.underline()); - - // Tie the font settings of the default style to that of style 0 (the style - // conventionally used for whitespace by lexers). This is needed so that - // fold marks, indentations, edge columns etc are set properly. - if (style == 0) - setStylesFont(f, STYLE_DEFAULT); -} - - -// Handle a change in lexer style background colour. -void QsciScintilla::handleStylePaperChange(const QColor &c, int style) -{ - SendScintilla(SCI_STYLESETBACK, style, c); -} - - -// Handle a change in lexer property. -void QsciScintilla::handlePropertyChange(const char *prop, const char *val) -{ - SendScintilla(SCI_SETPROPERTY, prop, val); -} - - -// Handle a change to the user visible user interface. -void QsciScintilla::handleUpdateUI(int) -{ - int newPos = SendScintilla(SCI_GETCURRENTPOS); - - if (newPos != oldPos) - { - oldPos = newPos; - - int line = SendScintilla(SCI_LINEFROMPOSITION, newPos); - int col = SendScintilla(SCI_GETCOLUMN, newPos); - - emit cursorPositionChanged(line, col); - - if (line != oldLine) - { - oldLine = line; - emit cursorPosChange(line, newPos); - } - } - - addHotSpot(); - - if (braceMode != NoBraceMatch) - braceMatch(); - - //只有html类语言,比如php jsp xml才会高亮tag - if (isHtmlHighLightTag) - { - XmlMatchedTagsHighlighter xmlTagMatchHiliter(this); - xmlTagMatchHiliter.tagMatch(true); -} -} - - -// Handle brace matching. -void QsciScintilla::braceMatch() -{ - long braceAtCaret, braceOpposite; - - findMatchingBrace(braceAtCaret, braceOpposite, braceMode); - - if (braceAtCaret >= 0 && braceOpposite < 0) - { - SendScintilla(SCI_BRACEBADLIGHT, braceAtCaret); - SendScintilla(SCI_SETHIGHLIGHTGUIDE, 0UL); - } - else - { - char chBrace = SendScintilla(SCI_GETCHARAT, braceAtCaret); - - SendScintilla(SCI_BRACEHIGHLIGHT, braceAtCaret, braceOpposite); - - long columnAtCaret = SendScintilla(SCI_GETCOLUMN, braceAtCaret); - long columnOpposite = SendScintilla(SCI_GETCOLUMN, braceOpposite); - - if (chBrace == ':') - { - long lineStart = SendScintilla(SCI_LINEFROMPOSITION, braceAtCaret); - long indentPos = SendScintilla(SCI_GETLINEINDENTPOSITION, - lineStart); - long indentPosNext = SendScintilla(SCI_GETLINEINDENTPOSITION, - lineStart + 1); - - columnAtCaret = SendScintilla(SCI_GETCOLUMN, indentPos); - - long columnAtCaretNext = SendScintilla(SCI_GETCOLUMN, - indentPosNext); - long indentSize = SendScintilla(SCI_GETINDENT); - - if (columnAtCaretNext - indentSize > 1) - columnAtCaret = columnAtCaretNext - indentSize; - - if (columnOpposite == 0) - columnOpposite = columnAtCaret; - } - - long column = columnAtCaret; - - if (column > columnOpposite) - column = columnOpposite; - - SendScintilla(SCI_SETHIGHLIGHTGUIDE, column); - } -} - - -// Check if the character at a position is a brace. -long QsciScintilla::checkBrace(long pos, int brace_style, bool &colonMode) -{ - long brace_pos = -1; - char ch = SendScintilla(SCI_GETCHARAT, pos); - - if (ch == ':') - { - // A bit of a hack, we should really use a virtual. - if (!lex.isNull() && qstrcmp(lex->lexer(), "python") == 0) - { - brace_pos = pos; - colonMode = true; - } - } - else if (ch && strchr("[](){}<>", ch)) - { - if (brace_style < 0) - brace_pos = pos; - else - { - int style = SendScintilla(SCI_GETSTYLEAT, pos) & 0x1f; - - if (style == brace_style) - brace_pos = pos; - } - } - - return brace_pos; -} - - -// Find a brace and it's match. Return true if the current position is inside -// a pair of braces. -bool QsciScintilla::findMatchingBrace(long &brace, long &other, BraceMatch mode) -{ - bool colonMode = false; - int brace_style = (lex.isNull() ? -1 : lex->braceStyle()); - - brace = -1; - other = -1; - - long caretPos = SendScintilla(SCI_GETCURRENTPOS); - - if (caretPos > 0) - brace = checkBrace(caretPos - 1, brace_style, colonMode); - - bool isInside = false; - - if (brace < 0 && mode == SloppyBraceMatch) - { - brace = checkBrace(caretPos, brace_style, colonMode); - - if (brace >= 0 && !colonMode) - isInside = true; - } - - if (brace >= 0) - { - if (colonMode) - { - // Find the end of the Python indented block. - long lineStart = SendScintilla(SCI_LINEFROMPOSITION, brace); - long lineMaxSubord = SendScintilla(SCI_GETLASTCHILD, lineStart, -1); - - other = SendScintilla(SCI_GETLINEENDPOSITION, lineMaxSubord); - } - else - other = SendScintilla(SCI_BRACEMATCH, brace, 0L); - - if (other > brace) - isInside = !isInside; - } - - return isInside; -} - - -// Move to the matching brace. -void QsciScintilla::moveToMatchingBrace() -{ - gotoMatchingBrace(false); -} - - -// Select to the matching brace. -void QsciScintilla::selectToMatchingBrace() -{ - gotoMatchingBrace(true); -} - - -// Move to the matching brace and optionally select the text. -void QsciScintilla::gotoMatchingBrace(bool select) -{ - long braceAtCaret; - long braceOpposite; - - bool isInside = findMatchingBrace(braceAtCaret, braceOpposite, - SloppyBraceMatch); - - if (braceOpposite >= 0) - { - // Convert the character positions into caret positions based on - // whether the caret position was inside or outside the braces. - if (isInside) - { - if (braceOpposite > braceAtCaret) - braceAtCaret++; - else - braceOpposite++; - } - else - { - if (braceOpposite > braceAtCaret) - braceOpposite++; - else - braceAtCaret++; - } - - ensureLineVisible(SendScintilla(SCI_LINEFROMPOSITION, braceOpposite)); - - if (select) - SendScintilla(SCI_SETSEL, braceAtCaret, braceOpposite); - else - SendScintilla(SCI_SETSEL, braceOpposite, braceOpposite); - } -} - - -// Return a position from a line number and an index within the line. -int QsciScintilla::positionFromLineIndex(int line, int index) const -{ - int pos = SendScintilla(SCI_POSITIONFROMLINE, line); - - // Allow for multi-byte characters. - for(int i = 0; i < index; i++) - pos = SendScintilla(SCI_POSITIONAFTER, pos); - - return pos; -} - - -// Return a line number and an index within the line from a position. -void QsciScintilla::lineIndexFromPosition(int position, int *line, int *index) const -{ - int lin = SendScintilla(SCI_LINEFROMPOSITION, position); - int linpos = SendScintilla(SCI_POSITIONFROMLINE, lin); - int indx = 0; - - // Allow for multi-byte characters. - while (linpos < position) - { - int new_linpos = SendScintilla(SCI_POSITIONAFTER, linpos); - - // If the position hasn't moved then we must be at the end of the text - // (which implies that the position passed was beyond the end of the - // text). - if (new_linpos == linpos) - break; - - linpos = new_linpos; - ++indx; - } - - *line = lin; - *index = indx; -} - - -// Set the source of the automatic auto-completion list. -void QsciScintilla::setAutoCompletionSource(AutoCompletionSource source) -{ - acSource = source; -} - - -// Set the threshold for automatic auto-completion. -void QsciScintilla::setAutoCompletionThreshold(int thresh) -{ - acThresh = thresh; -} - - -// Set the auto-completion word separators if there is no current lexer. -void QsciScintilla::setAutoCompletionWordSeparators(const QStringList &separators) -{ - if (lex.isNull()) - wseps = separators; -} - - -// Explicitly auto-complete from all sources. -void QsciScintilla::autoCompleteFromAll() -{ - startAutoCompletion(AcsAll, false, use_single != AcusNever); -} - - -// Explicitly auto-complete from the APIs. -void QsciScintilla::autoCompleteFromAPIs() -{ - startAutoCompletion(AcsAPIs, false, use_single != AcusNever); -} - - -// Explicitly auto-complete from the document. -void QsciScintilla::autoCompleteFromDocument() -{ - startAutoCompletion(AcsDocument, false, use_single != AcusNever); -} - - -// Check if a character can be in a word. -bool QsciScintilla::isWordCharacter(char ch) const -{ - return (strchr(wchars, ch) != NULL); -} - - -// Return the set of valid word characters. -const char *QsciScintilla::wordCharacters() const -{ - return wchars; -} - - -// Recolour the document. -void QsciScintilla::recolor(int start, int end) -{ - SendScintilla(SCI_COLOURISE, start, end); -} - - -// Registered a QPixmap image. -void QsciScintilla::registerImage(int id, const QPixmap &pm) -{ - SendScintilla(SCI_REGISTERIMAGE, id, pm); -} - - -// Registered a QImage image. -void QsciScintilla::registerImage(int id, const QImage &im) -{ - SendScintilla(SCI_RGBAIMAGESETHEIGHT, im.height()); - SendScintilla(SCI_RGBAIMAGESETWIDTH, im.width()); - SendScintilla(SCI_REGISTERRGBAIMAGE, id, im); -} - - -// Clear all registered images. -void QsciScintilla::clearRegisteredImages() -{ - SendScintilla(SCI_CLEARREGISTEREDIMAGES); -} - - -// Enable auto-completion fill-ups. -void QsciScintilla::setAutoCompletionFillupsEnabled(bool enable) -{ - const char *fillups; - - if (!enable) - fillups = ""; - else if (!lex.isNull()) - fillups = lex->autoCompletionFillups(); - else - fillups = explicit_fillups.data(); - - SendScintilla(SCI_AUTOCSETFILLUPS, fillups); - - fillups_enabled = enable; -} - - -// See if auto-completion fill-ups are enabled. -bool QsciScintilla::autoCompletionFillupsEnabled() const -{ - return fillups_enabled; -} - - -// Set the fill-up characters for auto-completion if there is no current lexer. -void QsciScintilla::setAutoCompletionFillups(const char *fillups) -{ - explicit_fillups = fillups; - setAutoCompletionFillupsEnabled(fillups_enabled); -} - - -// Set the case sensitivity for auto-completion. -void QsciScintilla::setAutoCompletionCaseSensitivity(bool cs) -{ - SendScintilla(SCI_AUTOCSETIGNORECASE, !cs); -} - - -// Return the case sensitivity for auto-completion. -bool QsciScintilla::autoCompletionCaseSensitivity() const -{ - return !SendScintilla(SCI_AUTOCGETIGNORECASE); -} - - -// Set the replace word mode for auto-completion. -void QsciScintilla::setAutoCompletionReplaceWord(bool replace) -{ - SendScintilla(SCI_AUTOCSETDROPRESTOFWORD, replace); -} - - -// Return the replace word mode for auto-completion. -bool QsciScintilla::autoCompletionReplaceWord() const -{ - return SendScintilla(SCI_AUTOCGETDROPRESTOFWORD); -} - - -// Set the single item mode for auto-completion. -void QsciScintilla::setAutoCompletionUseSingle(AutoCompletionUseSingle single) -{ - use_single = single; -} - - -// Return the single item mode for auto-completion. -QsciScintilla::AutoCompletionUseSingle QsciScintilla::autoCompletionUseSingle() const -{ - return use_single; -} - - -// Set the single item mode for auto-completion (deprecated). -void QsciScintilla::setAutoCompletionShowSingle(bool single) -{ - use_single = (single ? AcusExplicit : AcusNever); -} - - -// Return the single item mode for auto-completion (deprecated). -bool QsciScintilla::autoCompletionShowSingle() const -{ - return (use_single != AcusNever); -} - - -// Set current call tip position. -void QsciScintilla::setCallTipsPosition(CallTipsPosition position) -{ - SendScintilla(SCI_CALLTIPSETPOSITION, (position == CallTipsAboveText)); - call_tips_position = position; -} - - -// Set current call tip style. -void QsciScintilla::setCallTipsStyle(CallTipsStyle style) -{ - call_tips_style = style; -} - - -// Set maximum number of call tips displayed. -void QsciScintilla::setCallTipsVisible(int nr) -{ - maxCallTips = nr; -} - - -// Set the document to display. -void QsciScintilla::setDocument(const QsciDocument &document) -{ - if (doc.pdoc != document.pdoc) - { - doc.undisplay(this); - doc.attach(document); - doc.display(this,&document); - } -} - - -// Ensure the document is read-write and return true if was was read-only. -bool QsciScintilla::ensureRW() -{ - bool ro = isReadOnly(); - - if (ro) - setReadOnly(false); - - return ro; -} - - -// Return the number of the first visible line. -int QsciScintilla::firstVisibleLine() const -{ - return SendScintilla(SCI_GETFIRSTVISIBLELINE); -} - - -// Set the number of the first visible line. -void QsciScintilla::setFirstVisibleLine(int linenr) -{ - SendScintilla(SCI_SETFIRSTVISIBLELINE, linenr); -} - - -// Return the height in pixels of the text in a particular line. -int QsciScintilla::textHeight(int linenr) const -{ - return SendScintilla(SCI_TEXTHEIGHT, linenr); -} - - -// See if auto-completion or user list is active. -bool QsciScintilla::isListActive() const -{ - return SendScintilla(SCI_AUTOCACTIVE); -} - - -// Cancel any current auto-completion or user list. -void QsciScintilla::cancelList() -{ - SendScintilla(SCI_AUTOCCANCEL); -} - - -// Handle a selection from the auto-completion list. -void QsciScintilla::handleAutoCompletionSelection() -{ - if (!lex.isNull()) - { - QsciAbstractAPIs *apis = lex->apis(); - - if (apis) - apis->autoCompletionSelected(acSelection); - } -} - - -// Display a user list. -void QsciScintilla::showUserList(int id, const QStringList &list) -{ - // Sanity check to make sure auto-completion doesn't get confused. - if (id <= 0) - return; - - SendScintilla(SCI_AUTOCSETSEPARATOR, userSeparator); - - ScintillaBytes s = textAsBytes(list.join(QChar(userSeparator))); - SendScintilla(SCI_USERLISTSHOW, id, ScintillaBytesConstData(s)); -} - - -// Translate the SCN_USERLISTSELECTION notification into something more useful. -void QsciScintilla::handleUserListSelection(const char *text, int id) -{ - emit userListActivated(id, QString(text)); - - // Make sure the editor hasn't been deactivated as a side effect. - activateWindow(); -} - - -// Return the case sensitivity of any lexer. -bool QsciScintilla::caseSensitive() const -{ - return lex.isNull() ? true : lex->caseSensitive(); -} - - -// Return true if the current list is an auto-completion list rather than a -// user list. -bool QsciScintilla::isAutoCompletionList() const -{ - return (SendScintilla(SCI_AUTOCGETSEPARATOR) == acSeparator); -} - - -// Read the text from a QIODevice. -bool QsciScintilla::read(QIODevice *io) -{ - const int min_size = 1024 * 8; - - int buf_size = min_size; - char *buf = new char[buf_size]; - - int data_len = 0; - bool ok = true; - - qint64 part; - - // Read the whole lot in so we don't have to worry about character - // boundaries. - do - { - // Make sure there is a minimum amount of room. - if (buf_size - data_len < min_size) - { - buf_size *= 2; - char *new_buf = new char[buf_size * 2]; - - memcpy(new_buf, buf, data_len); - delete[] buf; - buf = new_buf; - } - - part = io->read(buf + data_len, buf_size - data_len - 1); - data_len += part; - } - while (part > 0); - - if (part < 0) - ok = false; - else - { - buf[data_len] = '\0'; - - bool ro = ensureRW(); - - SendScintilla(SCI_SETTEXT, buf); - SendScintilla(SCI_EMPTYUNDOBUFFER); - - setReadOnly(ro); - } - - delete[] buf; - - return ok; -} - - -// Write the text to a QIODevice. -bool QsciScintilla::write(QIODevice *io) const -{ - const char *buf = reinterpret_cast(SendScintillaPtrResult(SCI_GETCHARACTERPOINTER)); - - const char *bp = buf; - uint buflen = qstrlen(buf); - - while (buflen > 0) - { - qint64 part = io->write(bp, buflen); - - if (part < 0) - return false; - - bp += part; - buflen -= part; - } - - return true; -} - -//是否开启缩进。这个和前面的setIndentationGuides有冗余。暂时使用这个来确定,因为外部有一个详细检测是否python的作用 -void QsciScintilla::setIndentGuide(bool v) -{ - isIndentGuide = v; -} - -bool QsciScintilla::getIndentGuide() -{ - return isIndentGuide; -} - -void QsciScintilla::setHtmlHighLightTag(bool v) -{ - isHtmlHighLightTag = v; -} - -bool QsciScintilla::getHtmlHighLightTag() -{ - return isHtmlHighLightTag; -} - - -// Return the word at the given coordinates. -QString QsciScintilla::wordAtLineIndex(int line, int index) const -{ - return wordAtPosition(positionFromLineIndex(line, index)); -} - - -// Return the word at the given coordinates. -QString QsciScintilla::wordAtPoint(const QPoint &point) const -{ - long close_pos = SendScintilla(SCI_POSITIONFROMPOINTCLOSE, point.x(), - point.y()); - - return wordAtPosition(close_pos); -} - - -// Return the word at the given position. -QString QsciScintilla::wordAtPosition(int position) const -{ - if (position < 0) - return QString(); - - long start_pos = SendScintilla(SCI_WORDSTARTPOSITION, position, true); - long end_pos = SendScintilla(SCI_WORDENDPOSITION, position, true); - - if (start_pos >= end_pos) - return QString(); - - return text(start_pos, end_pos); -} - - -// Return the display style for annotations. -QsciScintilla::AnnotationDisplay QsciScintilla::annotationDisplay() const -{ - return (AnnotationDisplay)SendScintilla(SCI_ANNOTATIONGETVISIBLE); -} - - -// Set the display style for annotations. -void QsciScintilla::setAnnotationDisplay(QsciScintilla::AnnotationDisplay display) -{ - SendScintilla(SCI_ANNOTATIONSETVISIBLE, display); - setScrollBars(); -} - - -// Clear annotations. -void QsciScintilla::clearAnnotations(int line) -{ - if (line >= 0) - SendScintilla(SCI_ANNOTATIONSETTEXT, line, (const char *)0); - else - SendScintilla(SCI_ANNOTATIONCLEARALL); - - setScrollBars(); -} - - -// Annotate a line. -void QsciScintilla::annotate(int line, const QString &text, int style) -{ - int style_offset = SendScintilla(SCI_ANNOTATIONGETSTYLEOFFSET); - - ScintillaBytes s = textAsBytes(text); - - SendScintilla(SCI_ANNOTATIONSETTEXT, line, ScintillaBytesConstData(s)); - SendScintilla(SCI_ANNOTATIONSETSTYLE, line, style - style_offset); - - setScrollBars(); -} - - -// Annotate a line. -void QsciScintilla::annotate(int line, const QString &text, const QsciStyle &style) -{ - style.apply(this); - - annotate(line, text, style.style()); -} - - -// Annotate a line. -void QsciScintilla::annotate(int line, const QsciStyledText &text) -{ - text.apply(this); - - annotate(line, text.text(), text.style()); -} - - -// Annotate a line. -void QsciScintilla::annotate(int line, const QList &text) -{ - char *styles; - ScintillaBytes styled_text = styleText(text, &styles, - SendScintilla(SCI_ANNOTATIONGETSTYLEOFFSET)); - - SendScintilla(SCI_ANNOTATIONSETTEXT, line, - ScintillaBytesConstData(styled_text)); - SendScintilla(SCI_ANNOTATIONSETSTYLES, line, styles); - - delete[] styles; -} - - -// Get the annotation for a line, if any. -QString QsciScintilla::annotation(int line) const -{ - char *buf = new char[SendScintilla(SCI_ANNOTATIONGETTEXT, line, (const char *)0) + 1]; - - buf[SendScintilla(SCI_ANNOTATIONGETTEXT, line, buf)] = '\0'; - - QString qs = bytesAsText(buf); - delete[] buf; - - return qs; -} - - -// Convert a list of styled text to the low-level arrays. -QsciScintillaBase::ScintillaBytes QsciScintilla::styleText(const QList &styled_text, char **styles, int style_offset) -{ - QString text; - int i; - - // Build the full text. - for (i = 0; i < styled_text.count(); ++i) - { - const QsciStyledText &st = styled_text[i]; - - st.apply(this); - - text.append(st.text()); - } - - ScintillaBytes s = textAsBytes(text); - - // There is a style byte for every byte. - char *sp = *styles = new char[s.length()]; - - for (i = 0; i < styled_text.count(); ++i) - { - const QsciStyledText &st = styled_text[i]; - ScintillaBytes part = textAsBytes(st.text()); - int part_length = part.length(); - - for (int c = 0; c < part_length; ++c) - *sp++ = (char)(st.style() - style_offset); - } - - return s; -} - - -// Convert Scintilla modifiers to the Qt equivalent. -int QsciScintilla::mapModifiers(int modifiers) -{ - int state = 0; - - if (modifiers & SCMOD_SHIFT) - state |= Qt::ShiftModifier; - - if (modifiers & SCMOD_CTRL) - state |= Qt::ControlModifier; - - if (modifiers & SCMOD_ALT) - state |= Qt::AltModifier; - - if (modifiers & (SCMOD_SUPER | SCMOD_META)) - state |= Qt::MetaModifier; - - return state; +int QsciScintilla::setUtf8Text(const char*data, int len) +{ + //0 正常 1 只读模式。 + int ret = 0; + bool ro = ensureRW(); + + /*在setText旧逻辑中,会只显示strlen(data)部分的内容。strlen会去掉\0后的逻辑。 + *下面那个加1其实是不准确的,因为结尾可能有多个\0。这种情况,说明该文件肯定不是text文本模式。 + *为保险起见,我们还是只有在二进制文件强行以文本打开的情况下,才调用setUtf8Text函数。其余逻辑还是走setText + */ + if ((strlen(data) + 1) < len) + { + ro = true; + ret = 1; + /*如果文件小于TEXT_SIZE,我们还是全部显示出来。不纠结了,最多显示500K + *如果显示的太多,会比较慢。没有必要 + */ + if (len <= TEXT_SIZE) + { + SendScintilla(SCI_SET_UTF8_TEXT, len, data); + } + else + { + SendScintilla(SCI_SET_UTF8_TEXT, TEXT_SIZE, data); + } + } + else + { + SendScintilla(SCI_SET_UTF8_TEXT, len, data); + } + + SendScintilla(SCI_EMPTYUNDOBUFFER); + setReadOnly(ro); + return ret; } -// Re-implemented to handle shortcut overrides. -bool QsciScintilla::event(QEvent *e) -{ - if (e->type() == QEvent::ShortcutOverride && !isReadOnly()) - { - QKeyEvent *ke = static_cast(e); - - if (ke->key()) - { - // We want ordinary characters. - if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier || ke->modifiers() == Qt::KeypadModifier) && ke->key() < Qt::Key_Escape) - { - ke->accept(); - return true; - } - - // We want any key that is bound. - QsciCommand *cmd = stdCmds->boundTo(ke->key() | (ke->modifiers() & ~Qt::KeypadModifier)); - - if (cmd) - { - ke->accept(); - return true; - } - } - } - - return QsciScintillaBase::event(e); -} - - -// Re-implemented to zoom when the Control modifier is pressed. -void QsciScintilla::wheelEvent(QWheelEvent *e) -{ -#if defined(Q_OS_MAC) - const Qt::KeyboardModifier zoom_modifier = Qt::MetaModifier; -#else - const Qt::KeyboardModifier zoom_modifier = Qt::ControlModifier; -#endif - - if ((e->modifiers() & zoom_modifier) != 0) - { - QPoint ad = e->angleDelta(); - int delta = (qAbs(ad.x()) > qAbs(ad.y())) ? ad.x() : ad.y(); - - if (delta > 0) - zoomIn(); - else - zoomOut(); - } - else - { - QsciScintillaBase::wheelEvent(e); - } -} - - -// Re-implemented to handle chenges to the enabled state. -void QsciScintilla::changeEvent(QEvent *e) -{ - QsciScintillaBase::changeEvent(e); - - if (e->type() != QEvent::EnabledChange) - return; - - if (isEnabled()) - SendScintilla(SCI_SETCARETSTYLE, CARETSTYLE_LINE); - else - SendScintilla(SCI_SETCARETSTYLE, CARETSTYLE_INVISIBLE); - - QColor fore = palette().color(QPalette::Disabled, QPalette::Text); - QColor back = palette().color(QPalette::Disabled, QPalette::Base); - - if (lex.isNull()) - { - if (isEnabled()) - { - fore = nl_text_colour; - back = nl_paper_colour; - } - - SendScintilla(SCI_STYLESETFORE, 0, fore); - - // Assume style 0 applies to everything so that we don't need to use - // SCI_STYLECLEARALL which clears everything. We still have to set the - // default style as well for the background without any text. - SendScintilla(SCI_STYLESETBACK, 0, back); - SendScintilla(SCI_STYLESETBACK, STYLE_DEFAULT, back); - } - else - { - setEnabledColors(STYLE_DEFAULT, fore, back); - - for (int s = 0; s <= STYLE_MAX; ++s) - if (!lex->description(s).isNull()) - setEnabledColors(s, fore, back); - } -} - - -// Set the foreground and background colours for a style. -void QsciScintilla::setEnabledColors(int style, QColor &fore, QColor &back) -{ - if (isEnabled()) - { - fore = lex->color(style); - back = lex->paper(style); - } - - handleStyleColorChange(fore, style); - handleStylePaperChange(back, style); -} - - -// Re-implemented to implement a more Qt-like context menu. -void QsciScintilla::contextMenuEvent(QContextMenuEvent *e) -{ - if (contextMenuNeeded(e->x(), e->y())) - { - QMenu *menu = createStandardContextMenu(); - - contextUserDefineMenuEvent(menu); - - if (menu) - { - menu->setAttribute(Qt::WA_DeleteOnClose); - menu->popup(e->globalPos()); - } - } -} - -void QsciScintilla::contextUserDefineMenuEvent(QMenu* menu) -{ -} - - - -// Create an instance of the standard context menu. -QMenu *QsciScintilla::createStandardContextMenu() -{ - bool read_only = isReadOnly(); - bool has_selection = hasSelectedText(); - QMenu *menu = new QMenu(this); - QAction *action; - - if (!read_only) - { - /*action = menu->addAction(tr("&Undo"), this, SLOT(undo())); - set_shortcut(action, QsciCommand::Undo); - action->setEnabled(isUndoAvailable()); - - action = menu->addAction(tr("&Redo"), this, SLOT(redo())); - set_shortcut(action, QsciCommand::Redo); - action->setEnabled(isRedoAvailable());*/ - - menu->addSeparator(); - - action = menu->addAction(tr("&Cut"), this, SLOT(cut())); - set_shortcut(action, QsciCommand::SelectionCut); - action->setEnabled(has_selection); - } - - action = menu->addAction(tr("&Copy"), this, SLOT(copy())); - set_shortcut(action, QsciCommand::SelectionCopy); - action->setEnabled(has_selection); - - if (!read_only) - { - action = menu->addAction(tr("&Paste"), this, SLOT(paste())); - set_shortcut(action, QsciCommand::Paste); - action->setEnabled(SendScintilla(SCI_CANPASTE)); - - action = menu->addAction(tr("Delete"), this, SLOT(delete_selection())); - action->setEnabled(has_selection); - } - - if (!menu->isEmpty()) - menu->addSeparator(); - - action = menu->addAction(tr("Select All"), this, SLOT(selectAll())); - set_shortcut(action, QsciCommand::SelectAll); - action->setEnabled(length() != 0); - - return menu; -} - - -// Set the shortcut for an action using any current key binding. -void QsciScintilla::set_shortcut(QAction *action, QsciCommand::Command cmd_id) const -{ - QsciCommand *cmd = stdCmds->find(cmd_id); - - if (cmd && cmd->key()) - action->setShortcut(QKeySequence(cmd->key())); -} - - -// Delete the current selection. -void QsciScintilla::delete_selection() -{ - SendScintilla(SCI_CLEAR); -} - - -// Convert a Scintilla colour to a QColor. -static QColor asQColor(long sci_colour) -{ - return QColor( - ((int)sci_colour) & 0x00ff, - ((int)(sci_colour >> 8)) & 0x00ff, - ((int)(sci_colour >> 16)) & 0x00ff); -} - - -// Set the scroll width. -void QsciScintilla::setScrollWidth(int pixelWidth) -{ - SendScintilla(SCI_SETSCROLLWIDTH, pixelWidth); -} - -// Get the scroll width. -int QsciScintilla::scrollWidth() const -{ - return SendScintilla(SCI_GETSCROLLWIDTH); -} - - -// Set scroll width tracking. -void QsciScintilla::setScrollWidthTracking(bool enabled) -{ - SendScintilla(SCI_SETSCROLLWIDTHTRACKING, enabled); -} - - -// Get scroll width tracking. -bool QsciScintilla::scrollWidthTracking() const -{ - return SendScintilla(SCI_GETSCROLLWIDTHTRACKING); -} +// Get the cursor position +void QsciScintilla::getCursorPosition(int *line, int *index) const +{ + lineIndexFromPosition(SendScintilla(SCI_GETCURRENTPOS), line, index); +} + + +// Set the cursor position +void QsciScintilla::setCursorPosition(int line, int index) +{ + SendScintilla(SCI_GOTOPOS, positionFromLineIndex(line, index)); +} + + +// Ensure the cursor is visible. +void QsciScintilla::ensureCursorVisible() +{ + SendScintilla(SCI_SCROLLCARET); +} + + +// Ensure a line is visible. +void QsciScintilla::ensureLineVisible(int line) +{ + SendScintilla(SCI_ENSUREVISIBLEENFORCEPOLICY, line); +} + + +// Copy text to the clipboard. +void QsciScintilla::copy() +{ + SendScintilla(SCI_COPY); +} + + +// Cut text to the clipboard. +void QsciScintilla::cut() +{ + SendScintilla(SCI_CUT); +} + + +// Paste text from the clipboard. +void QsciScintilla::paste() +{ + SendScintilla(SCI_PASTE); +} + + +// Select all text, or deselect any selected text. +void QsciScintilla::selectAll(bool select) +{ + if (select) + SendScintilla(SCI_SELECTALL); + else + SendScintilla(SCI_SETANCHOR, SendScintilla(SCI_GETCURRENTPOS)); +} + + +// Delete all text. +void QsciScintilla::clear() +{ + bool ro = ensureRW(); + + SendScintilla(SCI_CLEARALL); + SendScintilla(SCI_EMPTYUNDOBUFFER); + + setReadOnly(ro); +} + + +// Return the indentation of a line. +int QsciScintilla::indentation(int line) const +{ + return SendScintilla(SCI_GETLINEINDENTATION, line); +} + + +// Set the indentation of a line. +void QsciScintilla::setIndentation(int line, int indentation) +{ + SendScintilla(SCI_BEGINUNDOACTION); + SendScintilla(SCI_SETLINEINDENTATION, line, indentation); + SendScintilla(SCI_ENDUNDOACTION); +} + + +// Indent a line. +void QsciScintilla::indent(int line) +{ + setIndentation(line, indentation(line) + indentWidth()); +} + + +// Unindent a line. +void QsciScintilla::unindent(int line) +{ + int newIndent = indentation(line) - indentWidth(); + + if (newIndent < 0) + newIndent = 0; + + setIndentation(line, newIndent); +} + + +// Return the indentation of the current line. +int QsciScintilla::currentIndent() const +{ + return indentation(SendScintilla(SCI_LINEFROMPOSITION, + SendScintilla(SCI_GETCURRENTPOS))); +} + + +// Return the current indentation width. +int QsciScintilla::indentWidth() const +{ + int w = indentationWidth(); + + if (w == 0) + w = tabWidth(); + + return w; +} + + +// Return the state of indentation guides. +bool QsciScintilla::indentationGuides() const +{ + return (SendScintilla(SCI_GETINDENTATIONGUIDES) != SC_IV_NONE); +} + + +// Enable and disable indentation guides. +void QsciScintilla::setIndentationGuides(bool enable) +{ + int iv; + + if (!enable) + iv = SC_IV_NONE; + else if (lex.isNull()) + iv = SC_IV_REAL; + else + iv = lex->indentationGuideView(); + + SendScintilla(SCI_SETINDENTATIONGUIDES, iv); +} + + +// Set the background colour of indentation guides. +void QsciScintilla::setIndentationGuidesBackgroundColor(const QColor &col) +{ + SendScintilla(SCI_STYLESETBACK, STYLE_INDENTGUIDE, col); +} + + +// Set the foreground colour of indentation guides. +void QsciScintilla::setIndentationGuidesForegroundColor(const QColor &col) +{ + SendScintilla(SCI_STYLESETFORE, STYLE_INDENTGUIDE, col); +} + + +// Return the indentation width. +int QsciScintilla::indentationWidth() const +{ + return SendScintilla(SCI_GETINDENT); +} + + +// Set the indentation width. +void QsciScintilla::setIndentationWidth(int width) +{ + SendScintilla(SCI_SETINDENT, width); +} + + +// Return the tab width. +int QsciScintilla::tabWidth() const +{ + return SendScintilla(SCI_GETTABWIDTH); +} + + +// Set the tab width. +void QsciScintilla::setTabWidth(int width) +{ + SendScintilla(SCI_SETTABWIDTH, width); +} + + +// Return the effect of the backspace key. +bool QsciScintilla::backspaceUnindents() const +{ + return SendScintilla(SCI_GETBACKSPACEUNINDENTS); +} + + +// Set the effect of the backspace key. +void QsciScintilla::setBackspaceUnindents(bool unindents) +{ + SendScintilla(SCI_SETBACKSPACEUNINDENTS, unindents); +} + + +// Return the effect of the tab key. +bool QsciScintilla::tabIndents() const +{ + return SendScintilla(SCI_GETTABINDENTS); +} + + +// Set the effect of the tab key. +void QsciScintilla::setTabIndents(bool indents) +{ + SendScintilla(SCI_SETTABINDENTS, indents); +} + + +// Return the indentation use of tabs. +bool QsciScintilla::indentationsUseTabs() const +{ + return SendScintilla(SCI_GETUSETABS); +} + + +// Set the indentation use of tabs. +void QsciScintilla::setIndentationsUseTabs(bool tabs) +{ + SendScintilla(SCI_SETUSETABS, tabs); +} + + +// Return the number of margins. +int QsciScintilla::margins() const +{ + return SendScintilla(SCI_GETMARGINS); +} + + +// Set the number of margins. +void QsciScintilla::setMargins(int margins) +{ + SendScintilla(SCI_SETMARGINS, margins); +} + + +// Return the margin background colour. +QColor QsciScintilla::marginBackgroundColor(int margin) const +{ + return asQColor(SendScintilla(SCI_GETMARGINBACKN, margin)); +} + + +// Set the margin background colour. +void QsciScintilla::setMarginBackgroundColor(int margin, const QColor &col) +{ + SendScintilla(SCI_SETMARGINBACKN, margin, col); +} + + +// Return the margin options. +int QsciScintilla::marginOptions() const +{ + return SendScintilla(SCI_GETMARGINOPTIONS); +} + + +// Set the margin options. +void QsciScintilla::setMarginOptions(int options) +{ + SendScintilla(SCI_SETMARGINOPTIONS, options); +} + + +// Return the margin type. +QsciScintilla::MarginType QsciScintilla::marginType(int margin) const +{ + return (MarginType)SendScintilla(SCI_GETMARGINTYPEN, margin); +} + + +// Set the margin type. +void QsciScintilla::setMarginType(int margin, QsciScintilla::MarginType type) +{ + SendScintilla(SCI_SETMARGINTYPEN, margin, type); +} + + +// Clear margin text. +void QsciScintilla::clearMarginText(int line) +{ + if (line < 0) + SendScintilla(SCI_MARGINTEXTCLEARALL); + else + SendScintilla(SCI_MARGINSETTEXT, line, (const char *)0); +} + + +// Annotate a line. +void QsciScintilla::setMarginText(int line, const QString &text, int style) +{ + int style_offset = SendScintilla(SCI_MARGINGETSTYLEOFFSET); + + SendScintilla(SCI_MARGINSETTEXT, line, + ScintillaBytesConstData(textAsBytes(text))); + + SendScintilla(SCI_MARGINSETSTYLE, line, style - style_offset); +} + + +// Annotate a line. +void QsciScintilla::setMarginText(int line, const QString &text, const QsciStyle &style) +{ + style.apply(this); + + setMarginText(line, text, style.style()); +} + + +// Annotate a line. +void QsciScintilla::setMarginText(int line, const QsciStyledText &text) +{ + text.apply(this); + + setMarginText(line, text.text(), text.style()); +} + + +// Annotate a line. +void QsciScintilla::setMarginText(int line, const QList &text) +{ + char *styles; + ScintillaBytes styled_text = styleText(text, &styles, + SendScintilla(SCI_MARGINGETSTYLEOFFSET)); + + SendScintilla(SCI_MARGINSETTEXT, line, + ScintillaBytesConstData(styled_text)); + SendScintilla(SCI_MARGINSETSTYLES, line, styles); + + delete[] styles; +} + + +// Return the state of line numbers in a margin. +bool QsciScintilla::marginLineNumbers(int margin) const +{ + return SendScintilla(SCI_GETMARGINTYPEN, margin); +} + + +// Enable and disable line numbers in a margin. +void QsciScintilla::setMarginLineNumbers(int margin, bool lnrs) +{ + SendScintilla(SCI_SETMARGINTYPEN, margin, + lnrs ? SC_MARGIN_NUMBER : SC_MARGIN_SYMBOL); +} + + +// Return the marker mask of a margin. +int QsciScintilla::marginMarkerMask(int margin) const +{ + return SendScintilla(SCI_GETMARGINMASKN, margin); +} + + +// Set the marker mask of a margin. +void QsciScintilla::setMarginMarkerMask(int margin,int mask) +{ + SendScintilla(SCI_SETMARGINMASKN, margin, mask); +} + + +// Return the state of a margin's sensitivity. +bool QsciScintilla::marginSensitivity(int margin) const +{ + return SendScintilla(SCI_GETMARGINSENSITIVEN, margin); +} + + +// Enable and disable a margin's sensitivity. +void QsciScintilla::setMarginSensitivity(int margin,bool sens) +{ + SendScintilla(SCI_SETMARGINSENSITIVEN, margin, sens); +} + + +// Return the width of a margin. +int QsciScintilla::marginWidth(int margin) const +{ + return SendScintilla(SCI_GETMARGINWIDTHN, margin); +} + + +// Set the width of a margin. +void QsciScintilla::setMarginWidth(int margin, int width) +{ + SendScintilla(SCI_SETMARGINWIDTHN, margin, width); +} + + +// Set the width of a margin to the width of some text. +void QsciScintilla::setMarginWidth(int margin, const QString &s) +{ + int width = SendScintilla(SCI_TEXTWIDTH, STYLE_LINENUMBER, + ScintillaBytesConstData(textAsBytes(s))); + + setMarginWidth(margin, width); +} + + +// Set the background colour of all margins. +void QsciScintilla::setMarginsBackgroundColor(const QColor &col) +{ + handleStylePaperChange(col, STYLE_LINENUMBER); +} + + +// Set the foreground colour of all margins. +void QsciScintilla::setMarginsForegroundColor(const QColor &col) +{ + handleStyleColorChange(col, STYLE_LINENUMBER); +} + + +// Set the font of all margins. +void QsciScintilla::setMarginsFont(const QFont &f) +{ + setStylesFont(f, STYLE_LINENUMBER); +} + + +// Define an indicator. +int QsciScintilla::indicatorDefine(IndicatorStyle style, int indicatorNumber) +{ + checkIndicator(indicatorNumber); + + if (indicatorNumber >= 0) + SendScintilla(SCI_INDICSETSTYLE, indicatorNumber, + static_cast(style)); + + return indicatorNumber; +} + + +// Return the state of an indicator being drawn under the text. +bool QsciScintilla::indicatorDrawUnder(int indicatorNumber) const +{ + if (indicatorNumber < 0 || indicatorNumber >= INDIC_IME) + return false; + + return SendScintilla(SCI_INDICGETUNDER, indicatorNumber); +} + + +// Set the state of indicators being drawn under the text. +void QsciScintilla::setIndicatorDrawUnder(bool under, int indicatorNumber) +{ + if (indicatorNumber < INDIC_IME) + { + // We ignore allocatedIndicators to allow any indicators defined + // elsewhere (e.g. in lexers) to be set. + if (indicatorNumber < 0) + { + for (int i = 0; i < INDIC_IME; ++i) + SendScintilla(SCI_INDICSETUNDER, i, under); + } + else + { + SendScintilla(SCI_INDICSETUNDER, indicatorNumber, under); + } + } +} + + +// Set the indicator foreground colour. +void QsciScintilla::setIndicatorForegroundColor(const QColor &col, + int indicatorNumber) +{ + if (indicatorNumber < INDIC_IME) + { + int alpha = col.alpha(); + + // We ignore allocatedIndicators to allow any indicators defined + // elsewhere (e.g. in lexers) to be set. + if (indicatorNumber < 0) + { + for (int i = 0; i < INDIC_IME; ++i) + { + SendScintilla(SCI_INDICSETFORE, i, col); + SendScintilla(SCI_INDICSETALPHA, i, alpha); + } + } + else + { + SendScintilla(SCI_INDICSETFORE, indicatorNumber, col); + SendScintilla(SCI_INDICSETALPHA, indicatorNumber, alpha); + } + } +} + + +// Set the indicator hover foreground colour. +void QsciScintilla::setIndicatorHoverForegroundColor(const QColor &col, + int indicatorNumber) +{ + if (indicatorNumber < INDIC_IME) + { + // We ignore allocatedIndicators to allow any indicators defined + // elsewhere (e.g. in lexers) to be set. + if (indicatorNumber < 0) + { + for (int i = 0; i < INDIC_IME; ++i) + SendScintilla(SCI_INDICSETHOVERFORE, i, col); + } + else + { + SendScintilla(SCI_INDICSETHOVERFORE, indicatorNumber, col); + } + } +} + + +// Set the indicator hover style. +void QsciScintilla::setIndicatorHoverStyle(IndicatorStyle style, + int indicatorNumber) +{ + if (indicatorNumber < INDIC_IME) + { + // We ignore allocatedIndicators to allow any indicators defined + // elsewhere (e.g. in lexers) to be set. + if (indicatorNumber < 0) + { + for (int i = 0; i < INDIC_IME; ++i) + SendScintilla(SCI_INDICSETHOVERSTYLE, i, + static_cast(style)); + } + else + { + SendScintilla(SCI_INDICSETHOVERSTYLE, indicatorNumber, + static_cast(style)); + } + } +} + + +// Set the indicator outline colour. +void QsciScintilla::setIndicatorOutlineColor(const QColor &col, int indicatorNumber) +{ + if (indicatorNumber < INDIC_IME) + { + int alpha = col.alpha(); + + // We ignore allocatedIndicators to allow any indicators defined + // elsewhere (e.g. in lexers) to be set. + if (indicatorNumber < 0) + { + for (int i = 0; i < INDIC_IME; ++i) + SendScintilla(SCI_INDICSETOUTLINEALPHA, i, alpha); + } + else + { + SendScintilla(SCI_INDICSETOUTLINEALPHA, indicatorNumber, alpha); + } + } +} + + +// Fill a range with an indicator. +void QsciScintilla::fillIndicatorRange(int lineFrom, int indexFrom, + int lineTo, int indexTo, int indicatorNumber) +{ + if (indicatorNumber < INDIC_IME) + { + int start = positionFromLineIndex(lineFrom, indexFrom); + int finish = positionFromLineIndex(lineTo, indexTo); + + // We ignore allocatedIndicators to allow any indicators defined + // elsewhere (e.g. in lexers) to be set. + if (indicatorNumber < 0) + { + for (int i = 0; i < INDIC_IME; ++i) + { + SendScintilla(SCI_SETINDICATORCURRENT, i); + SendScintilla(SCI_INDICATORFILLRANGE, start, finish - start); + } + } + else + { + SendScintilla(SCI_SETINDICATORCURRENT, indicatorNumber); + SendScintilla(SCI_INDICATORFILLRANGE, start, finish - start); + } + } +} + + +// Clear a range with an indicator. +void QsciScintilla::clearIndicatorRange(int lineFrom, int indexFrom, + int lineTo, int indexTo, int indicatorNumber) +{ + if (indicatorNumber < INDIC_IME) + { + int start = positionFromLineIndex(lineFrom, indexFrom); + int finish = positionFromLineIndex(lineTo, indexTo); + + // We ignore allocatedIndicators to allow any indicators defined + // elsewhere (e.g. in lexers) to be set. + if (indicatorNumber < 0) + { + for (int i = 0; i < INDIC_IME; ++i) + { + SendScintilla(SCI_SETINDICATORCURRENT, i); + SendScintilla(SCI_INDICATORCLEARRANGE, start, finish - start); + } + } + else + { + SendScintilla(SCI_SETINDICATORCURRENT, indicatorNumber); + SendScintilla(SCI_INDICATORCLEARRANGE, start, finish - start); + } + } +} + + +// Define a marker based on a symbol. +int QsciScintilla::markerDefine(MarkerSymbol sym, int markerNumber) +{ + checkMarker(markerNumber); + + if (markerNumber >= 0) + SendScintilla(SCI_MARKERDEFINE, markerNumber, static_cast(sym)); + + return markerNumber; +} + + +// Define a marker based on a character. +int QsciScintilla::markerDefine(char ch, int markerNumber) +{ + checkMarker(markerNumber); + + if (markerNumber >= 0) + SendScintilla(SCI_MARKERDEFINE, markerNumber, + static_cast(SC_MARK_CHARACTER) + ch); + + return markerNumber; +} + + +// Define a marker based on a QPixmap. +int QsciScintilla::markerDefine(const QPixmap &pm, int markerNumber) +{ + checkMarker(markerNumber); + + if (markerNumber >= 0) + SendScintilla(SCI_MARKERDEFINEPIXMAP, markerNumber, pm); + + return markerNumber; +} + + +// Define a marker based on a QImage. +int QsciScintilla::markerDefine(const QImage &im, int markerNumber) +{ + checkMarker(markerNumber); + + if (markerNumber >= 0) + { + SendScintilla(SCI_RGBAIMAGESETHEIGHT, im.height()); + SendScintilla(SCI_RGBAIMAGESETWIDTH, im.width()); + SendScintilla(SCI_MARKERDEFINERGBAIMAGE, markerNumber, im); + } + + return markerNumber; +} + + +// Add a marker to a line. +int QsciScintilla::markerAdd(int linenr, int markerNumber) +{ + if (markerNumber < 0 || markerNumber > MARKER_MAX || (allocatedMarkers & (1 << markerNumber)) == 0) + return -1; + + return SendScintilla(SCI_MARKERADD, linenr, markerNumber); +} + + +// Get the marker mask for a line. +unsigned QsciScintilla::markersAtLine(int linenr) const +{ + return SendScintilla(SCI_MARKERGET, linenr); +} + + +// Delete a marker from a line. +void QsciScintilla::markerDelete(int linenr, int markerNumber) +{ + if (markerNumber <= MARKER_MAX) + { + if (markerNumber < 0) + { + unsigned am = allocatedMarkers; + + for (int m = 0; m <= MARKER_MAX; ++m) + { + if (am & 1) + SendScintilla(SCI_MARKERDELETE, linenr, m); + + am >>= 1; + } + } + else if (allocatedMarkers & (1 << markerNumber)) + SendScintilla(SCI_MARKERDELETE, linenr, markerNumber); + } +} + +//删除一行的全部marker +void QsciScintilla::markerDelete(int linenr) +{ + if (allocatedMarkers) + SendScintilla(SCI_LINE_MARKERDELETE_ALL, linenr); +} + +// Delete a marker from the text. +void QsciScintilla::markerDeleteAll(int markerNumber) +{ + if (markerNumber <= MARKER_MAX) + { + if (markerNumber < 0) + SendScintilla(SCI_MARKERDELETEALL, -1); + else if (allocatedMarkers & (1 << markerNumber)) + SendScintilla(SCI_MARKERDELETEALL, markerNumber); + } +} + + +// Delete a marker handle from the text. +void QsciScintilla::markerDeleteHandle(int mhandle) +{ + SendScintilla(SCI_MARKERDELETEHANDLE, mhandle); +} + + +// Return the line containing a marker instance. +int QsciScintilla::markerLine(int mhandle) const +{ + return SendScintilla(SCI_MARKERLINEFROMHANDLE, mhandle); +} + + +// Search forwards for a marker. +int QsciScintilla::markerFindNext(int linenr, unsigned mask) const +{ + return SendScintilla(SCI_MARKERNEXT, linenr, mask); +} + + +// Search backwards for a marker. +int QsciScintilla::markerFindPrevious(int linenr, unsigned mask) const +{ + return SendScintilla(SCI_MARKERPREVIOUS, linenr, mask); +} + + +// Set the marker background colour. +void QsciScintilla::setMarkerBackgroundColor(const QColor &col, int markerNumber) +{ + if (markerNumber <= MARKER_MAX) + { + int alpha = col.alpha(); + + // An opaque background would make the text invisible. + if (alpha == 255) + alpha = SC_ALPHA_NOALPHA; + + if (markerNumber < 0) + { + unsigned am = allocatedMarkers; + + for (int m = 0; m <= MARKER_MAX; ++m) + { + if (am & 1) + { + SendScintilla(SCI_MARKERSETBACK, m, col); + SendScintilla(SCI_MARKERSETALPHA, m, alpha); + } + + am >>= 1; + } + } + else if (allocatedMarkers & (1 << markerNumber)) + { + SendScintilla(SCI_MARKERSETBACK, markerNumber, col); + SendScintilla(SCI_MARKERSETALPHA, markerNumber, alpha); + } + } +} + + +// Set the marker foreground colour. +void QsciScintilla::setMarkerForegroundColor(const QColor &col, int markerNumber) +{ + if (markerNumber <= MARKER_MAX) + { + if (markerNumber < 0) + { + unsigned am = allocatedMarkers; + + for (int m = 0; m <= MARKER_MAX; ++m) + { + if (am & 1) + SendScintilla(SCI_MARKERSETFORE, m, col); + + am >>= 1; + } + } + else if (allocatedMarkers & (1 << markerNumber)) + { + SendScintilla(SCI_MARKERSETFORE, markerNumber, col); + } + } +} + + +// Check a marker, allocating a marker number if necessary. +void QsciScintilla::checkMarker(int &markerNumber) +{ + allocateId(markerNumber, allocatedMarkers, 0, MARKER_MAX); +} + + +// Check an indicator, allocating an indicator number if necessary. +void QsciScintilla::checkIndicator(int &indicatorNumber) +{ + allocateId(indicatorNumber, allocatedIndicators, INDIC_CONTAINER, + INDIC_IME - 1); +} + + +// Make sure an identifier is valid and allocate it if necessary. +void QsciScintilla::allocateId(int &id, unsigned &allocated, int min, int max) +{ + if (id >= 0) + { + // Note that we allow existing identifiers to be explicitly redefined. + if (id > max) + id = -1; + } + else + { + unsigned aids = allocated >> min; + + // Find the smallest unallocated identifier. + for (id = min; id <= max; ++id) + { + if ((aids & 1) == 0) + break; + + aids >>= 1; + } + } + + // Allocate the identifier if it is valid. + if (id >= 0) + allocated |= (1 << id); +} + + +// Reset the fold margin colours. +void QsciScintilla::resetFoldMarginColors() +{ + SendScintilla(SCI_SETFOLDMARGINHICOLOUR, 0, 0L); + SendScintilla(SCI_SETFOLDMARGINCOLOUR, 0, 0L); +} + + +// Set the fold margin colours. +void QsciScintilla::setFoldMarginColors(const QColor &fore, const QColor &back) +{ + SendScintilla(SCI_SETFOLDMARGINHICOLOUR, 1, fore); + SendScintilla(SCI_SETFOLDMARGINCOLOUR, 1, back); +} + + +// Set the call tips background colour. +void QsciScintilla::setCallTipsBackgroundColor(const QColor &col) +{ + SendScintilla(SCI_CALLTIPSETBACK, col); +} + + +// Set the call tips foreground colour. +void QsciScintilla::setCallTipsForegroundColor(const QColor &col) +{ + SendScintilla(SCI_CALLTIPSETFORE, col); +} + + +// Set the call tips highlight colour. +void QsciScintilla::setCallTipsHighlightColor(const QColor &col) +{ + SendScintilla(SCI_CALLTIPSETFOREHLT, col); +} + + +// Set the matched brace background colour. +void QsciScintilla::setMatchedBraceBackgroundColor(const QColor &col) +{ + SendScintilla(SCI_STYLESETBACK, STYLE_BRACELIGHT, col); +} + + +// Set the matched brace foreground colour. +void QsciScintilla::setMatchedBraceForegroundColor(const QColor &col) +{ + SendScintilla(SCI_STYLESETFORE, STYLE_BRACELIGHT, col); +} + + +// Set the matched brace indicator. +void QsciScintilla::setMatchedBraceIndicator(int indicatorNumber) +{ + SendScintilla(SCI_BRACEHIGHLIGHTINDICATOR, 1, indicatorNumber); +} + + +// Reset the matched brace indicator. +void QsciScintilla::resetMatchedBraceIndicator() +{ + SendScintilla(SCI_BRACEHIGHLIGHTINDICATOR, 0, 0L); +} + + +// Set the unmatched brace background colour. +void QsciScintilla::setUnmatchedBraceBackgroundColor(const QColor &col) +{ + SendScintilla(SCI_STYLESETBACK, STYLE_BRACEBAD, col); +} + + +// Set the unmatched brace foreground colour. +void QsciScintilla::setUnmatchedBraceForegroundColor(const QColor &col) +{ + SendScintilla(SCI_STYLESETFORE, STYLE_BRACEBAD, col); +} + + +// Set the unmatched brace indicator. +void QsciScintilla::setUnmatchedBraceIndicator(int indicatorNumber) +{ + SendScintilla(SCI_BRACEBADLIGHTINDICATOR, 1, indicatorNumber); +} + + +// Reset the unmatched brace indicator. +void QsciScintilla::resetUnmatchedBraceIndicator() +{ + SendScintilla(SCI_BRACEBADLIGHTINDICATOR, 0, 0L); +} + + +// Detach any lexer. +void QsciScintilla::detachLexer() +{ + if (!lex.isNull()) + { + lex->setEditor(0); + lex->disconnect(this); + + SendScintilla(SCI_STYLERESETDEFAULT); + SendScintilla(SCI_STYLECLEARALL); + } +} + + +// Set the lexer. +void QsciScintilla::setLexer(QsciLexer *lexer) +{ + // Detach any current lexer. + detachLexer(); + + // Connect up the new lexer. + lex = lexer; + + if (lex != nullptr) + { + SendScintilla(SCI_CLEARDOCUMENTSTYLE); + + if (lex->lexer()) + SendScintilla(SCI_SETLEXERLANGUAGE, lex->lexer()); + else + SendScintilla(SCI_SETLEXER, lex->lexerId()); + + lex->setEditor(this); + + connect(lex,SIGNAL(colorChanged(const QColor &, int)), + SLOT(handleStyleColorChange(const QColor &, int))); + connect(lex,SIGNAL(eolFillChanged(bool, int)), + SLOT(handleStyleEolFillChange(bool, int))); + connect(lex,SIGNAL(fontChanged(const QFont &, int)), + SLOT(handleStyleFontChange(const QFont &, int))); + connect(lex,SIGNAL(paperChanged(const QColor &, int)), + SLOT(handleStylePaperChange(const QColor &, int))); + connect(lex,SIGNAL(propertyChanged(const char *, const char *)), + SLOT(handlePropertyChange(const char *, const char *))); + + SendScintilla(SCI_SETPROPERTY, "fold", "1"); + SendScintilla(SCI_SETPROPERTY, "fold.html", "1"); + + // Set the keywords. Scintilla allows for sets numbered 0 to + // KEYWORDSET_MAX (although the lexers only seem to exploit 0 to + // KEYWORDSET_MAX - 1). We number from 1 in line with SciTE's property + // files. + for (int k = 0; k <= KEYWORDSET_MAX; ++k) + { + const char *kw = lex -> keywords(k + 1); + + if (!kw) + kw = ""; + + SendScintilla(SCI_SETKEYWORDS, k, kw); + } + + // Initialise each style. Do the default first so its (possibly + // incorrect) font setting gets reset when style 0 is set. + setLexerStyle(STYLE_DEFAULT); + + for (int s = 0; s <= STYLE_MAX; ++s) + if (!lex->description(s).isEmpty()) + setLexerStyle(s); + + // Initialise the properties. + lex->refreshProperties(); + + // Set the auto-completion fillups and word separators. + setAutoCompletionFillupsEnabled(fillups_enabled); + wseps = lex->autoCompletionWordSeparators(); + + wchars = lex->wordCharacters(); + + if (!wchars) + wchars = defaultWordChars; + + SendScintilla(SCI_AUTOCSETIGNORECASE, !lex->caseSensitive()); + + recolor(); + + int lang = lexer->lexerId(); + + if (lang == L_XML || lang == L_HTML || lang == L_PHP || lang == L_ASP || lang == L_JSP) + { + setHtmlHighLightTag(true); + } + else + { + setHtmlHighLightTag(false); + } + } + else + { + SendScintilla(SCI_SETLEXER, SCLEX_CONTAINER); + + setColor(nl_text_colour); + setPaper(nl_paper_colour); + + SendScintilla(SCI_AUTOCSETFILLUPS, ""); + SendScintilla(SCI_AUTOCSETIGNORECASE, false); + wseps.clear(); + wchars = defaultWordChars; + + setHtmlHighLightTag(false); + } +} + + +// Set a particular style of the current lexer. +void QsciScintilla::setLexerStyle(int style) +{ + handleStyleColorChange(lex->color(style), style); + handleStyleEolFillChange(lex->eolFill(style), style); + handleStyleFontChange(lex->font(style), style); + handleStylePaperChange(lex->paper(style), style); +} + + +// Get the current lexer. +QsciLexer *QsciScintilla::lexer() const +{ + return lex; +} + + +// Handle a change in lexer style foreground colour. +void QsciScintilla::handleStyleColorChange(const QColor &c, int style) +{ + SendScintilla(SCI_STYLESETFORE, style, c); +} + + +// Handle a change in lexer style end-of-line fill. +void QsciScintilla::handleStyleEolFillChange(bool eolfill, int style) +{ + SendScintilla(SCI_STYLESETEOLFILLED, style, eolfill); +} + + +// Handle a change in lexer style font. +void QsciScintilla::handleStyleFontChange(const QFont &f, int style) +{ + setStylesFont(f, style); + + if (style == lex->braceStyle()) + { + setStylesFont(f, STYLE_BRACELIGHT); + setStylesFont(f, STYLE_BRACEBAD); + } +} + + +// Set the font for a style. +void QsciScintilla::setStylesFont(const QFont &f, int style) +{ + //20220629这里是中文编码的一个bug + SendScintilla(SCI_STYLESETFONT, style, f.family().toUtf8().data()); + SendScintilla(SCI_STYLESETSIZEFRACTIONAL, style, + long(f.pointSizeF() * SC_FONT_SIZE_MULTIPLIER)); + + // Pass the Qt weight via the back door. + SendScintilla(SCI_STYLESETWEIGHT, style, -f.weight()); + + SendScintilla(SCI_STYLESETITALIC, style, f.italic()); + SendScintilla(SCI_STYLESETUNDERLINE, style, f.underline()); + + // Tie the font settings of the default style to that of style 0 (the style + // conventionally used for whitespace by lexers). This is needed so that + // fold marks, indentations, edge columns etc are set properly. + if (style == 0) + setStylesFont(f, STYLE_DEFAULT); +} + + +// Handle a change in lexer style background colour. +void QsciScintilla::handleStylePaperChange(const QColor &c, int style) +{ + SendScintilla(SCI_STYLESETBACK, style, c); +} + + +// Handle a change in lexer property. +void QsciScintilla::handlePropertyChange(const char *prop, const char *val) +{ + SendScintilla(SCI_SETPROPERTY, prop, val); +} + + +// Handle a change to the user visible user interface. +void QsciScintilla::handleUpdateUI(int) +{ + int newPos = SendScintilla(SCI_GETCURRENTPOS); + + if (newPos != oldPos) + { + oldPos = newPos; + + int line = SendScintilla(SCI_LINEFROMPOSITION, newPos); + int col = SendScintilla(SCI_GETCOLUMN, newPos); + + emit cursorPositionChanged(line, col); + + if (line != oldLine) + { + oldLine = line; + emit cursorPosChange(line, newPos); + } + } + + addHotSpot(); + + if (braceMode != NoBraceMatch) + braceMatch(); + + //只有html类语言,比如php jsp xml才会高亮tag + if (isHtmlHighLightTag) + { + XmlMatchedTagsHighlighter xmlTagMatchHiliter(this); + xmlTagMatchHiliter.tagMatch(true); +} +} + + +// Handle brace matching. +void QsciScintilla::braceMatch() +{ + long braceAtCaret, braceOpposite; + + findMatchingBrace(braceAtCaret, braceOpposite, braceMode); + + if (braceAtCaret >= 0 && braceOpposite < 0) + { + SendScintilla(SCI_BRACEBADLIGHT, braceAtCaret); + SendScintilla(SCI_SETHIGHLIGHTGUIDE, 0UL); + } + else + { + char chBrace = SendScintilla(SCI_GETCHARAT, braceAtCaret); + + SendScintilla(SCI_BRACEHIGHLIGHT, braceAtCaret, braceOpposite); + + long columnAtCaret = SendScintilla(SCI_GETCOLUMN, braceAtCaret); + long columnOpposite = SendScintilla(SCI_GETCOLUMN, braceOpposite); + + if (chBrace == ':') + { + long lineStart = SendScintilla(SCI_LINEFROMPOSITION, braceAtCaret); + long indentPos = SendScintilla(SCI_GETLINEINDENTPOSITION, + lineStart); + long indentPosNext = SendScintilla(SCI_GETLINEINDENTPOSITION, + lineStart + 1); + + columnAtCaret = SendScintilla(SCI_GETCOLUMN, indentPos); + + long columnAtCaretNext = SendScintilla(SCI_GETCOLUMN, + indentPosNext); + long indentSize = SendScintilla(SCI_GETINDENT); + + if (columnAtCaretNext - indentSize > 1) + columnAtCaret = columnAtCaretNext - indentSize; + + if (columnOpposite == 0) + columnOpposite = columnAtCaret; + } + + long column = columnAtCaret; + + if (column > columnOpposite) + column = columnOpposite; + + SendScintilla(SCI_SETHIGHLIGHTGUIDE, column); + } +} + + +// Check if the character at a position is a brace. +long QsciScintilla::checkBrace(long pos, int brace_style, bool &colonMode) +{ + long brace_pos = -1; + char ch = SendScintilla(SCI_GETCHARAT, pos); + + if (ch == ':') + { + // A bit of a hack, we should really use a virtual. + if (!lex.isNull() && qstrcmp(lex->lexer(), "python") == 0) + { + brace_pos = pos; + colonMode = true; + } + } + else if (ch && strchr("[](){}<>", ch)) + { + if (brace_style < 0) + brace_pos = pos; + else + { + int style = SendScintilla(SCI_GETSTYLEAT, pos) & 0x1f; + + if (style == brace_style) + brace_pos = pos; + } + } + + return brace_pos; +} + + +// Find a brace and it's match. Return true if the current position is inside +// a pair of braces. +bool QsciScintilla::findMatchingBrace(long &brace, long &other, BraceMatch mode) +{ + bool colonMode = false; + int brace_style = (lex.isNull() ? -1 : lex->braceStyle()); + + brace = -1; + other = -1; + + long caretPos = SendScintilla(SCI_GETCURRENTPOS); + + if (caretPos > 0) + brace = checkBrace(caretPos - 1, brace_style, colonMode); + + bool isInside = false; + + if (brace < 0 && mode == SloppyBraceMatch) + { + brace = checkBrace(caretPos, brace_style, colonMode); + + if (brace >= 0 && !colonMode) + isInside = true; + } + + if (brace >= 0) + { + if (colonMode) + { + // Find the end of the Python indented block. + long lineStart = SendScintilla(SCI_LINEFROMPOSITION, brace); + long lineMaxSubord = SendScintilla(SCI_GETLASTCHILD, lineStart, -1); + + other = SendScintilla(SCI_GETLINEENDPOSITION, lineMaxSubord); + } + else + other = SendScintilla(SCI_BRACEMATCH, brace, 0L); + + if (other > brace) + isInside = !isInside; + } + + return isInside; +} + + +// Move to the matching brace. +void QsciScintilla::moveToMatchingBrace() +{ + gotoMatchingBrace(false); +} + + +// Select to the matching brace. +void QsciScintilla::selectToMatchingBrace() +{ + gotoMatchingBrace(true); +} + + +// Move to the matching brace and optionally select the text. +void QsciScintilla::gotoMatchingBrace(bool select) +{ + long braceAtCaret; + long braceOpposite; + + bool isInside = findMatchingBrace(braceAtCaret, braceOpposite, + SloppyBraceMatch); + + if (braceOpposite >= 0) + { + // Convert the character positions into caret positions based on + // whether the caret position was inside or outside the braces. + if (isInside) + { + if (braceOpposite > braceAtCaret) + braceAtCaret++; + else + braceOpposite++; + } + else + { + if (braceOpposite > braceAtCaret) + braceOpposite++; + else + braceAtCaret++; + } + + ensureLineVisible(SendScintilla(SCI_LINEFROMPOSITION, braceOpposite)); + + if (select) + SendScintilla(SCI_SETSEL, braceAtCaret, braceOpposite); + else + SendScintilla(SCI_SETSEL, braceOpposite, braceOpposite); + } +} + + +// Return a position from a line number and an index within the line. +int QsciScintilla::positionFromLineIndex(int line, int index) const +{ + int pos = SendScintilla(SCI_POSITIONFROMLINE, line); + + // Allow for multi-byte characters. + for(int i = 0; i < index; i++) + pos = SendScintilla(SCI_POSITIONAFTER, pos); + + return pos; +} + + +// Return a line number and an index within the line from a position. +void QsciScintilla::lineIndexFromPosition(int position, int *line, int *index) const +{ + int lin = SendScintilla(SCI_LINEFROMPOSITION, position); + int linpos = SendScintilla(SCI_POSITIONFROMLINE, lin); + int indx = 0; + + // Allow for multi-byte characters. + while (linpos < position) + { + int new_linpos = SendScintilla(SCI_POSITIONAFTER, linpos); + + // If the position hasn't moved then we must be at the end of the text + // (which implies that the position passed was beyond the end of the + // text). + if (new_linpos == linpos) + break; + + linpos = new_linpos; + ++indx; + } + + *line = lin; + *index = indx; +} + + +// Set the source of the automatic auto-completion list. +void QsciScintilla::setAutoCompletionSource(AutoCompletionSource source) +{ + acSource = source; +} + + +// Set the threshold for automatic auto-completion. +void QsciScintilla::setAutoCompletionThreshold(int thresh) +{ + acThresh = thresh; +} + + +// Set the auto-completion word separators if there is no current lexer. +void QsciScintilla::setAutoCompletionWordSeparators(const QStringList &separators) +{ + if (lex.isNull()) + wseps = separators; +} + + +// Explicitly auto-complete from all sources. +void QsciScintilla::autoCompleteFromAll() +{ + startAutoCompletion(AcsAll, false, use_single != AcusNever); +} + + +// Explicitly auto-complete from the APIs. +void QsciScintilla::autoCompleteFromAPIs() +{ + startAutoCompletion(AcsAPIs, false, use_single != AcusNever); +} + + +// Explicitly auto-complete from the document. +void QsciScintilla::autoCompleteFromDocument() +{ + startAutoCompletion(AcsDocument, false, use_single != AcusNever); +} + + +// Check if a character can be in a word. +bool QsciScintilla::isWordCharacter(char ch) const +{ + return (strchr(wchars, ch) != NULL); +} + + +// Return the set of valid word characters. +const char *QsciScintilla::wordCharacters() const +{ + return wchars; +} + + +// Recolour the document. +void QsciScintilla::recolor(int start, int end) +{ + SendScintilla(SCI_COLOURISE, start, end); +} + + +// Registered a QPixmap image. +void QsciScintilla::registerImage(int id, const QPixmap &pm) +{ + SendScintilla(SCI_REGISTERIMAGE, id, pm); +} + + +// Registered a QImage image. +void QsciScintilla::registerImage(int id, const QImage &im) +{ + SendScintilla(SCI_RGBAIMAGESETHEIGHT, im.height()); + SendScintilla(SCI_RGBAIMAGESETWIDTH, im.width()); + SendScintilla(SCI_REGISTERRGBAIMAGE, id, im); +} + + +// Clear all registered images. +void QsciScintilla::clearRegisteredImages() +{ + SendScintilla(SCI_CLEARREGISTEREDIMAGES); +} + + +// Enable auto-completion fill-ups. +void QsciScintilla::setAutoCompletionFillupsEnabled(bool enable) +{ + const char *fillups; + + if (!enable) + fillups = ""; + else if (!lex.isNull()) + fillups = lex->autoCompletionFillups(); + else + fillups = explicit_fillups.data(); + + SendScintilla(SCI_AUTOCSETFILLUPS, fillups); + + fillups_enabled = enable; +} + + +// See if auto-completion fill-ups are enabled. +bool QsciScintilla::autoCompletionFillupsEnabled() const +{ + return fillups_enabled; +} + + +// Set the fill-up characters for auto-completion if there is no current lexer. +void QsciScintilla::setAutoCompletionFillups(const char *fillups) +{ + explicit_fillups = fillups; + setAutoCompletionFillupsEnabled(fillups_enabled); +} + + +// Set the case sensitivity for auto-completion. +void QsciScintilla::setAutoCompletionCaseSensitivity(bool cs) +{ + SendScintilla(SCI_AUTOCSETIGNORECASE, !cs); +} + + +// Return the case sensitivity for auto-completion. +bool QsciScintilla::autoCompletionCaseSensitivity() const +{ + return !SendScintilla(SCI_AUTOCGETIGNORECASE); +} + + +// Set the replace word mode for auto-completion. +void QsciScintilla::setAutoCompletionReplaceWord(bool replace) +{ + SendScintilla(SCI_AUTOCSETDROPRESTOFWORD, replace); +} + + +// Return the replace word mode for auto-completion. +bool QsciScintilla::autoCompletionReplaceWord() const +{ + return SendScintilla(SCI_AUTOCGETDROPRESTOFWORD); +} + + +// Set the single item mode for auto-completion. +void QsciScintilla::setAutoCompletionUseSingle(AutoCompletionUseSingle single) +{ + use_single = single; +} + + +// Return the single item mode for auto-completion. +QsciScintilla::AutoCompletionUseSingle QsciScintilla::autoCompletionUseSingle() const +{ + return use_single; +} + + +// Set the single item mode for auto-completion (deprecated). +void QsciScintilla::setAutoCompletionShowSingle(bool single) +{ + use_single = (single ? AcusExplicit : AcusNever); +} + + +// Return the single item mode for auto-completion (deprecated). +bool QsciScintilla::autoCompletionShowSingle() const +{ + return (use_single != AcusNever); +} + + +// Set current call tip position. +void QsciScintilla::setCallTipsPosition(CallTipsPosition position) +{ + SendScintilla(SCI_CALLTIPSETPOSITION, (position == CallTipsAboveText)); + call_tips_position = position; +} + + +// Set current call tip style. +void QsciScintilla::setCallTipsStyle(CallTipsStyle style) +{ + call_tips_style = style; +} + + +// Set maximum number of call tips displayed. +void QsciScintilla::setCallTipsVisible(int nr) +{ + maxCallTips = nr; +} + + +// Set the document to display. +void QsciScintilla::setDocument(const QsciDocument &document) +{ + if (doc.pdoc != document.pdoc) + { + doc.undisplay(this); + doc.attach(document); + doc.display(this,&document); + } +} + + +// Ensure the document is read-write and return true if was was read-only. +bool QsciScintilla::ensureRW() +{ + bool ro = isReadOnly(); + + if (ro) + setReadOnly(false); + + return ro; +} + + +// Return the number of the first visible line. +int QsciScintilla::firstVisibleLine() const +{ + return SendScintilla(SCI_GETFIRSTVISIBLELINE); +} + + +// Set the number of the first visible line. +void QsciScintilla::setFirstVisibleLine(int linenr) +{ + SendScintilla(SCI_SETFIRSTVISIBLELINE, linenr); +} + + +// Return the height in pixels of the text in a particular line. +int QsciScintilla::textHeight(int linenr) const +{ + return SendScintilla(SCI_TEXTHEIGHT, linenr); +} + + +// See if auto-completion or user list is active. +bool QsciScintilla::isListActive() const +{ + return SendScintilla(SCI_AUTOCACTIVE); +} + + +// Cancel any current auto-completion or user list. +void QsciScintilla::cancelList() +{ + SendScintilla(SCI_AUTOCCANCEL); +} + + +// Handle a selection from the auto-completion list. +void QsciScintilla::handleAutoCompletionSelection() +{ + if (!lex.isNull()) + { + QsciAbstractAPIs *apis = lex->apis(); + + if (apis) + apis->autoCompletionSelected(acSelection); + } +} + + +// Display a user list. +void QsciScintilla::showUserList(int id, const QStringList &list) +{ + // Sanity check to make sure auto-completion doesn't get confused. + if (id <= 0) + return; + + SendScintilla(SCI_AUTOCSETSEPARATOR, userSeparator); + + ScintillaBytes s = textAsBytes(list.join(QChar(userSeparator))); + SendScintilla(SCI_USERLISTSHOW, id, ScintillaBytesConstData(s)); +} + + +// Translate the SCN_USERLISTSELECTION notification into something more useful. +void QsciScintilla::handleUserListSelection(const char *text, int id) +{ + emit userListActivated(id, QString(text)); + + // Make sure the editor hasn't been deactivated as a side effect. + activateWindow(); +} + + +// Return the case sensitivity of any lexer. +bool QsciScintilla::caseSensitive() const +{ + return lex.isNull() ? true : lex->caseSensitive(); +} + + +// Return true if the current list is an auto-completion list rather than a +// user list. +bool QsciScintilla::isAutoCompletionList() const +{ + return (SendScintilla(SCI_AUTOCGETSEPARATOR) == acSeparator); +} + + +// Read the text from a QIODevice. +bool QsciScintilla::read(QIODevice *io) +{ + const int min_size = 1024 * 8; + + int buf_size = min_size; + char *buf = new char[buf_size]; + + int data_len = 0; + bool ok = true; + + qint64 part; + + // Read the whole lot in so we don't have to worry about character + // boundaries. + do + { + // Make sure there is a minimum amount of room. + if (buf_size - data_len < min_size) + { + buf_size *= 2; + char *new_buf = new char[buf_size * 2]; + + memcpy(new_buf, buf, data_len); + delete[] buf; + buf = new_buf; + } + + part = io->read(buf + data_len, buf_size - data_len - 1); + data_len += part; + } + while (part > 0); + + if (part < 0) + ok = false; + else + { + buf[data_len] = '\0'; + + bool ro = ensureRW(); + + SendScintilla(SCI_SETTEXT, buf); + SendScintilla(SCI_EMPTYUNDOBUFFER); + + setReadOnly(ro); + } + + delete[] buf; + + return ok; +} + + +// Write the text to a QIODevice. +bool QsciScintilla::write(QIODevice *io) const +{ + const char *buf = reinterpret_cast(SendScintillaPtrResult(SCI_GETCHARACTERPOINTER)); + + const char *bp = buf; + uint buflen = qstrlen(buf); + + while (buflen > 0) + { + qint64 part = io->write(bp, buflen); + + if (part < 0) + return false; + + bp += part; + buflen -= part; + } + + return true; +} + +//是否开启缩进。这个和前面的setIndentationGuides有冗余。暂时使用这个来确定,因为外部有一个详细检测是否python的作用 +void QsciScintilla::setIndentGuide(bool v) +{ + isIndentGuide = v; +} + +bool QsciScintilla::getIndentGuide() +{ + return isIndentGuide; +} + +void QsciScintilla::setHtmlHighLightTag(bool v) +{ + isHtmlHighLightTag = v; +} + +bool QsciScintilla::getHtmlHighLightTag() +{ + return isHtmlHighLightTag; +} + + +// Return the word at the given coordinates. +QString QsciScintilla::wordAtLineIndex(int line, int index) const +{ + return wordAtPosition(positionFromLineIndex(line, index)); +} + + +// Return the word at the given coordinates. +QString QsciScintilla::wordAtPoint(const QPoint &point) const +{ + long close_pos = SendScintilla(SCI_POSITIONFROMPOINTCLOSE, point.x(), + point.y()); + + return wordAtPosition(close_pos); +} + + +// Return the word at the given position. +QString QsciScintilla::wordAtPosition(int position) const +{ + if (position < 0) + return QString(); + + long start_pos = SendScintilla(SCI_WORDSTARTPOSITION, position, true); + long end_pos = SendScintilla(SCI_WORDENDPOSITION, position, true); + + if (start_pos >= end_pos) + return QString(); + + return text(start_pos, end_pos); +} + + +// Return the display style for annotations. +QsciScintilla::AnnotationDisplay QsciScintilla::annotationDisplay() const +{ + return (AnnotationDisplay)SendScintilla(SCI_ANNOTATIONGETVISIBLE); +} + + +// Set the display style for annotations. +void QsciScintilla::setAnnotationDisplay(QsciScintilla::AnnotationDisplay display) +{ + SendScintilla(SCI_ANNOTATIONSETVISIBLE, display); + setScrollBars(); +} + + +// Clear annotations. +void QsciScintilla::clearAnnotations(int line) +{ + if (line >= 0) + SendScintilla(SCI_ANNOTATIONSETTEXT, line, (const char *)0); + else + SendScintilla(SCI_ANNOTATIONCLEARALL); + + setScrollBars(); +} + + +// Annotate a line. +void QsciScintilla::annotate(int line, const QString &text, int style) +{ + int style_offset = SendScintilla(SCI_ANNOTATIONGETSTYLEOFFSET); + + ScintillaBytes s = textAsBytes(text); + + SendScintilla(SCI_ANNOTATIONSETTEXT, line, ScintillaBytesConstData(s)); + SendScintilla(SCI_ANNOTATIONSETSTYLE, line, style - style_offset); + + setScrollBars(); +} + + +// Annotate a line. +void QsciScintilla::annotate(int line, const QString &text, const QsciStyle &style) +{ + style.apply(this); + + annotate(line, text, style.style()); +} + + +// Annotate a line. +void QsciScintilla::annotate(int line, const QsciStyledText &text) +{ + text.apply(this); + + annotate(line, text.text(), text.style()); +} + + +// Annotate a line. +void QsciScintilla::annotate(int line, const QList &text) +{ + char *styles; + ScintillaBytes styled_text = styleText(text, &styles, + SendScintilla(SCI_ANNOTATIONGETSTYLEOFFSET)); + + SendScintilla(SCI_ANNOTATIONSETTEXT, line, + ScintillaBytesConstData(styled_text)); + SendScintilla(SCI_ANNOTATIONSETSTYLES, line, styles); + + delete[] styles; +} + + +// Get the annotation for a line, if any. +QString QsciScintilla::annotation(int line) const +{ + char *buf = new char[SendScintilla(SCI_ANNOTATIONGETTEXT, line, (const char *)0) + 1]; + + buf[SendScintilla(SCI_ANNOTATIONGETTEXT, line, buf)] = '\0'; + + QString qs = bytesAsText(buf); + delete[] buf; + + return qs; +} + + +// Convert a list of styled text to the low-level arrays. +QsciScintillaBase::ScintillaBytes QsciScintilla::styleText(const QList &styled_text, char **styles, int style_offset) +{ + QString text; + int i; + + // Build the full text. + for (i = 0; i < styled_text.count(); ++i) + { + const QsciStyledText &st = styled_text[i]; + + st.apply(this); + + text.append(st.text()); + } + + ScintillaBytes s = textAsBytes(text); + + // There is a style byte for every byte. + char *sp = *styles = new char[s.length()]; + + for (i = 0; i < styled_text.count(); ++i) + { + const QsciStyledText &st = styled_text[i]; + ScintillaBytes part = textAsBytes(st.text()); + int part_length = part.length(); + + for (int c = 0; c < part_length; ++c) + *sp++ = (char)(st.style() - style_offset); + } + + return s; +} + + +// Convert Scintilla modifiers to the Qt equivalent. +int QsciScintilla::mapModifiers(int modifiers) +{ + int state = 0; + + if (modifiers & SCMOD_SHIFT) + state |= Qt::ShiftModifier; + + if (modifiers & SCMOD_CTRL) + state |= Qt::ControlModifier; + + if (modifiers & SCMOD_ALT) + state |= Qt::AltModifier; + + if (modifiers & (SCMOD_SUPER | SCMOD_META)) + state |= Qt::MetaModifier; + + return state; +} + +// Re-implemented to handle shortcut overrides. +bool QsciScintilla::event(QEvent *e) +{ + if (e->type() == QEvent::ShortcutOverride && !isReadOnly()) + { + QKeyEvent *ke = static_cast(e); + + if (ke->key()) + { + // We want ordinary characters. + if ((ke->modifiers() == Qt::NoModifier || ke->modifiers() == Qt::ShiftModifier || ke->modifiers() == Qt::KeypadModifier) && ke->key() < Qt::Key_Escape) + { + ke->accept(); + return true; + } + + // We want any key that is bound. + QsciCommand *cmd = stdCmds->boundTo(ke->key() | (ke->modifiers() & ~Qt::KeypadModifier)); + + if (cmd) + { + ke->accept(); + return true; + } + } + } + + return QsciScintillaBase::event(e); +} + + +// Re-implemented to zoom when the Control modifier is pressed. +void QsciScintilla::wheelEvent(QWheelEvent *e) +{ +#if defined(Q_OS_MAC) + const Qt::KeyboardModifier zoom_modifier = Qt::MetaModifier; +#else + const Qt::KeyboardModifier zoom_modifier = Qt::ControlModifier; +#endif + + if ((e->modifiers() & zoom_modifier) != 0) + { + QPoint ad = e->angleDelta(); + int delta = (qAbs(ad.x()) > qAbs(ad.y())) ? ad.x() : ad.y(); + + if (delta > 0) + zoomIn(); + else + zoomOut(); + } + else + { + QsciScintillaBase::wheelEvent(e); + } +} + + +// Re-implemented to handle chenges to the enabled state. +void QsciScintilla::changeEvent(QEvent *e) +{ + QsciScintillaBase::changeEvent(e); + + if (e->type() != QEvent::EnabledChange) + return; + + if (isEnabled()) + SendScintilla(SCI_SETCARETSTYLE, CARETSTYLE_LINE); + else + SendScintilla(SCI_SETCARETSTYLE, CARETSTYLE_INVISIBLE); + + QColor fore = palette().color(QPalette::Disabled, QPalette::Text); + QColor back = palette().color(QPalette::Disabled, QPalette::Base); + + if (lex.isNull()) + { + if (isEnabled()) + { + fore = nl_text_colour; + back = nl_paper_colour; + } + + SendScintilla(SCI_STYLESETFORE, 0, fore); + + // Assume style 0 applies to everything so that we don't need to use + // SCI_STYLECLEARALL which clears everything. We still have to set the + // default style as well for the background without any text. + SendScintilla(SCI_STYLESETBACK, 0, back); + SendScintilla(SCI_STYLESETBACK, STYLE_DEFAULT, back); + } + else + { + setEnabledColors(STYLE_DEFAULT, fore, back); + + for (int s = 0; s <= STYLE_MAX; ++s) + if (!lex->description(s).isNull()) + setEnabledColors(s, fore, back); + } +} + + +// Set the foreground and background colours for a style. +void QsciScintilla::setEnabledColors(int style, QColor &fore, QColor &back) +{ + if (isEnabled()) + { + fore = lex->color(style); + back = lex->paper(style); + } + + handleStyleColorChange(fore, style); + handleStylePaperChange(back, style); +} + + +// Re-implemented to implement a more Qt-like context menu. +void QsciScintilla::contextMenuEvent(QContextMenuEvent *e) +{ + if (contextMenuNeeded(e->x(), e->y())) + { + QMenu *menu = createStandardContextMenu(); + + contextUserDefineMenuEvent(menu); + + if (menu) + { + menu->setAttribute(Qt::WA_DeleteOnClose); + menu->popup(e->globalPos()); + } + } +} + +void QsciScintilla::contextUserDefineMenuEvent(QMenu* menu) +{ +} + + + +// Create an instance of the standard context menu. +QMenu *QsciScintilla::createStandardContextMenu() +{ + bool read_only = isReadOnly(); + bool has_selection = hasSelectedText(); + QMenu *menu = new QMenu(this); + QAction *action; + + if (!read_only) + { + /*action = menu->addAction(tr("&Undo"), this, SLOT(undo())); + set_shortcut(action, QsciCommand::Undo); + action->setEnabled(isUndoAvailable()); + + action = menu->addAction(tr("&Redo"), this, SLOT(redo())); + set_shortcut(action, QsciCommand::Redo); + action->setEnabled(isRedoAvailable());*/ + + menu->addSeparator(); + + action = menu->addAction(tr("&Cut"), this, SLOT(cut())); + set_shortcut(action, QsciCommand::SelectionCut); + action->setEnabled(has_selection); + } + + action = menu->addAction(tr("&Copy"), this, SLOT(copy())); + action->setObjectName("copy"); + set_shortcut(action, QsciCommand::SelectionCopy); + action->setEnabled(has_selection); + + if (!read_only) + { + action = menu->addAction(tr("&Paste"), this, SLOT(paste())); + set_shortcut(action, QsciCommand::Paste); + action->setEnabled(SendScintilla(SCI_CANPASTE)); + + action = menu->addAction(tr("Delete"), this, SLOT(delete_selection())); + action->setEnabled(has_selection); + } + + if (!read_only && !menu->isEmpty()) + menu->addSeparator(); + + action = menu->addAction(tr("Select All"), this, SLOT(selectAll())); + set_shortcut(action, QsciCommand::SelectAll); + action->setEnabled(length() != 0); + + return menu; +} + + +// Set the shortcut for an action using any current key binding. +void QsciScintilla::set_shortcut(QAction *action, QsciCommand::Command cmd_id) const +{ + QsciCommand *cmd = stdCmds->find(cmd_id); + + if (cmd && cmd->key()) + action->setShortcut(QKeySequence(cmd->key())); +} + + +// Delete the current selection. +void QsciScintilla::delete_selection() +{ + SendScintilla(SCI_CLEAR); +} + + +// Convert a Scintilla colour to a QColor. +static QColor asQColor(long sci_colour) +{ + return QColor( + ((int)sci_colour) & 0x00ff, + ((int)(sci_colour >> 8)) & 0x00ff, + ((int)(sci_colour >> 16)) & 0x00ff); +} + + +// Set the scroll width. +void QsciScintilla::setScrollWidth(int pixelWidth) +{ + SendScintilla(SCI_SETSCROLLWIDTH, pixelWidth); +} + +// Get the scroll width. +int QsciScintilla::scrollWidth() const +{ + return SendScintilla(SCI_GETSCROLLWIDTH); +} + + +// Set scroll width tracking. +void QsciScintilla::setScrollWidthTracking(bool enabled) +{ + SendScintilla(SCI_SETSCROLLWIDTHTRACKING, enabled); +} + + +// Get scroll width tracking. +bool QsciScintilla::scrollWidthTracking() const +{ + return SendScintilla(SCI_GETSCROLLWIDTHTRACKING); +} diff --git a/src/qscint/src/qsciscintillabase.cpp b/src/qscint/src/qsciscintillabase.cpp index 58133b0..7168e96 100755 --- a/src/qscint/src/qsciscintillabase.cpp +++ b/src/qscint/src/qsciscintillabase.cpp @@ -1,6 +1,6 @@ // This module implements the "official" low-level API. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscistyle.cpp b/src/qscint/src/qscistyle.cpp index 64075aa..408ac91 100755 --- a/src/qscint/src/qscistyle.cpp +++ b/src/qscint/src/qscistyle.cpp @@ -1,6 +1,6 @@ // This module implements the QsciStyle class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qscint/src/qscistyledtext.cpp b/src/qscint/src/qscistyledtext.cpp index 4c93e5c..8aa37f5 100755 --- a/src/qscint/src/qscistyledtext.cpp +++ b/src/qscint/src/qscistyledtext.cpp @@ -1,6 +1,6 @@ // This module implements the QsciStyledText class. // -// Copyright (c) 2021 Riverbank Computing Limited +// Copyright (c) 2023 Riverbank Computing Limited // // This file is part of QScintilla. // diff --git a/src/qss/mystyle.qss b/src/qss/mystyle.qss index 4081705..7f392d1 100755 --- a/src/qss/mystyle.qss +++ b/src/qss/mystyle.qss @@ -59,7 +59,6 @@ QTreeWidget{ QTreeWidget::item { height:22px; -/*background-color:rgba(255, 255, 255, 255); */ } QTreeView::item::selected { diff --git a/src/qtlangset.cpp b/src/qtlangset.cpp index 533623a..f830406 100755 --- a/src/qtlangset.cpp +++ b/src/qtlangset.cpp @@ -1,4 +1,4 @@ -#include "qtlangset.h" +#include "qtlangset.h" #include "scintillaeditview.h" #include "nddsetting.h" #include "rcglobal.h" @@ -42,7 +42,7 @@ QtLangSet::~QtLangSet() } -//ÔÚͬ²½×ÖÌåʱ£¬Îñ±ØÏȹرչØÁª²ۺ¯Êý£¬±ÜÃâѭ»·´¥·¢¡£Îñ±ØÅä¶ÔʹÓà +//在同步字体时,务必先关闭关联槽函数,避免循环触发。务必配对使用 void QtLangSet::enableFontChangeSensitive(bool isSensitive) { if (isSensitive) @@ -65,8 +65,8 @@ void QtLangSet::enableFontChangeSensitive(bool isSensitive) void QtLangSet::startSignSlot() { - //¿ªʼ±¾À´ʹÓõÄÊÇQListWidget::currentItemChangedÐźţ¬µ«ÊǷ¢ÏָÃÐźŴæÔÚĪÃûÆäÃîµĴ¥·¢»úÖơ£ - //¹À¼ÆÊÇQT5.12µÄbug¡£ËùÒԻ»³ÉitemClickedÐźÅ + //开始本来使用的是QListWidget::currentItemChanged信号,但是发现该信号存在莫名其妙的触发机制。 + //估计是QT5.12的bug。所以换成itemClicked信号 connect(ui.langListWidget, &QListWidget::itemClicked, this, &QtLangSet::slot_itemSelect); connect(ui.langListWidget, &QListWidget::currentRowChanged, this, &QtLangSet::slot_langListCurRowChanged); @@ -83,12 +83,12 @@ void QtLangSet::startSignSlot() connect(ui.fontComboBox, &QFontComboBox::currentFontChanged, this, &QtLangSet::slot_fontChange); } -//Èóõʼ»¯ʱѡÔñµ±ǰ±༭Æ÷µÄÓïÑÔ +//让初始化时选择当前编辑器的语言 void QtLangSet::selectInitLangTag(QString initLangTag) { - //µÚһ´αØÐëÒԳõʼ»¯lexidÏÔʾ¡£ÕâÑù×öʵÔÚÊÇÒòΪ³õʼ»¯listÆô¶¯º󣬻á×Զ¯°ѵÚһ¸öÉèÖÃΪµ±ǰ¡£ - //ÕâÀﻹÊÇÓÐÎÊÌ⣬ÊÇqt5.12.4µÄbug»úÖƵ¼ÖÂ:Èç¹ûûÓÐѡÔñQListWidget£¬»á×ÜÊÇ×Զ¯ѡÔñµÚһ¸ö + //第一次必须以初始化lexid显示。这样做实在是因为初始化list启动后,会自动把第一个设置为当前。 + //这里还是有问题,是qt5.12.4的bug机制导致:如果没有选择QListWidget,会总是自动选择第一个 if (!initLangTag.isEmpty()) { QList destItems = ui.langListWidget->findItems(initLangTag,Qt::MatchExactly); @@ -121,7 +121,7 @@ void QtLangSet::selectInitLangTag(QString initLangTag) void QtLangSet::slot_fontBoldChange(int state) { - //¼´ʱÉèÖ÷ç¸ñ + //即时设置风格 if (m_selectLexer != nullptr) { if (m_curStyleData.font.bold() != ((state == Qt::Unchecked) ? false : true)) @@ -139,19 +139,19 @@ void QtLangSet::slot_fontBoldChange(int state) } else if (ui.useGlobalFont->isVisible() && !ui.useGbFontBold->isChecked()) { - //±£´æȫ¾ÖÑùʽµÚһÌõÑùʽ±¾Éí + //保存全局样式第一条样式本身 saveLangeSet(m_selectLexer); } else if (!ui.useGlobalFont->isVisible()) { - //ȫ¾ַǵÚһ¸öÑùʽ£¬Ð޸ĵ±ǰȫ¾Ö×ÖÌå´óС - //ȫ¾ÖÑùʽµķǵÚһ¸ö + //全局非第一个样式,修改当前全局字体大小 + //全局样式的非第一个 StyleSet::setGlobalFont(m_selectStyleId, m_curStyleData.font); - //±£´æȫ¾ÖÑùʽµÚһÌõÑùʽ±¾Éí + //保存全局样式第一条样式本身 saveLangeSet(m_selectLexer); - //ÕâÀï¾ÍÊÇȫ¾ֵÄÑùʽ¡£֪ͨµ±ǰËùÓеı༭¿ò£¬ȥÐ޸ÄËûÃDZ¾ÉíµÄȫ¾ÖÑùʽ + //这里就是全局的样式。通知当前所有的编辑框,去修改他们本身的全局样式 CCNotePad* pMainNote = dynamic_cast(parent()); if (pMainNote != nullptr) { @@ -169,7 +169,7 @@ void QtLangSet::slot_fontBoldChange(int state) void QtLangSet::slot_fontItalicChange(int state) { - //¼´ʱÉèÖ÷ç¸ñ + //即时设置风格 if (m_selectLexer != nullptr) { if (m_curStyleData.font.italic() != ((state == Qt::Unchecked) ? false : true)) @@ -186,17 +186,17 @@ void QtLangSet::slot_fontItalicChange(int state) } else if (ui.useGlobalFont->isVisible() && !ui.useGbFontItalic->isChecked()) { - //±£´æȫ¾ÖÑùʽµÚһÌõÑùʽ±¾Éí + //保存全局样式第一条样式本身 saveLangeSet(m_selectLexer); } else if (!ui.useGlobalFont->isVisible()) { - //ȫ¾ַǵÚһ¸öÑùʽ£¬Ð޸ĵ±ǰȫ¾Ö×ÖÌå´óС - //ȫ¾ÖÑùʽµķǵÚһ¸ö + //全局非第一个样式,修改当前全局字体大小 + //全局样式的非第一个 StyleSet::setGlobalFont(m_selectStyleId, m_curStyleData.font); saveLangeSet(m_selectLexer); - //ÕâÀï¾ÍÊÇȫ¾ֵÄÑùʽ¡£֪ͨµ±ǰËùÓеı༭¿ò£¬ȥÐ޸ÄËûÃDZ¾ÉíµÄȫ¾ÖÑùʽ + //这里就是全局的样式。通知当前所有的编辑框,去修改他们本身的全局样式 CCNotePad* pMainNote = dynamic_cast(parent()); if (pMainNote != nullptr) { @@ -214,7 +214,7 @@ void QtLangSet::slot_fontItalicChange(int state) void QtLangSet::slot_fontUnderlineChange(int state) { - //¼´ʱÉèÖ÷ç¸ñ + //即时设置风格 if (m_selectLexer != nullptr) { if (m_curStyleData.font.underline() != ((state == Qt::Unchecked) ? false : true)) @@ -231,17 +231,17 @@ void QtLangSet::slot_fontUnderlineChange(int state) } else if (ui.useGlobalFont->isVisible() && !ui.useGbFontUnderline->isChecked()) { - //±£´æȫ¾ÖÑùʽµÚһÌõÑùʽ±¾Éí + //保存全局样式第一条样式本身 saveLangeSet(m_selectLexer); } else if (!ui.useGlobalFont->isVisible()) { - //ȫ¾ַǵÚһ¸öÑùʽ£¬Ð޸ĵ±ǰȫ¾Ö×ÖÌå´óС - //ȫ¾ÖÑùʽµķǵÚһ¸ö + //全局非第一个样式,修改当前全局字体大小 + //全局样式的非第一个 StyleSet::setGlobalFont(m_selectStyleId, m_curStyleData.font); saveLangeSet(m_selectLexer); - //ÕâÀï¾ÍÊÇȫ¾ֵÄÑùʽ¡£֪ͨµ±ǰËùÓеı༭¿ò£¬ȥÐ޸ÄËûÃDZ¾ÉíµÄȫ¾ÖÑùʽ + //这里就是全局的样式。通知当前所有的编辑框,去修改他们本身的全局样式 CCNotePad* pMainNote = dynamic_cast(parent()); if (pMainNote != nullptr) { @@ -257,13 +257,13 @@ void QtLangSet::slot_fontUnderlineChange(int state) } } -//·¢ÏÖһ¸öqtÏÖÏó£ºÔÚdebug¶Ïס¸Ãslot_fontSizeChangeº¯Êý£¬»ᵼÖ²۴¥·¢2´Σ»²»¶Ïס»òÕßreleaseģʽֱ½ÓÅܣ¬²»»ᴥ·¢2´Î +//发现一个qt现象:在debug断住该slot_fontSizeChange函数,会导致槽触发2次;不断住或者release模式直接跑,不会触发2次 void QtLangSet::slot_fontSizeChange(int v) { - //¼´ʱÉèÖ÷ç¸ñ + //即时设置风格 if (m_selectLexer != nullptr) { - //ȫ¾ÖÐ޸쬰ÑËùÓÐÓïÑԵÄËùÓзç¸ñ¶¼ÉèÖà + //全局修改,把所有语言的所有风格都设置 if (m_isGlobelItem) { if (m_curStyleData.font.pointSize() != v) @@ -273,7 +273,7 @@ void QtLangSet::slot_fontSizeChange(int v) m_isStyleChange = true; m_selectLexer->setFont(m_curStyleData.font, m_selectStyleId); - //ȫ¾ֵÚһ¸öÑùʽ£¬Ð޸ÄËùÓÐÓ﷨Ñùʽ + //全局第一个样式,修改所有语法样式 if (ui.useGlobalFont->isVisible() && ui.useGbFontSize->isChecked()) { slot_useAlobalFontSize(true); @@ -281,17 +281,17 @@ void QtLangSet::slot_fontSizeChange(int v) } else if (ui.useGlobalFont->isVisible() && !ui.useGbFontSize->isChecked()) { - //±£´æȫ¾ÖÑùʽµÚһÌõÑùʽ±¾Éí + //保存全局样式第一条样式本身 saveLangeSet(m_selectLexer); } else if (!ui.useGlobalFont->isVisible()) { - //ȫ¾ַǵÚһ¸öÑùʽ£¬Ð޸ĵ±ǰȫ¾Ö×ÖÌå´óС - //ȫ¾ÖÑùʽµķǵÚһ¸ö + //全局非第一个样式,修改当前全局字体大小 + //全局样式的非第一个 StyleSet::setGlobalFont(m_selectStyleId, m_curStyleData.font); saveLangeSet(m_selectLexer); - //ÕâÀï¾ÍÊÇȫ¾ֵÄÑùʽ¡£֪ͨµ±ǰËùÓеı༭¿ò£¬ȥÐ޸ÄËûÃDZ¾ÉíµÄȫ¾ÖÑùʽ + //这里就是全局的样式。通知当前所有的编辑框,去修改他们本身的全局样式 CCNotePad* pMainNote = dynamic_cast(parent()); if (pMainNote != nullptr) { @@ -325,7 +325,7 @@ void QtLangSet::slot_fontSizeChange(int v) m_curStyleData.font.setPointSize(v); m_selectLexer->setFont(m_curStyleData.font, m_selectStyleId); m_isStyleChange = true; - //¼´ʱÉèÖ÷ç¸ñ + //即时设置风格 if (m_selectLexer != nullptr) { int row = ui.styleListWidget->count(); @@ -337,7 +337,7 @@ void QtLangSet::slot_fontSizeChange(int v) item = ui.styleListWidget->item(i); int styleId = item->data(Qt::UserRole).toInt(); - //ËùÓÐ×ÖÌå´óСÐ޸ÄΪһÖ + //所有字体大小修改为一致 QFont f = m_selectLexer->font(styleId); f.setPointSize(v); m_selectLexer->setFont(f, styleId); @@ -360,7 +360,7 @@ void QtLangSet::getCurUseLexerTags(QVector& tag) } } -//ʹÓÃȫ¾ÖÉèÖÃÉ趨ËùÓÐÓïÑԷç¸ñ +//使用全局设置设定所有语言风格 void QtLangSet::updateAllLangeStyleWithGlobal(GLOBAL_STYLE_SET flag) { QFont oldfont; @@ -369,11 +369,12 @@ void QtLangSet::updateAllLangeStyleWithGlobal(GLOBAL_STYLE_SET flag) for (int index = 0; index <= L_TXT; ++index) { - //GLOBAL±¾Éí²»±£´棬ÒòΪGLOBAL²»ÊÇÓ﷨Ñùʽ£¬¶øÊÇȫ¾ֵÄÊôÐԷç¸ñ - //Èç¹ûȫ¾ÖÐ޸ĵÄÊÇȫ¾Ö×ÖÌå»ò×ÖÌå´óС£¬ȫ¾ÖҲÐ޸ÄһÏ¡£±ÜÃâÀ¨»¡µȴóСºÍȫ¾Ö×ÖÌ岻һÑù´ó¡£ + //GLOBAL本身不保存,因为GLOBAL不是语法样式,而是全局的属性风格 + //如果全局修改的是全局字体或字体大小,全局也修改一下。避免括弧等大小和全局字体不一样大。 + //全局颜色前景和背景时,也要特殊对待,要单独修改全局default的修改;否则编辑界面看起来颜色杂乱 if (index == L_GLOBAL) { - if (flag != GLOBAL_FONT_SIZE && flag != GLOBAL_FONT) + if (flag != GLOBAL_FONT_SIZE && flag != GLOBAL_FONT && flag != GLOBAL_FG_COLOR && flag != GLOBAL_BK_COLOR) { continue; } @@ -387,7 +388,7 @@ void QtLangSet::updateAllLangeStyleWithGlobal(GLOBAL_STYLE_SET flag) { case GLOBAL_FONT: { - //·Çȫ¾ÖÐ޸ÄËùÓеÄÓ﷨¶ÔӦÑùʽ + //非全局修改所有的语法对应样式 if (index != L_GLOBAL) { for (int i = 0; i <= 255; ++i) @@ -402,7 +403,7 @@ void QtLangSet::updateAllLangeStyleWithGlobal(GLOBAL_STYLE_SET flag) } else { - //ÊÇȫ¾ÖÊôÐÔÐ޸Ä×ÖÌå + //是全局属性修改字体 QsciLexerGlobal* pGlobalLexer = dynamic_cast(pLexer); if (pGlobalLexer != nullptr) { @@ -420,7 +421,7 @@ void QtLangSet::updateAllLangeStyleWithGlobal(GLOBAL_STYLE_SET flag) break; case GLOBAL_FONT_SIZE: { - //·Çȫ¾ÖÐ޸ÄËùÓеÄÓ﷨¶ÔӦÑùʽ + //非全局修改所有的语法对应样式 if (index != L_GLOBAL) { for (int i = 0; i <= 255; ++i) @@ -435,7 +436,7 @@ void QtLangSet::updateAllLangeStyleWithGlobal(GLOBAL_STYLE_SET flag) } else { - //ÊÇȫ¾Ö + //是全局 QsciLexerGlobal* pGlobalLexer = dynamic_cast(pLexer); if (pGlobalLexer != nullptr) { @@ -492,14 +493,37 @@ void QtLangSet::updateAllLangeStyleWithGlobal(GLOBAL_STYLE_SET flag) break; case GLOBAL_FG_COLOR: { + //非全局修改所有的语法对应样式 + if (index != L_GLOBAL) + { pLexer->setColor(m_curStyleData.color, -1); + pLexer->setDefaultColor(m_curStyleData.color); + } + else + { + //全局时,只修改default的颜色 + pLexer->setColor(m_curStyleData.color, GLOBAL_STYLES::GLOBAL_OVERRIDE); + pLexer->setColor(m_curStyleData.color, GLOBAL_STYLES::DEFAULT_STYLE); + isGlobalChange = true; + } } break; case GLOBAL_BK_COLOR: { + //非全局修改所有的语法对应样式 + if (index != L_GLOBAL) + { pLexer->setPaper(m_curStyleData.paper, -1); - //ĬÈÏֽ±³¾°ɫ»áºÍQPalette±£³ÖһÖ¡£µ¥¶ÀÐèҪµ¥¶ÀÉèÖÃһÏ + //默认纸背景色会和QPalette保持一致。单独需要单独设置一下 pLexer->setDefaultPaper(m_curStyleData.paper); + } + else + { + //全局时,只修改default的颜色 + pLexer->setPaper(m_curStyleData.paper, GLOBAL_STYLES::GLOBAL_OVERRIDE); + pLexer->setPaper(m_curStyleData.paper, GLOBAL_STYLES::DEFAULT_STYLE); + isGlobalChange = true; + } } break; default: @@ -511,34 +535,39 @@ void QtLangSet::updateAllLangeStyleWithGlobal(GLOBAL_STYLE_SET flag) delete pLexer; } - //Èç¹ûȫ¾ֱ仯Áˣ¬°ѵ±ǰȫ¾ֽçÃæˢÐÂһÏ - //»¹ÓУ¬»¹ÐèҪ°ѵ±ǰ´ò¿ªÎĵµµÄȫ¾ַç¸ñÉèÖÃһÏ£¬·ñÔòȫ¾ֲ»ÉúЧ + //如果全局变化了,把当前全局界面刷新一下 + //还有,还需要把当前打开文档的全局风格设置一下,否则全局不生效 if (isGlobalChange) { + refreshGlobalSet(); + } +} + +void QtLangSet::refreshGlobalSet() +{ m_previousSysLangItem = nullptr; slot_langListCurRowChanged(0); StyleSet::reloadGolbalStyleFromSetFile(); - //ÕâÀï¾ÍÊÇȫ¾ֵÄÑùʽ¡£֪ͨµ±ǰËùÓеı༭¿ò£¬ȥÐ޸ÄËûÃDZ¾ÉíµÄȫ¾ÖÑùʽ + //这里就是全局的样式。通知当前所有的编辑框,去修改他们本身的全局样式 CCNotePad* pMainNote = dynamic_cast(parent()); if (pMainNote != nullptr) { - + for (int i = 0; i <= GLOBAL_STYLES::URL_HOVERRED; ++i) { pMainNote->setGlobalFont(i); } } } -} -//»ָ´ËùÓÐÓïÑԵijõʼÅäÖá£ÓërestoreOriginLangOneStyleÀàËƣ¬µ«ÊÇÁ£¶ȸü´ó +//恢复所有语言的初始配置。与restoreOriginLangOneStyle类似,但是粒度更大 void QtLangSet::restoreOriginLangAllStyle() { QsciLexer *pLexer = nullptr; - //һµ©ÖØÖ㬵±ǰÐ޸ÄÎÞÌõ¼þ²»±£´档·ñÔò±ÜÃ⵱ǰµĸոÕÖØÖã¬Óֱ»±£´æ + //一旦重置,当前修改无条件不保存。否则避免当前的刚刚重置,又被保存 m_isStyleChange = false; for (int index = 0; index <= L_TXT; ++index) @@ -550,7 +579,7 @@ void QtLangSet::restoreOriginLangAllStyle() continue; } - //Èç¹û´æÔÚ×Զ¨ÒåµÄÅäÖã¬ֱ½Óȫ²¿ɾ³ýµô + //如果存在自定义的配置,直接全部删除掉 QString cfgPath = QString("notepad/userstyle/%1/%2").arg(StyleSet::getCurrentStyle()).arg(pLexer->lexerTag()); QSettings qs(QSettings::IniFormat, QSettings::UserScope, cfgPath); @@ -562,7 +591,7 @@ void QtLangSet::restoreOriginLangAllStyle() delete pLexer; pLexer = nullptr; - //Èç¹ûÊÇȫ¾ֵ쬰ѵ±ǰÄڴæÖеÄȫ¾ַç¸ñҲ¸üÐÂһÏ + //如果是全局的,把当前内存中的全局风格也更新一下 if (index == L_GLOBAL) { StyleSet::loadGolbalStyle(); @@ -570,7 +599,7 @@ void QtLangSet::restoreOriginLangAllStyle() } } -//ֻÔÚrestoreOriginLangOneStyleÖе÷Óà +//只在restoreOriginLangOneStyle中调用 static void restoreLangFontFgColorToDarkStyle(QsciLexer *pLexer, int i) { //if (QtLangSet::s_darkColorMap.contains(pLexer->color(i).name())) @@ -579,11 +608,11 @@ static void restoreLangFontFgColorToDarkStyle(QsciLexer *pLexer, int i) //} } -//ֻÔÚrestoreOriginLangOneStyleÖе÷Óà +//只在restoreOriginLangOneStyle中调用 static void restoreLangPaperColorToDarkStyle(QsciLexer *pLexer, int i) { - //עÒâÏÂÃæÕâ¸öÑÕɫºÍvoid StyleSet::setBlackStyle()Öб£³ÖһÖ - //±³¾°Ҳ±ä³ɰµºÚɫ + //注意下面这个颜色和void StyleSet::setBlackStyle()中保持一致 + //背景也变成暗黑色 if (StyleSet::foldbgColor != pLexer->paper(i)) { pLexer->setPaper(StyleSet::foldbgColor, i); @@ -591,7 +620,7 @@ static void restoreLangPaperColorToDarkStyle(QsciLexer *pLexer, int i) } } -//»ָ´ËùÓÐÓïÑԵijõʼÅäÖÃ,ֻ»ָ´GLOBAL_STYLE_SETָ¶¨µķç¸ñ +//恢复所有语言的初始配置,只恢复GLOBAL_STYLE_SET指定的风格 void QtLangSet::restoreOriginLangOneStyle(GLOBAL_STYLE_SET flag) { @@ -655,7 +684,6 @@ void QtLangSet::restoreOriginLangOneStyle(GLOBAL_STYLE_SET flag) { oldClor = pOriginLexer->color(i); pLexer->setColor(oldClor, i); - } break; case GLOBAL_BK_COLOR: @@ -669,14 +697,33 @@ void QtLangSet::restoreOriginLangOneStyle(GLOBAL_STYLE_SET flag) } } } + + switch (flag) + { + case GLOBAL_FG_COLOR: + //把默认颜色修改一下 + oldClor = pOriginLexer->defaultColor(); + pLexer->setDefaultColor(oldClor); + break; + case GLOBAL_BK_COLOR: + //把默认颜色修改一下 + oldClor = pOriginLexer->defaultPaper(); + pLexer->setDefaultPaper(oldClor); + break; + + } saveLangeSet(pLexer); } delete pLexer; delete pOriginLexer; } + + //全局变化了,把当前全局界面刷新一下 + //还有,还需要把当前打开文档的全局风格设置一下,否则全局不生效 + refreshGlobalSet(); } -//ԤÀÀȫ¾ÖÐ޸Ä×ÖÌåЧ¹û¡£°ѵ±ǰËùÓеÄÓ﷨£¬·ç¸ñ×ÖÌ嶼Ð޸Äһ±é +//预览全局修改字体效果。把当前所有的语法,风格字体都修改一遍 void QtLangSet::previewAllGoblalChange() { QVector tags; @@ -688,10 +735,10 @@ void QtLangSet::previewAllGoblalChange() emit viewLexerChange(tags.at(i)); } - //ÕâÀﻹ²îһ²½ - //ÕâÀﻹÓÐÎÊÌ⣬»¹ÐèҪ°ѵ±ǰ´ò¿ªÎĵµµÄȫ¾ַç¸ñÉèÖÃһÏ£¬·ñÔòȫ¾ֲ»ÉúЧ + //这里还差一步 + //这里还有问题,还需要把当前打开文档的全局风格设置一下,否则全局不生效 - //ÕâÀï¾ÍÊÇȫ¾ֵÄÑùʽ¡£֪ͨµ±ǰËùÓеı༭¿ò£¬ȥÐ޸ÄËûÃDZ¾ÉíµÄȫ¾ÖÑùʽ + //这里就是全局的样式。通知当前所有的编辑框,去修改他们本身的全局样式 CCNotePad* pMainNote = dynamic_cast(parent()); if (pMainNote != nullptr) { @@ -704,10 +751,10 @@ void QtLangSet::previewAllGoblalChange() void QtLangSet::slot_fontChange(const QFont &font) { - //¼´ʱÉèÖ÷ç¸ñ + //即时设置风格 if (m_selectLexer != nullptr) { - //ȫ¾ÖÐ޸Ä + //全局修改 if (m_isGlobelItem) { if (m_curStyleData.font != font) @@ -716,7 +763,7 @@ void QtLangSet::slot_fontChange(const QFont &font) m_selectLexer->setFont(m_curStyleData.font, m_selectStyleId); m_isStyleChange = true; - //Ð޸ÄËùÓÐ×ÖÌå + //修改所有字体 if (ui.useGlobalFont->isVisible() && ui.useGbFont->isChecked()) { slot_useAlobalFont(true); @@ -724,18 +771,18 @@ void QtLangSet::slot_fontChange(const QFont &font) } else if (ui.useGlobalFont->isVisible() && !ui.useGbFont->isChecked()) { - //±£´æȫ¾ÖÑùʽµÚһÌõÑùʽ±¾Éí + //保存全局样式第一条样式本身 saveLangeSet(m_selectLexer); } else if(!ui.useGlobalFont->isVisible()) { - //ȫ¾ÖÑùʽµķǵÚһ¸ö + //全局样式的非第一个 StyleSet::setGlobalFont(m_selectStyleId, m_curStyleData.font); - //±£´æȫ¾ÖÑùʽµÚһÌõÑùʽ±¾Éí + //保存全局样式第一条样式本身 saveLangeSet(m_selectLexer); - //ÕâÀï¾ÍÊÇȫ¾ֵÄÑùʽ¡£֪ͨµ±ǰËùÓеı༭¿ò£¬ȥÐ޸ÄËûÃDZ¾ÉíµÄȫ¾ÖÑùʽ + //这里就是全局的样式。通知当前所有的编辑框,去修改他们本身的全局样式 CCNotePad* pMainNote = dynamic_cast(parent()); if (pMainNote != nullptr) { @@ -747,7 +794,7 @@ void QtLangSet::slot_fontChange(const QFont &font) else { #if 0 - //ͳһÐ޸Ä×ÖÌ壬´óСºͷç¸񱣴治±ä + //统一修改字体,大小和风格保存不变 QFont oldf = m_curStyleData.font; m_curStyleData.font = font; m_curStyleData.font.setBold(oldf.bold()); @@ -755,7 +802,7 @@ void QtLangSet::slot_fontChange(const QFont &font) m_curStyleData.font.setUnderline(oldf.underline()); m_isStyleChange = true; - //¼´ʱÉèÖ÷ç¸ñ + //即时设置风格 if (m_selectLexer != nullptr) { int row = ui.styleListWidget->count(); @@ -768,7 +815,7 @@ void QtLangSet::slot_fontChange(const QFont &font) int styleId = item->data(Qt::UserRole).toInt(); QFont f = m_selectLexer->font(styleId); - //ÐÂ×ÖÌåµÄÃûͳһÉèÖ㬵«ÊǷç¸ñ×ÖÌå´óС±£´æÀϵÄһÖ + //新字体的名统一设置,但是风格字体大小保存老的一致 QFont newFont = m_curStyleData.font; newFont.setBold(f.bold()); newFont.setItalic(f.italic()); @@ -811,20 +858,20 @@ void QtLangSet::initLangList() } } - //»³ÒÉÕâ¸öÊǶÓÁÐÁ´½ӵ쬻áÑӳÙִÐС£¹Ê×ÜÊǵ¼ÖÂѡÔñµÄѡ²»ÖУ¬¶øÊǵÚһ¸öÓïÑÔasp¡£ + //怀疑这个是队列链接的,会延迟执行。故总是导致选择的选不中,而是第一个语言asp。 ui.langListWidget->sortItems(Qt::AscendingOrder); - //Êֶ¯Ð޸ĵÚһ¸öÃû³ÆΪÖÐÎġ£ + //手动修改第一个名称为中文。 if (ui.langListWidget->item(0)->text() == QString("AllGlobal")) { ui.langListWidget->item(0)->setText(tr("AllGlobal")); } } -//isLoadToUIÊǷñ¼ÓÔØÏÔʾµ½µ±ǰUI½çÃæ +//isLoadToUI是否加载显示到当前UI界面 bool QtLangSet::readLangSetFile(QString langName,QString &keyword, QString &motherLang, QString & extTypes) { - QString userLangFile = QString("notepad/userlang/%1").arg(langName);//×Զ¨ÒåÓïÑÔÖв»ÄÜÓÐ.×ַû£¬·ñÔò¿ÉÄÜÓдí£¬ºóÐøҪ¼ì²é + QString userLangFile = QString("notepad/userlang/%1").arg(langName);//自定义语言中不能有.字符,否则可能有错,后续要检查 QSettings qs(QSettings::IniFormat, QSettings::UserScope, userLangFile); qs.setIniCodec("UTF-8"); //qDebug() << qs.fileName(); @@ -834,11 +881,11 @@ bool QtLangSet::readLangSetFile(QString langName,QString &keyword, QString &moth return false; } - //×Զ¨ÒåÓïÑԸñʽ¡£ + //自定义语言格式。 //mz:ndd //name:xxx - //mother:xxx none/cpp/html ¾ÍÈýÖÖ - //ext:xx xx xx Îļþ¹ØÁªºó׺Ãû + //mother:xxx none/cpp/html 就三种 + //ext:xx xx xx 文件关联后缀名 //keword:xxx keyword = qs.value("keyword").toString(); extTypes = qs.value("ext").toString(); @@ -847,20 +894,20 @@ bool QtLangSet::readLangSetFile(QString langName,QString &keyword, QString &moth return true; } -//³õʼ»¯Óû§×Զ¨ÒåµÄÓïÑÔÅäÖà +//初始化用户自定义的语言配置 void QtLangSet::initUserDefineLangList() { QString userLangDirPath = getUserLangDirPath(); - //±éÀúÎļþ¼Ð + //遍历文件夹 QDir dir_file(userLangDirPath); QFileInfoList list_file = dir_file.entryInfoList(QDir::Files | QDir::NoDotAndDotDot | QDir::NoSymLinks, QDir::Name); for (int i = 0; i < list_file.size(); ++i) - { //½«µ±ǰĿ¼ÖÐËùÓÐÎļþÌí¼ӵ½treewidgetÖÐ + { //将当前目录中所有文件添加到treewidget中 QFileInfo fileInfo = list_file.at(i); - //Õâ¸öÎļþÊÇextºÍtagµÄӳÉäÎļþ£¬²»×öÅäÖýâÎö + //这个文件是ext和tag的映射文件,不做配置解析 if (fileInfo.baseName() == "ext_tag") { continue; @@ -872,9 +919,9 @@ void QtLangSet::initUserDefineLangList() } -//Çл»µ±ǰÓïÑԡ£ -//QListWidget::currentItemChangedÕâ¸öÐźÅqt5.12.10ÖÐӦ¸ÃÊǴæÔÚbug,×ÜÊÇĪÃûÆäÃîµÄҪ·¢һ´ÎcurrentItemChangedÐźųöÀ´¡£µ¼ÖµÚһ´θÃѡµÄÏ¸²¸ǡ£ -//»»³ÉitemClickedÐźÅ +//切换当前语言。 +//QListWidget::currentItemChanged这个信号qt5.12.10中应该是存在bug,总是莫名其妙的要发一次currentItemChanged信号出来。导致第一次该选的项被覆盖。 +//换成itemClicked信号 void QtLangSet::slot_itemSelect(QListWidgetItem *item) { if (item == nullptr) @@ -883,7 +930,7 @@ void QtLangSet::slot_itemSelect(QListWidgetItem *item) } //qDebug() << item->text() << (previous ? previous->text() : 0); - //Èç¹ûǰºóÖ÷ÌⷢÉúÁ˱仯£¬ÔòÒÀ¾ÉҪ×߸üУ¬·ÀֹÖ÷ÌâÇл»ºóû¼°ʱ¸üР+ //如果前后主题发生了变化,则依旧要走更新,防止主题切换后没及时更新 if (m_previousSysLangItem == item && (m_lastThemesId == m_themesId)) { return; @@ -896,11 +943,11 @@ void QtLangSet::slot_itemSelect(QListWidgetItem *item) ui.userLangListWidget->setCurrentItem(nullptr); - //±£´æǰһ¸öÒѾ­Ð޸ĵġ£ѯÎÊÓû§ÊǷ񱣴æ + //保存前一个已经修改的。询问用户是否保存 if (m_isStyleChange && m_previousSysLangItem != nullptr && m_selectLexer !=nullptr) { - //ֻÓе±ǰÊǷÇȫ¾֣¬²ÅÐèҪÌáʾÓû§ÊǷñҪ±£³֡£ - //ȫ¾ֵIJ»ÐèҪÌáʾ£¬ÒòΪÒѾ­ÎÞÌõ¼þȫ²¿±£´æ¹ýÁˡ£ + //只有当前是非全局,才需要提示用户是否要保持。 + //全局的不需要提示,因为已经无条件全部保存过了。 if (!m_isGlobelItem) { if (QMessageBox::Yes == QMessageBox::question(this, tr("Save Change"), tr("%1 style configuration has been modified. Do you want to save it?").arg(m_previousSysLangItem->text()))) @@ -925,7 +972,7 @@ void QtLangSet::slot_itemSelect(QListWidgetItem *item) int lexId = item->data(Qt::UserRole).toInt(); - //ȫ¾ֵÄÕâ¸öҪµ¥¶À¶Դý£¬ÔÝʱûÓÐÈκηç¸ñ¡£ + //全局的这个要单独对待,暂时没有任何风格。 if (lexId == L_GLOBAL) { m_isGlobelItem = true; @@ -948,7 +995,7 @@ void QtLangSet::slot_itemSelect(QListWidgetItem *item) ui.keywordTe->setPlainText(keyword); ui.motherLangCb->setCurrentIndex(0); - //ÉèÖùØÁªÎļþÏî + //设置关联文件项 QString langName = item->text(); QStringList extList; ExtLexerManager::getInstance()->getExtlistByLangTag(langName, extList); @@ -968,7 +1015,7 @@ void QtLangSet::slot_itemSelect(QListWidgetItem *item) m_previousSysLangItem = item; - //×Զ¯ÏÔʾµÚһÌõµĽá¹û + //自动显示第一条的结果 QListWidgetItem *itemtemp = ui.styleListWidget->item(0); if (itemtemp != nullptr) { @@ -988,7 +1035,7 @@ void QtLangSet::slot_langListCurRowChanged(int row) slot_itemSelect(current); } -//¸ù¾ÝĸÇ×ģ¿éÓïÑԣ¬°ÑÊôÐԷç¸ñÏÔʾ³öÀ´ +//根据母亲模块语言,把属性风格显示出来 void QtLangSet::displayUserMotherLangsStyle(QString langTagName, UserLangMother motherLang) { QsciLexer *pLexer = nullptr; @@ -1010,7 +1057,7 @@ void QtLangSet::displayUserMotherLangsStyle(QString langTagName, UserLangMother if (nullptr != pLexer) { - //ÕâÀïһ¶¨ҪÒÔÐÂÓïÑԵÄÃû³Æ×÷ΪlexerµÄtag¡£ + //这里一定要以新语言的名称作为lexer的tag。 //pLexer->setLexerTag(langTagName); pLexer->setIsUserDefineKeywords(true); @@ -1033,7 +1080,7 @@ void QtLangSet::displayUserMotherLangsStyle(QString langTagName, UserLangMother } } - //×Զ¯ÏÔʾµÚһÌõµĽá¹û + //自动显示第一条的结果 QListWidgetItem *itemtemp = ui.styleListWidget->item(0); if (itemtemp != nullptr) { @@ -1046,7 +1093,7 @@ void QtLangSet::displayUserMotherLangsStyle(QString langTagName, UserLangMother } -//µã»÷µ±ǰÓû§×Զ¨ÒåÓïÑԵÄÓïÑÔitem¡£todo:ÔÝʱûÓÐ×öǰһ¸öµÄÐ޸ı£´棬ÐèҪÓû§ÿ´ÎÐ޸ĺó×Լºµã»÷save£¬·ñÔò¿ÉÄܲ»»ᱣ´æ +//点击当前用户自定义语言的语言item。todo:暂时没有做前一个的修改保存,需要用户每次修改后自己点击save,否则可能不会保存 void QtLangSet::slot_userLangItemSelect(QListWidgetItem *item) { if (item == nullptr) @@ -1054,7 +1101,7 @@ void QtLangSet::slot_userLangItemSelect(QListWidgetItem *item) return; } - //¿϶¨²»ÄÜÊÇȫ¾ÖÉèÖÃÁË + //肯定不能是全局设置了 if(m_isGlobelItem || (ui.stackedWidget->currentIndex() == 1)) { m_isGlobelItem = false; @@ -1086,7 +1133,7 @@ void QtLangSet::slot_userLangItemSelect(QListWidgetItem *item) ui.motherLangCb->setCurrentText(motherLang); ui.extFileType->setText(extTypes); - //¸ù¾ÝĸÇ×ģ¿éÓïÑԣ¬°ÑÊôÐԷç¸ñÏÔʾ³öÀ´ + //根据母亲模块语言,把属性风格显示出来 displayUserMotherLangsStyle(langName, (UserLangMother)(LangType::L_USER_TXT + ui.motherLangCb->currentIndex())); } else @@ -1096,7 +1143,7 @@ void QtLangSet::slot_userLangItemSelect(QListWidgetItem *item) } -//»ñȡµ±ǰuiÉϵÄ×ÖÌå +//获取当前ui上的字体 void QtLangSet::getCurUiFont(QFont& font) { font = ui.fontComboBox->currentFont(); @@ -1111,7 +1158,7 @@ void QtLangSet::closeEvent(QCloseEvent * e) saveCurLangSettings(); } -//°ÑitemµĶÔӦ·ç¸ñÏÔʾÔڽçÃæÉÏ +//把item的对应风格显示在界面上 void QtLangSet::syncShowStyleItemToUI(QListWidgetItem *item) { if (item != nullptr && m_selectLexer != nullptr) @@ -1154,9 +1201,11 @@ void QtLangSet::syncShowStyleItemToUI(QListWidgetItem *item) QsciLexer::StyleData & sd = m_selectLexer->styleData(styleId); m_curStyleData = sd; setStyleShow(sd.font, sd.color, sd.paper); - m_isStyleChange = false; - //Èç¹ûÊÇȫ¾֣¬Ôò°Ѳ»ÄÜÐ޸ĵÄȫ¾ÖÑùʽ»ҵô£¬±ÜÃâ¸ÉÈÅÓû§µÄѡÔñ + //这里不能直接设置为非修改,如果之前已经修改过,则还是要认定为修改。 + //m_isStyleChange = false; + + //如果是全局,则把不能修改的全局样式灰掉,避免干扰用户的选择 if (m_isGlobelItem) { QsciLexerGlobal* pGlobalLexer = dynamic_cast(m_selectLexer); @@ -1191,10 +1240,10 @@ void QtLangSet::syncShowStyleItemToUI(QListWidgetItem *item) } } } -//µã»÷µ±ǰµķç¸ñitem +//点击当前的风格item void QtLangSet::slot_styleItemSelect(QListWidgetItem *current) { - qDebug() << "slot_styleItemSelect"; + //qDebug() << "slot_styleItemSelect"; syncShowStyleItemToUI(current); @@ -1217,10 +1266,10 @@ void QtLangSet::slot_styleItemSelect(QListWidgetItem *current) } -//ʹÓüüÅÌÉÏÏÂÇл» +//使用键盘上下切换 void QtLangSet::slot_styleListCurRowChanged(int row) { - qDebug() << "slot_curRowChanged"; + //qDebug() << "slot_curRowChanged"; QListWidgetItem* current = ui.styleListWidget->item(row); slot_styleItemSelect(current); } @@ -1242,7 +1291,7 @@ void QtLangSet::fillBackgroundColor(QColor &bkColor) void QtLangSet::setStyleShow(QFont& font, QColor& fcColor, QColor &bkColor) { - //Ð޸Ä×ÖÌå»ᴥ·¢²ۺ¯ÊýִÐУ¬Îñ±ØÏȹرÕһÏÂÐźÅ + //修改字体会触发槽函数执行,务必先关闭一下信号 enableFontChangeSensitive(false); ui.fontComboBox->setCurrentFont(font); @@ -1259,7 +1308,7 @@ void QtLangSet::setStyleShow(QFont& font, QColor& fcColor, QColor &bkColor) } -//¶ÁȡÌض¨ÓïÑԵÄÉèÖã»StyleId-1Ôò¶Áȡµ±ǰÖ÷Ì⣬·ñÔòָ¶¨µÄStyleIdÖ÷Ìâ +//读取特定语言的设置;StyleId-1则读取当前主题,否则指定的StyleId主题 bool QtLangSet::readLangSettings(QsciLexer *lexer, QString tag, int StyleId) { QString cfgPath = QString("notepad/userstyle/%1/%2").arg((StyleId == -1) ? StyleSet::getCurrentStyle() : StyleSet::getStyleName(StyleId)).arg(tag); @@ -1269,7 +1318,7 @@ bool QtLangSet::readLangSettings(QsciLexer *lexer, QString tag, int StyleId) { return lexer->readSettings(qs); } - else//ÕâÀïӦ¸üӸöÂ߼­Í걸µı£»¤¡£Èç¹ûûÓжÁȡµ½Óû§ÅäÖã¬ÔòӦ¸ôӱê׼Ŀ±êȥ¶ÁԭʼÅäÖà + else//这里应该加个逻辑完备的保护。如果没有读取到用户配置,则应该从标准目标去读原始配置 { return readLangOriginSettings(lexer, tag, StyleId, true); } @@ -1277,17 +1326,17 @@ bool QtLangSet::readLangSettings(QsciLexer *lexer, QString tag, int StyleId) return false; } -//¶ÁȡÌض¨ÓïÑԵÄԭʼÑùʽÉèÖã»StyleId-1Ôò¶Áȡµ±ǰÖ÷Ì⣬·ñÔòָ¶¨µÄStyleIdÖ÷Ìâ -//force:ÎÞÌõ¼þ¶Áȡ +//读取特定语言的原始样式设置;StyleId-1则读取当前主题,否则指定的StyleId主题 +//force:无条件读取 bool QtLangSet::readLangOriginSettings(QsciLexer* lexer, QString tag, int StyleId, bool force) { - //ĬÈÏÖ÷ÌⲻÐèҪ¶Áȡ£¬ÄڴæÖÐÒѾ­´æÔÚ + //默认主题不需要读取,内存中已经存在 if (StyleId == 0 && !force) { return true; } - //ĬÈÏƤ·ô·¾¶·ÅÔÚÈí¼þµÄͬ¼¶Ŀ¼ÏÂÃæµÄthemesĿ¼ + //默认皮肤路径放在软件的同级目录下面的themes目录 QString cfgPath = QString("%1/themes/%2/%3.ini").arg(QCoreApplication::applicationDirPath()).arg((StyleId == -1)?StyleSet::getCurrentStyle(): StyleSet::getStyleName(StyleId)).arg(tag); QSettings qs(cfgPath, QSettings::IniFormat); if (QFile::exists(qs.fileName())) @@ -1298,7 +1347,7 @@ bool QtLangSet::readLangOriginSettings(QsciLexer* lexer, QString tag, int StyleI } -//±£´æһÖÖÓïÑԵÄÅäÖᣠ+//保存一种语言的配置。 void QtLangSet::saveLangeSet(QsciLexer *lexer, int StyleId) { if (lexer != nullptr) @@ -1313,7 +1362,7 @@ void QtLangSet::saveLangeSet(QsciLexer *lexer, int StyleId) } } -//±£´浱ǰѡ¶¨ÓïÑԵÄÅäÖà +//保存当前选定语言的配置 bool QtLangSet::saveCurLangSettings() { if (m_isStyleChange && m_selectLexer != nullptr) @@ -1337,13 +1386,13 @@ bool QtLangSet::isUseGlobalBgColor() return ui.useGlobalColor->isVisible() && ui.useGbBc->isChecked(); } -//Ð޸Äǰ¾°ɫ +//修改前景色 void QtLangSet::slot_changeFgColor() { QColor color = QColorDialog::getColor(m_curStyleData.color, this, tr("Style Foreground Color")); if (color.isValid()) { - //ȫ¾ÖÐ޸Ä + //全局修改 if (m_isGlobelItem) { if (m_curStyleData.color != color) @@ -1352,24 +1401,24 @@ void QtLangSet::slot_changeFgColor() fillForegroundColor(color); m_isStyleChange = true; - //¼´ʱÉèÖ÷ç¸ñ + //即时设置风格 if (m_selectLexer != nullptr) { - //´Ëʱһ¶¨ÊÇQsciLexerGlobal + //此时一定是QsciLexerGlobal m_selectLexer->setColor(color, m_selectStyleId); } - //ֻÓÐÔڵÚһ¸öȫ¾ÖÑùʽʱ£¬isUseGlobalFgColorÏÂÃæ²ÅΪtrue¡£°ÑËùÓÐÓïÑԵÄËùÓзç¸ñ¶¼ÉèÖà + //只有在第一个全局样式时,isUseGlobalFgColor下面才为true。把所有语言的所有风格都设置 if (isUseGlobalFgColor()) { slot_useAlobalFgColor(true); } else if(!ui.useGlobalColor->isVisible()) { - //ȫ¾ÖÑùʽµķǵÚһ¸ö + //全局样式的非第一个 StyleSet::setGlobalFgColor(m_selectStyleId, color); - //ÕâÀï¾ÍÊÇȫ¾ֵÄÑùʽ¡£֪ͨµ±ǰËùÓеı༭¿ò£¬ȥÐ޸ÄËûÃDZ¾ÉíµÄȫ¾ÖÑùʽ + //这里就是全局的样式。通知当前所有的编辑框,去修改他们本身的全局样式 CCNotePad* pMainNote = dynamic_cast(parent()); if (pMainNote != nullptr) { @@ -1383,14 +1432,14 @@ void QtLangSet::slot_changeFgColor() } else { - //µ±ǰǰ¾°ɫÊǷñ±仯 + //当前前景色是否变化 if (m_curStyleData.color != color) { m_curStyleData.color = color; fillForegroundColor(color); m_isStyleChange = true; - //¼´ʱÉèÖ÷ç¸ñ + //即时设置风格 if (m_selectLexer != nullptr) { m_selectLexer->setColor(color, m_selectStyleId); @@ -1401,14 +1450,14 @@ void QtLangSet::slot_changeFgColor() } /*else if (!ui.modiryAllColor->isChecked()) { - µ±ǰǰ¾°ɫÊǷñ±仯 + 当前前景色是否变化 if (m_curStyleData.color != color) { m_curStyleData.color = color; fillForegroundColor(color); m_isStyleChange = true; - ¼´ʱÉèÖ÷ç¸ñ + 即时设置风格 if (m_selectLexer != nullptr) { m_selectLexer->setColor(color, m_selectStyleId); @@ -1419,13 +1468,13 @@ void QtLangSet::slot_changeFgColor() }*/ /*else { - ȫ²¿·ç¸ñÑÕɫÐ޸Ä - µ±ǰǰ¾°ɫÊǷñ±仯 + 全部风格颜色修改 + 当前前景色是否变化 m_curStyleData.color = color; fillForegroundColor(color); m_isStyleChange = true; - ¼´ʱÉèÖ÷ç¸ñ + 即时设置风格 if (m_selectLexer != nullptr) { m_selectLexer->setColor(color, -1); @@ -1438,13 +1487,13 @@ void QtLangSet::slot_changeFgColor() } -//Ð޸ı³¾°ɫ +//修改背景色 void QtLangSet::slot_changeBkColor() { QColor color = QColorDialog::getColor(m_curStyleData.paper, this, tr("Style Background Color")); if (color.isValid()) { - //ȫ¾ÖÐ޸쬰ÑËùÓÐÓïÑԵÄËùÓзç¸ñ¶¼ÉèÖà + //全局修改,把所有语言的所有风格都设置 if (m_isGlobelItem) { if (m_curStyleData.paper != color) @@ -1453,7 +1502,7 @@ void QtLangSet::slot_changeBkColor() fillBackgroundColor(color); m_isStyleChange = true; - //¼´ʱÉèÖ÷ç¸ñ + //即时设置风格 if (m_selectLexer != nullptr) { m_selectLexer->setPaper(color, m_selectStyleId); @@ -1467,7 +1516,7 @@ void QtLangSet::slot_changeBkColor() { StyleSet::setGlobalBgColor(m_selectStyleId, color); - //ÕâÀï¾ÍÊÇȫ¾ֵÄÑùʽ¡£֪ͨµ±ǰËùÓеı༭¿ò£¬ȥÐ޸ÄËûÃDZ¾ÉíµÄȫ¾ÖÑùʽ + //这里就是全局的样式。通知当前所有的编辑框,去修改他们本身的全局样式 CCNotePad* pMainNote = dynamic_cast(parent()); if (pMainNote != nullptr) { @@ -1478,16 +1527,34 @@ void QtLangSet::slot_changeBkColor() } } + else + { + //当前背景色是否变化 + if (m_curStyleData.paper != color) + { + m_curStyleData.paper = color; + fillBackgroundColor(color); + m_isStyleChange = true; + + //即时设置风格 + if (m_selectLexer != nullptr) + { + m_selectLexer->setPaper(color, m_selectStyleId); + + emit viewStyleChange(m_selectLexer->lexerTag(), m_selectStyleId, m_curStyleData.color, m_curStyleData.paper, m_curStyleData.font, false); + } + } + } // else if (!ui.modiryAllColor->isChecked()) // { - // //µ±ǰǰ¾°ɫÊǷñ±仯 + // //当前前景色是否变化 // if (m_curStyleData.paper != color) // { // m_curStyleData.paper = color; // fillBackgroundColor(color); // m_isStyleChange = true; - // //¼´ʱÉèÖ÷ç¸ñ + // //即时设置风格 // if (m_selectLexer != nullptr) // { // m_selectLexer->setPaper(color, m_selectStyleId); @@ -1495,33 +1562,16 @@ void QtLangSet::slot_changeBkColor() // } // } //} - else - { - //ȫ²¿·ç¸ñÑÕɫÐ޸Ä - //µ±ǰǰ¾°ɫÊǷñ±仯 - m_curStyleData.paper = color; - fillBackgroundColor(color); - m_isStyleChange = true; - - //¼´ʱÉèÖ÷ç¸ñ - if (m_selectLexer != nullptr) - { - m_selectLexer->setPaper(color, -1); - saveCurLangSettings(); - emit viewLexerChange(m_selectLexer->lexerTag()); } - } - } -} void QtLangSet::slot_saveClick() { saveCurLangSettings(); } -//»ָ´³õʼ»¯ÉèÖà +//恢复初始化设置 void QtLangSet::slot_reset() { if (m_selectLexer != nullptr) @@ -1533,10 +1583,10 @@ void QtLangSet::slot_reset() return; } - //һµ©ÖØÖ㬵±ǰÐ޸ÄÎÞÌõ¼þ²»±£´档·ñÔò±ÜÃ⵱ǰµĸոÕÖØÖã¬Óֱ»±£´æ + //一旦重置,当前修改无条件不保存。否则避免当前的刚刚重置,又被保存 m_isStyleChange = false; - //Èç¹û´æÔÚ×Զ¨ÒåµÄÅäÖã¬Ҳɾ³ýµô + //如果存在自定义的配置,也删除掉 QString cfgPath = QString("notepad/userstyle/%1/%2").arg(StyleSet::getCurrentStyle()).arg(m_selectLexer->lexerTag()); QSettings qs(QSettings::IniFormat, QSettings::UserScope, cfgPath); @@ -1545,15 +1595,15 @@ void QtLangSet::slot_reset() QFile::remove(qs.fileName()); } - //һ¶¨ҪÏȱ£´棬ÒòΪselectInitLangTagºó¿ÉÄܻá±仯 + //一定要先保存,因为selectInitLangTag后可能会变化 int row = ui.styleListWidget->currentRow(); - //ǿÐÐÈÃslot_itemSelectÀïÃæµĽøÐÐÇл» + //强行让slot_itemSelect里面的进行切换 m_previousSysLangItem = nullptr; selectInitLangTag(m_selectLexer->lexerTag()); - //Êֶ¯ˢÐÂUI + //手动刷新UI QListWidgetItem* styleItem = ui.styleListWidget->item(row); m_selectStyleId = -1; @@ -1566,7 +1616,7 @@ void QtLangSet::slot_reset() { if (ui.useGlobalFont->isVisible()) { - //Èç¹ûÊÇȫ¾ÖÖØÖã¬Ôò°ÑËùÓÐÓïÑԶ¼ÖØÖà + //如果是全局重置,则把所有语言都重置 if (QMessageBox::Yes != QMessageBox::question(this, tr("Reset All Style"), tr("Are you sure to reset All language sytle"))) { return; @@ -1575,7 +1625,7 @@ void QtLangSet::slot_reset() previewAllGoblalChange(); - //Êֶ¯ˢÐÂUI¡£ȫ¾ÖĿǰֻÓÐһÐÐȫ¾ÖÉèÖà + //手动刷新UI。全局目前只有一行全局设置 if (m_selectLexer != nullptr) { @@ -1592,11 +1642,11 @@ void QtLangSet::slot_reset() } else { - //ÖØÖÃËùÓÐȫ¾ÖÑùʽ - //һµ©ÖØÖ㬵±ǰÐ޸ÄÎÞÌõ¼þ²»±£´档·ñÔò±ÜÃ⵱ǰµĸոÕÖØÖã¬Óֱ»±£´æ + //重置所有全局样式 + //一旦重置,当前修改无条件不保存。否则避免当前的刚刚重置,又被保存 m_isStyleChange = false; - //Èç¹û´æÔÚ×Զ¨ÒåµÄÅäÖã¬Ҳɾ³ýµô + //如果存在自定义的配置,也删除掉 QString cfgPath = QString("notepad/userstyle/%1/%2").arg(StyleSet::getCurrentStyle()).arg(m_selectLexer->lexerTag()); QSettings qs(QSettings::IniFormat, QSettings::UserScope, cfgPath); @@ -1605,24 +1655,24 @@ void QtLangSet::slot_reset() QFile::remove(qs.fileName()); } - //һ¶¨ҪÏȱ£´棬ÒòΪselectInitLangTagºó¿ÉÄܻá±仯 + //一定要先保存,因为selectInitLangTag后可能会变化 int row = ui.styleListWidget->currentRow(); - //ǿÐÐÈÃslot_itemSelectÀïÃæµĽøÐÐÇл» + //强行让slot_itemSelect里面的进行切换 m_previousSysLangItem = nullptr; - //ÕâÀï±ØÐëдALLglobal£¬·ñÔòÖÐÎIJéÕҲ»µ½ + //这里必须写ALLglobal,否则中文查找不到 selectInitLangTag(tr("AllGlobal")); - //Êֶ¯ˢÐÂUI + //手动刷新UI QListWidgetItem* styleItem = ui.styleListWidget->item(row); m_selectStyleId = -1; syncShowStyleItemToUI(styleItem); - //ÖØÐ´ӼÓÔØһ´δ¿¾»µÄȫ¾ÖÑùʽ¡£ÒòΪǰÃ汣´æµÄÒѾ­ɾÁˣ¬ËùÒԼÓÔصÄÊǴ¿¾»µġ£ + //重新从加载一次纯净的全局样式。因为前面保存的已经删了,所以加载的是纯净的。 StyleSet::loadGolbalStyle(); updateThemes(); @@ -1733,8 +1783,8 @@ void QtLangSet::slot_useAlobalFontItalic(bool check) -//°ÑĬÈÏÓïÑԷç¸ñµIJ¿·ÖÑÕɫ£¬Ì滻Ϊ°µɫÏÂÏÔÑ۵ÄÑÕɫ -//Õâ¸öº¯ÊýÊǿÉÒԴ¦Àí×Զ¨ÒåÓïÑԵġ£ +//把默认语言风格的部分颜色,替换为暗色下显眼的颜色 +//这个函数是可以处理自定义语言的。 //void QtLangSet::setLangFontFgColorToDarkStyle(LangType langId, QString tag) //{ // QColor blackColor(Qt::black); @@ -1744,7 +1794,7 @@ void QtLangSet::slot_useAlobalFontItalic(bool check) // QColor lightColor1(0xffaa00); // // -// //C++עÊ͵ÄĬÈÏÑÕɫ£¬²»ÏÔÑÛ +// //C++注释的默认颜色,不显眼 // QColor blackColor2(0x007f00); // QColor lightColor2(0x009000); // @@ -1755,7 +1805,7 @@ void QtLangSet::slot_useAlobalFontItalic(bool check) // QColor blackColor4(0x8000ff); // QColor lightColor4(0xffaa00); // -// עÒâÏÂÃæÕâ¸öÑÕɫºÍvoid StyleSet::setBlackStyle()Öб£³ÖһÖ +// 注意下面这个颜色和void StyleSet::setBlackStyle()中保持一致 // QColor bkPaperColor(0, 0, 0); // // QsciLexer *pLexer = ScintillaEditView::createLexer(langId, tag); @@ -1791,24 +1841,24 @@ void QtLangSet::slot_useAlobalFontItalic(bool check) // pLexer->setColor(QtLangSet::s_darkColorMap.value(pLexer->color(i).name()), i); // } // -// ±³¾°Ҳ±ä³ɰµºÚɫ +// 背景也变成暗黑色 // if (StyleSet::foldbgColor != pLexer->paper(i)) // { // pLexer->setPaper(StyleSet::foldbgColor, i); // } // } // } -// ĬÈÏֽ±³¾°ɫ»áºÍQPalette±£³ÖһÖ¡£µ«ÊÇÒòΪºÚɫÌØɫ£¬Æ䱳¾°ºÍQPalette²»һÑù£¬ËùÓÐÐèҪµ¥¶ÀÉèÖÃһÏ +// 默认纸背景色会和QPalette保持一致。但是因为黑色特色,其背景和QPalette不一样,所有需要单独设置一下 // pLexer->setDefaultPaper(StyleSet::foldbgColor); // saveLangeSet(pLexer); // delete pLexer; // } // } -//°ѰµɫϵÏÂÃ治ÈÝÒ׿´ÇåµÄÑÕɫ¸øÌ滻һÏ¡£ĬÈÏÊÇÓзç¸ñµģ¬µ«ÊÇĬÈϷç¸ñÊÇÁÁɫϵµġ£ -//°ѷ²ÊÇ0x000000µÄ×ÖÌ壬±ä³É0xdedede -//·²ÊÇ0x0000ffµÄÑÕɫ£¬±ä³É0xffff00 -//Õâ¸öº¯ÊýûÓд¦Àí×Զ¨ÒåÓïÑԡ£ +//把暗色系下面不容易看清的颜色给替换一下。默认是有风格的,但是默认风格是亮色系的。 +//把凡是0x000000的字体,变成0xdedede +//凡是0x0000ff的颜色,变成0xffff00 +//这个函数没有处理自定义语言。 //void QtLangSet::setAllLangFontFgColorToDarkStyle() //{ // initDarkColorMap(); @@ -1820,14 +1870,14 @@ void QtLangSet::slot_useAlobalFontItalic(bool check) //} -//´ÓĬÈÏÖ÷Ìâģ°崴½¨һ·ÝÓû§µÄÓïÑԷç¸ñÎļþ +//从默认主题模板创建一份用户的语言风格文件 void QtLangSet::createOneLangStyleFromThemes(int styleId, LangType langId, QString tag) { if (langId == L_GLOBAL) { qDebug("global call"); } - //ָ¶¨´Óԭʼģ°åµÄÖ÷ÌâÖжÁȡһ·ÝÊý¾Ý + //指定从原始模板的主题中读取一份数据 QsciLexer* pLexer = ScintillaEditView::createLexer(langId, tag, true, styleId); if (nullptr != pLexer) { @@ -1836,7 +1886,7 @@ void QtLangSet::createOneLangStyleFromThemes(int styleId, LangType langId, QStri } } -//´ÓԭʼÖ÷Ìâģ°åÖУ¬´´½¨һ·ÝÓû§Ö÷ÌâÎļþ +//从原始主题模板中,创建一份用户主题文件 void QtLangSet::createUserStyleFormThemes(int styleId) { for (int index = 0; index <= L_TXT; ++index) @@ -1845,7 +1895,7 @@ void QtLangSet::createUserStyleFormThemes(int styleId) } } -//¼ì²鵱ǰÊǷñÒѾ­´æÔڰµºÚɫÓïÑÔÅäÖà +//检查当前是否已经存在暗黑色语言配置 //bool QtLangSet::isExistDarkLangSetings() //{ // QString cfgPath = QString("notepad/userstyle/black/AllGlobal"); @@ -1853,7 +1903,7 @@ void QtLangSet::createUserStyleFormThemes(int styleId) // return QFile::exists(qs.fileName()); //} -//¼ì²鵱ǰÊǷñÒѾ­´æÔÚÖ÷ÌâÅäÖà +//检查当前是否已经存在主题配置 bool QtLangSet::isExistThemesSetings(int styleId) { QString cfgPath = QString("notepad/userstyle/%1/AllGlobal").arg(StyleSet::getStyleName(styleId)); @@ -1861,10 +1911,10 @@ bool QtLangSet::isExistThemesSetings(int styleId) return QFile::exists(qs.fileName()); } -//µ±ǰÖ÷ÌⷢÉú±仯 +//当前主题发生变化 void QtLangSet::on_themesChange(int styleIndex) { - //µÚһ´ÎÆô¶¯ʱ£¬·Àֹ³õʼÇé¿öûÓгõʼ»¯Ö÷Ì⣬¹ʼì²âһÏÂisExistThemesSetings + //第一次启动时,防止初始情况没有初始化主题,故检测一下isExistThemesSetings if (m_themesId == styleIndex && isExistThemesSetings(styleIndex)) { return; @@ -1873,12 +1923,12 @@ void QtLangSet::on_themesChange(int styleIndex) m_themesId = styleIndex; - //Õâ¸öÓиöñîºϣºÏÈҪÉèÖÃQsciLexerµĵ±ǰÖ÷Ì⡣ֻÓÐĬÈÏÖ÷Ìâ²ÅÓÐÏêϸ¶ÀÁ¢µķç¸ñ¡£ - //·ÇĬÈÏÖ÷Ì⣬Æä³õʼ·ç¸ñȫÊÇĬÈÏÑùʽ¡£ + //这个有个耦合:先要设置QsciLexer的当前主题。只有默认主题才有详细独立的风格。 + //非默认主题,其初始风格全是默认样式。 QsciLexer::setCurThemes(m_themesId); - //Èç¹û²»´æÔÚÖ÷ÌâÉèÖã¬Ôò´Óģ°åÀïÃ濽±´һ·ݳöÀ´ + //如果不存在主题设置,则从模板里面拷贝一份出来 if (!isExistThemesSetings(styleIndex)) { createUserStyleFormThemes(styleIndex); @@ -1888,15 +1938,15 @@ void QtLangSet::on_themesChange(int styleIndex) NddSetting::updataKeyValueFromNumSets(SKIN_KEY, m_themesId); - //ÕâÀï¾ÍҪ¼°ʱÇл»µ±ǰÖ÷Ì⣬ԤÀÀÑÕɫ + //这里就要及时切换当前主题,预览颜色 updateThemes(); - //ÏÂһ²½¾ÍÊÇҪ¸üºõ±ǰ±༭Æ÷µÄÓ﷨ÉèÖà + //下一步就是要更好当前编辑器的语法设置 previewAllGoblalChange(); int row = ui.langListWidget->currentRow(); - //Êֶ¯ˢÐÂUI + //手动刷新UI QListWidgetItem* styleItem = ui.langListWidget->item(row); slot_itemSelect(styleItem); @@ -1906,7 +1956,7 @@ void QtLangSet::on_themesChange(int styleIndex) ui.statusBar->showMessage(tr("themes changed finished ..."), 5000); } -//¸üе±ǰ±༭¿òÖÐÖ÷ÌâµÄÑùʽ +//更新当前编辑框中主题的样式 void QtLangSet::updateThemes() { CCNotePad* pMainNote = dynamic_cast(parent()); @@ -1916,7 +1966,7 @@ void QtLangSet::updateThemes() } } -//Ôö¼Óһ¸ö¿ì½ÝÏÔʾȫ¾ֵİ´ť£¬±ÜÃâÓû§¾­³£ÕҲ»µ½ +//增加一个快捷显示全局的按钮,避免用户经常找不到 void QtLangSet::on_showGlobalItem() { if (ui.langListWidget->currentRow() != 0) diff --git a/src/qtlangset.h b/src/qtlangset.h index 614733a..b3feaa2 100755 --- a/src/qtlangset.h +++ b/src/qtlangset.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include @@ -110,12 +110,9 @@ private: bool isUseGlobalFgColor(); bool isUseGlobalBgColor(); - //void setGlobalFgColor(int style, QColor color); - //void setGlobalBgColor(int style, QColor color); - //void setGlobalFont(int style, QFont font); - bool isExistThemesSetings(int styleId); void createUserStyleFormThemes(int styleId); + void refreshGlobalSet(); private: Ui::QtLangSetClass ui; diff --git a/src/rcglobal.h b/src/rcglobal.h index 50a4d4c..f657a26 100755 --- a/src/rcglobal.h +++ b/src/rcglobal.h @@ -8,10 +8,10 @@ //#define TEST_PRE #ifdef TEST_PRE -static const char* VersionStr = u8"(内部测试非稳定) v1.22.1"; +static const char* VersionStr = u8"(内部测试非稳定) v2.0.0"; #else -static const char* VersionStr = "v1.22.2"; +static const char* VersionStr = "v1.23.2"; #endif // TEST_PRE diff --git a/src/realcompare_zh.qm b/src/realcompare_zh.qm index 472ce1b..fc26ea9 100755 Binary files a/src/realcompare_zh.qm and b/src/realcompare_zh.qm differ diff --git a/src/realcompare_zh.ts b/src/realcompare_zh.ts index ee6f9d2..64fdab4 100755 --- a/src/realcompare_zh.ts +++ b/src/realcompare_zh.ts @@ -3,10 +3,6 @@ AboutNddClass - - AboutNdd - 关于Ndd - <html><head/><body><p><a href="https://gitee.com/cxasm/notepad--"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">Click to get the latest version of notepad-- or source code</span></a></p></body></html> <html><head/><body><p><a href="https://gitee.com/cxasm/notepad--"><span style=" font-size:10pt; text-decoration: underline; color:#0000ff;">点击获取最新版的 notepad-- 或开源代码</span></a></p></body></html> @@ -94,16 +90,12 @@ BatchFindReplace - + $1 has no find match work item %1 没有对应的查找匹配项! - Max find key word 10000 ! - 最多支持10000条关键字! - - - + Please input find keyword ! 请输入批量查找的关键字! @@ -112,43 +104,44 @@ 批量查找完成! - + Max find key word 20000 ! 最多支持10000条关键字! {20000 ?} - - - total %1 keyword, please wait ... - + + + + Please fresh first ! + 查找替换表为空,请先刷新! - + Batch Find Finished! total %1 found. - + 批量查找完成!一共发现 %1 处。 - + Batch Replace Finished, total Replace %1 times ! 批量替换完成,一共替换 %1 处! - + Save File As ... 另存为文件 ... - + Export File finished ! 导出配置文件成功 ! - + No Content to Export ! 没有内容以供导出! - + Batch Mark Finished, total Mark %1 times ! 批量标记完成,一共标记 %1 处! @@ -331,7 +324,7 @@ - + Format Conversion 换行符转换 @@ -345,7 +338,7 @@ - + Display symbols 显示符号 @@ -355,151 +348,143 @@ - + Language 语言 - + P - + Recene File 最近文件 - - - + + + C - + J - - - - - + + + + + R - + H - + M - + B - + I - + N - + A - + S - + V - + L - + T - + F - - - - - + + + + + D - + O - + E - + G - - Set - 设置 - - - Style - 皮肤风格 - - + About 关于 @@ -509,387 +494,379 @@ - + Recently 最近对比 - Dir ... - 目录... - - - File ... - 文件... - - - - + + New 新建 - - + + Open ... 打开 - - + + Ctrl+O - - + + Save 保存 - - + + Ctrl+S - - + + Save As ... 另存为 - - + + Ctrl+Alt+S - - - - + + + + Close 关闭 - - + + Ctrl+W - - + + Exit 退出 - - + + Ctrl+Q - - - + + + Close All 关闭所有 - - + + Ctrl+Shift+W - - - + + + Undo 撤销 - - + + Ctrl+Z - - - + + + Redo 重做 - - + + Ctrl+Y - - - + + + Cut 剪切 - - + + Ctrl+X - - - + + + Copy 拷贝 - - + + Ctrl+C - - - + + + Paste 粘贴 - - + + Ctrl+V - - + + Select All 全选 - - + + Ctrl+A - - + + Windows(CR+LF) - - + + Unix(LF) - - + + Mac(CR) - - - + + + Find 查找 - - + + Ctrl+F - - - + + + Replace 替换 - - + + Go line 跳转 - - + + Ctrl+G - - + + Show spaces/tabs 显示空格 - - + + Show end of line 显示行尾 - - + + Show all 显示所有 - - - - Encode in GBK - 编码 GBK - - - Encode in UTF8 - 编码 UTF8 + + Encode in GBK + 使用编码 ANSI/GBK 打开 - - Encode in UTF8-BOM - 编码 UTF8-BOM + + Encode in UTF8 + 使用编码 UTF8 打开 - - Encode in UCS-2 BE BOM - 编码 UCS-2 BE BOM + + Encode in UTF8-BOM + 使用编码 UTF8-BOM 打开 - + + Encode in UCS-2 BE BOM + 使用编码 UCS-2 BE BOM 打开 + + + + Encode in UCS-2 LE BOM - 编码 UCS-2 LE BOM + 使用编码 UCS-2 LE BOM 打开 - - + + Convert to GBK - 转换为 GBK 编码 + 转换为 ANSI/GBK 编码 - - + + Convert to UTF8 转换为 UTF8 编码 - - + + Convert to UTF8-BOM 转换为 UTF8-BOM 编码 - - + + Convert to UCS-2 BE BOM 转换为 UCS-2 BE BOM 编码 - - + + Convert to UCS-2 LE BOM 转换为 UCS-2 LE BOM 编码 - - + + Batch convert 批量转换编码 - - + + Options 选项 - - + + BugFix 问题反馈 - - + + Donate 捐赠作者 - - + + Default 默认 - - + + LightBlue 亮蓝 - - + + ThinBlue 淡蓝 - - + + RiceYellow 纸黄 - - - - + + + + Yellow 黄色 - - + + Silver 银色 - - + + LavenderBlush 淡紫红 - - + + MistyRose 浅玫瑰色 - - + + English 英文 - - + + Chinese 中文 @@ -898,158 +875,158 @@ 捐赠软件 - - + + TXT - - + + Search Result 查找结果 - - - - - - + + + + + + test - - + + Go go - - + + File compare 文件对比 - + notepad-- - + &File File(&F) 文件(&F) - + &Edit Edit(&E) 编辑(&E) - + Blank CharOperate 空白字符操作 - + Convert Case to 大小写转换 - + Line Operations 行编辑 - + &Search Search(&S) 查找(&S) - + Bookmark Book Mark 书签 - + Mark Color 标记颜色... - + &View View(&V) 视图(&V) - + Icon Size 图标大小 - + E&ncoding Encoding(&N) 编码(&N) - + Other 其它编码 - + Convert to Other 转换为其它编码 - + &Language Language(&L) 语言(&L) - + Se&t Set(&T) 设置(&T) - + Format Language 格式化语言 - + Feedback 反馈问题 - + &Compare Compare(&C) 对比(&C) @@ -1059,1113 +1036,1134 @@ 最近对比(&R) - - + + Ctrl+T - - + + Ctrl+H - - + + Dir compare 目录对比 - - + + XML - - + + YAML - - + + PHP Php - - + + C++ - - + + C# - - + + Objective C - - + + Java - - + + RC - - + + HTML - - + + Makefile - - + + Pascal - - + + Batch - - + + ini - - + + Nfo - - + + Asp - - + + Sql - - + + Visual Basic Virsual Basic - - + + JavaScript - - + + CSS Css - - + + Perl - - + + Python - - + + Lua - - + + TeX Tex - - + + Fortran - - + + Shell - - + + ActionScript - - + + NSIS - - + + Tcl - - + + Lisp - - + + Scheme - - + + Assembly - - + + Diff - - + + Properties file - - + + PostScript - - + + Ruby - - + + Smalltalk - - + + VHDL - - + + AutoIt - - + + CMake - - + + PowerShell - - + + Jsp - - + + CoffeeScript - - + + BaanC - - + + S-Record - - + + TypeScript - - + + Visual Prolog - - + + Txt2tags - - + + Rust - - + + Registry - - + + REBOL - - + + OScript - - + + NCrontab Nncrontab - - + + Nim - - + + MMIXAL - - + + LaTeX LaTex - - + + Forth - - + + ESCRIPT - - + + Erlang - - + + Csound - - + + FreeBasic - - + + BlitzBasic - - + + PureBasic - - + + AviSynth - - + + ASN.1 - - + + Swift - - + + Intel HEX - - + + Fortran77 - - + + Edifact - - - + + + MarkDown - - + + Octave - - + + Po - - + + Pov - - + + JSON json - - + + AVS - - + + Bash - - + + IDL - - + + Matlab - - + + SPICE Spice - - + + Verilog - - + + Register 注册版本 - - + + + Alt+X + + + + + + About Notepad-- + 关于 Notepad-- + + + + Language File Suffix 语法文件后缀关联 - - + + Shortcut Key Manager 快捷键管理 + + + + Md5/Sha + + Language Format 编程语言格式 - - + + Open In Text 以文本模式打开 - - + + Open In Bin 以二进制模式打开 - - + + Remove Head Blank 去除行首空白 - - + + Remove End Blank 去除行尾空白 - - + + Remove Head End Blank 去除行首尾空白 - - + + Column Block Editing 列块编辑 - - + + Wrap 自动换行 - - + + Define Language 自定义语言 - - + + UPPERCASE 转成大写 - - + + lowercase 转成小写 - - + + Proper Case 每词转成仅首字母大写 - - + + Proper Case (blend) 每词的首字母转成大写 - - + + Sentence case 每句转成仅首字母大写 - - + + Sentence case (blend) 每句的首字母转成大写 - - + + Invert Case 大小写互换 - - + + Random Case 随机大小写 - - + + Remove Empty Lines 移除空行 - - + + Remove Empty Lines (Containing Blank characters) 移除空行(包括空白字符) - - + + UserDefine 用户自定义 - - + + Column Block Mode 列块模式... - - + + TAB to Space TAB 转空格 - - + + Space to TAB (All) 空格转 TAB (全部) - - + + Space to TAB (Leading) 空格转 TAB (行首) - - + + Duplicate Current Line 复制当前行 - - + + Ctrl+D - - + + Remove Duplicate Lines 删除重复行 - - + + Remove Consecutive Duplicate Lines 删除连续的重复行 - - + + Split Lines - 分隔行 + 分割行 - - + + Join Lines 合并行 - - + + Move Up Current Line 上移当前行 - - + + Ctrl+Shift+Up - - + + Move Down Current Line 下移当前行 - - + + Ctrl+Shift+Down - - + + Insert Blank Line Above Current 在当前行上方插入空行 - - + + Ctrl+Alt+Return - - + + Insert Blank Line Below Current 在当前行下方插入空行 - - + + Ctrl+Alt+Shift+Return - - + + Reverse Line Order 反排序行 - - + + Randomize Line Order - - + + Sort Lines Lexicographically Ascending 升序排列文本行 - - + + Sort Lines Lex. Ascending Ignoring Case 升序排列文本行(不分大小写) - - + + Sort Lines As Integers Ascending - - + + Sort Lines As Decimals (Comma) Ascending - - + + Sort Lines As Decimals (Dot) Ascending - - + + Sort Lines Lexicographically Descending 降序排列文本行 - - + + Sort Lines Lex. Descending Ignoring Case 降序排列文本行(不分大小写) - - + + Sort Lines As Integers Descending - - + + Sort Lines As Decimals (Comma) Descending - - + + Sort Lines As Decimals (Dot) Descending - - + + Find In Dir 在目录查找 - - + + Ctrl+Shift+D - - - - + + + + 1 - - - + + + Format Xml 格式化 Xml - - - + + + Format Json 格式化 Json - - + + Dark 深色 - - + + VB - - + + 2 - - + + 3 - - + + 4 - - + + 5 - - + + loop - - + + Clear History 清除历史打开记录 - - + + FileListView 文件列表窗口 - - + + Show ToolBar 显示工具栏 - - - + + + Batch Find 批量查找替换 - - + + Show Web Addr(Not recommended) 显示网站(不推荐开启) - - + + Find Next 查找下一个 - + menuDir 目录对比记录 - + menuReceFile 文件对比记录 - + T&ools Tools(&O) 工具(&O) - - + + Theme Style 主题与语法样式 - - + + F3 - - + + Find Prev 查找前一个 - - + + F4 - - + + Red - - + + Blue - - - - + + + + Big5 Big5(繁体中文) - - + + 24x24 - - + + 36x36 - - + + 48x48 - - AboutNdd About ndd - 关于 Ndd + 关于 Ndd info 信息 - - + + Ln:0 Col:0 行 0 列 0 - - + + Quit 退出 - + + load plugin in dir %1 success, plugin num %2 + + + + Edit with Notepad-- Edit with Notebook CC - + Close Current Document 关闭当前文档 - + Close Non-Current documents 关闭所有非当前文档 - + Close Left All 关闭左边所有文档 - + Close Right All 关闭右边所有文档 - + Current Document Sava as... 当前文件另存为 - + Show File in Explorer... 定位到文件路径 - + Open in New Window 在新窗口中打开 - + Can't Get Admin Auth, Open File %1 failed 获取管理员权限失败,打开文件 %1 失败。修改系统文件请以管理员权限执行ndd程序。 - + Please run in admin auth 请在管理员权限下执行程序 - + Rename Current Document 重命名当前文件 - + Reload With Text Mode 重新以文本模式打开 - + Reload With Hex Mode 重新以二进制模式打开 - + Select Left Cmp File 选择为左边对比文件 - + Select Right Cmp File 选择为右边对比文件 @@ -2174,258 +2172,310 @@ 大文本文件只读模式 - + New File 新建 - + Open File 打开 - - + + Save File 保存 - + Save All File 保存所有 - + Cycle Auto Save 周期自动保存 - + Mark 标记 - + word highlight(F8) 高亮单词(F8) - + clear all highlight(F7) 取消所有高亮(F7) - + Zoom In 放大 - + Zoom Out 缩小 - + Word Wrap 自动换行 - + Show Blank 显示空白字符 - + Indent Guide 缩进参考线 - + + tailf file + 监控文件 + + + Pre Hex Page 上一页/位置 - + Next Hex Page 下一页/位置 - + Goto Hex Page 跳转到文件偏移地址 - + File Compare 文件对比 - + Dir Compare 目录对比 - + Bin Compare 二进制对比 - + transform encoding 转换编码 - + batch rename file 批量重命名 - + Zoom: %1% 缩放率: %1% - + Big5(Traditional Chinese) Big5(繁体中文) - + + reload file %1 failed + 重加载文件 %1 失败 + + + + Yes[Reload] + 是 [重新加载] + + + + No[Drop] + 否 [放弃更新] + + + + On Tailf + 开启自动监控 + + + Do you want to save changes to before closing? Do you want to save changes to « %1 » before closing? 关闭文件之前,是否保存修改? - + If you don't save the changes you made in file %1, you'll lose them forever. 如果你不保存在文件 %1 中的修改,变更操作将不会生效。 - + + &Yes + 是[&Y] + + + + &No + 否[&N] + + + + &Cancel + 取消[&C] + + + New File Finished [Text Mode] Zoom %1% 创建新文件成功 缩放率 %1% - + Use < (Prev) or > (Next) and Goto Buttons to Change Page Num . Use < (Pre) or > (Next) and Goto Buttons to Change Page Num . 使用工具栏按钮 < (前一页) >(下一页) Go(跳转) 进行翻页。 - + File %1 File Size %2 > %3M, How to Open it ? 文件 %1 文件大小 %2 大于 %3M,请选择打开方式。 - + + + File %1 open success. But Exist Garbled code ! - + File %1 Open Finished [Text Mode] Zoom %2% 文件 %1 打开成功 [文本模式] 缩放率 %2% - - + + Format Error - - - - + + + + Not a txt format file , load with big txt is garbled code! 文件不是文本格式,强制以大文本打开时乱码! - - + + Current offset is %1 , line nums is %2 - %3 load Contens Size is %4, File Total Size is %5 当前文件偏移 %1 ,行号 %2-%3 ,分块加载大小 %4 ,文件大小是 %5 - + File List 文件列表 - + Save Swap File %1 failed. Write the target file directly ? 保存交换文件 %1 失败,是否直接保存写入原始文件? - - + + Current Zoom Value is %1% 当前缩放率 %1% - + + Only Text File Can Use it ! + + + + + File %1 into tailf mode, readonly ! + + + + out of file line range,mar line num is %1 ! - + Registered Version 注册过的正版软件!(恭喜) - + Free Trial 免费永久试用版本(捐赠可获取注册码) - + %1 is not a file, skip open it... %1 不是一个文件,跳过打开它...... - - - - + + + + The ReadOnly document does not allow this operation. 当前只读显示文件不允许该操作! - + Column Edit Mode Tips 列块模式提示 - + "ALT+Mouse Click" or "Alt+Shift+Arrow keys" Switch to mode! 请使用'ALT+鼠标点选' 或 'Alt+Shif+箭头键'切换列块模式。 - + SortingError 排序错误 - + Unable to perform numeric sorting due to line %1. 行 %1 不能进行排序操作! - - + + what find is null ! 查找字段为空 - + XML format error, please check! Xml format error, please check! Xml 格式化错误,请检查文件格式! - + JSON format error, please check! Json format error, please check! Json 格式化错误,请检查文件格式! @@ -2435,65 +2485,62 @@ File Size %2 > %3M, How to Open it ? 已打开的窗口背景颜色,将在文件重新打开后才会生效! - + GB18030(Simplified Chinese) GB18030(简体中文) - + Language: %1 语法:%1 - + Reload 重加载 - Yes - 保存 + 保存 - - + No 放弃修改 - Cancel - 取消 + 取消 - - + + Restore Last Temp File %1 Failed 恢复临时文件 %1 失败! - + Recover File? 是否恢复文件? - + File %1 abnormally closed last time , Restore it ? 文件 %1 上次异常退出并留下未保存存档,是否恢复文件存档? - + Restore 恢复文件? - - + + File %1 Open Failed 文件 %1 打开失败! - + <a href="https://gitee.com/cxasm/notepad--">https://gitee.com/cxasm/notepad--</a> <br/> @@ -2502,23 +2549,23 @@ File Size %2 > %3M, How to Open it ? - + Notepad-- Version %1 - + File %1 Open Finished [Text Mode] 文件 %1 打开成功 [文本模式] - - + + Current offset is %1 , load Contens Size is %2, File Total Size is %3 当前文件偏移 %1 , 加载内容大小是 %2,文件总大小是 %3 (字节) - + File %1 Open Finished [Hex ReayOnly Mode] 文件 %1 打开成功 [二进制只读模式] @@ -2527,23 +2574,23 @@ File Size %2 > %3M, How to Open it ? 文件 %1 可能是二进制文件,尝试以文本格式打开。 - + Save File %1 failed. You may not have write privileges Please save as a new file! 保存文件 %1 失败! 你可能没有文件写权限,请另存为一个新文件! - + Cycle autosave on ... 周期性自动保存文件已开启... - + Cycle autosave off ... 周期性自动保存文件已关闭... - + The current document has been automatically saved 当前文件周期性自动保存完毕! @@ -2560,9 +2607,9 @@ Do you want to reload it? %1\n\n \n文件已在外部被其它程序修改。\n是否重新加载该文件? - - - + + + Ln: %1 Col: %2 行:%1 列:%2 @@ -2579,31 +2626,31 @@ Do you want to reload it? 当前文件偏移 %1 , 文件大小是 %2 (字节) - - - - - - - - + + + + + + + + Error 错误 - + file %1 not exist. 文件 %1 不存在 - - + + file %1 already open at tab %2 文件 %1 已经在页面 %2 中打开 - - + + Save File %1 failed. Can not write auth, Please save as new file 保存 %1 失败。当前文件没有写权限,请另存为一个新文件 @@ -2612,148 +2659,161 @@ Do you want to reload it? 打开文件 %1 失败 - - - - + + + + Only Text File Can Use it, Current Doc is a Hex File ! 只有文本模式才能使用该功能,当前文件是二进制文件! - + "%1" This file has been modified by another program. Do you want to reload it? %1 该文件已在外部被其它程序修改,是否重新加载? - + Run As Admin Failed to save the file. Please check the file permissions. 以管理员模式保存文件失败!请检查文件的权限。 - + + Plugin Manager 插件管理 - + + plugin %1 load failed ! - + + Plugin 插件 - + If display exceptions,Please Install System Font Courier 如果界面字体不满意,还请安装windows系统字体 Courier - + Set/Remove BookMark 设置/取消书签 - + Next BookMark 下一书签 - + Prev BookMark 上一书签 - + ClearAll BookMark 清除所有书签 - + Cut BookMark Lines 剪切书签行 - + Copy BookMark Lines 复制书签行 - + Paste BookMark Lines 粘贴(替换)书签行 - + Delete BookMark Lines 删除书签行 - + Delete UnBookMark Lines 删除未标记行 - + Clip BookMark 反向标记书签 - + Color %1 颜色 %1 - + + Cmd in Explorer... + 在文件目录打开CMD窗口 + + + The currently file %1 is already in text mode 当前文件 %1 已经是文本模式 - + The currently file %1 is already in bin mode 当前文件 %1 已经是二进制模式 - - + + open cmd in file dir %1 failed. + + + + + File %1 Open Finished [Text ReadOnly Mode] (Note: display up to 50K bytes ...) 文件 %1 打开成功 [文本只读模式] (乱码:二进制文件强行以文本格式显示,最多显示50K字节的内容,后面忽略...) - - + + file %1 already open at tab %2, please select other file name. 文件 %1 已经存在于页面 %2 中,请选择一个其它名称 - + Rename File As ... 重命名... - + file %1 reanme failed! 文件 %1 重命名失败! - - + + Save File As ... 另存为文件 ... - + Close ? 关闭? - + already has child window open, close all ? 目前还有子窗口处于打开状态,关闭所有窗口吗? - + Find result 查找结果 @@ -2762,50 +2822,50 @@ Do you want to reload it? 文件已关闭 - - + + Find result - %1 hit 查找结果 - %1 命中 - + Convert end of line In progress, please wait ... 行尾转换中,请等待... - + Convert end of line finish. 行尾转换完毕 - + Go to line 跳转到行 - + Line Num: 行号 - + no more pre pos 没有前一个位置了 - + no more next pos 没有后一个位置了 - - - + + + The Last Page ! Current offset is %1 , load Contens Size is %2, File Total Size is %3 最后一页!当前文件偏移是 %1 ,加载内容大小是 %2 ,文件总大小是 %3 (字节) - + Only Hex File Can Use it, Current Doc not a Hex File ! 只有二进制文件具备该功能。当前文件不是二进制文件! @@ -2814,24 +2874,25 @@ Do you want to reload it? 最后一页!当前文件偏移是 %1 ,文件大小是 %2 (字节) - + + file %1 was not exists ! 文件 %1 不存在! - - + + Error file offset addr , please check ! 错误的文件偏移量地址,请检查! - - + + File Size is %1, addr %2 is exceeds file size 文件大小是 %1,当前地址 %2 超过了文件大小。 - + Current Text Doc Can Not Use it ! Current Text Doc Canp Not Use it ! 当前是常规文本文档,不能使用该功能! @@ -2844,14 +2905,14 @@ china: https://gitee.com/cxasm/notepad-- 国内:https://gitee.com/cxasm/notepad-- - - + + notice 消息 - - + + file path not exist, remove recent record! 文件路径不存在,删除历史记录! @@ -2884,7 +2945,7 @@ china: https://gitee.com/cxasm/notepad-- 文件开始偏移位置超过文件长度! - + BigFile Compare, left linenum %1 , right lineNum %2, Please Waiting ! 大文件对比,左文件行数 %1 ,右文件行数 %2, 请等待 ! @@ -3068,255 +3129,265 @@ china: https://gitee.com/cxasm/notepad-- 不同 - + + only diff + 差异 + + + + unique + 独有 + + + expand 展开 - + fold 收起 - + clear 清空 - + swap 交换 - + reload 重载 - + Status: normal 状态:正常 - - + + error: %1 not a dir ! 错误:%1 不是一个目录! - + now busy, please try later ... 当前忙,稍后再试... - - + + Copy to right 拷贝到右边 - - + + Cover Diffent File To Right 覆盖不同文件到右边 - - + + Cover Diffent File To Right (Traverse subdirectories) 覆盖不同文件到右边(递归子目录) - - + + Copy to left 拷贝到左边 - - + + Cover Diffent File To Left 覆盖不同文件到左边 - - + + Cover Diffent File To Left (Traverse subdirectories) 覆盖不同文件到左边(递归子目录) - + Mark as equal 标记为相等 - + Copy Unique File To Other Side 拷贝独有文件到对方 - + Copy Unique File To Other Side (Traverse subdirectories) 拷贝独有文件到对方(递归子目录) - + Delete This File 删除该文件 - + Delete Only in This Side 删除本侧独有文件 - + Cope Path To Clipboard 拷贝文件路径到剪切板 - + Find File By Name 查找文件 - + %1 not exist, please check! 文件 %1 不存在,请检查! - - - - - - - + + + + + + + Notice 消息 - + del file %1 success! 删除文件 %1 成功! - + del file %1 failed, maybe other place using ! 删除文件 %1 失败,可能其它地方在使用中! - + Do you want to delete this files ? 您确定删除该文件吗? - + right Dirs No Find Prev! 右边目录没有找到前一个! - + right Dirs No Find Next! 右边目录没有找到下一个! - - - + + + Not Find 没有找到 - + left Dirs No Find Next! 左边目录没有找到下一个! - + left Dirs No Find Prev! 左边目录没有找到上一个! - + can not find %1 没有找到相关文件 %1 - + Do you want to overwrite all files (excluding folders) to the other side? 您确定覆盖目录下所有不同文件到对方吗?(不递归子目录) - - + + cover file %1 please waiting 覆盖文件 %1 请等待 - - - - + + + + cover file finish, total cover %1 files 覆盖文件完成,一共覆盖 %1 个文件 - + Do you want to overwrite all files (Traverse subdirs) to the other side? 您确定覆盖目录下所有不同文件到对方吗?(递归覆盖子目录) - + Do you want to copy unique files (excluding folders) to the other side? 您确定拷贝此目录下独有文件到对方?(不递归子目录) - + Do you want to copy unique files (Traverse subdirs) to the other side? 您确定拷贝此目录下独有文件到对方?(递归拷贝子目录) - + Do you want to delete all files (excluding folders) only in this side? 您确定删除目录下的独有文件吗?(不递归子目录) - + delete file finish, total del %1 files 删除文件完成,一共删除 %1 个文件 - - - + + + %1 not exist, skip ... 文件 %1 不存在,跳过... - - - + + + %1 is exist, if replace ? %1 已经存在,是否替换文件? - - - + + + Replace ? 是否替换? - - - + + + copy file %1 failed, please check file auth ! 拷贝文件 %1 失败,请检查文件权限! - - + + current file: %1 current file %1 当前文件:%1 @@ -3326,73 +3397,73 @@ china: https://gitee.com/cxasm/notepad-- 放弃修改 - - - - + + + + Cancel 取消 - - - - + + + + Yes[hex cmp] 是[进行二进制对比] - - - - + + + + No[text cmp] 否[进行文件对比] - + current exec rule mode is quick mode, please wait ... 当前执行的对比模式是快速模式,请等待... - + current exec rule mode is deep slow mode, please wait ... 当前执行的对比模式是深入文本慢速模式,请等待... - + There are still %1 files haven't returned comparison results 还有 %1 个文件正在对比中 - + file is %1 in comparing ! 文件 %1 对比进行中! - + load dir file tree in progress , please wait ... 正在加载文件树目录,请等待... - - + + skip dir %1 跳过目录 %1 - + load %1 dir %2 加载第 %1 个目录 %2 - + skip file ext %1 跳过文件类型 %1 - + skip file prefix %1 跳过文件前缀 %1 @@ -3406,65 +3477,65 @@ china: https://gitee.com/cxasm/notepad-- 文件 [%1] 可能不是文本文件,比较操作危险,强行比较吗?(不建议) - - + + Open Directory 打开目录 - + init dir file tree in progress total %1 file, please wait ... 初始化文件树目录中,一共 %1 文件,请等待... - - - + + + Comparison in progress, please wait ... 对比文件进行中,请等待... - - - - + + + + file [%1] may be not a text file, cmp in hex mode? 文件 %1 可能不是文本格式,是否进行二进制格式对比? - - - - + + + + compare canceled ... 对比被取消 - + compare not finished, user canceled ... 对比没有完成,用户取消 - - + + user canceled finished ... 用户取消完成 - - - + + + compare file finish ... 文件对比完成 - + load dir files, please wait ... 加载目录中,请等待... - + load dir finish, total %1 files 加载目录完成,一共加载 %1 个文件 @@ -4395,63 +4466,63 @@ Left Equal ratio %4 Right Equal ratio %5 打开目录 - + start scan file text code, please wait... 开始扫描文件编码,请等待... - - + + ignore 忽略 - + please wait, total file %1,cur scan index %2, scan finish %3% 请等待,一共 %1个文件,当前扫描第 %2 个,扫描完成率 %3% - + scan finished, total file %1 扫描完成,一共%1个文件 - + already %1 ignore 已经是 %1编码,忽略 - + total file %1,cur deal index %2,finish %3% 一共 %1 个文件,当前处理第 %2 个,完成率%3% - + total file %1,cur deal index %2,finish 100% 一共 %1 个 文件,当前处理第 %2 个,完成率100% - + convert finished ! 转换完成! - + convert finish 转换完成 - + convert fail 转换失败 - + file %1 convert failed,pleas check... 文件 %1 转换编码失败,请检查... - + please drop a file dir ... 请拖入一个文件夹... @@ -4563,8 +4634,11 @@ Left Equal ratio %4 Right Equal ratio %5 FileManager - - + + + + + Error 错误 @@ -4573,17 +4647,21 @@ Left Equal ratio %4 Right Equal ratio %5 打开文件 %1 失败。没有读文件的权限。 - + + + Open File %1 failed 打开文件 %1 失败。 - + + File is too big to be opened by Notepad-- 文件太大,不能使用Notepad--打开! - + + The file %1 is likely to be binary. Do you want to open it in binary? 文件 %1 可能是二进制格式,你想以二进制(只读)格式打开文件吗? @@ -4592,27 +4670,31 @@ Left Equal ratio %4 Right Equal ratio %5 二进制或文本打开? - + + Hex Open 以二进制打开 - + + Text Open 以文本打开 - + + Cancel 取消 - + + Open with Text or Hex? [Exist Garbled Code] - + 打开为文本或二进制?[检测存在乱码] - + load bit text file tree in progress file size %1, please wait ... 加载大文件中,文件大小 %1,请等待... @@ -4736,11 +4818,44 @@ file size %1, please wait ... 没有更多的字段 '%1' + + FindResultView + + + Fold All + 全部折叠 + + + + Expand All + 全部展开 + + + + copy select line + 复制选择行 + + + + warp + 自动换行 + + + + clear + 清空 + + + + close + 关闭 + + FindResultWin - + FindResultWin 查找结果 @@ -4749,103 +4864,132 @@ file size %1, please wait ... 清空 - clear this find result - 清除当前结果 + 清除当前结果 - clear all find result - 清除所有结果 + 清除所有结果 copy item content 拷贝到剪切板 - copy select item (Ctrl Muli) - 复制选中项(按ctrl多选) + 复制选中项(按ctrl多选) - copy select Line (Ctrl Muli) - 复制选中行(按ctrl多选) + 复制选中行(按ctrl多选) - select section - 选中所在节 + 选中所在节 - select all item - 全部选择 + 全部选择 - Zoom In - 放大 + 放大 - Zoom Out - 缩小 + 缩小 - close - 关闭 + 关闭 - - %1 rows selected ! - %1 行被选中! + %1 行被选中! - %1 items have been copied to the clipboard ! - %1 项已经被复制到剪切板 + %1 项已经被复制到剪切板 - %1 lines have been copied to the clipboard ! - %1 行已经被复制到剪切板 + %1 行已经被复制到剪切板 - + + Search "%1" (%2 hits) + + 查找 "%1" (%2 处命中) + + + + + + Line %1 : %2 + + 行 %1 : %2 + + + + <font style='font-size:14px;font-weight:bold;color:#343497'>Search "%1" (%2 hits)</font> <font style='font-size:14px;font-weight:bold;color:#343497'>查找 "%1" (%2 命中)</font> - - + <font style='font-size:14px;font-weight:bold;color:#309730'>%1 (%2 hits)</font> <font style='font-size:14px;font-weight:bold;color:#309730'>%1 (%2 命中)</font> - - + <font style='font-size:14px;color:#99cc99'>%1 (%2 hits)</font> <font style='font-size:14px;color:#99cc99'>%1 (%2 命中)</font> - - + <font style='font-size:14px;'>Line </font><font style='font-size:14px;color:#ff8040'>%1</font> : %2 <font style='font-size:14px;'>行 </font><font style='font-size:14px;color:#ff8040'>%1</font> : %2 - - + <font style='font-size:14px;color:#ffffff'>Line </font><font style='font-size:14px;color:#ff8040'>%1</font> : %2 <font style='font-size:14px;color:#ffffff'>行 </font><font style='font-size:14px;color:#ff8040'>%1</font> : %2 - + + Search "%1" (%2 hits in %3 files) + + 查找 "%1" (%2 处命中在 %3 文件) + + + + + + %1 (%2 hits) + + %1 (%2 命中) + + + + + Line %1: + 行 %1: + + + + + %1%2 + + + + + + Line + 行 + + <font style='font-size:14px;font-weight:bold;color:#343497'>Search "%1" (%2 hits in %3 files)</font> - <font style='font-size:14px;font-weight:bold;color:#343497'>查找 "%1" (%2 命中在 %3 文件)</font> + <font style='font-size:14px;font-weight:bold;color:#343497'>查找 "%1" (%2 命中在 %3 文件)</font> <font style='font-weight:bold;color:#343497'>Search "%1" (%2 hits)</font> @@ -4881,282 +5025,294 @@ file size %1, please wait ... FindWin - + MainWindow 查找与替换 - + find 查找 - - - - - + + + + + Find what : 查找目标: - - - + + + Backward direction 反向查找 - - - - - - - + + + + + + + Match whole word only 全词匹配 - - - - - - - + + + + + + + Match case 匹配大小写 - - - + + + Wrap around 循环查找 - - - - - - - + + + + + + + Search Mode 查找模式 - - - - - - - + + + + + + + Regular expression 正则表达式 - - - - - - - + + + + + + + Normal 普通 - - - - - - - + + + + + + + Extend(\n,\r,\t,\0,\x...) 扩展(\n,\r,\t,\0,\x...) - + Find Next(F3) 查找下一个(F3) - + F3 - + Find Prev(F4) 查找上一个(F4) - + F4 - + Counter(T) 计数(T) - + Ctrl+T - + + Copy Regular Result + 提取正则结果到剪切板 + + + + Find Next 查找下一个 - - + + File Type : 文件类型: - - + + Skip Dir Name : 跳过目录名: - - + + Clear All 清除全部标记 - + Find All in Current Document 在当前文件中查找 - + Find All in All Opened Documents 查找所有打开文件 - - - - - - - - + + + + + + + + Close 关闭 - - - - + + + + Replace 替换 - - - - + + + + Replace with : 替换为: - - + + Replace All 在当前文件中替换 - - + + Replace All in All Opened Documents 替换所有打开文件 - - + + Replace In File 在目录文件中替换 - - - - + + + + Clear Result 清空结果 - - + + Mark 标记 - - + + Mark What 标记目标: - - + + Mark All 全部标记 - - + + + Mark & Bookmark + 标记加书签 + + + + Clear Mark 清除 - - + + Dir Find 在目录查找 - - + + Dest Dir : 目标目录: - - + + Select 选择 @@ -5165,8 +5321,8 @@ file size %1, please wait ... 文件类型: - - + + *.c:*.cpp:*.h @@ -5175,280 +5331,308 @@ file size %1, please wait ... 跳过目录名 - - + + debug:Debug:.vs:.git:.svn - - + + Options 选项 - - + + Skip child dirs 跳过子目录 - - + + Skip hide file 跳过隐藏文件 - - + + Skip binary file 跳过二进制文件 - - + + Skip Big file exceed 跳过超过大小的文件 - - + + MB - - + + Find All 全部查找 - - - - - - - - - - - + + + + + + + + + + + + what find is null ! 查找字段为空 - - - - - + + + + + cant't find text '%1' 找不到字段 '%1' - - + + no more find text '%1' 没有更多的字段 '%1' - - - - + + + + The ReadOnly document does not allow this operation. 当前只读显示文件不允许该操作! - - + + + find finished, total %1 found! 查找完成,一共 %1 处发现。 - - + + The mode of the current document does not allow this operation. 当前模式下的文档不允许该操作! - - - - + + + + + + The ReadOnly document does not allow replacement. 当前只读文档不允许执行替换操作! - - + + no more replace text '%1' 没有更多替换文本 '%1' - + find-regex-zero-length-match 正则查找零长匹配 - + target info linenum %1 pos is %2 - %3 目标在行 %1 位置 %2 - %3 - - + + count %1 times with '%2' 计数 %1 次匹配 '%2' - + + + total %1 keyword, please wait ... - + 一共 %1 关键字,请等待...... - - + + find finished, total %1 found! Result in clipboard. + 查找完成,一共 %1 处发现,目标结果字段已经提取到剪切板。 + + + + The mode of the current document does not allow replacement. 当前模式的文档不允许执行替换操作! - - + + Replace All current Doc - 在所有打开文件中替换 + 在当前文件中替换所有 - - + + Are you sure replace all occurrences in current documents? 是否确认在当前打开的文档中替换? - - + + replace finished, total %1 replaced! 替换完成,一共 %1 处替换! - + Replace All Open Doc 替换所有打开的文档 - + Are you sure replace all occurrences in all open documents? 是否确认在所有打开的文档中替换? - + Replace in Opened Files: %1 occurrences were replaced. 在打开的文档中替换:%1 处已经被替换。 - - + + what mark is null ! 标记字段为空! - + cant't mark text '%1' 不能标记文本 ‘%1’ - + mark finished, total %1 found! 标记完成,一共 %1 处发现! - + The mode of the current document does not allow mark. 当前模式的文档不允许执行标记操作! - + Open Directory 打开目录 - + load dir file in progress , please wait ... 加载目录文件中,请等待... - - + + skip dir %1 跳过目录 %1 - + found %1 dir %2 发现 %1 个目录 %2 - + ext type skip file %1 跳过类型文件 %1 - + found in dir canceled ... 查找取消... - + + find finished, walk %1 files, total %2 found in %3 file! + 查找完成,遍历 %1 个文件,一共 %2 处发现在 %3 个文件! + + + + replace finished, walk %1 files, total %2 replace ! + 替换完成,遍历 %1 个文件,一共 %2 处替换! + + + + Only regular lookup mode can be used! + 只在正则查找模式才能使用该功能! + + + + Continue Find ? 是否继续查找? - + + The search results have been greater than %1 times in %2 files, and more may be slow. Continue to search? 查找结果已经有 %1 处在 %2 个文件中,结果太多会比较慢,是否继续查找? - + + Yes 继续查找 - + + Abort 终止查找 - - + + please select find dest dir ! 请选择目标文件夹! - + dest dir %1 not exist ! 目标文件夹 %1 不存在! - find finished, total %1 found in %2 file! - 查找完成,一共发现 %1 处在 %2 个文件中! + 查找完成,一共发现 %1 处在 %2 个文件中! - + Replace All Dirs 目录全部替换 - + Are you sure replace all "%1" to "%2" occurrences in selected dirs ? 您确定替换目录文件中所有 "%1" 为 "%2" 吗? - replace finished, total %1 replace in %2 file! - 替换完成,一共替换 %1 处在 %2 个文件中! + 替换完成,一共替换 %1 处在 %2 个文件中! @@ -5891,6 +6075,98 @@ Double-click a column item to modify the syntax association file. 对比循环 %1 次,还剩余 %2 次 ... + + MarkdownViewClass + + + + MarkdownView + + + + + Md5hash + + + Copy to clipboard Finished! + 拷贝到剪切板完成! + + + + Md5hashClass + + + + Md5hash + + + + + + Copy Text Or Select File + 拷贝文本或选择文件 + + + + + select + 选择 + + + + + Algorithm + 算法 + + + + + Md4 + + + + + + Sha1 + + + + + + Sha3_256 + + + + + + Md5 + + + + + + Sha256 + + + + + + Keccak_256 + + + + + + Copy to Clipboard + 拷贝到剪切板 + + + + + Close + 关闭 + + NetRegister @@ -6125,6 +6401,245 @@ Double-click a column item to modify the syntax association file. 文件模式 + + QsciCommand + + Move down one line + 光标下移一行 + + + Extend selection down one line + 继续选中下一行 + + + Extend rectangular selection down one line + 列编辑:扩展选中下一行 + + + Scroll view down one line + 视图滚动到下一行 + + + Move up one line + 光标上移一行 + + + Extend selection up one line + 继续选中上一行 + + + Extend rectangular selection up one line + 列编辑:继续选中上一行 + + + Scroll view up one line + 视图滚动到上一行 + + + Scroll to start of document + 光标移到行首 + + + Scroll to end of document + 光标移到行尾 + + + Extend selection down one paragraph + 继续选中下一段落 + + + Move up one paragraph + 光标移到上一段落 + + + Extend selection up one paragraph + 继续选中上一段落 + + + Move left one character + 光标右移一格 + + + Extend selection left one character + 继续选中左边一个字符 + + + Extend rectangular selection left one character + 列编辑:继续选中左边一个字符 + + + Move right one character + 光标右移一格 + + + Extend selection right one character + 继续选中右边一个字符 + + + Extend rectangular selection right one character + 列编辑:继续选中右边一个字符 + + + Move left one word + 光标左移一个单词 + + + Extend selection left one word + 继续选中左边一个单词 + + + Move right one word + 光标右移一个单词 + + + Extend selection to start of document line + 扩展选中光标至行首 + + + Move to first visible character in document line + 光标移到行首 + + + Extend selection to first visible character in document line + 扩展选中光标至行首 + + + Move to end of document line + 光标移到行尾 + + + Extend selection to end of document line + 扩展选中光标至行尾 + + + Extend rectangular selection to end of document line + 列编辑:继续选中到文件尾部 + + + Move to start of document + 光标移到文档首 + + + Extend selection to start of document + 扩展选中光标至文档首部 + + + Move to end of document + 光标移到文档尾 + + + Extend selection to end of document + 扩展选中光标至文档尾部 + + + Move up one page + 光标移到上一页 + + + Extend selection up one page + 继续选中上一页 + + + Extend rectangular selection up one page + 列编辑:继续选中上一页 + + + Move down one page + 光标移到下一页 + + + Extend selection down one page + 继续选中下一页 + + + Extend rectangular selection down one page + 列编辑:扩展选中下一页 + + + Delete current character + 删除当前字符 + + + Delete previous character + 删除上一个字符 + + + Delete line to left + 删除光标左边的行内容 + + + Delete line to right + 删除光右边的行内容 + + + Delete current line + 删除当前行 + + + Cut current line + 剪切当前行 + + + Copy current line + 复制当前行 + + + Select all + 全选 + + + Convert selection to lower case + 将选中文本转换为小写字母 + + + Convert selection to upper case + 将选中文本转换为大写字母 + + + Cut selection + 剪切选中内容 + + + Copy selection + 复制选中内容 + + + Paste + 粘贴 + + + Toggle insert/overtype + 插入覆盖模式 + + + Insert newline + 插入新行 + + + Indent one level + 键入制表符 + + + Cancel + 取消 + + + Undo last command + 撤销一步 + + + Redo last command + 重做一步 + + + Zoom in + 放大 + + + Zoom out + 缩小 + + QsciDisplayWindow @@ -6163,211 +6678,207 @@ Double-click a column item to modify the syntax association file. QsciLexerGlobal Global override - 全局样式覆盖所有语言 + 全局样式覆盖所有语言 Default - 默认 + 默认 Indent guideline style - 缩进参考线风格 + 缩进参考线风格 Brace highlight style - 括弧高亮风格 + 括弧高亮风格 Current line background colour - 当前行背景色 + 当前行背景色 Select text colour - 选中文本颜色 + 选中文本颜色 Caret colour - 光标颜色 + 光标颜色 Line number margin - 行号风格 + 行号风格 Bookmark margin - 书签风格 + 书签风格 Fold - 折叠符号风格 + 折叠符号风格 Fold active - 折叠激活风格(目前无效) + 折叠激活风格(目前无效) Fold margin - 折叠样式 + 折叠样式 White space symbol - 空白字符样式 + 空白字符样式 Smart HighLighting - 智能高亮 + 智能高亮 Find Mark Style - 查找结果样式 + 查找结果样式 Mark Style 1 - 标记样式1 + 标记样式1 Mark Style 2 - 标记样式2 + 标记样式2 Mark Style 3 - 标记样式3 + 标记样式3 Mark Style 4 - 标记样式4 + 标记样式4 Mark Style 5 - 标记样式5 + 标记样式5 URL hovered - 网址鼠标悬浮样式 + 网址鼠标悬浮样式 QsciLexerText Chinese And Others - 中文字符及其它 + 中文字符及其它 Ascii - 英文字符 + 英文字符 Keyword - 关键词 + 关键词 QsciScintilla &Cut - 剪切 + 剪切 &Copy - 复制 + 复制 &Paste - 粘贴 + 粘贴 Delete - 删除 + 删除 Select All - 全选 + 全选 Show File in Explorer - 定位到文件目录 + 定位到文件目录 QtLangSet - + Save Change 保存修改 - The current style configuration has been modified. Do you want to save it? - 当前语言的格式风格已经被修改,是否保存? - - - - + + AllGlobal 全局格式统一设置 - + Current themes : %1, language : %2 当前主题:%1,当前语言:%2 - + %1 style configuration has been modified. Do you want to save it? %1 类型的显示风格已经被修改,是否保存? - + Read %1 language user define format error. 读取 %1 语言用户自定义格式失败! - + Save Finished ! 保存成功! - + Not change, no need save ! 没有改变,无需保存! - + Style Foreground Color 风格背景色 风格前景色 - + Style Background Color 风格背景色 - + Reset Style 重置风格 - + Are you sure to reset language %1 sytle 您确定重置语言 %1 的风格吗? - + Reset All Style 重置所有风格 - + Are you sure to reset All language sytle 您确定重置所有语言风格吗? - + themes changing, please waiting ... 主题切换中,请等待 ... - + themes changed finished ... 主题切换完成 ... @@ -6910,145 +7421,95 @@ Double-click a column item to modify the syntax association file. 请选择目录或目标文件后缀 - - RealCompareClass - - MainPage - 主页 - - - dir compare - 目录对比 - - - file compare - 文件对比 - - - encode convert - 编码转换 - - - About - 关于 - - - donate - 捐赠软件 - - - Language - 语言 - - - bin compare - 二进制对比 - - - Recently - 最近对比 - - - Dir ... - 目录... - - - File ... - 文件... - - - dir - 目录 - - - file - 文件 - - - rule - 规则 - - - English - 英文 - - - Chinese - 中文 - - - main - 主页 - - ScintillaEditView - + Show File in Explorer 定位到文件目录 - - + + mark with color 使用颜色标记 - - + + Color %1 颜色 %1 - - - + + + Clear Select 清除选择标记 - - - + + + Clear All 清除全部标记 - + Add/Del line comment 添加/删除当行注释 - + Add Block comment 区块注释 - + Del Block comment 清除区块注释 - + + Markdown View + 预览 MarkDown + + + Word Count 字数统计 - - + + Word Nums 字符数量 - + + Current Select Word Nums is %1 . +Line nums is %2 . +Space nums is %3, Non-space is %4 . + 当前选择文本字符数量是 %1 +行数量是 %2 +空格字符 %3,非空格字符数 %4 + + + + Current Doc Word Nums is %1 . +Line nums is %2 . +Space nums is %3, Non-space is %4 . + 当前文本字符数量是 %1 +行数量是 %2 +空格字符 %3,非空格字符数 %4 + + Current Select Word Nums is %1 . - 当前选择的字符数量是 %1 . + 当前选择的字符数量是 %1 . - Current Doc Word Nums is %1 . - 当前文档的字符数量是 %1 . + 当前文档的字符数量是 %1 . @@ -7106,205 +7567,300 @@ Double-click a column item to modify the syntax association file. ShortcutKeyMgr - + New File 新建 - + Open File 打开 - + Save File 保存 - + Save All File 保存所有 - + Close 关闭 - + Close All 关闭所有 - + Cut 剪切 - + Copy 拷贝 - + Paste 粘贴 - + Undo 撤销 - + Redo 重做 - + Find 查找 - + Replace 替换 - + Dir Find 在目录查找 - + Mark 标记 - + word highlight(F8) 高亮单词(F8) - + clear all highlight(F7) 取消所有高亮(F7) - + Zoom In 放大 - + Zoom Out 缩小 - + Word Wrap 自动换行 - + Show Blank 显示空白字符 - + Indent Guide 缩进参考线 - + Pre Hex Page 上一页/位置 - + Next Hex Page 下一页/位置 - + Goto Hex Page 跳转到文件偏移地址 - + File Compare 文件对比 - + Dir Compare 目录对比 - + Bin Compare 二进制对比 - + transform encoding 转换编码 - + batch rename file 批量重命名 - + Format Xml 格式化 Xml - + Format Json 格式化 Json - - + + Add/Del Line Comment + 添加/删除当行注释 + + + + Add Block Comment + 区块注释 + + + + Del Block Comment + 清除区块注释 + + + + Fold Level 1 + 折叠层次 1 + + + + Fold Level 2 + 折叠层次 2 + + + + Fold Level 3 + 折叠层次 3 + + + + Fold Level 4 + 折叠层次 4 + + + + Fold Level 5 + 折叠层次 5 + + + + Fold Level 6 + 折叠层次 6 + + + + Fold Level 7 + 折叠层次 7 + + + + Fold Level 8 + 折叠层次 8 + + + + UNFold Level 1 + 展开层次 1 + + + + UNFold Level 2 + 展开层次 2 + + + + UNFold Level 3 + 展开层次 3 + + + + UNFold Level 4 + 展开层次 4 + + + + UNFold Level 5 + 展开层次 5 + + + + UNFold Level 6 + 展开层次 6 + + + + UNFold Level 7 + 展开层次 7 + + + + UNFold Level 8 + 展开层次 8 + + + + Can't Modify 不可修改 - + Double Click To Modify 双击修改快捷键 - + row %1 shortcut key '%2' can't modify ! 行 %1 快捷键 ‘%2’不可修改! - - + + modify row %1 to '%2' shortcut key success! 修改行 %1 快捷键为 %2 成功! - - + + error:modify row %1 to '%2' shortcut key failed ! 错误:修改行 %1 为快捷键 %2 失败! - + conflict error! '%1' Already exist at row %2 冲突错误!'%1' 已经存在行 %2 - + conflict error! '%1' Already exist at qscint row %2 冲突错误!'%1' 已经存在于qscint表格行 %2 - + modify canceled ! 修改取消! @@ -7373,91 +7929,91 @@ Double-click a column item to modify the syntax association file. TextEditSetWin - + TextEditSetWin - + Tab Setting Tab 设置 - + Set Tab Length Tab 字符长度 - + Space Replacement Tab 使用空格替换tab - + Big Text Size 大文本文件大小 - + Beyond this size, it can only be read-only and displayed in blocks 文本文件超过该值时,只能以只读的方式进行分块加载显示。 - + Exceed(MB) 超过(MB) - - - (50-300MB) - + + + Clear openfile list record on close + 关闭时清除打开历史记录 - + Font Setting 字体设置 - + Txt File Font: Txt 文件字体 - + Set 设置 - + App Font Color: - + TextLabel - + Set 设置 - + Restore files opened on close 恢复上次关闭时的打开文件 @@ -7491,17 +8047,17 @@ Double-click a column item to modify the syntax association file. 选择字体 - + App Font Foreground Color - + The App Font - + User define Txt Font 用户自定义文本字体 @@ -7548,75 +8104,63 @@ Double-click a column item to modify the syntax association file. UserRegister - + Free Trial 免费永久试用版本(捐赠可获取注册码) - - + + Registered Version 注册过的正版软件!(恭喜) - + License Expired 许可证过期(可捐赠获取) - + License Error 错误的注册码(可重新输入) - - - - - - + + + + + + Licence Key 许可证 - + It is already a registered version. 当前已经是注册版! - + Please scanning the donation, Write your email address in the message area. You will get the registration code! 请微信扫描捐赠,在留言处留下您的邮件地址,注册码将通过邮件发送给您。 - + Please enter the correct registration code! 请输入正确的注册码! - + Congratulations on your successful registration. 恭喜注册成功! - - + + Registration failed. Please try again later. 注册失败,请稍后再试! - - Please scanning the donation, get and enter the correct code ! - 请微信扫码赞赏后,输入转账单号后11位到许可序列码中。 - - - Please check code length , Only the last 11 digits are required ! - 请检查许可序列长度,只需要后11位即可。 - - - Processing succeeded. We will process your registration code in the background. It may take 1-3 days. - 处理成功。我们将在1-3天内处理您的许可注册码。 - UserRegisterClass diff --git a/src/scintillaeditview.cpp b/src/scintillaeditview.cpp index f3413a6..1ad4494 100755 --- a/src/scintillaeditview.cpp +++ b/src/scintillaeditview.cpp @@ -1,4 +1,4 @@ -#include "scintillaeditview.h" +#include "scintillaeditview.h" #include "common.h" #include "rgba_icons.h" @@ -7,12 +7,13 @@ #include "qtlangset.h" #include "findwin.h" #include "filemanager.h" +#include "shortcutkeymgr.h" +#include "markdownview.h" #include #include #include #include -//#include #include #include #include @@ -198,6 +199,9 @@ LanguageName ScintillaEditView::langNames[L_EXTERNAL + 1] = { ScintillaEditView::ScintillaEditView(QWidget *parent,bool isBigText) : QsciScintilla(parent), m_NoteWin(nullptr), m_preFirstLineNum(0), m_curPos(0), m_hasHighlight(false), m_bookmarkPng(nullptr), m_styleColorMenu(nullptr), m_isBigText(isBigText), m_curBlockLineStartNum(0) +#ifdef Q_OS_WIN + ,m_isInTailStatus(false) +#endif { init(); } @@ -210,8 +214,69 @@ ScintillaEditView::~ScintillaEditView() { delete m_bookmarkPng; } +#ifdef Q_OS_WIN + deleteTailFileThread(); +#endif } +ScintillaEditView::ScintillaEditView():QsciScintilla(nullptr),m_NoteWin(nullptr), m_preFirstLineNum(0), m_curPos(0), m_hasHighlight(false), m_bookmarkPng(nullptr), m_styleColorMenu(nullptr), m_isBigText(false), m_curBlockLineStartNum(0) +#ifdef Q_OS_WIN +, m_isInTailStatus(false) +#endif +{ + m_pScintillaFunc = (SCINTILLA_FUNC)this->SendScintillaPtrResult(SCI_GETDIRECTFUNCTION); + m_pScintillaPtr = (SCINTILLA_PTR)this->SendScintillaPtrResult(SCI_GETDIRECTPOINTER); + + + if (!m_pScintillaFunc) + { + throw std::runtime_error("ScintillaEditView::init : SCI_GETDIRECTFUNCTION message failed"); + } + + if (!m_pScintillaPtr) + { + throw std::runtime_error("ScintillaEditView::init : SCI_GETDIRECTPOINTER message failed"); + } +} + +ScintillaEditView* ScintillaEditView::createEditForSearch() +{ + return new ScintillaEditView(); +} + + +//截获ESC键盘,让界面去退出当前的子界面 +void ScintillaEditView::keyPressEvent(QKeyEvent* event) +{ + switch (event->key()) + { + case Qt::Key_Escape: + if (m_NoteWin != nullptr) + { + m_NoteWin->on_quitActiveWindow(); + } + break; + default: + break; + } + return QsciScintilla::keyPressEvent(event); +} + + +void ScintillaEditView::mouseReleaseEvent(QMouseEvent* ev) +{ + QsciScintilla::mouseReleaseEvent(ev); + + if (ev->button() == Qt::LeftButton) + { + if (hasSelectedText()) + { + emit delayWork(); + } + } +} + + void ScintillaEditView::setBigTextMode(bool isBigText) { m_isBigText = isBigText; @@ -432,6 +497,12 @@ QString ScintillaEditView::getTagByLexerId(int lexerId) case L_FLASH: return("flash"); + case L_MATLAB: + return ("matlab"); + + case L_MARKDOWN: + return("markdown"); + case L_NSIS: return "nsis"; @@ -475,9 +546,6 @@ QString ScintillaEditView::getTagByLexerId(int lexerId) case L_VERILOG: return "verilog"; - case L_MATLAB: - return "matlab"; - case L_HASKELL: break; case L_INNO: @@ -692,6 +760,12 @@ QsciLexer* ScintillaEditView::createLexer(int lexerId, QString tag, bool isOrigi ret = new QsciLexerCPP(); ret->setLexerTag("flash"); break; + case L_MATLAB: + ret = new QsciLexerMatlab(); + break; + case L_MARKDOWN: + ret = new QsciLexerMarkdown(); + break; case L_NSIS: ret = new QsciLexerNsis(); break; @@ -735,9 +809,6 @@ QsciLexer* ScintillaEditView::createLexer(int lexerId, QString tag, bool isOrigi case L_VERILOG: ret = new QsciLexerVerilog(); break; - case L_MATLAB: - ret = new QsciLexerMatlab(); - break; case L_HASKELL: break; case L_INNO: @@ -1373,6 +1444,16 @@ void ScintillaEditView::bookmarkToggle(intptr_t lineno) const { bookmarkAdd(lineno); } +void ScintillaEditView::bookmarkAdd(QSet& lineSet) +{ + QSet::const_iterator i = lineSet.constBegin(); + while (i != lineSet.constEnd()) { + bookmarkAdd(*i); + ++i; + } +} + + void ScintillaEditView::bookmarkClearAll() const { this->execute(SCI_MARKERDELETEALL, _SC_MARGE_SYBOLE); } @@ -1720,7 +1801,7 @@ void ScintillaEditView::highlightViewWithWord(QString & word2Hilite) QByteArray whatMark = word2Hilite.toUtf8(); - SendScintilla(SCI_SETSEARCHFLAGS, SCFIND_REGEXP | SCFIND_MATCHCASE | SCFIND_WHOLEWORD | SCFIND_REGEXP_SKIPCRLFASONE); + SendScintilla(SCI_SETSEARCHFLAGS, SCFIND_MATCHCASE /*| SCFIND_WHOLEWORD*/ | SCFIND_REGEXP_SKIPCRLFASONE); for (; currentLine < lastLine; ++currentLine) { @@ -1891,6 +1972,9 @@ void ScintillaEditView::contextUserDefineMenuEvent(QMenu* menu) }); menu->addSeparator(); + + menu->addAction(tr("Markdown View"), this, &ScintillaEditView::on_viewMarkdown); + menu->addAction(tr("Word Count"), [this]() { showWordNums(); }); @@ -2205,12 +2289,34 @@ void ScintillaEditView::showWordNums() QString word = selectedText(); if (!word.isEmpty()) { - QMessageBox::about(this, tr("Word Nums"), tr("Current Select Word Nums is %1 .").arg(word.size())); + int lineNum = word.count("\n"); + if (!word.endsWith("\n")) + { + ++lineNum; } + + //\s是包含了换行符的,所有要单独统计\r\n换换行符,排除一下 + QRegExp warpRe("[\r\n]"); + int wrapNums = word.count(warpRe); + QRegExp bkRe("\\s"); + int blank = word.count(bkRe); + QMessageBox::about(this, tr("Word Nums"), tr("Current Select Word Nums is %1 . \nLine nums is %2 . \nSpace nums is %3, Non-space is %4 .").\ + arg(word.size()-wrapNums).arg(lineNum).arg(blank-wrapNums).arg(word.size()-blank)); + } } else { - QMessageBox::about(this, tr("Word Nums"), tr("Current Doc Word Nums is %1 .").arg(this->text().size())); + int lineNum = this->lines(); + QString text = this->text(); + + //\s是包含了换行符的,所有要单独统计\r\n换换行符,排除一下 + QRegExp warpRe("[\r\n]"); + int wrapNums = text.count(warpRe); + QRegExp bkRe("\\s"); + int blank = text.count(bkRe); + + QMessageBox::about(this, tr("Word Nums"), tr("Current Doc Word Nums is %1 . \nLine nums is %2 . \nSpace nums is %3, Non-space is %4 .").\ + arg(text.size() - wrapNums).arg(lineNum).arg(blank - wrapNums).arg(text.size() - blank)); } } @@ -2568,12 +2674,22 @@ void ScintillaEditView::mouseDoubleClickEvent(QMouseEvent * e) } while (0); } + //20230219先双击选中,再按住ctrl,再双击别的地方选中。此时是进入多选状态。 + //这里必须要直接返回,不能做delayWork。否则因为delaywork里面不能判断多选,而数据越界崩溃 + if (hasSelectedText()) + { + QsciScintilla::mouseDoubleClickEvent(e); + return; + } + + //执行下面mouseDoubleClickEvent后,又会选中。此时如果上面已经有选中,则会多选 QsciScintilla::mouseDoubleClickEvent(e); if (hasSelectedText()) { emit delayWork(); } + } void ScintillaEditView::changeCase(const TextCaseType & caseToConvert, QString& strToConvert) const @@ -3617,7 +3733,7 @@ void ScintillaEditView::updateThemes() } } -void getFoldColor(QColor& fgColor, QColor& bgColor, QColor& activeFgColor) +static void getFoldColor(QColor& fgColor, QColor& bgColor, QColor& activeFgColor) { //这里看起来反了,但是实际代码就是如此 fgColor = StyleSet::s_global_style->fold.bgColor; @@ -4024,3 +4140,197 @@ void ScintillaEditView::setGlobalFont(int style) break; } } + +bool ScintillaEditView::isFoldIndentBased() const +{ + QsciLexer* lexer = this->lexer(); + + if (lexer != nullptr) + { + int lexerId = lexer->lexerId(); + + return lexerId == L_PYTHON + || lexerId == L_COFFEESCRIPT + || lexerId == L_HASKELL + || lexerId == L_VB + || lexerId == L_YAML; + } + return false; +} + +const int MAX_FOLD_COLLAPSE_LEVEL = 8; + +struct FoldLevelStack +{ + int levelCount = 0; + intptr_t levelStack[MAX_FOLD_COLLAPSE_LEVEL]{}; + + void push(intptr_t level) + { + while (levelCount != 0 && level <= levelStack[levelCount - 1]) + { + --levelCount; + } + levelStack[levelCount++] = level; + } +}; + +bool ScintillaEditView::isFolded(size_t line) +{ + return (0 != execute(SCI_GETFOLDEXPANDED, line)); +}; + +void ScintillaEditView::fold(size_t line, bool mode) +{ + auto endStyled = execute(SCI_GETENDSTYLED); + auto len = execute(SCI_GETTEXTLENGTH); + + if (endStyled < len) + execute(SCI_COLOURISE, 0, -1); + + intptr_t headerLine; + auto level = execute(SCI_GETFOLDLEVEL, line); + + if (level & SC_FOLDLEVELHEADERFLAG) + headerLine = line; + else + { + headerLine = execute(SCI_GETFOLDPARENT, line); + if (headerLine == -1) + return; + } + + if (isFolded(headerLine) != mode) + { + execute(SCI_TOGGLEFOLD, headerLine); + + //SCNotification scnN; + //scnN.nmhdr.code = SCN_FOLDINGSTATECHANGED; + //scnN.nmhdr.hwndFrom = _hSelf; + //scnN.nmhdr.idFrom = 0; + //scnN.line = headerLine; + //scnN.foldLevelNow = isFolded(headerLine) ? 1 : 0; //folded:1, unfolded:0 + + //::SendMessage(_hParent, WM_NOTIFY, 0, reinterpret_cast(&scnN)); + } +} + +void ScintillaEditView::collapseFoldIndentBased(int level, bool mode) +{ + execute(SCI_COLOURISE, 0, -1); + + FoldLevelStack levelStack; + ++level; + + const intptr_t maxLine = execute(SCI_GETLINECOUNT); + intptr_t line = 0; + + while (line < maxLine) + { + intptr_t level = execute(SCI_GETFOLDLEVEL, line); + if (level & SC_FOLDLEVELHEADERFLAG) + { + level &= SC_FOLDLEVELNUMBERMASK; + levelStack.push(level); + if (level == levelStack.levelCount) + { + if (isFolded(line) != mode) + { + fold(line, mode); + } + line = execute(SCI_GETLASTCHILD, line, -1); + } + } + ++line; + } +} + +void ScintillaEditView::collapse(int level, bool mode) +{ + if (isFoldIndentBased()) + { + return collapseFoldIndentBased(level, mode); + } + + execute(SCI_COLOURISE, 0, -1); + + intptr_t maxLine = execute(SCI_GETLINECOUNT); + + for (int line = 0; line < maxLine; ++line) + { + intptr_t lineLevel = execute(SCI_GETFOLDLEVEL, line); + if (lineLevel & SC_FOLDLEVELHEADERFLAG) + { + lineLevel -= SC_FOLDLEVELBASE; + if (level == (lineLevel & SC_FOLDLEVELNUMBERMASK)) + if (isFolded(line) != mode) + { + fold(line, mode); + } + } + } +} + +void ScintillaEditView::comment(int type) +{ + switch (type) + { + case ADD_DEL_LINE_COM: + doBlockComment(cm_toggle); + break; + case ADD_BK_COM: + doStreamComment(); + break; + case DEL_BK_COM: + undoStreamComment(); + break; + default: + break; + } +} + +#ifdef Q_OS_WIN +void ScintillaEditView::deleteTailFileThread() +{ + if (m_isInTailStatus) + { + m_isInTailStatus = false; + + qlonglong threadAddr = this->property(Tail_Thread).toLongLong(); + + std::thread* pListenThread = (std::thread*)(threadAddr); + + if (pListenThread->joinable()) + { + pListenThread->join(); + } + + delete pListenThread; + } +} +#endif + +//显示markdown编辑器 +void ScintillaEditView::on_viewMarkdown() +{ + if (m_markdownWin.isNull()) + { + m_markdownWin = new MarkdownView(this); + m_markdownWin->setAttribute(Qt::WA_DeleteOnClose); + connect(this, &ScintillaEditView::textChanged, this, &ScintillaEditView::on_updataMarkdown); + } + + QString text = this->text(); + m_markdownWin->viewMarkdown(text); + m_markdownWin->show(); +} + +void ScintillaEditView::on_updataMarkdown() +{ + if (!m_markdownWin.isNull()) + { + QString text = this->text(); + m_markdownWin->viewMarkdown(text); + m_markdownWin->show(); + } +} diff --git a/src/scintillaeditview.h b/src/scintillaeditview.h index db44317..71180e4 100755 --- a/src/scintillaeditview.h +++ b/src/scintillaeditview.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include #include @@ -7,6 +7,7 @@ #include #include "common.h" #include "Sorters.h" +#include "markdownview.h" typedef sptr_t(*SCINTILLA_FUNC) (sptr_t ptr, unsigned int, uptr_t, sptr_t); @@ -139,9 +140,6 @@ public: bool gotoPrePos(); bool gotoNextPos(); - - /*virtual void adjuctSkinStyle();*/ - //设置文档的缩进参考线 void setIndentGuide(bool willBeShowed); @@ -210,16 +208,27 @@ public: //获取当前块的开始行号。只在大文件只读模式下有效。其余模式下均返回0 quint32 getBigTextBlockStartLine(); void setBigTextBlockStartLine(quint32 line); + void collapse(int level, bool mode); + void comment(int type); +#ifdef Q_OS_WIN + void deleteTailFileThread(); +#endif + + void bookmarkAdd(QSet& lineSet); + + static ScintillaEditView* createEditForSearch(); + signals: void delayWork(); protected: - virtual void addHotSpot(); void setStylesFont(const QFont& f, int style, int setBitMask = ALL_SET_Bit); + void keyPressEvent(QKeyEvent* event) override; + virtual void mouseReleaseEvent(QMouseEvent* ev) override; private: - + ScintillaEditView(); void getText(char * dest, size_t start, size_t end) const; QString getGenericTextAsQString(size_t start, size_t end) const; @@ -237,6 +246,12 @@ private: void changeStyleColor(int sytleId); void initStyleColorMenu(); + bool isFolded(size_t line); + void fold(size_t line, bool mode); + void collapseFoldIndentBased(int level, bool mode); + bool isFoldIndentBased() const; + + public: static const int _SC_MARGE_LINENUMBER; static const int _SC_MARGE_SYBOLE; @@ -283,8 +298,8 @@ private slots: void slot_clearHightWord(); void slot_bookMarkClicked(int margin, int line, Qt::KeyboardModifiers state); - - + void on_viewMarkdown(); + void on_updataMarkdown(); private: @@ -313,10 +328,18 @@ private: quint32 m_curBlockLineStartNum; QMap m_addrLineNumMap;//大文本模式下,地址和行号的对应关系。只需要首尾即可 + + QPointer m_markdownWin; + public: static int s_tabLens; static bool s_noUseTab; static int s_bigTextSize; bool m_hasHighlight; + + +#ifdef Q_OS_WIN + std::atomic m_isInTailStatus; +#endif }; diff --git a/src/scintillahexeditview.cpp b/src/scintillahexeditview.cpp index 94526ae..8a0002c 100755 --- a/src/scintillahexeditview.cpp +++ b/src/scintillahexeditview.cpp @@ -1,4 +1,4 @@ -#include "scintillahexeditview.h" +#include "scintillahexeditview.h" #include "styleset.h" #include "ccnotepad.h" @@ -6,10 +6,11 @@ #include #include -// initialize the static variable bool ScintillaHexEditView::_SciInit = false; #define DEFAULT_FONT_NAME "Courier New" +const int STYLE_COLOR_SELECT = 1; + ScintillaHexEditView::ScintillaHexEditView(QWidget *parent):QsciScintilla(parent), m_NoteWin(nullptr) { init(); @@ -98,16 +99,9 @@ void ScintillaHexEditView::slot_scrollYValueChange(int value) void ScintillaHexEditView::dragEnterEvent(QDragEnterEvent* event) { - //if (event->mimeData()->hasFormat("text/uri-list")) //只能打开文本文件 - //{ - // event->accept(); //可以在这个窗口部件上拖放对象 - //} - //else - //{ - // event->ignore(); - //} event->accept(); } + void ScintillaHexEditView::dropEvent(QDropEvent* e) { @@ -130,3 +124,10 @@ void ScintillaHexEditView::updateThemes() setMarginsBackgroundColor(StyleSet::s_global_style->line_number_margin.bgColor); setPaper(StyleSet::s_global_style->default_style.bgColor); } + +void ScintillaHexEditView::setStyle(int style, int startPos, int length) +{ + SendScintilla(SCI_STARTSTYLING, startPos); + SendScintilla(SCI_SETSTYLING, length, style); +} + diff --git a/src/scintillahexeditview.h b/src/scintillahexeditview.h index fc824ca..7a810a6 100755 --- a/src/scintillahexeditview.h +++ b/src/scintillahexeditview.h @@ -1,7 +1,8 @@ -#pragma once +#pragma once #include #include +#include #include #include @@ -25,6 +26,7 @@ public: private: void init(); + void setStyle(int style, int startPos, int length); private slots: void slot_scrollYValueChange(int value); @@ -33,7 +35,6 @@ protected: void dragEnterEvent(QDragEnterEvent * event); void dropEvent(QDropEvent * e); - private: static bool _SciInit; diff --git a/src/shortcutkeymgr.cpp b/src/shortcutkeymgr.cpp index 3a2507a..88e3969 100755 --- a/src/shortcutkeymgr.cpp +++ b/src/shortcutkeymgr.cpp @@ -1,4 +1,4 @@ -#include "shortcutkeymgr.h" +#include "shortcutkeymgr.h" #include "shortcutkeyeditwin.h" #include "ccnotepad.h" @@ -10,15 +10,12 @@ QMap* ShortcutKeyMgr::s_shortcutKeysMap = nullptr; -//QMap * qScintShortcutKeyValueMap = nullptr; - struct ShortcutKeySt { - QString iniTag;//±£´æÔÚIniÎļþÖеÄÃû³Æ - QString name;//ÏÔʾÔڱí¸ñÖеÄÃû³Æ - //QString keyDesc;//qkeysequenceµÄÃèÊö + QString iniTag;//保存在Ini文件中的名称 + QString name;//显示在表格中的名称 QKeySequence key; - bool canModify;//ÄܷñÐ޸Ä + bool canModify;//能否修改 ShortcutKeySt() = default; ShortcutKeySt(QString name_, QString iniTag_, bool canMofidy=true) :name(name_), iniTag(iniTag_), canModify(canMofidy) @@ -86,12 +83,12 @@ void ShortcutKeyMgr::initShortcutKeysMap() << ShortcutKeySt(tr("Save All File"), Save_All_File) \ << ShortcutKeySt(tr("Close"), Close, QString("Ctrl+W")) \ << ShortcutKeySt(tr("Close All"), Close_All, QString("Ctrl+Shift+W")) \ - << ShortcutKeySt(tr("Cut"), Cut, QString("Ctrl+X"),false) \ + << ShortcutKeySt(tr("Cut"), Cut, QString("Ctrl+X"), false) \ << ShortcutKeySt(tr("Copy"), Copy, QString("Ctrl+C"), false) \ << ShortcutKeySt(tr("Paste"), Paste, QString("Ctrl+V"), false) \ << ShortcutKeySt(tr("Undo"), Undo, QString("Ctrl+Z"), false) \ << ShortcutKeySt(tr("Redo"), Redo, QString("Ctrl+Y"), false) \ - << ShortcutKeySt(tr("Find"), Find, QString("Ctrl+F"),false) \ + << ShortcutKeySt(tr("Find"), Find, QString("Ctrl+F"), false) \ << ShortcutKeySt(tr("Replace"), Replace, QString("Ctrl+H")) \ << ShortcutKeySt(tr("Dir Find"), DirFind, QString("Ctrl+Shift+D")) \ << ShortcutKeySt(tr("Mark"), Mark) \ @@ -111,20 +108,38 @@ void ShortcutKeyMgr::initShortcutKeysMap() << ShortcutKeySt(tr("transform encoding"), Trans_code) \ << ShortcutKeySt(tr("batch rename file"), Batch_rename) \ << ShortcutKeySt(tr("Format Xml"), Format_Xml) \ - << ShortcutKeySt(tr("Format Json"), Format_Json); + << ShortcutKeySt(tr("Format Json"), Format_Json) \ + << ShortcutKeySt(tr("Add/Del Line Comment"), ADD_DELETE_LINE_COMMENT, QString("Ctrl+Q")) \ + << ShortcutKeySt(tr("Add Block Comment"), ADD_BLOCK_COMMENT, QString("Ctrl+K")) \ + << ShortcutKeySt(tr("Del Block Comment"), CANCEL_BLOCK_COMMENT, QString("Ctrl+Shift+K")) \ + << ShortcutKeySt(tr("Fold Level 1"), FOLD_1, QString("Alt+1")) \ + << ShortcutKeySt(tr("Fold Level 2"), FOLD_2, QString("Alt+2")) \ + << ShortcutKeySt(tr("Fold Level 3"), FOLD_3, QString("Alt+3")) \ + << ShortcutKeySt(tr("Fold Level 4"), FOLD_4, QString("Alt+4")) \ + << ShortcutKeySt(tr("Fold Level 5"), FOLD_5, QString("Alt+5")) \ + << ShortcutKeySt(tr("Fold Level 6"), FOLD_6, QString("Alt+6")) \ + << ShortcutKeySt(tr("Fold Level 7"), FOLD_7, QString("Alt+7")) \ + << ShortcutKeySt(tr("Fold Level 8"), FOLD_8, QString("Alt+8")) \ + << ShortcutKeySt(tr("UNFold Level 1"), UNFOLD_1, QString("Alt+Shift+1")) \ + << ShortcutKeySt(tr("UNFold Level 2"), UNFOLD_2, QString("Alt+Shift+2")) \ + << ShortcutKeySt(tr("UNFold Level 3"), UNFOLD_3, QString("Alt+Shift+3")) \ + << ShortcutKeySt(tr("UNFold Level 4"), UNFOLD_4, QString("Alt+Shift+4")) \ + << ShortcutKeySt(tr("UNFold Level 5"), UNFOLD_5, QString("Alt+Shift+5")) \ + << ShortcutKeySt(tr("UNFold Level 6"), UNFOLD_6, QString("Alt+Shift+6")) \ + << ShortcutKeySt(tr("UNFold Level 7"), UNFOLD_7, QString("Alt+Shift+7")) \ + << ShortcutKeySt(tr("UNFold Level 8"), UNFOLD_8, QString("Alt+Shift+8")); - for (int i = 0; i < shortCutTable.size(); ++i) { s_shortcutKeysMap->insert(shortCutTable.at(i).iniTag, i); } - //´ÓÎļþÖжÁȡÓû§Ð޸ĹýµÄÅäÖñí¡£ + //从文件中读取用户修改过的配置表。 loadUserDefSet(); } } -//Îñ±ØÏȵ÷ÓÃinitShortcutKeysMap() +//务必先调用initShortcutKeysMap() QKeySequence ShortcutKeyMgr::getUserDefShortcutKey(QString iniTag) { if (s_shortcutKeysMap->contains(iniTag)) @@ -134,7 +149,7 @@ QKeySequence ShortcutKeyMgr::getUserDefShortcutKey(QString iniTag) return QKeySequence(); } -//´ÓÓû§iniÅäÖÃÖмÓÔؿì½ݼüÅäÖà +//从用户ini配置中加载快捷键配置 void ShortcutKeyMgr::loadUserDefSet() { QString userDefFile = QString("notepad/shortcuttab"); @@ -159,7 +174,7 @@ void ShortcutKeyMgr::loadUserDefSet() } } -//Ð޸ÄÅäÖÃÎļþÖеĿì½ݼü¶¨Ò塣inittag iniµÄkey, keySeqStr iniµÄvalue¡£ÄڴæҲÐ޸ÄÁË +//修改配置文件中的快捷键定义。inittag ini的key, keySeqStr ini的value。内存也修改了 bool ShortcutKeyMgr::ModifyShortCutKey(QString initTag, QString keySeqStr) { QString userDefFile = QString("notepad/shortcuttab"); @@ -210,7 +225,7 @@ void ShortcutKeyMgr::initNddShortcutTable() } } -//³õʼ»¯qscintÄڲ¿µĿì½ݼü¡£ĿǰÕⲿ·ֲ»ÄÜÐ޸ġ£ +//初始化qscint内部的快捷键。目前这部分不能修改。 void ShortcutKeyMgr::initQscintShortcutTable() { QsciScintilla* pNote = new QsciScintilla(nullptr); @@ -273,7 +288,7 @@ int ShortcutKeyMgr::isKeySeqExist(int row, QString keySeq, int &type) } return -1; } -//˫»÷Ð޸IJۺ¯Êý +//双击修改槽函数 void ShortcutKeyMgr::slot_edit(QTableWidgetItem* item) { int row = item->row(); @@ -289,14 +304,14 @@ void ShortcutKeyMgr::slot_edit(QTableWidgetItem* item) pWin->setCurKeyDesc(shortCutTable.at(row).key.toString()); int ret = pWin->exec(); - if (1 == ret) //ȷ¶¨ + if (1 == ret) //确定 { QKeySequence newKeySeq = pWin->getNewKeySeq(); QTableWidgetItem* item = ui.tableWidget->item(row, 1); if (item != nullptr) { - //¼ì²éÊǷñ³åͻ£¬Èç¹û³åͻ£¬Ôò²»ÉèÖá£ÏÈԤÁô + //检查是否冲突,如果冲突,则不设置。先预留 int conflictType = 0; int existId = isKeySeqExist(row, newKeySeq.toString(), conflictType); if (-1 == existId) @@ -329,7 +344,7 @@ void ShortcutKeyMgr::slot_edit(QTableWidgetItem* item) } } } - else if (2 == ret)//ɾ³ý + else if (2 == ret)//删除 { QKeySequence newKeySeq(QKeySequence::UnknownKey); diff --git a/src/shortcutkeymgr.h b/src/shortcutkeymgr.h index f7c4e34..65bf293 100755 --- a/src/shortcutkeymgr.h +++ b/src/shortcutkeymgr.h @@ -1,4 +1,4 @@ -#pragma once +#pragma once #include #include "ui_shortcutkeymgr.h" @@ -36,9 +36,27 @@ enum Shortcut_Key_ID { Batch_rename_ID, Format_Xml_ID, Format_Json_ID, + ADD_DEL_LINE_COM, + ADD_BK_COM, + DEL_BK_COM, + S_K_FOLD_1, + S_K_FOLD_2, + S_K_FOLD_3, + S_K_FOLD_4, + S_K_FOLD_5, + S_K_FOLD_6, + S_K_FOLD_7, + S_K_FOLD_8, + S_K_UNFOLD_1, + S_K_UNFOLD_2, + S_K_UNFOLD_3, + S_K_UNFOLD_4, + S_K_UNFOLD_5, + S_K_UNFOLD_6, + S_K_UNFOLD_7, + S_K_UNFOLD_8, - - Shortcut_End_ID,//×ÜÊÇÔÚ×îµ×Ï + Shortcut_End_ID,//总是在最底下 }; static const char* New_File = "newfile"; @@ -74,6 +92,26 @@ static const char* Batch_rename = "batchrename"; static const char* Format_Xml = "formatxml"; static const char* Format_Json = "formatjson"; +static const char* ADD_DELETE_LINE_COMMENT = "linecom"; +static const char* ADD_BLOCK_COMMENT = "bkcom"; +static const char* CANCEL_BLOCK_COMMENT = "cbkcom"; + +static const char* FOLD_1 = "fold_1"; +static const char* FOLD_2 = "fold_2"; +static const char* FOLD_3 = "fold_3"; +static const char* FOLD_4 = "fold_4"; +static const char* FOLD_5 = "fold_5"; +static const char* FOLD_6 = "fold_6"; +static const char* FOLD_7 = "fold_7"; +static const char* FOLD_8 = "fold_8"; +static const char* UNFOLD_1 = "unfold_1"; +static const char* UNFOLD_2 = "unfold_2"; +static const char* UNFOLD_3 = "unfold_3"; +static const char* UNFOLD_4 = "unfold_4"; +static const char* UNFOLD_5 = "unfold_5"; +static const char* UNFOLD_6 = "unfold_6"; +static const char* UNFOLD_7 = "unfold_7"; +static const char* UNFOLD_8 = "unfold_8"; class ShortcutKeyMgr : public QMainWindow { diff --git a/src/texteditsetwin.cpp b/src/texteditsetwin.cpp index 78d82bc..5698527 100755 --- a/src/texteditsetwin.cpp +++ b/src/texteditsetwin.cpp @@ -2,6 +2,7 @@ #include "scintillaeditview.h" #include "ccnotepad.h" #include "qtlangset.h" +#include "nddsetting.h" #include #include @@ -21,6 +22,9 @@ TextEditSetWin::TextEditSetWin(QWidget *parent) ui.restoreFile->setChecked((CCNotePad::s_restoreLastFile == 1)); + int clearOpenfilelist = NddSetting::getKeyValueFromDelayNumSets(CLEAR_OPENFILE_ON_CLOSE); + + ui.openfileRecord->setChecked((clearOpenfilelist ==1)); QPalette pal = QApplication::palette(); @@ -28,7 +32,6 @@ TextEditSetWin::TextEditSetWin(QWidget *parent) f.fill(pal.text().color()); ui.appFontColorLabel->setPixmap(f); - //ui.appFontColorLabel } TextEditSetWin::~TextEditSetWin() @@ -87,6 +90,11 @@ void TextEditSetWin::save() { CCNotePad::s_restoreLastFile = restoreFile; } + + //注意这里是禁用,和启用是相反的意思 + int clearOpenfilelist = (ui.openfileRecord->isChecked() ? 1 : 0); + + NddSetting::updataKeyValueFromDelayNumSets(CLEAR_OPENFILE_ON_CLOSE, clearOpenfilelist); } void TextEditSetWin::slot_txtFontSet() @@ -97,15 +105,21 @@ void TextEditSetWin::slot_txtFontSet() //是从对比规则里面弹出来的,不进行文本的设置 return; } + QtLangSet* pWin = pMainWin->getLangSet(); +#if 0 QtLangSet* pWin = new QtLangSet(QString("txt"), this); pWin->setAttribute(Qt::WA_DeleteOnClose); connect(pWin, &QtLangSet::viewStyleChange, pMainWin, &CCNotePad::slot_viewStyleChange); connect(pWin, &QtLangSet::viewLexerChange, pMainWin, &CCNotePad::slot_viewLexerChange); pWin->show(); +#endif + if (pWin != nullptr) + { pWin->selectInitLangTag("txt"); } +} #if 0 //app字体颜色设置 diff --git a/src/texteditsetwin.ui b/src/texteditsetwin.ui index 69c1e89..8a29b98 100755 --- a/src/texteditsetwin.ui +++ b/src/texteditsetwin.ui @@ -84,7 +84,7 @@ 50 - 300 + 600 100 @@ -94,7 +94,7 @@ - (50-300MB) + (50-600MB) @@ -221,6 +221,13 @@ + + + + Clear openfile list record on close + + + diff --git a/插件编程开发说明.docx b/插件编程开发说明.docx index 7208087..1875478 100755 Binary files a/插件编程开发说明.docx and b/插件编程开发说明.docx differ