#include "scintillaeditview.h" #include "common.h" #include "rgba_icons.h" #include "ccnotepad.h" #include "styleset.h" #include "qtlangset.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "findwin.h" // initialize the static variable #define DEFAULT_FONT_NAME "Courier New" //"Microsoft YaHei" int ScintillaEditView::s_tabLens = 4; //默认不使用tab,使用space替换 bool ScintillaEditView::s_noUseTab = true; int ScintillaEditView::s_bigTextSize = 100; const int ScintillaEditView::_SC_MARGE_LINENUMBER = 0; const int ScintillaEditView::_SC_MARGE_SYBOLE = 1; const int ScintillaEditView::_SC_MARGE_FOLDER = 2; const int MAX_PRE_NEXT_TIMES = 30; //const int ScintillaEditView::_markersArray[][NB_FOLDER_STATE] = { // {SC_MARKNUM_FOLDEROPEN, SC_MARKNUM_FOLDER, SC_MARKNUM_FOLDERSUB, SC_MARKNUM_FOLDERTAIL, SC_MARKNUM_FOLDEREND, SC_MARKNUM_FOLDEROPENMID, SC_MARKNUM_FOLDERMIDTAIL}, // {SC_MARK_MINUS, SC_MARK_PLUS, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY}, // {SC_MARK_ARROWDOWN, SC_MARK_ARROW, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY, SC_MARK_EMPTY}, // {SC_MARK_CIRCLEMINUS, SC_MARK_CIRCLEPLUS,SC_MARK_VLINE, SC_MARK_LCORNERCURVE, SC_MARK_CIRCLEPLUSCONNECTED, SC_MARK_CIRCLEMINUSCONNECTED, SC_MARK_TCORNERCURVE}, // {SC_MARK_BOXMINUS, SC_MARK_BOXPLUS, SC_MARK_VLINE, SC_MARK_LCORNER, SC_MARK_BOXPLUSCONNECTED, SC_MARK_BOXMINUSCONNECTED, SC_MARK_TCORNER} //}; #ifdef Q_OS_WIN LanguageName ScintillaEditView::langNames[L_EXTERNAL + 1] = { {QString("normal"), QString("Normal QString"), QString("Normal text file"), L_TXT, SCLEX_NULL}, {QString("php"), QString("PHP"), QString("PHP Hypertext Preprocessor file"), L_PHP, SCLEX_HTML}, {QString("c"), QString("C"), QString("C source file"), L_C, SCLEX_CPP}, {QString("cpp"), QString("C++"), QString("C++ source file"), L_CPP, SCLEX_CPP}, {QString("cs"), QString("C#"), QString("C# source file"), L_CS, SCLEX_CPP}, {QString("objc"), QString("Objective-C"), QString("Objective-C source file"), L_OBJC, SCLEX_CPP}, {QString("java"), QString("Java"), QString("Java source file"), L_JAVA, SCLEX_CPP}, {QString("rc"), QString("RC"), QString("Windows Resource file"), L_RC, SCLEX_CPP}, {QString("html"), QString("HTML"), QString("Hyper Text Markup Language file"), L_HTML, SCLEX_HTML}, {QString("xml"), QString("XML"), QString("eXtensible Markup Language file"), L_XML, SCLEX_XML}, {QString("makefile"), QString("Makefile"), QString("Makefile"), L_MAKEFILE, SCLEX_MAKEFILE}, {QString("pascal"), QString("Pascal"), QString("Pascal source file"), L_PASCAL, SCLEX_PASCAL}, {QString("batch"), QString("Batch"), QString("Batch file"), L_BATCH, SCLEX_BATCH}, {QString("ini"), QString("ini"), QString("MS ini file"), L_INI, SCLEX_PROPERTIES}, {QString("nfo"), QString("NFO"), QString("MSDOS Style/ASCII Art"), L_ASCII, SCLEX_NULL}, {QString("udf"), QString("udf"), QString("User Defined language file"), L_USER, SCLEX_USER}, {QString("asp"), QString("ASP"), QString("Active Server Pages script file"), L_ASP, SCLEX_HTML}, {QString("sql"), QString("SQL"), QString("Structured Query Language file"), L_SQL, SCLEX_SQL}, {QString("vb"), QString("Visual Basic"), QString("Visual Basic file"), L_VB, SCLEX_VB}, {QString("javascript"), QString("JavaScript"), QString("JavaScript file"), L_JS, L_JAVASCRIPT}, {QString("css"), QString("CSS"), QString("Cascade Style Sheets File"), L_CSS, SCLEX_CSS}, {QString("perl"), QString("Perl"), QString("Perl source file"), L_PERL, SCLEX_PERL}, {QString("python"), QString("Python"), QString("Python file"), L_PYTHON, SCLEX_PYTHON}, {QString("lua"), QString("Lua"), QString("Lua source File"), L_LUA, SCLEX_LUA}, {QString("tex"), QString("TeX"), QString("TeX file"), L_TEX, SCLEX_TEX}, {QString("fortran"), QString("Fortran free form"), QString("Fortran free form source file"), L_FORTRAN, SCLEX_FORTRAN}, {QString("bash"), QString("Shell"), QString("Unix script file"), L_BASH, SCLEX_BASH}, {QString("actionscript"), QString("ActionScript"), QString("Flash ActionScript file"), L_FLASH, SCLEX_CPP}, {QString("nsis"), QString("NSIS"), QString("Nullsoft Scriptable Install System script file"), L_NSIS, SCLEX_NSIS}, {QString("tcl"), QString("TCL"), QString("Tool Command Language file"), L_TCL, SCLEX_TCL}, {QString("lisp"), QString("Lisp"), QString("List Processing language file"), L_LISP, SCLEX_LISP}, {QString("scheme"), QString("Scheme"), QString("Scheme file"), L_SCHEME, SCLEX_LISP}, {QString("asm"), QString("Assembly"), QString("Assembly language source file"), L_ASM, SCLEX_ASM}, {QString("diff"), QString("Diff"), QString("Diff file"), L_DIFF, SCLEX_DIFF}, {QString("props"), QString("Properties file"), QString("Properties file"), L_PROPS, SCLEX_PROPERTIES}, {QString("postscript"), QString("PostScript"), QString("PostScript file"), L_PS, SCLEX_PS}, {QString("ruby"), QString("Ruby"), QString("Ruby file"), L_RUBY, SCLEX_RUBY}, {QString("smalltalk"), QString("Smalltalk"), QString("Smalltalk file"), L_SMALLTALK, SCLEX_SMALLTALK}, {QString("vhdl"), QString("VHDL"), QString("VHSIC Hardware Description Language file"), L_VHDL, SCLEX_VHDL}, {QString("kix"), QString("KiXtart"), QString("KiXtart file"), L_KIX, SCLEX_KIX}, {QString("autoit"), QString("AutoIt"), QString("AutoIt"), L_AU3, SCLEX_AU3}, {QString("caml"), QString("CAML"), QString("Categorical Abstract Machine Language"), L_CAML, SCLEX_CAML}, {QString("ada"), QString("Ada"), QString("Ada file"), L_ADA, SCLEX_ADA}, {QString("verilog"), QString("Verilog"), QString("Verilog file"), L_VERILOG, SCLEX_VERILOG}, {QString("matlab"), QString("MATLAB"), QString("MATrix LABoratory"), L_MATLAB, SCLEX_MATLAB}, {QString("haskell"), QString("Haskell"), QString("Haskell"), L_HASKELL, SCLEX_HASKELL}, {QString("inno"), QString("Inno Setup"), QString("Inno Setup script"), L_INNO, SCLEX_INNOSETUP}, {QString("searchResult"), QString("Internal Search"), QString("Internal Search"), L_SEARCHRESULT, SCLEX_SEARCHRESULT}, {QString("cmake"), QString("CMake"), QString("CMake file"), L_CMAKE, SCLEX_CMAKE}, {QString("yaml"), QString("YAML"), QString("YAML Ain't Markup Language"), L_YAML, SCLEX_YAML}, {QString("cobol"), QString("COBOL"), QString("COmmon Business Oriented Language"), L_COBOL, SCLEX_COBOL}, {QString("gui4cli"), QString("Gui4Cli"), QString("Gui4Cli file"), L_GUI4CLI, SCLEX_GUI4CLI}, {QString("d"), QString("D"), QString("D programming language"), L_D, SCLEX_D}, {QString("powershell"), QString("PowerShell"), QString("Windows PowerShell"), L_POWERSHELL, SCLEX_POWERSHELL}, {QString("r"), QString("R"), QString("R programming language"), L_R, SCLEX_R}, {QString("jsp"), QString("JSP"), QString("JavaServer Pages script file"), L_JSP, SCLEX_HTML}, {QString("coffeescript"), QString("CoffeeScript"), QString("CoffeeScript file"), L_COFFEESCRIPT, SCLEX_COFFEESCRIPT}, {QString("json"), QString("json"), QString("JSON file"), L_JSON, SCLEX_JSON }, {QString("javascript.js"), QString("JavaScript"), QString("JavaScript file"), L_JAVASCRIPT, SCLEX_CPP }, {QString("fortran77"), QString("Fortran fixed form"), QString("Fortran fixed form source file"), L_FORTRAN_77, SCLEX_F77}, {QString("baanc"), QString("BaanC"), QString("BaanC File"), L_BAANC, SCLEX_BAAN }, {QString("srec"), QString("S-Record"), QString("Motorola S-Record binary data"), L_SREC, SCLEX_SREC}, {QString("ihex"), QString("Intel HEX"), QString("Intel HEX binary data"), L_IHEX, SCLEX_IHEX}, {QString("tehex"), QString("Tektronix extended HEX"), QString("Tektronix extended HEX binary data"), L_TEHEX, SCLEX_TEHEX}, {QString("swift"), QString("Swift"), QString("Swift file"), L_SWIFT, SCLEX_CPP}, {QString("asn1"), QString("ASN.1"), QString("Abstract Syntax Notation One file"), L_ASN1, SCLEX_ASN1}, {QString("avs"), QString("AviSynth"), QString("AviSynth scripts files"), L_AVS, SCLEX_AVS}, {QString("blitzbasic"), QString("BlitzBasic"), QString("BlitzBasic file"), L_BLITZBASIC, SCLEX_BLITZBASIC}, {QString("purebasic"), QString("PureBasic"), QString("PureBasic file"), L_PUREBASIC, SCLEX_PUREBASIC}, {QString("freebasic"), QString("FreeBasic"), QString("FreeBasic file"), L_FREEBASIC, SCLEX_FREEBASIC}, {QString("csound"), QString("Csound"), QString("Csound file"), L_CSOUND, SCLEX_CSOUND}, {QString("erlang"), QString("Erlang"), QString("Erlang file"), L_ERLANG, SCLEX_ERLANG}, {QString("escript"), QString("ESCRIPT"), QString("ESCRIPT file"), L_ESCRIPT, SCLEX_ESCRIPT}, {QString("forth"), QString("Forth"), QString("Forth file"), L_FORTH, SCLEX_FORTH}, {QString("latex"), QString("LaTeX"), QString("LaTeX file"), L_LATEX, SCLEX_LATEX}, {QString("mmixal"), QString("MMIXAL"), QString("MMIXAL file"), L_MMIXAL, SCLEX_MMIXAL}, {QString("nim"), QString("Nim"), QString("Nim file"), L_NIM, SCLEX_NIMROD}, {QString("nncrontab"), QString("Nncrontab"), QString("extended crontab file"), L_NNCRONTAB, SCLEX_NNCRONTAB}, {QString("oscript"), QString("OScript"), QString("OScript source file"), L_OSCRIPT, SCLEX_OSCRIPT}, {QString("rebol"), QString("REBOL"), QString("REBOL file"), L_REBOL, SCLEX_REBOL}, {QString("registry"), QString("registry"), QString("registry file"), L_REGISTRY, SCLEX_REGISTRY}, {QString("rust"), QString("Rust"), QString("Rust file"), L_RUST, SCLEX_RUST}, {QString("spice"), QString("Spice"), QString("spice file"), L_SPICE, SCLEX_SPICE}, {QString("txt2tags"), QString("txt2tags"), QString("txt2tags file"), L_TXT2TAGS, SCLEX_TXT2TAGS}, {QString("visualprolog"), QString("Visual Prolog"), QString("Visual Prolog file"), L_VISUALPROLOG, SCLEX_VISUALPROLOG}, {QString("typescript"), QString("TypeScript"), QString("TypeScript file"), L_TYPESCRIPT, SCLEX_CPP}, {QString("edifact"), QString("Edifact"), QString("Edifact file"), L_EDIFACT, SCLEX_EDIFACT}, {QString("markdown"), QString("Markdown"), QString("Markdown file"), L_MARKDOWN, SCLEX_MARKDOWN}, {QString("octave"), QString("Octave"), QString("Octave file"), L_OCTAVE, SCLEX_OCTAVE}, {QString("po"), QString("PO"), QString("PO file"), L_PO, SCLEX_PO}, {QString("pov"), QString("POV"), QString("POV file"), L_POV, SCLEX_POV}, {QString("avs"), QString("AVS"), QString("AVS file"), L_AVS, SCLEX_AVS}, {QString("idl"), QString("IDL"), QString("IDL file"), L_IDL, SCLEX_IDL}, {QString("go"), QString("GO"), QString("GO file"), L_GO, SCLEX_GO}, {QString("txt"), QString("TEXT"), QString("TXT file"), L_TXT, SCLEX_TXT}, {QString("ext"), QString("External"), QString("External"), L_EXTERNAL, SCLEX_NULL} }; #endif ScintillaEditView::ScintillaEditView(QWidget *parent) : QsciScintilla(parent), m_NoteWin(nullptr), m_preFirstLineNum(0), m_curPos(0) { init(); } ScintillaEditView::~ScintillaEditView() { releaseAllMark(); } //void ScintillaEditView::resetDefaultFontStyle() //{ // QFont font(DEFAULT_FONT_NAME, 11/*QsciLexer::s_defaultFontSize*/, QFont::Normal); // setFont(font); // setMarginsFont(font); // setMarginsForegroundColor(QColor(0x80, 0x80, 0x80)); //} void ScintillaEditView::setNoteWidget(QWidget * win) { m_NoteWin = win; } void ScintillaEditView::updateLineNumbersMargin(bool forcedToHide) { if (forcedToHide) { execute(SCI_SETMARGINWIDTHN, _SC_MARGE_LINENUMBER, (sptr_t)0); } else { updateLineNumberWidth(0); } } //根据现有滚动条来决定是否更新屏幕线宽长度。每滚动2000个单位必须调整line宽 void ScintillaEditView::autoAdjustLineWidth(int xScrollValue) { if (std::abs(xScrollValue - m_preFirstLineNum) > 400) { m_preFirstLineNum = xScrollValue; updateLineNumberWidth(1); } } void ScintillaEditView::updateLineNumberWidth(int lineNumberMarginDynamicWidth) { auto linesVisible = execute(SCI_LINESONSCREEN); if (linesVisible) { int nbDigits = 0; if(lineNumberMarginDynamicWidth != 0) { auto firstVisibleLineVis = execute(SCI_GETFIRSTVISIBLELINE); auto lastVisibleLineVis = linesVisible + firstVisibleLineVis + 1; auto lastVisibleLineDoc = execute(SCI_DOCLINEFROMVISIBLE, (long)lastVisibleLineVis); nbDigits = nbDigitsFromNbLines(lastVisibleLineDoc); nbDigits = nbDigits < 4 ? 4 : nbDigits; } else { auto nbLines = execute(SCI_GETLINECOUNT); nbDigits = nbDigitsFromNbLines(nbLines); nbDigits = nbDigits < 5 ? 5 : nbDigits; } auto pixelWidth = 6 + nbDigits * execute(SCI_TEXTWIDTH, STYLE_LINENUMBER, reinterpret_cast("8")); execute(SCI_SETMARGINWIDTHN, _SC_MARGE_LINENUMBER, pixelWidth); } } void ScintillaEditView::showMargin(int whichMarge, bool willBeShowed) { if (whichMarge == _SC_MARGE_LINENUMBER) { bool forcedToHide = !willBeShowed; updateLineNumbersMargin(forcedToHide); } else { //后面再来解决像素的问题 //DPIManager& dpiManager = NppParameters::getInstance()._dpiManager; int width = 3; if (whichMarge == _SC_MARGE_SYBOLE) width = 8; else if (whichMarge == _SC_MARGE_FOLDER) width = 14; execute(SCI_SETMARGINWIDTHN, whichMarge, willBeShowed ? width : 0); } } sptr_t ScintillaEditView::execute(quint32 Msg, uptr_t wParam, sptr_t lParam) const { try { return (m_pScintillaFunc) ? m_pScintillaFunc(m_pScintillaPtr, Msg, wParam, lParam) : -1; } catch (...) { return -1; } }; //status : true 表示存在, false 表示不存在 QsciLexer* ScintillaEditView::createLexer(int lexerId) { QsciLexer* ret = nullptr; switch (lexerId) { case L_PHP: ret = new QsciLexerHTML(); ret->setLexerTag("php"); break; case L_HTML: ret = new QsciLexerHTML(); ret->setLexerTag("html"); break; case L_ASP: ret = new QsciLexerHTML(); ret->setLexerTag("asp"); break; case L_JSP: ret = new QsciLexerHTML(); ret->setLexerTag("jsp"); break; case L_C: ret = new QsciLexerCPP(); ret->setLexerTag("c"); break; case L_RC: ret = new QsciLexerCPP(); ret->setLexerTag("rc"); break; case L_CPP: ret = new QsciLexerCPP(); break; case L_OBJC: ret = new QsciLexerCPP(); ret->setLexerTag("objc"); break; case L_CS: ret = new QsciLexerCSharp(); ret->setLexerTag("csharp"); break; case L_JAVA: ret = new QsciLexerJava(); ret->setLexerTag("java"); break; case L_XML: ret = new QsciLexerXML(); break; case L_MAKEFILE: ret = new QsciLexerMakefile(); break; case L_PASCAL: ret = new QsciLexerPascal(); break; case L_BATCH: ret = new QsciLexerBatch(); break; case L_INI: ret = new QsciLexerProperties(); ret->setLexerTag("ini"); break; case L_ASCII: break; case L_USER: break; case L_SQL: ret = new QsciLexerSQL(); break; case L_VB: break; case L_CSS: ret = new QsciLexerCSS(); break; case L_PERL: ret = new QsciLexerPerl(); break; case L_PYTHON: ret = new QsciLexerPython(); break; case L_LUA: ret = new QsciLexerLua(); break; case L_TEX: break; case L_FORTRAN: ret = new QsciLexerFortran(); break; case L_BASH: ret = new QsciLexerBash(); break; case L_FLASH: ret = new QsciLexerCPP(); ret->setLexerTag("flash"); break; case L_NSIS: ret = new QsciLexerNsis(); break; case L_TCL: ret = new QsciLexerTCL(); break; case L_LISP: break; case L_SCHEME: break; case L_ASM: break; case L_DIFF: ret = new QsciLexerDiff(); break; case L_PROPS: ret = new QsciLexerProperties(); break; case L_PS: break; case L_RUBY: ret = new QsciLexerRuby(); break; case L_SMALLTALK: break; case L_VHDL: ret = new QsciLexerVHDL(); break; case L_KIX: break; case L_AU3: break; case L_CAML: break; case L_ADA: break; case L_VERILOG: ret = new QsciLexerVerilog(); break; case L_MATLAB: ret = new QsciLexerMatlab(); break; case L_HASKELL: break; case L_INNO: break; case L_SEARCHRESULT: break; case L_CMAKE: ret = new QsciLexerCMake(); break; case L_YAML: ret = new QsciLexerYAML(); break; case L_COBOL: break; case L_GUI4CLI: break; case L_D: break; case L_POWERSHELL: break; case L_COFFEESCRIPT: ret = new QsciLexerCoffeeScript(); break; case L_JSON: ret = new QsciLexerJSON(); break; case L_JAVASCRIPT: ret = new QsciLexerJavaScript(); ret->setLexerTag("javascript"); break; case L_FORTRAN_77: ret = new QsciLexerFortran77(); break; case L_BAANC: break; case L_SREC: break; case L_IHEX: break; case L_TEHEX: break; case L_SWIFT: break; case L_ASN1: break; case L_AVS: ret = new QsciLexerAVS(); break; case L_BLITZBASIC: break; case L_PUREBASIC: break; case L_FREEBASIC: break; case L_CSOUND: break; case L_ERLANG: break; case L_ESCRIPT: break; case L_FORTH: break; case L_LATEX: break; case L_MMIXAL: break; case L_NIM: break; case L_NNCRONTAB: break; case L_OSCRIPT: break; case L_REBOL: break; case L_REGISTRY: break; case L_RUST: break; case L_SPICE: ret = new QsciLexerSpice(); break; case L_TXT2TAGS: break; case L_VISUALPROLOG: break; case L_TYPESCRIPT: ret = new QsciLexerCPP(); ret->setLexerTag("typescript"); break; case L_EXTERNAL: break; case L_IDL: ret = new QsciLexerIDL(); ret->setLexerTag("idl"); break; case L_GO: ret = new QsciLexerGO(); ret->setLexerTag("go"); break; case L_TXT: ret = new QsciLexerText(); ret->setLexerTag("txt"); break; default: break; } if (ret != nullptr) { ret->setLexerId(lexerId); QtLangSet::readLangSettings(ret, ret->lexerTag()); } return ret; } void ScintillaEditView::appendMarkRecord(FindRecords * r) { m_curMarkList.append(r); } void ScintillaEditView::releaseAllMark() { for (int i = 0; i < m_curMarkList.size(); ++i) { delete m_curMarkList.at(i); } m_curMarkList.clear(); } QList& ScintillaEditView::getCurMarkRecord() { return m_curMarkList; } //调整颜色 void ScintillaEditView::adjuctSkinStyle() { setFoldMarginColors(StyleSet::foldfgColor, StyleSet::foldbgColor); setMarginsBackgroundColor(StyleSet::marginsBackgroundColor); } void ScintillaEditView::setIndentGuide(bool willBeShowed) { QsciLexer* pLexer = this->lexer(); if (nullptr == pLexer || (pLexer->lexerId() == L_TXT)) { return; } const int docIndentMode = (pLexer->lexerId() == L_PYTHON) ? SC_IV_LOOKFORWARD : SC_IV_LOOKBOTH; execute(SCI_SETINDENTATIONGUIDES, willBeShowed ? docIndentMode : SC_IV_NONE); QsciScintilla::setIndentGuide(willBeShowed); } #if 0 void ScintillaEditView::setLexer(QsciLexer * lexer) { //加个保护,只有文本模式下,才能加lexer if (lexer != nullptr) { OpenAttr openType = (OpenAttr)this->property(Open_Attr).toInt(); if (Text != openType) { return; } } QsciScintilla::setLexer(lexer); } #endif void ScintillaEditView::init() { 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"); } //开启行号marge //markerDefine(SC_MARGIN_NUMBER,_SC_MARGE_LINENUMBER); setMarginLineNumbers(_SC_MARGE_LINENUMBER, true); //execute(SCI_SETMARGINMASKN, _SC_MARGE_FOLDER, SC_MARGIN_SYMBOL); //execute(SCI_SETMARGINMASKN, _SC_MARGE_FOLDER, SC_MASK_FOLDERS); QColor foldfgColor(StyleSet::foldfgColor); QColor foldbgColor(StyleSet::foldbgColor);//默认0xff,0xff,0xff //QColor activeFoldFgColor(0xFF, 0, 0); //通过fold发现,尽量使用qscint的功能,因为他做了大量封装和简化 setFolding(BoxedTreeFoldStyle, _SC_MARGE_FOLDER); setFoldMarginColors(foldfgColor, foldbgColor); //当前fold高亮。QT下面有bug暂时不开启 //execute(SCI_MARKERENABLEHIGHLIGHT, true); setMarginsBackgroundColor(StyleSet::marginsBackgroundColor); //0xea, 0xf7, 0xff //默认0xf0f0f0 //execute(SCI_MARKERSETBACK, _SC_MARGE_FOLDER, 0x808080); //execute(SCI_MARKERSETBACKSELECTED, _SC_MARGE_FOLDER, 0xff0000); showMargin(_SC_MARGE_LINENUMBER, true); //行号、符号、折叠。中间符号留一个很小的间隔 showMargin(_SC_MARGE_SYBOLE, true); //showMargin(_SC_MARGE_FOLDER, true); //设置选中背景色 //setSelectionBackgroundColor(QColor(117, 217, 117)); //开始括号匹配,比如html的<>,开启前后这类字段的匹配 setBraceMatching(SloppyBraceMatch); setMatchedBraceForegroundColor(QColor(191, 141, 255)); //setMatchedBraceBackgroundColor(QColor(191, 141, 255)); //自动补全效果不好,不开启20211017 //setAutoCompletionSource(QsciScintilla::AcsAPIs); //设置源,自动补全所有地方出现的 //setAutoCompletionCaseSensitivity(true); //设置自动补全大小写敏感 //setAutoCompletionThreshold(1); //设置每输入一个字符就会出现自动补全的提示 //设置字体 QFont font(DEFAULT_FONT_NAME, 11/*QsciLexer::s_defaultFontSize*/, QFont::Normal); setFont(font); setMarginsFont(font); //execute(SCI_SETMARGINMASKN, _SC_MARGE_SYBOLE, (1 << MARK_BOOKMARK) | (1 << MARK_HIDELINESBEGIN) | (1 << MARK_HIDELINESEND) | (1 << MARK_HIDELINESUNDERLINE)); setMarginsForegroundColor(QColor(0x80, 0x80, 0x80)); //默认0x80, 0x80, 0x80 execute(SCI_SETTABWIDTH, 4); //setPaper(QColor(0xfc, 0xfc, 0xfc));//这个无效 //使用空格替换tab execute(SCI_SETUSETABS, !ScintillaEditView::s_noUseTab); //这个无比要设置false,否则双击后高亮单词,拷贝时会拷贝多个选择。 execute(SCI_SETMULTIPLESELECTION, false); //execute(SCI_SETADDITIONALSELALPHA, 100); execute(SCI_SETMULTIPASTE, 1); execute(SCI_SETADDITIONALCARETSVISIBLE, false); //execute(SCI_SETADDITIONALSELFORE, 0); //execute(SCI_SETADDITIONALSELBACK, 0x98ff98); execute(SCI_SETSELFORE, true, 0x0); //execute(SCI_SETSELBACK, true, 0x9ACC9A); execute(SCI_SETSELBACK, true, 0x9bff9b); //0x00ffff原来的黄色 //设置查找到Mark的风格。定义其前景颜色和形状 execute(SCI_INDICSETSTYLE, SCE_UNIVERSAL_FOUND_STYLE, INDIC_ROUNDBOX); execute(SCI_INDICSETALPHA, SCE_UNIVERSAL_FOUND_STYLE, 130); execute(SCI_INDICSETUNDER, SCE_UNIVERSAL_FOUND_STYLE, false); execute(SCI_INDICSETFORE, SCE_UNIVERSAL_FOUND_STYLE, 0x00ffff); //下面这两个是HTML文件的tag高亮的表示。 execute(SCI_INDICSETSTYLE, SCE_UNIVERSAL_TAGMATCH, INDIC_STRAIGHTBOX); execute(SCI_INDICSETALPHA, SCE_UNIVERSAL_TAGMATCH, 100); execute(SCI_INDICSETUNDER, SCE_UNIVERSAL_TAGMATCH, false); execute(SCI_INDICSETFORE, SCE_UNIVERSAL_TAGMATCH, 0xff0080); execute(SCI_INDICSETSTYLE, SCE_UNIVERSAL_TAGATTR, INDIC_STRAIGHTBOX); execute(SCI_INDICSETALPHA, SCE_UNIVERSAL_TAGATTR, 100); execute(SCI_INDICSETUNDER, SCE_UNIVERSAL_TAGATTR, false); execute(SCI_INDICSETFORE, SCE_UNIVERSAL_TAGATTR, 0x00ffff); setCaretLineVisible(true); setCaretLineBackgroundColor(QColor(0xe8e8ff)); //记住position变化。不能使用cursorPositionChanged,因为他的列考虑uft8字符,中文一个也算1个,每次列不一定相等。 //要使用自定义的cursorPosChange,跟踪的是SCI_GETCURRENTPOS 的值 connect(this,&QsciScintilla::cursorPosChange,this,&ScintillaEditView::slot_linePosChanged, Qt::QueuedConnection); execute(SCI_SETSCROLLWIDTH, 1); //20220226发现高亮全选如果范围过大,会导致卡死。借鉴notepad的只高亮可视化区域。但是滚动时也必须生效 connect(this->verticalScrollBar(), &QScrollBar::valueChanged, this, &ScintillaEditView::slot_scrollXValueChange); connect(this, &ScintillaEditView::delayWork, this,&ScintillaEditView::slot_delayWork, Qt::QueuedConnection); } //X方向滚动条值变化后的槽函数。一旦滚动则会出发这里,发送消息给中介,让中介去同步另外一方 void ScintillaEditView::slot_scrollXValueChange(int value) { slot_delayWork(); autoAdjustLineWidth(value); } void ScintillaEditView::slot_linePosChanged(int /*line*/, int pos) { //避免循环触发的slot_positionChanged if (m_curPos == pos) { return; } m_prePosRecord.append(pos); if (m_prePosRecord.size() >= MAX_PRE_NEXT_TIMES) { m_prePosRecord.takeFirst(); } } //回退一个位置 bool ScintillaEditView::gotoPrePos() { if (m_prePosRecord.size() > 1) { int v = m_prePosRecord.takeLast(); m_nextPosRecord.push_front(v); if (m_nextPosRecord.size() >= MAX_PRE_NEXT_TIMES) { m_nextPosRecord.takeLast(); } int pos = m_prePosRecord.last(); //下面这个函数比较坑,里面要循环Index次,每次返回的index值是不一样的。只能使用SCI_GOTOPOS可自定义的信号 //setCursorPosition(pos.line, pos.index); //会循环触发slot_positionChanged this->execute(SCI_GOTOPOS, pos); m_curPos = pos; return true; } return false; } bool ScintillaEditView::gotoNextPos() { if (m_nextPosRecord.size() > 0) { int pos = m_nextPosRecord.takeFirst(); m_prePosRecord.append(pos); this->execute(SCI_GOTOPOS, pos); m_curPos = pos; return true; } return false; } const int MAXLINEHIGHLIGHT = 400; void ScintillaEditView::slot_delayWork() { if (!hasSelectedText()) { return; } QString word = selectedText(); if (!word.isEmpty()) { QVectorresultPos; resultPos.reserve(50); int firstLine = execute(SCI_GETFIRSTVISIBLELINE); int nbLineOnScreen = execute(SCI_LINESONSCREEN); int nbLines = std::min(nbLineOnScreen, MAXLINEHIGHLIGHT) + 1; int lastLine = firstLine + nbLines; long startPos = execute(SCI_POSITIONFROMLINE, firstLine); long endPos = execute(SCI_POSITIONFROMLINE, lastLine); if (endPos == -1) { endPos = execute(SCI_GETLENGTH); } int curpos = execute(SCI_GETCURRENTPOS); int mainSelect = 1; //struct Sci_TextToFind findOptions; ////20220226发现高亮全选如果范围过大,会导致卡死。借鉴notepad的只高亮可视化区域。但是滚动时也必须生效 ////findOptions.chrg.cpMin = 0; ////findOptions.chrg.cpMax = execute(SCI_GETLENGTH); // //findOptions.chrg.cpMin = startPos; //findOptions.chrg.cpMax = endPos; //findOptions.lpstrText = wordStr.c_str(); //20220422 升级高版本scint后,发现Sci_TextToFind要崩溃,替换为SCI_SEARCHINTARGET //int pos = execute(SCI_FINDTEXT, SCFIND_MATCHCASE | SCFIND_WHOLEWORD, reinterpret_cast(&findOptions)); //std::string wordStr = word.toStdString(); QByteArray wordStr = word.toUtf8(); SendScintilla(SCI_SETTARGETSTART, startPos); SendScintilla(SCI_SETTARGETEND, endPos); SendScintilla(SCI_SETSEARCHFLAGS, SCFIND_MATCHCASE|SCFIND_WHOLEWORD); long lens = wordStr.length(); long pos = SendScintilla(SCI_SEARCHINTARGET, lens, wordStr.data()/*,wordStr.c_str()*/); while ((pos != -1)&&(pos < endPos)) { resultPos.append(pos); if (pos <= curpos) { mainSelect = resultPos.size(); } SendScintilla(SCI_SETTARGETSTART, pos + lens); SendScintilla(SCI_SETTARGETEND, endPos); pos = SendScintilla(SCI_SEARCHINTARGET, wordStr.length(), wordStr.data()/*,wordStr.c_str()*/); //findOptions.chrg.cpMin = findOptions.chrgText.cpMax; //pos = execute(SCI_FINDTEXT, SCFIND_MATCHCASE | SCFIND_WHOLEWORD, reinterpret_cast(&findOptions)); } for (int i = 0, size = resultPos.size(); i < size; ++i) { //execute(SCI_ADDSELECTION, resultPos.at(i), resultPos.at(i) + word.size()); execute(SCI_ADDSELECTION, resultPos.at(i) + lens, resultPos.at(i) ); } if (!resultPos.isEmpty()) { execute(SCI_SETMAINSELECTION, mainSelect - 1); } } } void ScintillaEditView::dragEnterEvent(QDragEnterEvent* event) { //if (event->mimeData()->hasFormat("text/uri-list")) //只能打开文本文件 //{ // event->accept(); //可以在这个窗口部件上拖放对象 //} //else //{ // event->ignore(); //} event->accept(); } void ScintillaEditView::dropEvent(QDropEvent* e) { QList urls = e->mimeData()->urls(); if (urls.isEmpty()) return; CCNotePad* pv = dynamic_cast(m_NoteWin); if (pv != nullptr) pv->receiveEditDrop(e); //qDebug() << ui.leftSrc->geometry() << ui.rightSrc->geometry() << QCursor::pos() << this->mapFromGlobal(QCursor::pos()); } void ScintillaEditView::mouseDoubleClickEvent(QMouseEvent * e) { QsciScintilla::mouseDoubleClickEvent(e); if (hasSelectedText()) { emit delayWork(); } }