notepad--/scintillaeditview.cpp

907 lines
31 KiB
C++
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "scintillaeditview.h"
#include "common.h"
#include "rgba_icons.h"
#include "ccnotepad.h"
#include "styleset.h"
#include "qtlangset.h"
#include <Scintilla.h>
#include <SciLexer.h>
#include <QImage>
#include <Qsci/qscilexerpython.h>
#include <Qsci/qscilexeravs.h>
#include <Qsci/qscilexerbash.h>
#include <Qsci/qscilexerbatch.h>
#include <Qsci/qscilexercmake.h>
#include <Qsci/qscilexercoffeescript.h>
#include <Qsci/qscilexercpp.h>
#include <Qsci/qscilexercsharp.h>
#include <Qsci/qscilexercss.h>
#include <Qsci/qscilexercustom.h>
#include <Qsci/qscilexerd.h>
#include <Qsci/qscilexerdiff.h>
#include <Qsci/qscilexeredifact.h>
#include <Qsci/qscilexerfortran.h>
#include <Qsci/qscilexerfortran77.h>
#include <Qsci/qscilexerhtml.h>
#include <Qsci/qscilexeridl.h>
#include <Qsci/qscilexerjava.h>
#include <Qsci/qscilexerjavascript.h>
#include <Qsci/qscilexerjson.h>
#include <Qsci/qscilexerlua.h>
#include <Qsci/qscilexermakefile.h>
#include <Qsci/qscilexermarkdown.h>
#include <Qsci/qscilexermatlab.h>
#include <Qsci/qscilexeroctave.h>
#include <Qsci/qscilexerpascal.h>
#include <Qsci/qscilexerperl.h>
#include <Qsci/qscilexerpo.h>
#include <Qsci/qscilexerpostscript.h>
#include <Qsci/qscilexerpov.h>
#include <Qsci/qscilexerproperties.h>
#include <Qsci/qscilexerpython.h>
#include <Qsci/qscilexerruby.h>
#include <Qsci/qscilexerspice.h>
#include <Qsci/qscilexersql.h>
#include <Qsci/qscilexertcl.h>
#include <Qsci/qscilexertex.h>
#include <Qsci/qscilexerverilog.h>
#include <Qsci/qscilexervhdl.h>
#include <Qsci/qscilexerxml.h>
#include <Qsci/qscilexeryaml.h>
#include <Qsci/qscilexergo.h>
#include <Qsci/qscilexertext.h>
#include <Qsci/qscilexernsis.h>
#include <QScrollBar>
#include <QDebug>
#include <stdexcept>
#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<sptr_t>("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<FindRecords *>& 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())
{
QVector<int>resultPos;
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<sptr_t>(&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<sptr_t>(&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<QUrl> urls = e->mimeData()->urls();
if (urls.isEmpty())
return;
CCNotePad* pv = dynamic_cast<CCNotePad*>(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();
}
}