From 1dcf666dc7872fca0366db62c4740d96beb7b074 Mon Sep 17 00:00:00 2001 From: Robin Dunn <robin@alldunn.com> Date: Tue, 14 Aug 2012 05:14:09 +0000 Subject: [PATCH] Initial copy of Scintilla 3.21 code git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@72331 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775 --- src/stc/scintilla/include/Accessor.h | 79 - src/stc/scintilla/include/ILexer.h | 77 + src/stc/scintilla/include/KeyWords.h | 113 - src/stc/scintilla/include/Platform.h | 223 +- src/stc/scintilla/include/PropSet.h | 26 - src/stc/scintilla/include/SString.h | 289 -- src/stc/scintilla/include/SciLexer.h | 241 +- src/stc/scintilla/include/Scintilla.h | 152 +- src/stc/scintilla/include/Scintilla.iface | 581 +++- src/stc/scintilla/include/ScintillaWidget.h | 12 +- src/stc/scintilla/include/WindowAccessor.h | 67 - src/stc/scintilla/lexers/LexA68k.cxx | 318 ++ src/stc/scintilla/{src => lexers}/LexAPDL.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexASY.cxx | 27 +- src/stc/scintilla/{src => lexers}/LexAU3.cxx | 137 +- src/stc/scintilla/{src => lexers}/LexAVE.cxx | 19 +- src/stc/scintilla/lexers/LexAVS.cxx | 293 ++ .../scintilla/{src => lexers}/LexAbaqus.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexAda.cxx | 15 +- src/stc/scintilla/lexers/LexAsm.cxx | 460 +++ src/stc/scintilla/{src => lexers}/LexAsn1.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexBaan.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexBash.cxx | 291 +- .../scintilla/{src => lexers}/LexBasic.cxx | 379 ++- .../scintilla/{src => lexers}/LexBullant.cxx | 19 +- src/stc/scintilla/{src => lexers}/LexCLW.cxx | 45 +- .../scintilla/{src => lexers}/LexCOBOL.cxx | 29 +- src/stc/scintilla/lexers/LexCPP.cxx | 1209 ++++++++ src/stc/scintilla/{src => lexers}/LexCSS.cxx | 272 +- src/stc/scintilla/{src => lexers}/LexCaml.cxx | 29 +- .../scintilla/{src => lexers}/LexCmake.cxx | 18 +- src/stc/scintilla/lexers/LexCoffeeScript.cxx | 571 ++++ src/stc/scintilla/{src => lexers}/LexConf.cxx | 30 +- .../scintilla/{src => lexers}/LexCrontab.cxx | 24 +- .../scintilla/{src => lexers}/LexCsound.cxx | 24 +- src/stc/scintilla/{src => lexers}/LexD.cxx | 285 +- .../{src/LexCPP.cxx => lexers/LexECL.cxx} | 416 +-- .../scintilla/{src => lexers}/LexEScript.cxx | 15 +- .../scintilla/{src => lexers}/LexEiffel.cxx | 17 +- .../scintilla/{src => lexers}/LexErlang.cxx | 26 +- src/stc/scintilla/lexers/LexFlagship.cxx | 354 +++ .../scintilla/{src => lexers}/LexForth.cxx | 19 +- .../scintilla/{src => lexers}/LexFortran.cxx | 50 +- src/stc/scintilla/{src => lexers}/LexGAP.cxx | 17 +- .../scintilla/{src => lexers}/LexGui4Cli.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexHTML.cxx | 329 ++- src/stc/scintilla/lexers/LexHaskell.cxx | 368 +++ src/stc/scintilla/{src => lexers}/LexInno.cxx | 27 +- src/stc/scintilla/{src => lexers}/LexKix.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexLisp.cxx | 19 +- src/stc/scintilla/{src => lexers}/LexLout.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexLua.cxx | 135 +- .../scintilla/{src => lexers}/LexMMIXAL.cxx | 19 +- src/stc/scintilla/{src => lexers}/LexMPT.cxx | 31 +- .../scintilla/{src => lexers}/LexMSSQL.cxx | 16 +- .../scintilla/{src => lexers}/LexMagik.cxx | 17 +- .../scintilla/{src => lexers}/LexMarkdown.cxx | 99 +- .../scintilla/{src => lexers}/LexMatlab.cxx | 27 +- .../scintilla/{src => lexers}/LexMetapost.cxx | 31 +- src/stc/scintilla/lexers/LexModula.cxx | 743 +++++ .../scintilla/{src => lexers}/LexMySQL.cxx | 215 +- .../scintilla/{src => lexers}/LexNimrod.cxx | 33 +- src/stc/scintilla/{src => lexers}/LexNsis.cxx | 19 +- src/stc/scintilla/lexers/LexOScript.cxx | 548 ++++ src/stc/scintilla/{src => lexers}/LexOpal.cxx | 71 +- .../scintilla/{src => lexers}/LexOthers.cxx | 356 ++- src/stc/scintilla/{src => lexers}/LexPB.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexPLM.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexPOV.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexPS.cxx | 17 +- .../scintilla/{src => lexers}/LexPascal.cxx | 182 +- src/stc/scintilla/{src => lexers}/LexPerl.cxx | 1264 +++++--- .../scintilla/{src => lexers}/LexPowerPro.cxx | 398 +-- .../{src => lexers}/LexPowerShell.cxx | 44 +- .../scintilla/{src => lexers}/LexProgress.cxx | 19 +- .../scintilla/{src => lexers}/LexPython.cxx | 106 +- src/stc/scintilla/{src => lexers}/LexR.cxx | 19 +- .../scintilla/{src => lexers}/LexRebol.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexRuby.cxx | 174 +- src/stc/scintilla/{src => lexers}/LexSML.cxx | 30 +- src/stc/scintilla/lexers/LexSQL.cxx | 834 ++++++ .../scintilla/{src => lexers}/LexScriptol.cxx | 23 +- .../{src => lexers}/LexSmalltalk.cxx | 33 +- .../scintilla/{src => lexers}/LexSorcus.cxx | 135 +- .../scintilla/{src => lexers}/LexSpecman.cxx | 13 +- .../scintilla/{src => lexers}/LexSpice.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexTACL.cxx | 15 +- .../scintilla/{src => lexers}/LexTADS3.cxx | 29 +- src/stc/scintilla/{src => lexers}/LexTAL.cxx | 17 +- src/stc/scintilla/{src => lexers}/LexTCL.cxx | 30 +- src/stc/scintilla/lexers/LexTCMD.cxx | 511 ++++ src/stc/scintilla/{src => lexers}/LexTeX.cxx | 57 +- src/stc/scintilla/lexers/LexTxt2tags.cxx | 480 +++ src/stc/scintilla/{src => lexers}/LexVB.cxx | 15 +- src/stc/scintilla/{src => lexers}/LexVHDL.cxx | 63 +- .../scintilla/{src => lexers}/LexVerilog.cxx | 70 +- src/stc/scintilla/lexers/LexVisualProlog.cxx | 470 +++ src/stc/scintilla/{src => lexers}/LexYAML.cxx | 17 +- src/stc/scintilla/lexlib/Accessor.cxx | 79 + src/stc/scintilla/lexlib/Accessor.h | 35 + src/stc/scintilla/lexlib/CharacterSet.cxx | 61 + src/stc/scintilla/lexlib/CharacterSet.h | 177 ++ src/stc/scintilla/lexlib/LexAccessor.h | 175 ++ src/stc/scintilla/lexlib/LexerBase.cxx | 92 + src/stc/scintilla/lexlib/LexerBase.h | 41 + src/stc/scintilla/lexlib/LexerModule.cxx | 121 + src/stc/scintilla/lexlib/LexerModule.h | 82 + .../scintilla/lexlib/LexerNoExceptions.cxx | 68 + src/stc/scintilla/lexlib/LexerNoExceptions.h | 32 + src/stc/scintilla/lexlib/LexerSimple.cxx | 57 + src/stc/scintilla/lexlib/LexerSimple.h | 30 + src/stc/scintilla/lexlib/OptionSet.h | 142 + .../PropSet.cxx => lexlib/PropSetSimple.cxx} | 36 +- .../scintilla/{src => lexlib}/PropSetSimple.h | 4 +- src/stc/scintilla/lexlib/SparseState.h | 110 + .../{src => lexlib}/StyleContext.cxx | 9 +- .../scintilla/{src => lexlib}/StyleContext.h | 53 +- src/stc/scintilla/lexlib/WordList.cxx | 219 ++ src/stc/scintilla/lexlib/WordList.h | 41 + src/stc/scintilla/src/AutoComplete.cxx | 39 +- src/stc/scintilla/src/AutoComplete.h | 17 +- src/stc/scintilla/src/CallTip.cxx | 72 +- src/stc/scintilla/src/CallTip.h | 27 +- src/stc/scintilla/src/Catalogue.cxx | 192 ++ src/stc/scintilla/src/Catalogue.h | 26 + src/stc/scintilla/src/CellBuffer.cxx | 53 +- src/stc/scintilla/src/CellBuffer.h | 23 +- src/stc/scintilla/src/CharClassify.cxx | 46 +- src/stc/scintilla/src/CharClassify.h | 16 +- src/stc/scintilla/src/CharacterSet.h | 58 - src/stc/scintilla/src/ContractionState.cxx | 33 +- src/stc/scintilla/src/ContractionState.h | 2 + src/stc/scintilla/src/Decoration.cxx | 8 +- src/stc/scintilla/src/Decoration.h | 4 +- src/stc/scintilla/src/Document.cxx | 981 +++++-- src/stc/scintilla/src/Document.h | 178 +- src/stc/scintilla/src/DocumentAccessor.cxx | 199 -- src/stc/scintilla/src/DocumentAccessor.h | 77 - src/stc/scintilla/src/Editor.cxx | 2562 +++++++++++------ src/stc/scintilla/src/Editor.h | 124 +- src/stc/scintilla/src/ExternalLexer.cxx | 122 +- src/stc/scintilla/src/ExternalLexer.h | 42 +- src/stc/scintilla/src/FontQuality.h | 3 + src/stc/scintilla/src/Indicator.cxx | 56 +- src/stc/scintilla/src/Indicator.h | 5 +- src/stc/scintilla/src/KeyMap.cxx | 47 +- src/stc/scintilla/src/KeyMap.h | 1 + src/stc/scintilla/src/KeyWords.cxx | 429 --- src/stc/scintilla/src/LexAsm.cxx | 180 -- src/stc/scintilla/src/LexFlagship.cxx | 230 -- src/stc/scintilla/src/LexGen.py | 96 +- src/stc/scintilla/src/LexHaskell.cxx | 275 -- src/stc/scintilla/src/LexSQL.cxx | 357 --- src/stc/scintilla/src/LineMarker.cxx | 221 +- src/stc/scintilla/src/LineMarker.h | 45 +- src/stc/scintilla/src/Partitioning.h | 7 +- src/stc/scintilla/src/PerLine.cxx | 93 +- src/stc/scintilla/src/PerLine.h | 7 +- src/stc/scintilla/src/PositionCache.cxx | 122 +- src/stc/scintilla/src/PositionCache.h | 43 +- src/stc/scintilla/src/RESearch.cxx | 104 +- src/stc/scintilla/src/RunStyles.cxx | 38 +- src/stc/scintilla/src/RunStyles.h | 8 +- src/stc/scintilla/src/SVector.h | 14 +- src/stc/scintilla/src/ScintillaBase.cxx | 382 ++- src/stc/scintilla/src/ScintillaBase.h | 19 +- src/stc/scintilla/src/Selection.cxx | 13 +- src/stc/scintilla/src/Selection.h | 18 +- src/stc/scintilla/src/SplitVector.h | 47 +- src/stc/scintilla/src/Style.cxx | 163 +- src/stc/scintilla/src/Style.h | 68 +- src/stc/scintilla/src/UniConversion.cxx | 133 +- src/stc/scintilla/src/UniConversion.h | 18 +- src/stc/scintilla/src/ViewStyle.cxx | 291 +- src/stc/scintilla/src/ViewStyle.h | 68 +- src/stc/scintilla/src/WindowAccessor.cxx | 191 -- src/stc/scintilla/src/XPM.cxx | 183 +- src/stc/scintilla/src/XPM.h | 70 +- src/stc/scintilla/src/descrip.mms | 236 -- 179 files changed, 18897 insertions(+), 7565 deletions(-) delete mode 100644 src/stc/scintilla/include/Accessor.h create mode 100644 src/stc/scintilla/include/ILexer.h delete mode 100644 src/stc/scintilla/include/KeyWords.h delete mode 100644 src/stc/scintilla/include/PropSet.h delete mode 100644 src/stc/scintilla/include/SString.h delete mode 100644 src/stc/scintilla/include/WindowAccessor.h create mode 100644 src/stc/scintilla/lexers/LexA68k.cxx rename src/stc/scintilla/{src => lexers}/LexAPDL.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexASY.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexAU3.cxx (93%) rename src/stc/scintilla/{src => lexers}/LexAVE.cxx (97%) create mode 100644 src/stc/scintilla/lexers/LexAVS.cxx rename src/stc/scintilla/{src => lexers}/LexAbaqus.cxx (99%) rename src/stc/scintilla/{src => lexers}/LexAda.cxx (98%) create mode 100644 src/stc/scintilla/lexers/LexAsm.cxx rename src/stc/scintilla/{src => lexers}/LexAsn1.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexBaan.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexBash.cxx (63%) rename src/stc/scintilla/{src => lexers}/LexBasic.cxx (57%) rename src/stc/scintilla/{src => lexers}/LexBullant.cxx (96%) rename src/stc/scintilla/{src => lexers}/LexCLW.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexCOBOL.cxx (93%) create mode 100644 src/stc/scintilla/lexers/LexCPP.cxx rename src/stc/scintilla/{src => lexers}/LexCSS.cxx (61%) rename src/stc/scintilla/{src => lexers}/LexCaml.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexCmake.cxx (98%) create mode 100644 src/stc/scintilla/lexers/LexCoffeeScript.cxx rename src/stc/scintilla/{src => lexers}/LexConf.cxx (88%) rename src/stc/scintilla/{src => lexers}/LexCrontab.cxx (94%) rename src/stc/scintilla/{src => lexers}/LexCsound.cxx (96%) rename src/stc/scintilla/{src => lexers}/LexD.cxx (64%) rename src/stc/scintilla/{src/LexCPP.cxx => lexers/LexECL.cxx} (52%) rename src/stc/scintilla/{src => lexers}/LexEScript.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexEiffel.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexErlang.cxx (98%) create mode 100644 src/stc/scintilla/lexers/LexFlagship.cxx rename src/stc/scintilla/{src => lexers}/LexForth.cxx (96%) rename src/stc/scintilla/{src => lexers}/LexFortran.cxx (91%) rename src/stc/scintilla/{src => lexers}/LexGAP.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexGui4Cli.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexHTML.cxx (89%) create mode 100644 src/stc/scintilla/lexers/LexHaskell.cxx rename src/stc/scintilla/{src => lexers}/LexInno.cxx (94%) rename src/stc/scintilla/{src => lexers}/LexKix.cxx (96%) rename src/stc/scintilla/{src => lexers}/LexLisp.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexLout.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexLua.cxx (75%) rename src/stc/scintilla/{src => lexers}/LexMMIXAL.cxx (96%) rename src/stc/scintilla/{src => lexers}/LexMPT.cxx (91%) rename src/stc/scintilla/{src => lexers}/LexMSSQL.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexMagik.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexMarkdown.cxx (89%) rename src/stc/scintilla/{src => lexers}/LexMatlab.cxx (96%) rename src/stc/scintilla/{src => lexers}/LexMetapost.cxx (98%) create mode 100644 src/stc/scintilla/lexers/LexModula.cxx rename src/stc/scintilla/{src => lexers}/LexMySQL.cxx (77%) rename src/stc/scintilla/{src => lexers}/LexNimrod.cxx (96%) rename src/stc/scintilla/{src => lexers}/LexNsis.cxx (99%) create mode 100644 src/stc/scintilla/lexers/LexOScript.cxx rename src/stc/scintilla/{src => lexers}/LexOpal.cxx (93%) rename src/stc/scintilla/{src => lexers}/LexOthers.cxx (83%) rename src/stc/scintilla/{src => lexers}/LexPB.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexPLM.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexPOV.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexPS.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexPascal.cxx (88%) rename src/stc/scintilla/{src => lexers}/LexPerl.cxx (53%) rename src/stc/scintilla/{src => lexers}/LexPowerPro.cxx (64%) rename src/stc/scintilla/{src => lexers}/LexPowerShell.cxx (82%) rename src/stc/scintilla/{src => lexers}/LexProgress.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexPython.cxx (87%) rename src/stc/scintilla/{src => lexers}/LexR.cxx (96%) rename src/stc/scintilla/{src => lexers}/LexRebol.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexRuby.cxx (95%) rename src/stc/scintilla/{src => lexers}/LexSML.cxx (95%) create mode 100644 src/stc/scintilla/lexers/LexSQL.cxx rename src/stc/scintilla/{src => lexers}/LexScriptol.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexSmalltalk.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexSorcus.cxx (83%) rename src/stc/scintilla/{src => lexers}/LexSpecman.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexSpice.cxx (97%) rename src/stc/scintilla/{src => lexers}/LexTACL.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexTADS3.cxx (99%) rename src/stc/scintilla/{src => lexers}/LexTAL.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexTCL.cxx (97%) create mode 100644 src/stc/scintilla/lexers/LexTCMD.cxx rename src/stc/scintilla/{src => lexers}/LexTeX.cxx (96%) create mode 100644 src/stc/scintilla/lexers/LexTxt2tags.cxx rename src/stc/scintilla/{src => lexers}/LexVB.cxx (98%) rename src/stc/scintilla/{src => lexers}/LexVHDL.cxx (93%) rename src/stc/scintilla/{src => lexers}/LexVerilog.cxx (85%) create mode 100644 src/stc/scintilla/lexers/LexVisualProlog.cxx rename src/stc/scintilla/{src => lexers}/LexYAML.cxx (97%) create mode 100644 src/stc/scintilla/lexlib/Accessor.cxx create mode 100644 src/stc/scintilla/lexlib/Accessor.h create mode 100644 src/stc/scintilla/lexlib/CharacterSet.cxx create mode 100644 src/stc/scintilla/lexlib/CharacterSet.h create mode 100644 src/stc/scintilla/lexlib/LexAccessor.h create mode 100644 src/stc/scintilla/lexlib/LexerBase.cxx create mode 100644 src/stc/scintilla/lexlib/LexerBase.h create mode 100644 src/stc/scintilla/lexlib/LexerModule.cxx create mode 100644 src/stc/scintilla/lexlib/LexerModule.h create mode 100644 src/stc/scintilla/lexlib/LexerNoExceptions.cxx create mode 100644 src/stc/scintilla/lexlib/LexerNoExceptions.h create mode 100644 src/stc/scintilla/lexlib/LexerSimple.cxx create mode 100644 src/stc/scintilla/lexlib/LexerSimple.h create mode 100644 src/stc/scintilla/lexlib/OptionSet.h rename src/stc/scintilla/{src/PropSet.cxx => lexlib/PropSetSimple.cxx} (83%) rename src/stc/scintilla/{src => lexlib}/PropSetSimple.h (90%) create mode 100644 src/stc/scintilla/lexlib/SparseState.h rename src/stc/scintilla/{src => lexlib}/StyleContext.cxx (91%) rename src/stc/scintilla/{src => lexlib}/StyleContext.h (78%) create mode 100644 src/stc/scintilla/lexlib/WordList.cxx create mode 100644 src/stc/scintilla/lexlib/WordList.h create mode 100644 src/stc/scintilla/src/Catalogue.cxx create mode 100644 src/stc/scintilla/src/Catalogue.h delete mode 100644 src/stc/scintilla/src/CharacterSet.h delete mode 100644 src/stc/scintilla/src/DocumentAccessor.cxx delete mode 100644 src/stc/scintilla/src/DocumentAccessor.h delete mode 100644 src/stc/scintilla/src/KeyWords.cxx delete mode 100644 src/stc/scintilla/src/LexAsm.cxx delete mode 100644 src/stc/scintilla/src/LexFlagship.cxx mode change 100644 => 100755 src/stc/scintilla/src/LexGen.py delete mode 100644 src/stc/scintilla/src/LexHaskell.cxx delete mode 100644 src/stc/scintilla/src/LexSQL.cxx delete mode 100644 src/stc/scintilla/src/WindowAccessor.cxx delete mode 100644 src/stc/scintilla/src/descrip.mms diff --git a/src/stc/scintilla/include/Accessor.h b/src/stc/scintilla/include/Accessor.h deleted file mode 100644 index d9db9c7bfe..0000000000 --- a/src/stc/scintilla/include/Accessor.h +++ /dev/null @@ -1,79 +0,0 @@ -// Scintilla source code edit control -/** @file Accessor.h - ** Rapid easy access to contents of a Scintilla. - **/ -// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8}; - -class Accessor; - -typedef bool (*PFNIsCommentLeader)(Accessor &styler, int pos, int len); - -/** - * Interface to data in a Scintilla. - */ -class Accessor { -protected: - enum {extremePosition=0x7FFFFFFF}; - /** @a bufferSize is a trade off between time taken to copy the characters - * and retrieval overhead. - * @a slopSize positions the buffer before the desired position - * in case there is some backtracking. */ - enum {bufferSize=4000, slopSize=bufferSize/8}; - char buf[bufferSize+1]; - int startPos; - int endPos; - int codePage; - - virtual bool InternalIsLeadByte(char ch)=0; - virtual void Fill(int position)=0; - -public: - Accessor() : startPos(extremePosition), endPos(0), codePage(0) {} - virtual ~Accessor() {} - char operator[](int position) { - if (position < startPos || position >= endPos) { - Fill(position); - } - return buf[position - startPos]; - } - /** Safe version of operator[], returning a defined value for invalid position. */ - char SafeGetCharAt(int position, char chDefault=' ') { - if (position < startPos || position >= endPos) { - Fill(position); - if (position < startPos || position >= endPos) { - // Position is outside range of document - return chDefault; - } - } - return buf[position - startPos]; - } - bool IsLeadByte(char ch) { - return codePage && InternalIsLeadByte(ch); - } - void SetCodePage(int codePage_) { codePage = codePage_; } - - virtual bool Match(int pos, const char *s)=0; - virtual char StyleAt(int position)=0; - virtual int GetLine(int position)=0; - virtual int LineStart(int line)=0; - virtual int LevelAt(int line)=0; - virtual int Length()=0; - virtual void Flush()=0; - virtual int GetLineState(int line)=0; - virtual int SetLineState(int line, int state)=0; - virtual int GetPropertyInt(const char *key, int defaultValue=0)=0; - virtual char *GetProperties()=0; - - // Style setting - virtual void StartAt(unsigned int start, char chMask=31)=0; - virtual void SetFlags(char chFlags_, char chWhile_)=0; - virtual unsigned int GetStartSegment()=0; - virtual void StartSegment(unsigned int pos)=0; - virtual void ColourTo(unsigned int pos, int chAttr)=0; - virtual void SetLevel(int line, int level)=0; - virtual int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0)=0; - virtual void IndicatorFill(int start, int end, int indicator, int value)=0; -}; diff --git a/src/stc/scintilla/include/ILexer.h b/src/stc/scintilla/include/ILexer.h new file mode 100644 index 0000000000..e08b8701c2 --- /dev/null +++ b/src/stc/scintilla/include/ILexer.h @@ -0,0 +1,77 @@ +// Scintilla source code edit control +/** @file ILexer.h + ** Interface between Scintilla and lexers. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef ILEXER_H +#define ILEXER_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +#ifdef _WIN32 + #define SCI_METHOD __stdcall +#else + #define SCI_METHOD +#endif + +enum { dvOriginal=0 }; + +class IDocument { +public: + virtual int SCI_METHOD Version() const = 0; + virtual void SCI_METHOD SetErrorStatus(int status) = 0; + virtual int SCI_METHOD Length() const = 0; + virtual void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const = 0; + virtual char SCI_METHOD StyleAt(int position) const = 0; + virtual int SCI_METHOD LineFromPosition(int position) const = 0; + virtual int SCI_METHOD LineStart(int line) const = 0; + virtual int SCI_METHOD GetLevel(int line) const = 0; + virtual int SCI_METHOD SetLevel(int line, int level) = 0; + virtual int SCI_METHOD GetLineState(int line) const = 0; + virtual int SCI_METHOD SetLineState(int line, int state) = 0; + virtual void SCI_METHOD StartStyling(int position, char mask) = 0; + virtual bool SCI_METHOD SetStyleFor(int length, char style) = 0; + virtual bool SCI_METHOD SetStyles(int length, const char *styles) = 0; + virtual void SCI_METHOD DecorationSetCurrentIndicator(int indicator) = 0; + virtual void SCI_METHOD DecorationFillRange(int position, int value, int fillLength) = 0; + virtual void SCI_METHOD ChangeLexerState(int start, int end) = 0; + virtual int SCI_METHOD CodePage() const = 0; + virtual bool SCI_METHOD IsDBCSLeadByte(char ch) const = 0; + virtual const char * SCI_METHOD BufferPointer() = 0; + virtual int SCI_METHOD GetLineIndentation(int line) = 0; +}; + +enum { lvOriginal=0 }; + +class ILexer { +public: + virtual int SCI_METHOD Version() const = 0; + virtual void SCI_METHOD Release() = 0; + virtual const char * SCI_METHOD PropertyNames() = 0; + virtual int SCI_METHOD PropertyType(const char *name) = 0; + virtual const char * SCI_METHOD DescribeProperty(const char *name) = 0; + virtual int SCI_METHOD PropertySet(const char *key, const char *val) = 0; + virtual const char * SCI_METHOD DescribeWordListSets() = 0; + virtual int SCI_METHOD WordListSet(int n, const char *wl) = 0; + virtual void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; + virtual void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; + virtual void * SCI_METHOD PrivateCall(int operation, void *pointer) = 0; +}; + +class ILoader { +public: + virtual int SCI_METHOD Release() = 0; + // Returns a status code from SC_STATUS_* + virtual int SCI_METHOD AddData(char *data, int length) = 0; + virtual void * SCI_METHOD ConvertToDocument() = 0; +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/include/KeyWords.h b/src/stc/scintilla/include/KeyWords.h deleted file mode 100644 index 5593b7d091..0000000000 --- a/src/stc/scintilla/include/KeyWords.h +++ /dev/null @@ -1,113 +0,0 @@ -// Scintilla source code edit control -/** @file KeyWords.h - ** Colourise for particular languages. - **/ -// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -/** - */ -class WordList { -public: - // Each word contains at least one character - a empty word acts as sentinel at the end. - char **words; - char *list; - int len; - bool onlyLineEnds; ///< Delimited by any white space or only line ends - bool sorted; - int starts[256]; - WordList(bool onlyLineEnds_ = false) : - words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_), - sorted(false) - {} - ~WordList() { Clear(); } - operator bool() { return len ? true : false; } - void Clear(); - void Set(const char *s); - bool InList(const char *s); - bool InListAbbreviated(const char *s, const char marker); -}; - -typedef void (*LexerFunction)(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler); - -/** - * A LexerModule is responsible for lexing and folding a particular language. - * The class maintains a list of LexerModules which can be searched to find a - * module appropriate to a particular language. - */ -class LexerModule { -protected: - const LexerModule *next; - int language; - LexerFunction fnLexer; - LexerFunction fnFolder; - const char * const * wordListDescriptions; - int styleBits; - - static const LexerModule *base; - static int nextLanguage; - -public: - const char *languageName; - LexerModule(int language_, - LexerFunction fnLexer_, - const char *languageName_=0, - LexerFunction fnFolder_=0, - const char * const wordListDescriptions_[] = NULL, - int styleBits_=5); - virtual ~LexerModule() { - } - int GetLanguage() const { return language; } - - // -1 is returned if no WordList information is available - int GetNumWordLists() const; - const char *GetWordListDescription(int index) const; - - int GetStyleBitsNeeded() const; - - virtual void Lex(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) const; - virtual void Fold(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) const; - static const LexerModule *Find(int language); - static const LexerModule *Find(const char *languageName); -}; - -#ifdef SCI_NAMESPACE -} -#endif - -/** - * Check if a character is a space. - * This is ASCII specific but is safe with chars >= 0x80. - */ -inline bool isspacechar(unsigned char ch) { - return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d)); -} - -inline bool iswordchar(char ch) { - return isascii(ch) && (isalnum(ch) || ch == '.' || ch == '_'); -} - -inline bool iswordstart(char ch) { - return isascii(ch) && (isalnum(ch) || ch == '_'); -} - -inline bool isoperator(char ch) { - if (isascii(ch) && isalnum(ch)) - return false; - // '.' left out as it is used to make up numbers - if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || - ch == '(' || ch == ')' || ch == '-' || ch == '+' || - ch == '=' || ch == '|' || ch == '{' || ch == '}' || - ch == '[' || ch == ']' || ch == ':' || ch == ';' || - ch == '<' || ch == '>' || ch == ',' || ch == '/' || - ch == '?' || ch == '!' || ch == '.' || ch == '~') - return true; - return false; -} diff --git a/src/stc/scintilla/include/Platform.h b/src/stc/scintilla/include/Platform.h index b5d6d9bf8d..1b5dfbe3df 100644 --- a/src/stc/scintilla/include/Platform.h +++ b/src/stc/scintilla/include/Platform.h @@ -16,9 +16,11 @@ #define PLAT_GTK 0 #define PLAT_GTK_WIN32 0 +#define PLAT_GTK_MACOSX 0 #define PLAT_MACOSX 0 #define PLAT_WIN 0 #define PLAT_WX 0 +#define PLAT_QT 0 #define PLAT_FOX 0 #if defined(FOX) @@ -29,6 +31,10 @@ #undef PLAT_WX #define PLAT_WX 1 +#elif defined(SCINTILLA_QT) +#undef PLAT_QT +#define PLAT_QT 1 + #elif defined(GTK) #undef PLAT_GTK #define PLAT_GTK 1 @@ -38,6 +44,11 @@ #define PLAT_GTK_WIN32 1 #endif +#if defined(__APPLE__) +#undef PLAT_GTK_MACOSX +#define PLAT_GTK_MACOSX 1 +#endif + #elif defined(__APPLE__) #undef PLAT_MACOSX @@ -53,6 +64,10 @@ namespace Scintilla { #endif +typedef float XYPOSITION; +typedef double XYACCUMULATOR; +//#define XYPOSITION int + // Underlying the implementation of the platform classes are platform specific types. // Sometimes these need to be passed around by client code so they are defined here @@ -70,10 +85,10 @@ typedef void *IdlerID; */ class Point { public: - int x; - int y; + XYPOSITION x; + XYPOSITION y; - explicit Point(int x_=0, int y_=0) : x(x_), y(y_) { + explicit Point(XYPOSITION x_=0, XYPOSITION y_=0) : x(x_), y(y_) { } // Other automatically defined methods (assignment, copy constructor, destructor) are fine @@ -88,12 +103,12 @@ public: */ class PRectangle { public: - int left; - int top; - int right; - int bottom; + XYPOSITION left; + XYPOSITION top; + XYPOSITION right; + XYPOSITION bottom; - PRectangle(int left_=0, int top_=0, int right_=0, int bottom_ = 0) : + PRectangle(XYPOSITION left_=0, XYPOSITION top_=0, XYPOSITION right_=0, XYPOSITION bottom_ = 0) : left(left_), top(top_), right(right_), bottom(bottom_) { } @@ -115,31 +130,19 @@ public: return (right > other.left) && (left < other.right) && (bottom > other.top) && (top < other.bottom); } - void Move(int xDelta, int yDelta) { + void Move(XYPOSITION xDelta, XYPOSITION yDelta) { left += xDelta; top += yDelta; right += xDelta; bottom += yDelta; } - int Width() { return right - left; } - int Height() { return bottom - top; } + XYPOSITION Width() { return right - left; } + XYPOSITION Height() { return bottom - top; } bool Empty() { return (Height() <= 0) || (Width() <= 0); } }; -/** - * In some circumstances, including Win32 in paletted mode and GTK+, each colour - * must be allocated before use. The desired colours are held in the ColourDesired class, - * and after allocation the allocation entry is stored in the ColourAllocated class. In other - * circumstances, such as Win32 in true colour mode, the allocation process just copies - * the RGB values from the desired to the allocated class. - * As each desired colour requires allocation before it can be used, the ColourPair class - * holds both a ColourDesired and a ColourAllocated - * The Palette class is responsible for managing the palette of colours which contains a - * list of ColourPair objects and performs the allocation. - */ - /** * Holds a desired RGB colour. */ @@ -205,82 +208,39 @@ public: }; /** - * Holds an allocated RGB colour which may be an approximation to the desired colour. - */ -class ColourAllocated { - long coAllocated; - -public: - - ColourAllocated(long lcol=0) { - coAllocated = lcol; - } - - void Set(long lcol) { - coAllocated = lcol; - } - - long AsLong() const { - return coAllocated; - } -}; - -/** - * Colour pairs hold a desired colour and an allocated colour. + * Font management. */ -struct ColourPair { - ColourDesired desired; - ColourAllocated allocated; - ColourPair(ColourDesired desired_=ColourDesired(0,0,0)) { - desired = desired_; - allocated.Set(desired.AsLong()); - } - void Copy() { - allocated.Set(desired.AsLong()); +struct FontParameters { + const char *faceName; + float size; + int weight; + bool italic; + int extraFontFlag; + int technology; + int characterSet; + + FontParameters( + const char *faceName_, + float size_=10, + int weight_=400, + bool italic_=false, + int extraFontFlag_=0, + int technology_=0, + int characterSet_=0) : + + faceName(faceName_), + size(size_), + weight(weight_), + italic(italic_), + extraFontFlag(extraFontFlag_), + technology(technology_), + characterSet(characterSet_) + { } -}; - -class Window; // Forward declaration for Palette - -/** - * Colour palette management. - */ -class Palette { - int used; - int size; - ColourPair *entries; -#if PLAT_GTK - void *allocatedPalette; // GdkColor * - int allocatedLen; -#endif - // Private so Palette objects can not be copied - Palette(const Palette &) {} - Palette &operator=(const Palette &) { return *this; } -public: -#if PLAT_WIN - void *hpal; -#endif - bool allowRealization; - - Palette(); - ~Palette(); - void Release(); - - /** - * This method either adds a colour to the list of wanted colours (want==true) - * or retrieves the allocated colour back to the ColourPair. - * This is one method to make it easier to keep the code for wanting and retrieving in sync. - */ - void WantFind(ColourPair &cp, bool want); - - void Allocate(Window &w); }; -/** - * Font management. - */ class Font { protected: FontID fid; @@ -288,21 +248,23 @@ protected: int ascent; #endif // Private so Font objects can not be copied - Font(const Font &) {} - Font &operator=(const Font &) { fid=0; return *this; } + Font(const Font &); + Font &operator=(const Font &); public: Font(); virtual ~Font(); - virtual void Create(const char *faceName, int characterSet, int size, - bool bold, bool italic, int extraFontFlag=0); + virtual void Create(const FontParameters &fp); virtual void Release(); FontID GetID() { return fid; } // Alias another font - caller guarantees not to Release void SetID(FontID fid_) { fid = fid_; } +#if PLAT_WX + void SetAscent(int ascent_) { ascent = ascent_; } +#endif friend class Surface; - friend class SurfaceImpl; + friend class SurfaceImpl; }; /** @@ -314,9 +276,9 @@ private: Surface(const Surface &) {} Surface &operator=(const Surface &) { return *this; } public: - Surface() {}; - virtual ~Surface() {}; - static Surface *Allocate(); + Surface() {} + virtual ~Surface() {} + static Surface *Allocate(int technology); virtual void Init(WindowID wid)=0; virtual void Init(SurfaceID sid, WindowID wid)=0; @@ -324,35 +286,35 @@ public: virtual void Release()=0; virtual bool Initialised()=0; - virtual void PenColour(ColourAllocated fore)=0; + virtual void PenColour(ColourDesired fore)=0; virtual int LogPixelsY()=0; virtual int DeviceHeightFont(int points)=0; virtual void MoveTo(int x_, int y_)=0; virtual void LineTo(int x_, int y_)=0; - virtual void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back)=0; - virtual void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0; - virtual void FillRectangle(PRectangle rc, ColourAllocated back)=0; + virtual void Polygon(Point *pts, int npts, ColourDesired fore, ColourDesired back)=0; + virtual void RectangleDraw(PRectangle rc, ColourDesired fore, ColourDesired back)=0; + virtual void FillRectangle(PRectangle rc, ColourDesired back)=0; virtual void FillRectangle(PRectangle rc, Surface &surfacePattern)=0; - virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0; - virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill, - ColourAllocated outline, int alphaOutline, int flags)=0; - virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back)=0; + virtual void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back)=0; + virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, + ColourDesired outline, int alphaOutline, int flags)=0; + virtual void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) = 0; + virtual void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back)=0; virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource)=0; - virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0; - virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back)=0; - virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore)=0; - virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions)=0; - virtual int WidthText(Font &font_, const char *s, int len)=0; - virtual int WidthChar(Font &font_, char ch)=0; - virtual int Ascent(Font &font_)=0; - virtual int Descent(Font &font_)=0; - virtual int InternalLeading(Font &font_)=0; - virtual int ExternalLeading(Font &font_)=0; - virtual int Height(Font &font_)=0; - virtual int AverageCharWidth(Font &font_)=0; - - virtual int SetPalette(Palette *pal, bool inBackGround)=0; + virtual void DrawTextNoClip(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0; + virtual void DrawTextClipped(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore, ColourDesired back)=0; + virtual void DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybase, const char *s, int len, ColourDesired fore)=0; + virtual void MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions)=0; + virtual XYPOSITION WidthText(Font &font_, const char *s, int len)=0; + virtual XYPOSITION WidthChar(Font &font_, char ch)=0; + virtual XYPOSITION Ascent(Font &font_)=0; + virtual XYPOSITION Descent(Font &font_)=0; + virtual XYPOSITION InternalLeading(Font &font_)=0; + virtual XYPOSITION ExternalLeading(Font &font_)=0; + virtual XYPOSITION Height(Font &font_)=0; + virtual XYPOSITION AverageCharWidth(Font &font_)=0; + virtual void SetClip(PRectangle rc)=0; virtual void FlushCachedState()=0; @@ -411,8 +373,8 @@ public: void SetTitle(const char *s); PRectangle GetMonitorRect(Point pt); #if PLAT_MACOSX - void SetWindow(void *ref) { windowRef = ref; }; - void SetControl(void *_control) { control = _control; }; + void SetWindow(void *ref) { windowRef = ref; } + void SetControl(void *_control) { control = _control; } #endif private: Cursor cursorLast; @@ -429,7 +391,7 @@ public: static ListBox *Allocate(); virtual void SetFont(Font &font)=0; - virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_)=0; + virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_, int technology_)=0; virtual void SetAverageCharWidth(int width)=0; virtual void SetVisibleRows(int rows)=0; virtual int GetVisibleRows() const=0; @@ -443,6 +405,7 @@ public: virtual int Find(const char *prefix)=0; virtual void GetValue(int n, char *value, int len)=0; virtual void RegisterImage(int type, const char *xpm_data)=0; + virtual void RegisterRGBAImage(int type, int width, int height, const unsigned char *pixelsImage) = 0; virtual void ClearRegisteredImages()=0; virtual void SetDoubleClickAction(CallBackAction, void *)=0; virtual void SetList(const char* list, char separator, char typesep)=0; @@ -474,7 +437,7 @@ public: */ class DynamicLibrary { public: - virtual ~DynamicLibrary() {}; + virtual ~DynamicLibrary() {} /// @return Pointer to function "name", or NULL on failure. virtual Function FindFunction(const char *name) = 0; @@ -553,4 +516,10 @@ public: #pragma warning(disable: 4244 4309 4514 4710) #endif +#if defined(__GNUC__) && defined(SCINTILLA_QT) +#pragma GCC diagnostic ignored "-Wmissing-braces" +#pragma GCC diagnostic ignored "-Wmissing-field-initializers" +#pragma GCC diagnostic ignored "-Wchar-subscripts" +#endif + #endif diff --git a/src/stc/scintilla/include/PropSet.h b/src/stc/scintilla/include/PropSet.h deleted file mode 100644 index c95202174f..0000000000 --- a/src/stc/scintilla/include/PropSet.h +++ /dev/null @@ -1,26 +0,0 @@ -// Scintilla source code edit control -/** @file PropSet.h - ** An interface to the methods needed for access to property sets inside lexers. - **/ -// Copyright 1998-2009 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef PROPSET_H -#define PROPSET_H - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -class PropertyGet { -public: - virtual char *ToString() const=0; // Caller must delete[] the return value - virtual int GetInt(const char *key, int defaultValue=0) const=0; - virtual ~PropertyGet() {} -}; - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/src/stc/scintilla/include/SString.h b/src/stc/scintilla/include/SString.h deleted file mode 100644 index b770afebee..0000000000 --- a/src/stc/scintilla/include/SString.h +++ /dev/null @@ -1,289 +0,0 @@ -// SciTE - Scintilla based Text Editor -/** @file SString.h - ** A simple string class. - **/ -// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#ifndef SSTRING_H -#define SSTRING_H - - -// These functions are implemented because each platform calls them something different. -int CompareCaseInsensitive(const char *a, const char *b); -int CompareNCaseInsensitive(const char *a, const char *b, size_t len); -bool EqualCaseInsensitive(const char *a, const char *b); - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -// Define another string class. -// While it would be 'better' to use std::string, that doubles the executable size. -// An SString may contain embedded nul characters. - -/** - * Base class from which the two other classes (SBuffer & SString) - * are derived. - */ -class SContainer { -public: - /** Type of string lengths (sizes) and positions (indexes). */ - typedef size_t lenpos_t; - /** Out of bounds value indicating that the string argument should be measured. */ - enum { measure_length=0xffffffffU}; - -protected: - char *s; ///< The C string - lenpos_t sSize; ///< The size of the buffer, less 1: ie. the maximum size of the string - - SContainer() : s(0), sSize(0) {} - ~SContainer() { - delete []s; // Suppose it was allocated using StringAllocate - s = 0; - sSize = 0; - } - /** Size of buffer. */ - lenpos_t size() const { - if (s) { - return sSize; - } else { - return 0; - } - } -public: - /** - * Allocate uninitialized memory big enough to fit a string of the given length. - * @return the pointer to the new string - */ - static char *StringAllocate(lenpos_t len); - /** - * Duplicate a buffer/C string. - * Allocate memory of the given size, or big enough to fit the string if length isn't given; - * then copy the given string in the allocated memory. - * @return the pointer to the new string - */ - static char *StringAllocate( - const char *s, ///< The string to duplicate - lenpos_t len=measure_length); ///< The length of memory to allocate. Optional. -}; - - -/** - * @brief A string buffer class. - * - * Main use is to ask an API the length of a string it can provide, - * then to allocate a buffer of the given size, and to provide this buffer - * to the API to put the string. - * This class is intended to be shortlived, to be transformed as SString - * as soon as it holds the string, so it has little members. - * Note: we assume the buffer is filled by the API. If the length can be shorter, - * we should set sLen to strlen(sb.ptr()) in related SString constructor and assignment. - */ -class SBuffer : protected SContainer { -public: - SBuffer(lenpos_t len) { - s = StringAllocate(len); - if (s) { - *s = '\0'; - sSize = len; - } else { - sSize = 0; - } - } -private: - /// Copy constructor - // Here only to be on the safe size, user should avoid returning SBuffer values. - SBuffer(const SBuffer &source) : SContainer() { - s = StringAllocate(source.s, source.sSize); - sSize = (s) ? source.sSize : 0; - } - /// Default assignment operator - // Same here, shouldn't be used - SBuffer &operator=(const SBuffer &source) { - if (this != &source) { - delete []s; - s = StringAllocate(source.s, source.sSize); - sSize = (s) ? source.sSize : 0; - } - return *this; - } -public: - /** Provide direct read/write access to buffer. */ - char *ptr() { - return s; - } - /** Ownership of the buffer have been taken, so release it. */ - void reset() { - s = 0; - sSize = 0; - } - /** Size of buffer. */ - lenpos_t size() const { - return SContainer::size(); - } -}; - - -/** - * @brief A simple string class. - * - * Hold the length of the string for quick operations, - * can have a buffer bigger than the string to avoid too many memory allocations and copies. - * May have embedded zeroes as a result of @a substitute, but relies too heavily on C string - * functions to allow reliable manipulations of these strings, other than simple appends, etc. - */ -class SString : protected SContainer { - lenpos_t sLen; ///< The size of the string in s - lenpos_t sizeGrowth; ///< Minimum growth size when appending strings - enum { sizeGrowthDefault = 64 }; - - bool grow(lenpos_t lenNew); - SString &assign(const char *sOther, lenpos_t sSize_=measure_length); - -public: - SString() : sLen(0), sizeGrowth(sizeGrowthDefault) {} - SString(const SString &source) : SContainer(), sizeGrowth(sizeGrowthDefault) { - s = StringAllocate(source.s, source.sLen); - sSize = sLen = (s) ? source.sLen : 0; - } - SString(const char *s_) : sizeGrowth(sizeGrowthDefault) { - s = StringAllocate(s_); - sSize = sLen = (s) ? strlen(s) : 0; - } - SString(SBuffer &buf) : sizeGrowth(sizeGrowthDefault) { - s = buf.ptr(); - sSize = sLen = buf.size(); - // Consumes the given buffer! - buf.reset(); - } - SString(const char *s_, lenpos_t first, lenpos_t last) : sizeGrowth(sizeGrowthDefault) { - // note: expects the "last" argument to point one beyond the range end (a la STL iterators) - s = StringAllocate(s_ + first, last - first); - sSize = sLen = (s) ? last - first : 0; - } - SString(int i); - SString(double d, int precision); - ~SString() { - sLen = 0; - } - void clear() { - if (s) { - *s = '\0'; - } - sLen = 0; - } - /** Size of buffer. */ - lenpos_t size() const { - return SContainer::size(); - } - /** Size of string in buffer. */ - lenpos_t length() const { - return sLen; - } - /** Read access to a character of the string. */ - char operator[](lenpos_t i) const { - return (s && i < sSize) ? s[i] : '\0'; - } - SString &operator=(const char *source) { - return assign(source); - } - SString &operator=(const SString &source) { - if (this != &source) { - assign(source.s, source.sLen); - } - return *this; - } - bool operator==(const SString &sOther) const; - bool operator!=(const SString &sOther) const { - return !operator==(sOther); - } - bool operator==(const char *sOther) const; - bool operator!=(const char *sOther) const { - return !operator==(sOther); - } - bool contains(char ch) const { - return (s && *s) ? strchr(s, ch) != 0 : false; - } - void setsizegrowth(lenpos_t sizeGrowth_) { - sizeGrowth = sizeGrowth_; - } - const char *c_str() const { - return s ? s : ""; - } - /** Give ownership of buffer to caller which must use delete[] to free buffer. */ - char *detach() { - char *sRet = s; - s = 0; - sSize = 0; - sLen = 0; - return sRet; - } - SString substr(lenpos_t subPos, lenpos_t subLen=measure_length) const; - SString &lowercase(lenpos_t subPos = 0, lenpos_t subLen=measure_length); - SString &uppercase(lenpos_t subPos = 0, lenpos_t subLen=measure_length); - SString &append(const char *sOther, lenpos_t sLenOther=measure_length, char sep = '\0'); - SString &operator+=(const char *sOther) { - return append(sOther, static_cast<lenpos_t>(measure_length)); - } - SString &operator+=(const SString &sOther) { - return append(sOther.s, sOther.sLen); - } - SString &operator+=(char ch) { - return append(&ch, 1); - } - SString &appendwithseparator(const char *sOther, char sep) { - return append(sOther, strlen(sOther), sep); - } - SString &insert(lenpos_t pos, const char *sOther, lenpos_t sLenOther=measure_length); - - /** - * Remove @a len characters from the @a pos position, included. - * Characters at pos + len and beyond replace characters at pos. - * If @a len is 0, or greater than the length of the string - * starting at @a pos, the string is just truncated at @a pos. - */ - void remove(lenpos_t pos, lenpos_t len); - - SString &change(lenpos_t pos, char ch) { - if (pos < sLen) { // character changed must be in string bounds - *(s + pos) = ch; - } - return *this; - } - /** Read an integral numeric value from the string. */ - int value() const { - return s ? atoi(s) : 0; - } - bool startswith(const char *prefix); - bool endswith(const char *suffix); - int search(const char *sFind, lenpos_t start=0) const; - bool contains(const char *sFind) const { - return search(sFind) >= 0; - } - int substitute(char chFind, char chReplace); - int substitute(const char *sFind, const char *sReplace); - int remove(const char *sFind) { - return substitute(sFind, ""); - } -}; - - -/** - * Duplicate a C string. - * Allocate memory of the given size, or big enough to fit the string if length isn't given; - * then copy the given string in the allocated memory. - * @return the pointer to the new string - */ -inline char *StringDup( - const char *s, ///< The string to duplicate - SContainer::lenpos_t len=SContainer::measure_length) ///< The length of memory to allocate. Optional. -{ - return SContainer::StringAllocate(s, len); -} - -#ifdef SCI_NAMESPACE -} -#endif - -#endif diff --git a/src/stc/scintilla/include/SciLexer.h b/src/stc/scintilla/include/SciLexer.h index ced86f4339..57b5cf6e7b 100644 --- a/src/stc/scintilla/include/SciLexer.h +++ b/src/stc/scintilla/include/SciLexer.h @@ -111,6 +111,15 @@ #define SCLEX_NIMROD 96 #define SCLEX_SML 97 #define SCLEX_MARKDOWN 98 +#define SCLEX_TXT2TAGS 99 +#define SCLEX_A68K 100 +#define SCLEX_MODULA 101 +#define SCLEX_COFFEESCRIPT 102 +#define SCLEX_TCMD 103 +#define SCLEX_AVS 104 +#define SCLEX_ECL 105 +#define SCLEX_OSCRIPT 106 +#define SCLEX_VISUALPROLOG 107 #define SCLEX_AUTOMATIC 1000 #define SCE_P_DEFAULT 0 #define SCE_P_COMMENTLINE 1 @@ -148,6 +157,10 @@ #define SCE_C_COMMENTDOCKEYWORD 17 #define SCE_C_COMMENTDOCKEYWORDERROR 18 #define SCE_C_GLOBALCLASS 19 +#define SCE_C_STRINGRAW 20 +#define SCE_C_TRIPLEVERBATIM 21 +#define SCE_C_HASHQUOTEDSTRING 22 +#define SCE_C_PREPROCESSORCOMMENT 23 #define SCE_D_DEFAULT 0 #define SCE_D_COMMENT 1 #define SCE_D_COMMENTLINE 2 @@ -339,6 +352,16 @@ #define SCE_PL_SUB_PROTOTYPE 40 #define SCE_PL_FORMAT_IDENT 41 #define SCE_PL_FORMAT 42 +#define SCE_PL_STRING_VAR 43 +#define SCE_PL_XLAT 44 +#define SCE_PL_REGEX_VAR 54 +#define SCE_PL_REGSUBST_VAR 55 +#define SCE_PL_BACKTICKS_VAR 57 +#define SCE_PL_HERE_QQ_VAR 61 +#define SCE_PL_HERE_QX_VAR 62 +#define SCE_PL_STRING_QQ_VAR 64 +#define SCE_PL_STRING_QX_VAR 65 +#define SCE_PL_STRING_QR_VAR 66 #define SCE_RB_DEFAULT 0 #define SCE_RB_ERROR 1 #define SCE_RB_COMMENTLINE 2 @@ -403,6 +426,14 @@ #define SCE_L_TAG 2 #define SCE_L_MATH 3 #define SCE_L_COMMENT 4 +#define SCE_L_TAG2 5 +#define SCE_L_MATH2 6 +#define SCE_L_COMMENT2 7 +#define SCE_L_VERBATIM 8 +#define SCE_L_SHORTCMD 9 +#define SCE_L_SPECIAL 10 +#define SCE_L_CMDOPT 11 +#define SCE_L_ERROR 12 #define SCE_LUA_DEFAULT 0 #define SCE_LUA_COMMENT 1 #define SCE_LUA_COMMENTLINE 2 @@ -423,6 +454,7 @@ #define SCE_LUA_WORD6 17 #define SCE_LUA_WORD7 18 #define SCE_LUA_WORD8 19 +#define SCE_LUA_LABEL 20 #define SCE_ERR_DEFAULT 0 #define SCE_ERR_PYTHON 1 #define SCE_ERR_GCC 2 @@ -453,6 +485,17 @@ #define SCE_BAT_COMMAND 5 #define SCE_BAT_IDENTIFIER 6 #define SCE_BAT_OPERATOR 7 +#define SCE_TCMD_DEFAULT 0 +#define SCE_TCMD_COMMENT 1 +#define SCE_TCMD_WORD 2 +#define SCE_TCMD_LABEL 3 +#define SCE_TCMD_HIDE 4 +#define SCE_TCMD_COMMAND 5 +#define SCE_TCMD_IDENTIFIER 6 +#define SCE_TCMD_OPERATOR 7 +#define SCE_TCMD_ENVIRONMENT 8 +#define SCE_TCMD_EXPANSION 9 +#define SCE_TCMD_CLABEL 10 #define SCE_MAKE_DEFAULT 0 #define SCE_MAKE_COMMENT 1 #define SCE_MAKE_PREPROCESSOR 2 @@ -600,6 +643,7 @@ #define SCE_ASM_CHARACTER 12 #define SCE_ASM_STRINGEOL 13 #define SCE_ASM_EXTINSTRUCTION 14 +#define SCE_ASM_COMMENTDIRECTIVE 15 #define SCE_F_DEFAULT 0 #define SCE_F_COMMENT 1 #define SCE_F_NUMBER 2 @@ -637,6 +681,8 @@ #define SCE_CSS_EXTENDED_IDENTIFIER 19 #define SCE_CSS_EXTENDED_PSEUDOCLASS 20 #define SCE_CSS_EXTENDED_PSEUDOELEMENT 21 +#define SCE_CSS_MEDIA 22 +#define SCE_CSS_VARIABLE 23 #define SCE_POV_DEFAULT 0 #define SCE_POV_COMMENT 1 #define SCE_POV_COMMENTLINE 2 @@ -1081,11 +1127,19 @@ #define SCE_FS_DATE 16 #define SCE_FS_STRINGEOL 17 #define SCE_FS_CONSTANT 18 -#define SCE_FS_ASM 19 -#define SCE_FS_LABEL 20 -#define SCE_FS_ERROR 21 -#define SCE_FS_HEXNUMBER 22 -#define SCE_FS_BINNUMBER 23 +#define SCE_FS_WORDOPERATOR 19 +#define SCE_FS_DISABLEDCODE 20 +#define SCE_FS_DEFAULT_C 21 +#define SCE_FS_COMMENTDOC_C 22 +#define SCE_FS_COMMENTLINEDOC_C 23 +#define SCE_FS_KEYWORD_C 24 +#define SCE_FS_KEYWORD2_C 25 +#define SCE_FS_NUMBER_C 26 +#define SCE_FS_STRING_C 27 +#define SCE_FS_PREPROCESSOR_C 28 +#define SCE_FS_OPERATOR_C 29 +#define SCE_FS_IDENTIFIER_C 30 +#define SCE_FS_STRINGEOL_C 31 #define SCE_CSOUND_DEFAULT 0 #define SCE_CSOUND_COMMENT 1 #define SCE_CSOUND_NUMBER 2 @@ -1266,6 +1320,9 @@ #define SCE_POWERSHELL_KEYWORD 8 #define SCE_POWERSHELL_CMDLET 9 #define SCE_POWERSHELL_ALIAS 10 +#define SCE_POWERSHELL_FUNCTION 11 +#define SCE_POWERSHELL_USER1 12 +#define SCE_POWERSHELL_COMMENTSTREAM 13 #define SCE_MYSQL_DEFAULT 0 #define SCE_MYSQL_COMMENT 1 #define SCE_MYSQL_COMMENTLINE 2 @@ -1376,6 +1433,180 @@ #define SCE_MARKDOWN_CODE 19 #define SCE_MARKDOWN_CODE2 20 #define SCE_MARKDOWN_CODEBK 21 +#define SCE_TXT2TAGS_DEFAULT 0 +#define SCE_TXT2TAGS_LINE_BEGIN 1 +#define SCE_TXT2TAGS_STRONG1 2 +#define SCE_TXT2TAGS_STRONG2 3 +#define SCE_TXT2TAGS_EM1 4 +#define SCE_TXT2TAGS_EM2 5 +#define SCE_TXT2TAGS_HEADER1 6 +#define SCE_TXT2TAGS_HEADER2 7 +#define SCE_TXT2TAGS_HEADER3 8 +#define SCE_TXT2TAGS_HEADER4 9 +#define SCE_TXT2TAGS_HEADER5 10 +#define SCE_TXT2TAGS_HEADER6 11 +#define SCE_TXT2TAGS_PRECHAR 12 +#define SCE_TXT2TAGS_ULIST_ITEM 13 +#define SCE_TXT2TAGS_OLIST_ITEM 14 +#define SCE_TXT2TAGS_BLOCKQUOTE 15 +#define SCE_TXT2TAGS_STRIKEOUT 16 +#define SCE_TXT2TAGS_HRULE 17 +#define SCE_TXT2TAGS_LINK 18 +#define SCE_TXT2TAGS_CODE 19 +#define SCE_TXT2TAGS_CODE2 20 +#define SCE_TXT2TAGS_CODEBK 21 +#define SCE_TXT2TAGS_COMMENT 22 +#define SCE_TXT2TAGS_OPTION 23 +#define SCE_TXT2TAGS_PREPROC 24 +#define SCE_TXT2TAGS_POSTPROC 25 +#define SCE_A68K_DEFAULT 0 +#define SCE_A68K_COMMENT 1 +#define SCE_A68K_NUMBER_DEC 2 +#define SCE_A68K_NUMBER_BIN 3 +#define SCE_A68K_NUMBER_HEX 4 +#define SCE_A68K_STRING1 5 +#define SCE_A68K_OPERATOR 6 +#define SCE_A68K_CPUINSTRUCTION 7 +#define SCE_A68K_EXTINSTRUCTION 8 +#define SCE_A68K_REGISTER 9 +#define SCE_A68K_DIRECTIVE 10 +#define SCE_A68K_MACRO_ARG 11 +#define SCE_A68K_LABEL 12 +#define SCE_A68K_STRING2 13 +#define SCE_A68K_IDENTIFIER 14 +#define SCE_A68K_MACRO_DECLARATION 15 +#define SCE_A68K_COMMENT_WORD 16 +#define SCE_A68K_COMMENT_SPECIAL 17 +#define SCE_A68K_COMMENT_DOXYGEN 18 +#define SCE_MODULA_DEFAULT 0 +#define SCE_MODULA_COMMENT 1 +#define SCE_MODULA_DOXYCOMM 2 +#define SCE_MODULA_DOXYKEY 3 +#define SCE_MODULA_KEYWORD 4 +#define SCE_MODULA_RESERVED 5 +#define SCE_MODULA_NUMBER 6 +#define SCE_MODULA_BASENUM 7 +#define SCE_MODULA_FLOAT 8 +#define SCE_MODULA_STRING 9 +#define SCE_MODULA_STRSPEC 10 +#define SCE_MODULA_CHAR 11 +#define SCE_MODULA_CHARSPEC 12 +#define SCE_MODULA_PROC 13 +#define SCE_MODULA_PRAGMA 14 +#define SCE_MODULA_PRGKEY 15 +#define SCE_MODULA_OPERATOR 16 +#define SCE_MODULA_BADSTR 17 +#define SCE_COFFEESCRIPT_DEFAULT 0 +#define SCE_COFFEESCRIPT_COMMENT 1 +#define SCE_COFFEESCRIPT_COMMENTLINE 2 +#define SCE_COFFEESCRIPT_COMMENTDOC 3 +#define SCE_COFFEESCRIPT_NUMBER 4 +#define SCE_COFFEESCRIPT_WORD 5 +#define SCE_COFFEESCRIPT_STRING 6 +#define SCE_COFFEESCRIPT_CHARACTER 7 +#define SCE_COFFEESCRIPT_UUID 8 +#define SCE_COFFEESCRIPT_PREPROCESSOR 9 +#define SCE_COFFEESCRIPT_OPERATOR 10 +#define SCE_COFFEESCRIPT_IDENTIFIER 11 +#define SCE_COFFEESCRIPT_STRINGEOL 12 +#define SCE_COFFEESCRIPT_VERBATIM 13 +#define SCE_COFFEESCRIPT_REGEX 14 +#define SCE_COFFEESCRIPT_COMMENTLINEDOC 15 +#define SCE_COFFEESCRIPT_WORD2 16 +#define SCE_COFFEESCRIPT_COMMENTDOCKEYWORD 17 +#define SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR 18 +#define SCE_COFFEESCRIPT_GLOBALCLASS 19 +#define SCE_COFFEESCRIPT_STRINGRAW 20 +#define SCE_COFFEESCRIPT_TRIPLEVERBATIM 21 +#define SCE_COFFEESCRIPT_HASHQUOTEDSTRING 22 +#define SCE_COFFEESCRIPT_COMMENTBLOCK 22 +#define SCE_COFFEESCRIPT_VERBOSE_REGEX 23 +#define SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT 24 +#define SCE_AVS_DEFAULT 0 +#define SCE_AVS_COMMENTBLOCK 1 +#define SCE_AVS_COMMENTBLOCKN 2 +#define SCE_AVS_COMMENTLINE 3 +#define SCE_AVS_NUMBER 4 +#define SCE_AVS_OPERATOR 5 +#define SCE_AVS_IDENTIFIER 6 +#define SCE_AVS_STRING 7 +#define SCE_AVS_TRIPLESTRING 8 +#define SCE_AVS_KEYWORD 9 +#define SCE_AVS_FILTER 10 +#define SCE_AVS_PLUGIN 11 +#define SCE_AVS_FUNCTION 12 +#define SCE_AVS_CLIPPROP 13 +#define SCE_AVS_USERDFN 14 +#define SCE_ECL_DEFAULT 0 +#define SCE_ECL_COMMENT 1 +#define SCE_ECL_COMMENTLINE 2 +#define SCE_ECL_NUMBER 3 +#define SCE_ECL_STRING 4 +#define SCE_ECL_WORD0 5 +#define SCE_ECL_OPERATOR 6 +#define SCE_ECL_CHARACTER 7 +#define SCE_ECL_UUID 8 +#define SCE_ECL_PREPROCESSOR 9 +#define SCE_ECL_UNKNOWN 10 +#define SCE_ECL_IDENTIFIER 11 +#define SCE_ECL_STRINGEOL 12 +#define SCE_ECL_VERBATIM 13 +#define SCE_ECL_REGEX 14 +#define SCE_ECL_COMMENTLINEDOC 15 +#define SCE_ECL_WORD1 16 +#define SCE_ECL_COMMENTDOCKEYWORD 17 +#define SCE_ECL_COMMENTDOCKEYWORDERROR 18 +#define SCE_ECL_WORD2 19 +#define SCE_ECL_WORD3 20 +#define SCE_ECL_WORD4 21 +#define SCE_ECL_WORD5 22 +#define SCE_ECL_COMMENTDOC 23 +#define SCE_ECL_ADDED 24 +#define SCE_ECL_DELETED 25 +#define SCE_ECL_CHANGED 26 +#define SCE_ECL_MOVED 27 +#define SCE_OSCRIPT_DEFAULT 0 +#define SCE_OSCRIPT_LINE_COMMENT 1 +#define SCE_OSCRIPT_BLOCK_COMMENT 2 +#define SCE_OSCRIPT_DOC_COMMENT 3 +#define SCE_OSCRIPT_PREPROCESSOR 4 +#define SCE_OSCRIPT_NUMBER 5 +#define SCE_OSCRIPT_SINGLEQUOTE_STRING 6 +#define SCE_OSCRIPT_DOUBLEQUOTE_STRING 7 +#define SCE_OSCRIPT_CONSTANT 8 +#define SCE_OSCRIPT_IDENTIFIER 9 +#define SCE_OSCRIPT_GLOBAL 10 +#define SCE_OSCRIPT_KEYWORD 11 +#define SCE_OSCRIPT_OPERATOR 12 +#define SCE_OSCRIPT_LABEL 13 +#define SCE_OSCRIPT_TYPE 14 +#define SCE_OSCRIPT_FUNCTION 15 +#define SCE_OSCRIPT_OBJECT 16 +#define SCE_OSCRIPT_PROPERTY 17 +#define SCE_OSCRIPT_METHOD 18 +#define SCE_VISUALPROLOG_DEFAULT 0 +#define SCE_VISUALPROLOG_KEY_MAJOR 1 +#define SCE_VISUALPROLOG_KEY_MINOR 2 +#define SCE_VISUALPROLOG_KEY_DIRECTIVE 3 +#define SCE_VISUALPROLOG_COMMENT_BLOCK 4 +#define SCE_VISUALPROLOG_COMMENT_LINE 5 +#define SCE_VISUALPROLOG_COMMENT_KEY 6 +#define SCE_VISUALPROLOG_COMMENT_KEY_ERROR 7 +#define SCE_VISUALPROLOG_IDENTIFIER 8 +#define SCE_VISUALPROLOG_VARIABLE 9 +#define SCE_VISUALPROLOG_ANONYMOUS 10 +#define SCE_VISUALPROLOG_NUMBER 11 +#define SCE_VISUALPROLOG_OPERATOR 12 +#define SCE_VISUALPROLOG_CHARACTER 13 +#define SCE_VISUALPROLOG_CHARACTER_TOO_MANY 14 +#define SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR 15 +#define SCE_VISUALPROLOG_STRING 16 +#define SCE_VISUALPROLOG_STRING_ESCAPE 17 +#define SCE_VISUALPROLOG_STRING_ESCAPE_ERROR 18 +#define SCE_VISUALPROLOG_STRING_EOL_OPEN 19 +#define SCE_VISUALPROLOG_STRING_VERBATIM 20 +#define SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL 21 +#define SCE_VISUALPROLOG_STRING_VERBATIM_EOL 22 /* --Autogenerated -- end of section automatically generated from Scintilla.iface */ #endif diff --git a/src/stc/scintilla/include/Scintilla.h b/src/stc/scintilla/include/Scintilla.h index 0687c5df26..3cacd53101 100644 --- a/src/stc/scintilla/include/Scintilla.h +++ b/src/stc/scintilla/include/Scintilla.h @@ -11,18 +11,14 @@ #ifndef SCINTILLA_H #define SCINTILLA_H -#if defined(LCCWIN) && LCCWIN -typedef BOOL bool; -#endif - #ifdef __cplusplus extern "C" { #endif -#if PLAT_WIN +#if defined(_WIN32) /* Return false on failure: */ -bool Scintilla_RegisterClasses(void *hInstance); -bool Scintilla_ReleaseResources(); +int Scintilla_RegisterClasses(void *hInstance); +int Scintilla_ReleaseResources(); #endif int Scintilla_LinkLexers(); @@ -55,6 +51,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_ADDSTYLEDTEXT 2002 #define SCI_INSERTTEXT 2003 #define SCI_CLEARALL 2004 +#define SCI_DELETERANGE 2645 #define SCI_CLEARDOCUMENTSTYLE 2005 #define SCI_GETLENGTH 2006 #define SCI_GETCHARAT 2007 @@ -95,9 +92,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SETTABWIDTH 2036 #define SCI_GETTABWIDTH 2121 #define SC_CP_UTF8 65001 -#define SC_CP_DBCS 1 #define SCI_SETCODEPAGE 2037 -#define SCI_SETUSEPALETTE 2039 #define MARKER_MAX 31 #define SC_MARK_CIRCLE 0 #define SC_MARK_ROUNDRECT 1 @@ -129,6 +124,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_MARK_LEFTRECT 27 #define SC_MARK_AVAILABLE 28 #define SC_MARK_UNDERLINE 29 +#define SC_MARK_RGBAIMAGE 30 #define SC_MARK_CHARACTER 10000 #define SC_MARKNUM_FOLDEREND 25 #define SC_MARKNUM_FOLDEROPENMID 26 @@ -141,6 +137,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_MARKERDEFINE 2040 #define SCI_MARKERSETFORE 2041 #define SCI_MARKERSETBACK 2042 +#define SCI_MARKERSETBACKSELECTED 2292 +#define SCI_MARKERENABLEHIGHLIGHT 2293 #define SCI_MARKERADD 2043 #define SCI_MARKERDELETE 2044 #define SCI_MARKERDELETEALL 2045 @@ -164,6 +162,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_GETMARGINMASKN 2245 #define SCI_SETMARGINSENSITIVEN 2246 #define SCI_GETMARGINSENSITIVEN 2247 +#define SCI_SETMARGINCURSORN 2248 +#define SCI_GETMARGINCURSORN 2249 #define STYLE_DEFAULT 32 #define STYLE_LINENUMBER 33 #define STYLE_BRACELIGHT 34 @@ -221,6 +221,14 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_STYLEGETCHANGEABLE 2492 #define SCI_STYLEGETHOTSPOT 2493 #define SCI_STYLESETCASE 2060 +#define SC_FONT_SIZE_MULTIPLIER 100 +#define SCI_STYLESETSIZEFRACTIONAL 2061 +#define SCI_STYLEGETSIZEFRACTIONAL 2062 +#define SC_WEIGHT_NORMAL 400 +#define SC_WEIGHT_SEMIBOLD 600 +#define SC_WEIGHT_BOLD 700 +#define SCI_STYLESETWEIGHT 2063 +#define SCI_STYLEGETWEIGHT 2064 #define SCI_STYLESETCHARACTERSET 2066 #define SCI_STYLESETHOTSPOT 2409 #define SCI_SETSELFORE 2067 @@ -238,6 +246,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_GETCARETPERIOD 2075 #define SCI_SETCARETPERIOD 2076 #define SCI_SETWORDCHARS 2077 +#define SCI_GETWORDCHARS 2646 #define SCI_BEGINUNDOACTION 2078 #define SCI_ENDUNDOACTION 2079 #define INDIC_PLAIN 0 @@ -248,6 +257,11 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define INDIC_HIDDEN 5 #define INDIC_BOX 6 #define INDIC_ROUNDBOX 7 +#define INDIC_STRAIGHTBOX 8 +#define INDIC_DASH 9 +#define INDIC_DOTS 10 +#define INDIC_SQUIGGLELOW 11 +#define INDIC_DOTBOX 12 #define INDIC_MAX 31 #define INDIC_CONTAINER 8 #define INDIC0_MASK 0x20 @@ -311,6 +325,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_GETLINEINDENTATION 2127 #define SCI_GETLINEINDENTPOSITION 2128 #define SCI_GETCOLUMN 2129 +#define SCI_COUNTCHARACTERS 2633 #define SCI_SETHSCROLLBAR 2130 #define SCI_GETHSCROLLBAR 2131 #define SC_IV_NONE 0 @@ -324,13 +339,13 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_GETLINEENDPOSITION 2136 #define SCI_GETCODEPAGE 2137 #define SCI_GETCARETFORE 2138 -#define SCI_GETUSEPALETTE 2139 #define SCI_GETREADONLY 2140 #define SCI_SETCURRENTPOS 2141 #define SCI_SETSELECTIONSTART 2142 #define SCI_GETSELECTIONSTART 2143 #define SCI_SETSELECTIONEND 2144 #define SCI_GETSELECTIONEND 2145 +#define SCI_SETEMPTYSELECTION 2556 #define SCI_SETPRINTMAGNIFICATION 2146 #define SCI_GETPRINTMAGNIFICATION 2147 #define SC_PRINT_NORMAL 0 @@ -403,6 +418,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_CALLTIPSETFORE 2206 #define SCI_CALLTIPSETFOREHLT 2207 #define SCI_CALLTIPUSESTYLE 2212 +#define SCI_CALLTIPSETPOSITION 2213 #define SCI_VISIBLEFROMDOCLINE 2220 #define SCI_DOCLINEFROMVISIBLE 2221 #define SCI_WRAPCOUNT 2235 @@ -417,6 +433,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SHOWLINES 2226 #define SCI_HIDELINES 2227 #define SCI_GETLINEVISIBLE 2228 +#define SCI_GETALLLINESVISIBLE 2236 #define SCI_SETFOLDEXPANDED 2229 #define SCI_GETFOLDEXPANDED 2230 #define SCI_TOGGLEFOLD 2231 @@ -445,6 +462,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_WRAPVISUALFLAG_NONE 0x0000 #define SC_WRAPVISUALFLAG_END 0x0001 #define SC_WRAPVISUALFLAG_START 0x0002 +#define SC_WRAPVISUALFLAG_MARGIN 0x0004 #define SCI_SETWRAPVISUALFLAGS 2460 #define SCI_GETWRAPVISUALFLAGS 2461 #define SC_WRAPVISUALFLAGLOC_DEFAULT 0x0000 @@ -486,6 +504,11 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SETFONTQUALITY 2611 #define SCI_GETFONTQUALITY 2612 #define SCI_SETFIRSTVISIBLELINE 2613 +#define SC_MULTIPASTE_ONCE 0 +#define SC_MULTIPASTE_EACH 1 +#define SCI_SETMULTIPASTE 2614 +#define SCI_GETMULTIPASTE 2615 +#define SCI_GETTAG 2616 #define SCI_TARGETFROMSELECTION 2287 #define SCI_LINESJOIN 2288 #define SCI_LINESSPLIT 2289 @@ -552,7 +575,9 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_MOVECARETINSIDEVIEW 2401 #define SCI_LINELENGTH 2350 #define SCI_BRACEHIGHLIGHT 2351 +#define SCI_BRACEHIGHLIGHTINDICATOR 2498 #define SCI_BRACEBADLIGHT 2352 +#define SCI_BRACEBADLIGHTINDICATOR 2499 #define SCI_BRACEMATCH 2353 #define SCI_GETVIEWEOL 2355 #define SCI_SETVIEWEOL 2356 @@ -590,7 +615,9 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_SETMOUSEDOWNCAPTURES 2384 #define SCI_GETMOUSEDOWNCAPTURES 2385 #define SC_CURSORNORMAL -1 +#define SC_CURSORARROW 2 #define SC_CURSORWAIT 4 +#define SC_CURSORREVERSEARROW 7 #define SCI_SETCURSOR 2386 #define SCI_GETCURSOR 2387 #define SCI_SETCONTROLCHARSYMBOL 2388 @@ -658,9 +685,16 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_WORDRIGHTEND 2441 #define SCI_WORDRIGHTENDEXTEND 2442 #define SCI_SETWHITESPACECHARS 2443 +#define SCI_GETWHITESPACECHARS 2647 +#define SCI_SETPUNCTUATIONCHARS 2648 +#define SCI_GETPUNCTUATIONCHARS 2649 #define SCI_SETCHARSDEFAULT 2444 #define SCI_AUTOCGETCURRENT 2445 #define SCI_AUTOCGETCURRENTTEXT 2610 +#define SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE 0 +#define SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE 1 +#define SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR 2634 +#define SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR 2635 #define SCI_ALLOCATE 2446 #define SCI_TARGETASUTF8 2447 #define SCI_SETLENGTHFORENCODE 2448 @@ -668,6 +702,9 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_FINDCOLUMN 2456 #define SCI_GETCARETSTICKY 2457 #define SCI_SETCARETSTICKY 2458 +#define SC_CARETSTICKY_OFF 0 +#define SC_CARETSTICKY_ON 1 +#define SC_CARETSTICKY_WHITESPACE 2 #define SCI_TOGGLECARETSTICKY 2459 #define SCI_SETPASTECONVERTENDINGS 2467 #define SCI_GETPASTECONVERTENDINGS 2468 @@ -696,10 +733,14 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_GETPOSITIONCACHE 2515 #define SCI_COPYALLOWLINE 2519 #define SCI_GETCHARACTERPOINTER 2520 +#define SCI_GETRANGEPOINTER 2643 +#define SCI_GETGAPPOSITION 2644 #define SCI_SETKEYSUNICODE 2521 #define SCI_GETKEYSUNICODE 2522 #define SCI_INDICSETALPHA 2523 #define SCI_INDICGETALPHA 2524 +#define SCI_INDICSETOUTLINEALPHA 2558 +#define SCI_INDICGETOUTLINEALPHA 2559 #define SCI_SETEXTRAASCENT 2525 #define SCI_GETEXTRAASCENT 2526 #define SCI_SETEXTRADESCENT 2527 @@ -714,6 +755,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_MARGINTEXTCLEARALL 2536 #define SCI_MARGINSETSTYLEOFFSET 2537 #define SCI_MARGINGETSTYLEOFFSET 2538 +#define SC_MARGINOPTION_NONE 0 +#define SC_MARGINOPTION_SUBLINESELECT 1 +#define SCI_SETMARGINOPTIONS 2539 +#define SCI_GETMARGINOPTIONS 2557 #define SCI_ANNOTATIONSETTEXT 2540 #define SCI_ANNOTATIONGETTEXT 2541 #define SCI_ANNOTATIONSETSTYLE 2542 @@ -782,6 +827,27 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_GETADDITIONALCARETFORE 2605 #define SCI_ROTATESELECTION 2606 #define SCI_SWAPMAINANCHORCARET 2607 +#define SCI_CHANGELEXERSTATE 2617 +#define SCI_CONTRACTEDFOLDNEXT 2618 +#define SCI_VERTICALCENTRECARET 2619 +#define SCI_MOVESELECTEDLINESUP 2620 +#define SCI_MOVESELECTEDLINESDOWN 2621 +#define SCI_SETIDENTIFIER 2622 +#define SCI_GETIDENTIFIER 2623 +#define SCI_RGBAIMAGESETWIDTH 2624 +#define SCI_RGBAIMAGESETHEIGHT 2625 +#define SCI_MARKERDEFINERGBAIMAGE 2626 +#define SCI_REGISTERRGBAIMAGE 2627 +#define SCI_SCROLLTOSTART 2628 +#define SCI_SCROLLTOEND 2629 +#define SC_TECHNOLOGY_DEFAULT 0 +#define SC_TECHNOLOGY_DIRECTWRITE 1 +#define SCI_SETTECHNOLOGY 2630 +#define SCI_GETTECHNOLOGY 2631 +#define SCI_CREATELOADER 2632 +#define SCI_FINDINDICATORSHOW 2640 +#define SCI_FINDINDICATORFLASH 2641 +#define SCI_FINDINDICATORHIDE 2642 #define SCI_STARTRECORD 3001 #define SCI_STOPRECORD 3002 #define SCI_SETLEXER 4001 @@ -797,6 +863,14 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_GETPROPERTYINT 4010 #define SCI_GETSTYLEBITSNEEDED 4011 #define SCI_GETLEXERLANGUAGE 4012 +#define SCI_PRIVATELEXERCALL 4013 +#define SCI_PROPERTYNAMES 4014 +#define SC_TYPE_BOOLEAN 0 +#define SC_TYPE_INTEGER 1 +#define SC_TYPE_STRING 2 +#define SCI_PROPERTYTYPE 4015 +#define SCI_DESCRIBEPROPERTY 4016 +#define SCI_DESCRIBEKEYWORDSETS 4017 #define SC_MOD_INSERTTEXT 0x1 #define SC_MOD_DELETETEXT 0x2 #define SC_MOD_CHANGESTYLE 0x4 @@ -816,7 +890,12 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_MOD_CHANGEMARGIN 0x10000 #define SC_MOD_CHANGEANNOTATION 0x20000 #define SC_MOD_CONTAINER 0x40000 -#define SC_MODEVENTMASKALL 0x7FFFF +#define SC_MOD_LEXERSTATE 0x80000 +#define SC_MODEVENTMASKALL 0xFFFFF +#define SC_UPDATE_CONTENT 0x1 +#define SC_UPDATE_SELECTION 0x2 +#define SC_UPDATE_V_SCROLL 0x4 +#define SC_UPDATE_H_SCROLL 0x8 #define SCEN_CHANGE 768 #define SCEN_SETFOCUS 512 #define SCEN_KILLFOCUS 256 @@ -845,6 +924,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCMOD_CTRL 2 #define SCMOD_ALT 4 #define SCMOD_SUPER 8 +#define SCMOD_META 16 #define SCN_STYLENEEDED 2000 #define SCN_CHARADDED 2001 #define SCN_SAVEPOINTREACHED 2002 @@ -871,6 +951,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCN_INDICATORRELEASE 2024 #define SCN_AUTOCCANCELLED 2025 #define SCN_AUTOCCHARDELETED 2026 +#define SCN_HOTSPOTRELEASECLICK 2027 /* --Autogenerated -- end of section automatically generated from Scintilla.iface */ /* These structures are defined to be exactly the same shape as the Win32 @@ -901,23 +982,28 @@ struct Sci_TextToFind { #define TextRange Sci_TextRange #define TextToFind Sci_TextToFind -#ifdef PLATFORM_H +typedef void *Sci_SurfaceID; + +struct Sci_Rectangle { + int left; + int top; + int right; + int bottom; +}; /* This structure is used in printing and requires some of the graphics types * from Platform.h. Not needed by most client code. */ struct Sci_RangeToFormat { - SurfaceID hdc; - SurfaceID hdcTarget; - PRectangle rc; - PRectangle rcPage; - Sci_CharacterRange chrg; + Sci_SurfaceID hdc; + Sci_SurfaceID hdcTarget; + struct Sci_Rectangle rc; + struct Sci_Rectangle rcPage; + struct Sci_CharacterRange chrg; }; #define RangeToFormat Sci_RangeToFormat -#endif - struct Sci_NotifyHeader { /* Compatible with Windows NMHDR. * hwndFrom is really an environment specific window handle or pointer @@ -931,11 +1017,22 @@ struct Sci_NotifyHeader { struct SCNotification { struct Sci_NotifyHeader nmhdr; - int position; /* SCN_STYLENEEDED, SCN_MODIFIED, SCN_DWELLSTART, SCN_DWELLEND */ + int position; + /* SCN_STYLENEEDED, SCN_DOUBLECLICK, SCN_MODIFIED, SCN_MARGINCLICK, */ + /* SCN_NEEDSHOWN, SCN_DWELLSTART, SCN_DWELLEND, SCN_CALLTIPCLICK, */ + /* SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, SCN_HOTSPOTRELEASECLICK, */ + /* SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */ + /* SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */ + int ch; /* SCN_CHARADDED, SCN_KEY */ - int modifiers; /* SCN_KEY */ + int modifiers; + /* SCN_KEY, SCN_DOUBLECLICK, SCN_HOTSPOTCLICK, SCN_HOTSPOTDOUBLECLICK, */ + /* SCN_HOTSPOTRELEASECLICK, SCN_INDICATORCLICK, SCN_INDICATORRELEASE, */ + int modificationType; /* SCN_MODIFIED */ - const char *text; /* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION */ + const char *text; + /* SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION, SCN_URIDROPPED */ + int length; /* SCN_MODIFIED */ int linesAdded; /* SCN_MODIFIED */ int message; /* SCN_MACRORECORD */ @@ -949,11 +1046,20 @@ struct SCNotification { int x; /* SCN_DWELLSTART, SCN_DWELLEND */ int y; /* SCN_DWELLSTART, SCN_DWELLEND */ int token; /* SCN_MODIFIED with SC_MOD_CONTAINER */ - int annotationLinesAdded; /* SC_MOD_CHANGEANNOTATION */ + int annotationLinesAdded; /* SCN_MODIFIED with SC_MOD_CHANGEANNOTATION */ + int updated; /* SCN_UPDATEUI */ }; #ifdef SCI_NAMESPACE } #endif +#ifdef INCLUDE_DEPRECATED_FEATURES + +#define SC_CP_DBCS 1 +#define SCI_SETUSEPALETTE 2039 +#define SCI_GETUSEPALETTE 2139 + +#endif + #endif diff --git a/src/stc/scintilla/include/Scintilla.iface b/src/stc/scintilla/include/Scintilla.iface index f2810454d5..0456615e2f 100644 --- a/src/stc/scintilla/include/Scintilla.iface +++ b/src/stc/scintilla/include/Scintilla.iface @@ -101,6 +101,9 @@ fun void InsertText=2003(position pos, string text) # Delete all text in the document. fun void ClearAll=2004(,) +# Delete a range of text in the document. +fun void DeleteRange=2645(position pos, int deleteLength) + # Set all style bytes to 0, remove all folding information. fun void ClearDocumentStyle=2005(,) @@ -224,17 +227,10 @@ get int GetTabWidth=2121(,) # This is the same value as CP_UTF8 in Windows val SC_CP_UTF8=65001 -# The SC_CP_DBCS value can be used to indicate a DBCS mode for GTK+. -val SC_CP_DBCS=1 - # Set the code page used to interpret the bytes of the document as characters. # The SC_CP_UTF8 value can be used to enter Unicode mode. set void SetCodePage=2037(int codePage,) -# In palette mode, Scintilla uses the environment's palette calls to display -# more colours. This may lead to ugly displays. -set void SetUsePalette=2039(bool usePalette,) - enu MarkerSymbol=SC_MARK_ val MARKER_MAX=31 val SC_MARK_CIRCLE=0 @@ -262,7 +258,7 @@ val SC_MARK_CIRCLEPLUSCONNECTED=19 val SC_MARK_CIRCLEMINUS=20 val SC_MARK_CIRCLEMINUSCONNECTED=21 -# Invisible mark that only sets the line background color. +# Invisible mark that only sets the line background colour. val SC_MARK_BACKGROUND=22 val SC_MARK_DOTDOTDOT=23 val SC_MARK_ARROWS=24 @@ -271,6 +267,7 @@ val SC_MARK_FULLRECT=26 val SC_MARK_LEFTRECT=27 val SC_MARK_AVAILABLE=28 val SC_MARK_UNDERLINE=29 +val SC_MARK_RGBAIMAGE=30 val SC_MARK_CHARACTER=10000 @@ -290,10 +287,16 @@ val SC_MASK_FOLDERS=0xFE000000 fun void MarkerDefine=2040(int markerNumber, int markerSymbol) # Set the foreground colour used for a particular marker number. -fun void MarkerSetFore=2041(int markerNumber, colour fore) +set void MarkerSetFore=2041(int markerNumber, colour fore) # Set the background colour used for a particular marker number. -fun void MarkerSetBack=2042(int markerNumber, colour back) +set void MarkerSetBack=2042(int markerNumber, colour back) + +# Set the background colour used for a particular marker number when its folding block is selected. +set void MarkerSetBackSelected=2292(int markerNumber, colour back) + +# Enable/disable highlight for current folding bloc (smallest one that contains the caret) +fun void MarkerEnableHighlight=2293(bool enabled,) # Add a marker to a line, returning an ID which can be used to find or delete the marker. fun int MarkerAdd=2043(int line, int markerNumber) @@ -307,7 +310,8 @@ fun void MarkerDeleteAll=2045(int markerNumber,) # Get a bit mask of all the markers set on a line. fun int MarkerGet=2046(int line,) -# Find the next line after lineStart that includes a marker in mask. +# Find the next line at or after lineStart that includes a marker in mask. +# Return -1 when no more lines. fun int MarkerNext=2047(int lineStart, int markerMask) # Find the previous line before lineStart that includes a marker in mask. @@ -320,7 +324,7 @@ fun void MarkerDefinePixmap=2049(int markerNumber, string pixmap) fun void MarkerAddSet=2466(int line, int set) # Set the alpha used for a marker that is drawn in the text area, not the margin. -fun void MarkerSetAlpha=2476(int markerNumber, int alpha) +set void MarkerSetAlpha=2476(int markerNumber, int alpha) enu MarginType=SC_MARGIN_ val SC_MARGIN_SYMBOL=0 @@ -354,6 +358,12 @@ set void SetMarginSensitiveN=2246(int margin, bool sensitive) # Retrieve the mouse click sensitivity of a margin. get bool GetMarginSensitiveN=2247(int margin,) +# Set the cursor shown when the mouse is inside a margin. +set void SetMarginCursorN=2248(int margin, int cursor) + +# Retrieve the cursor shown in a margin. +get int GetMarginCursorN=2249(int margin,) + # Styles in range 32..38 are predefined for parts of the UI and are not used as normal styles. # Style 39 is for future use. enu StylesCommon=STYLE_ @@ -393,7 +403,7 @@ val SC_CHARSET_THAI=222 val SC_CHARSET_8859_15=1000 # Clear all the styles and make equivalent to the global default style. -set void StyleClearAll=2050(,) +fun void StyleClearAll=2050(,) # Set the foreground colour of a style. set void StyleSetFore=2051(int style, colour fore) @@ -444,7 +454,7 @@ get int StyleGetSize=2485(int style,) # Get the font of a style. # Returns the length of the fontName -fun int StyleGetFont=2486(int style, stringresult fontName) +get int StyleGetFont=2486(int style, stringresult fontName) # Get is a style to have its end of line filled or not. get bool StyleGetEOLFilled=2487(int style,) @@ -455,7 +465,7 @@ get bool StyleGetUnderline=2488(int style,) # Get is a style mixed case, or to force upper or lower case. get int StyleGetCase=2489(int style,) -# Get the character set of the font in a style. +# Get the character get of the font in a style. get int StyleGetCharacterSet=2490(int style,) # Get is a style visible or not. @@ -471,6 +481,25 @@ get bool StyleGetHotSpot=2493(int style,) # Set a style to be mixed case, or to force upper or lower case. set void StyleSetCase=2060(int style, int caseForce) +val SC_FONT_SIZE_MULTIPLIER=100 + +# Set the size of characters of a style. Size is in points multiplied by 100. +set void StyleSetSizeFractional=2061(int style, int caseForce) + +# Get the size of characters of a style in points multiplied by 100 +get int StyleGetSizeFractional=2062(int style,) + +enu FontWeight=SC_WEIGHT_ +val SC_WEIGHT_NORMAL=400 +val SC_WEIGHT_SEMIBOLD=600 +val SC_WEIGHT_BOLD=700 + +# Set the weight of characters of a style. +set void StyleSetWeight=2063(int style, int weight) + +# Get the weight of characters of a style. +get int StyleGetWeight=2064(int style,) + # Set the character set of the font in a style. set void StyleSetCharacterSet=2066(int style, int characterSet) @@ -523,6 +552,10 @@ set void SetCaretPeriod=2076(int periodMilliseconds,) # First sets defaults like SetCharsDefault. set void SetWordChars=2077(, string characters) +# Get the set of characters making up words for when moving or selecting by word. +# Retuns the number of characters +get int GetWordChars=2646(, stringresult characters) + # Start a sequence of actions that is undone and redone as a unit. # May be nested. fun void BeginUndoAction=2078(,) @@ -540,6 +573,11 @@ val INDIC_STRIKE=4 val INDIC_HIDDEN=5 val INDIC_BOX=6 val INDIC_ROUNDBOX=7 +val INDIC_STRAIGHTBOX=8 +val INDIC_DASH=9 +val INDIC_DOTS=10 +val INDIC_SQUIGGLELOW=11 +val INDIC_DOTBOX=12 val INDIC_MAX=31 val INDIC_CONTAINER=8 val INDIC0_MASK=0x20 @@ -732,9 +770,11 @@ get position GetLineIndentPosition=2128(int line,) # Retrieve the column number of a position, taking tab width into account. get int GetColumn=2129(position pos,) +# Count characters between two positions. +fun int CountCharacters=2633(int startPos, int endPos) + # Show or hide the horizontal scroll bar. set void SetHScrollBar=2130(bool show,) - # Is the horizontal scroll bar visible? get bool GetHScrollBar=2131(,) @@ -758,7 +798,7 @@ set void SetHighlightGuide=2134(int column,) get int GetHighlightGuide=2135(,) # Get the position after the last visible characters on a line. -get int GetLineEndPosition=2136(int line,) +get position GetLineEndPosition=2136(int line,) # Get the code page used to interpret the bytes of the document as characters. get int GetCodePage=2137(,) @@ -766,9 +806,6 @@ get int GetCodePage=2137(,) # Get the foreground colour of the caret. get colour GetCaretFore=2138(,) -# In palette mode? -get bool GetUsePalette=2139(,) - # In read-only mode? get bool GetReadOnly=2140(,) @@ -787,6 +824,9 @@ set void SetSelectionEnd=2144(position pos,) # Returns the position at the end of the selection. get position GetSelectionEnd=2145(,) +# Set caret to a position, while removing any existing selection. +fun void SetEmptySelection=2556(position pos,) + # Sets the print magnification added to the point size of each style for printing. set void SetPrintMagnification=2146(int magnification,) @@ -1008,6 +1048,9 @@ set void CallTipSetForeHlt=2207(colour fore,) # Enable use of STYLE_CALLTIP and set call tip tab size in pixels. set void CallTipUseStyle=2212(int tabSize,) +# Set position of calltip, above or below text. +set void CallTipSetPosition=2213(bool above,) + # Find the display line of a document line taking hidden lines into account. fun int VisibleFromDocLine=2220(int line,) @@ -1046,6 +1089,9 @@ fun void HideLines=2227(int lineStart, int lineEnd) # Is a line visible? get bool GetLineVisible=2228(int line,) +# Are all lines visible? +get bool GetAllLinesVisible=2236(,) + # Show the children of a header line. set void SetFoldExpanded=2229(int line, bool expanded) @@ -1066,7 +1112,7 @@ val SC_FOLDFLAG_LINEAFTER_CONTRACTED=0x0010 val SC_FOLDFLAG_LEVELNUMBERS=0x0040 # Set some style options for folding. -fun void SetFoldFlags=2233(int flags,) +set void SetFoldFlags=2233(int flags,) # Ensure a particular line is visible by expanding any header line hiding it. # Use the currently set visibility policy to determine which range to display. @@ -1113,6 +1159,7 @@ enu WrapVisualFlag=SC_WRAPVISUALFLAG_ val SC_WRAPVISUALFLAG_NONE=0x0000 val SC_WRAPVISUALFLAG_END=0x0001 val SC_WRAPVISUALFLAG_START=0x0002 +val SC_WRAPVISUALFLAG_MARGIN=0x0004 # Set the display mode of visual flags for wrapped lines. set void SetWrapVisualFlags=2460(int wrapVisualFlags,) @@ -1198,7 +1245,7 @@ get bool GetVScrollBar=2281(,) # Append a string to the end of the document without changing the selection. fun void AppendText=2282(int length, string text) -# Is drawing done in two phases with backgrounds drawn before foregrounds? +# Is drawing done in two phases with backgrounds drawn before faoregrounds? get bool GetTwoPhaseDraw=2283(,) # In twoPhaseDraw mode, drawing is performed in two phases, first the background @@ -1223,6 +1270,19 @@ get int GetFontQuality=2612(,) # Scroll so that a display line is at the top of the display. set void SetFirstVisibleLine=2613(int lineDisplay,) +enu MultiPaste=SC_MULTIPASTE_ +val SC_MULTIPASTE_ONCE=0 +val SC_MULTIPASTE_EACH=1 + +# Change the effect of pasting when there are multiple selections. +set void SetMultiPaste=2614(int multiPaste,) + +# Retrieve the effect of pasting when there are multiple selections.. +get int GetMultiPaste=2615(,) + +# Retrieve the value of a tag from a regular expression search. +get int GetTag=2616(int tagNumber, stringresult tagValue) + # Make the target range start and end be the same as the selection range start and end. fun void TargetFromSelection=2287(,) @@ -1423,9 +1483,15 @@ fun int LineLength=2350(int line,) # Highlight the characters at two positions. fun void BraceHighlight=2351(position pos1, position pos2) +# Use specified indicator to highlight matching braces instead of changing their style. +fun void BraceHighlightIndicator=2498(bool useBraceHighlightIndicator, int indicator) + # Highlight the character at a position indicating there is no matching brace. fun void BraceBadLight=2352(position pos,) +# Use specified indicator to highlight non matching brace instead of changing its style. +fun void BraceBadLightIndicator=2499(bool useBraceBadLightIndicator, int indicator) + # Find the position of a matching brace or INVALID_POSITION if no match. fun position BraceMatch=2353(position pos,) @@ -1529,7 +1595,9 @@ get bool GetMouseDownCaptures=2385(,) enu CursorShape=SC_CURSOR val SC_CURSORNORMAL=-1 +val SC_CURSORARROW=2 val SC_CURSORWAIT=4 +val SC_CURSORREVERSEARROW=7 # Sets the cursor to one of the SC_CURSOR* values. set void SetCursor=2386(int cursorType,) # Get cursor type. @@ -1565,7 +1633,7 @@ fun void DelLineLeft=2395(,) # Delete forwards from the current position to the end of the line. fun void DelLineRight=2396(,) -# Get and Set the xOffset (ie, horizonal scroll position). +# Get and Set the xOffset (ie, horizontal scroll position). set void SetXOffset=2397(int newOffset,) get int GetXOffset=2398(,) @@ -1599,7 +1667,7 @@ val CARET_JUMPS=0x10 # where most code reside, and the lines after the caret, eg. the body of a function. val CARET_EVEN=0x08 -# Set the way the caret is kept visible when going sideway. +# Set the way the caret is kept visible when going sideways. # The exclusion zone is given in pixels. fun void SetXCaretPolicy=2402(int caretPolicy, int caretSlop) @@ -1736,15 +1804,35 @@ fun void WordRightEndExtend=2442(,) # Should be called after SetWordChars. set void SetWhitespaceChars=2443(, string characters) +# Get the set of characters making up whitespace for when moving or selecting by word. +get int GetWhitespaceChars=2647(, stringresult characters) + +# Set the set of characters making up punctuation characters +# Should be called after SetWordChars. +set void SetPunctuationChars=2648(, string characters) + +# Get the set of characters making up punctuation characters +get int GetPunctuationChars=2649(, stringresult characters) + # Reset the set of characters for whitespace and word characters to the defaults. fun void SetCharsDefault=2444(,) # Get currently selected item position in the auto-completion list -fun int AutoCGetCurrent=2445(,) +get int AutoCGetCurrent=2445(,) # Get currently selected item text in the auto-completion list # Returns the length of the item text -fun int AutoCGetCurrentText=2610(, stringresult s) +get int AutoCGetCurrentText=2610(, stringresult s) + +enu CaseInsensitiveBehaviour=SC_CASEINSENSITIVEBEHAVIOUR_ +val SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE=0 +val SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE=1 + +# Set auto-completion case insensitive behaviour to either prefer case-sensitive matches or have no preference. +set void AutoCSetCaseInsensitiveBehaviour=2634(int behaviour,) + +# Get auto-completion case insensitive behaviour. +get int AutoCGetCaseInsensitiveBehaviour=2635(,) # Enlarge the document to a particular size of text bytes. fun void Allocate=2446(int bytes,) @@ -1767,10 +1855,15 @@ fun int EncodedFromUTF8=2449(string utf8, stringresult encoded) fun int FindColumn=2456(int line, int column) # Can the caret preferred x position only be changed by explicit movement commands? -get bool GetCaretSticky=2457(,) +get int GetCaretSticky=2457(,) # Stop the caret preferred x position changing when the user types. -set void SetCaretSticky=2458(bool useCaretStickyBehaviour,) +set void SetCaretSticky=2458(int useCaretStickyBehaviour,) + +enu CaretSticky=SC_CARETSTICKY_ +val SC_CARETSTICKY_OFF=0 +val SC_CARETSTICKY_ON=1 +val SC_CARETSTICKY_WHITESPACE=2 # Switch between sticky and non-sticky: meant to be bound to a key. fun void ToggleCaretSticky=2459(,) @@ -1814,7 +1907,7 @@ get int GetIndicatorCurrent=2501(,) # Set the value used for IndicatorFillRange set void SetIndicatorValue=2502(int value,) -# Get the current indicator vaue +# Get the current indicator value get int GetIndicatorValue=2503(,) # Turn a indicator on over a range. @@ -1848,6 +1941,15 @@ fun void CopyAllowLine=2519(,) # characters in the document. get int GetCharacterPointer=2520(,) +# Return a read-only pointer to a range of characters in the document. +# May move the gap so that the range is contiguous, but will only move up +# to rangeLength bytes. +get int GetRangePointer=2643(int position, int rangeLength) + +# Return a position which, to avoid performance costs, should not be within +# the range of a call to GetRangePointer. +get position GetGapPosition=2644(,) + # Always interpret keyboard input as Unicode set void SetKeysUnicode=2521(bool keysUnicode,) @@ -1860,6 +1962,12 @@ set void IndicSetAlpha=2523(int indicator, int alpha) # Get the alpha fill colour of the given indicator. get int IndicGetAlpha=2524(int indicator,) +# Set the alpha outline colour of the given indicator. +set void IndicSetOutlineAlpha=2558(int indicator, int alpha) + +# Get the alpha outline colour of the given indicator. +get int IndicGetOutlineAlpha=2559(int indicator,) + # Set extra ascent for each line set void SetExtraAscent=2525(int extraAscent,) @@ -1902,6 +2010,16 @@ set void MarginSetStyleOffset=2537(int style,) # Get the start of the range of style numbers used for margin text get int MarginGetStyleOffset=2538(,) +enu MarginOption=SC_MARGINOPTION_ +val SC_MARGINOPTION_NONE=0 +val SC_MARGINOPTION_SUBLINESELECT=1 + +# Set the margin options. +set void SetMarginOptions=2539(int marginOptions,) + +# Get the margin options. +get int GetMarginOptions=2557(,) + # Set the annotation text for a line set void AnnotationSetText=2540(int line, string text) @@ -1986,10 +2104,10 @@ get int GetSelections=2570(,) fun void ClearSelections=2571(,) # Set a simple selection -fun int SetSelection=2572(int caret,int anchor) +fun int SetSelection=2572(int caret, int anchor) # Add a selection -fun int AddSelection=2573(int caret,int anchor) +fun int AddSelection=2573(int caret, int anchor) # Set the main selection set void SetMainSelection=2574(int selection,) @@ -2013,7 +2131,7 @@ set void SetSelectionNStart=2584(int selection, position pos) get position GetSelectionNStart=2585(int selection,) # Sets the position that ends the selection - this becomes the currentPosition. -set void SetSelectionNEnd=2586(int selection, position pos,) +set void SetSelectionNEnd=2586(int selection, position pos) # Returns the position at the end of the selection. get position GetSelectionNEnd=2587(int selection,) @@ -2071,6 +2189,70 @@ fun void RotateSelection=2606(,) # Swap that caret and anchor of the main selection. fun void SwapMainAnchorCaret=2607(,) +# Indicate that the internal state of a lexer has changed over a range and therefore +# there may be a need to redraw. +fun int ChangeLexerState=2617(position start, position end) + +# Find the next line at or after lineStart that is a contracted fold header line. +# Return -1 when no more lines. +fun int ContractedFoldNext=2618(int lineStart,) + +# Centre current line in window. +fun void VerticalCentreCaret=2619(,) + +# Move the selected lines up one line, shifting the line above after the selection +fun void MoveSelectedLinesUp=2620(,) + +# Move the selected lines down one line, shifting the line below before the selection +fun void MoveSelectedLinesDown=2621(,) + +# Set the identifier reported as idFrom in notification messages. +set void SetIdentifier=2622(int identifier,) + +# Get the identifier. +get int GetIdentifier=2623(,) + +# Set the width for future RGBA image data. +set void RGBAImageSetWidth=2624(int width,) + +# Set the height for future RGBA image data. +set void RGBAImageSetHeight=2625(int height,) + +# Define a marker from RGBA data. +# It has the width and height from RGBAImageSetWidth/Height +fun void MarkerDefineRGBAImage=2626(int markerNumber, string pixels) + +# Register an RGBA image for use in autocompletion lists. +# It has the width and height from RGBAImageSetWidth/Height +fun void RegisterRGBAImage=2627(int type, string pixels) + +# Scroll to start of document. +fun void ScrollToStart=2628(,) + +# Scroll to end of document. +fun void ScrollToEnd=2629(,) + +val SC_TECHNOLOGY_DEFAULT=0 +val SC_TECHNOLOGY_DIRECTWRITE=1 + +# Set the technology used. +set void SetTechnology=2630(int technology,) + +# Get the tech. +get int GetTechnology=2631(,) + +# Create an ILoader*. +fun int CreateLoader=2632(int bytes,) + +# On OS X, show a find indicator. +fun void FindIndicatorShow=2640(position start, position end) + +# On OS X, flash a find indicator, then fade out. +fun void FindIndicatorFlash=2641(position start, position end) + +# On OS X, hide the find indicator. +fun void FindIndicatorHide=2642(,) + # Start notifying the container of all key presses and commands. fun void StartRecord=3001(,) @@ -2102,11 +2284,11 @@ set void SetLexerLanguage=4006(, string language) fun void LoadLexerLibrary=4007(, string path) # Retrieve a "property" value previously set with SetProperty. -fun int GetProperty=4008(string key, stringresult buf) +get int GetProperty=4008(string key, stringresult buf) # Retrieve a "property" value previously set with SetProperty, # with "$()" variable replacement on returned buffer. -fun int GetPropertyExpanded=4009(string key, stringresult buf) +get int GetPropertyExpanded=4009(string key, stringresult buf) # Retrieve a "property" value previously set with SetProperty, # interpreted as an int AFTER any "$()" variable replacement. @@ -2119,11 +2301,31 @@ get int GetStyleBitsNeeded=4011(,) # Return the length of the text. get int GetLexerLanguage=4012(, stringresult text) +# For private communication between an application and a known lexer. +fun int PrivateLexerCall=4013(int operation, int pointer) + +# Retrieve a '\n' separated list of properties understood by the current lexer. +fun int PropertyNames=4014(, stringresult names) + +enu TypeProperty=SC_TYPE_ +val SC_TYPE_BOOLEAN=0 +val SC_TYPE_INTEGER=1 +val SC_TYPE_STRING=2 + +# Retrieve the type of a property. +fun int PropertyType=4015(string name,) + +# Describe a property. +fun int DescribeProperty=4016(string name, stringresult description) + +# Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer. +fun int DescribeKeyWordSets=4017(, stringresult descriptions) + # Notifications # Type of modification and the action which caused the modification. # These are defined as a bit mask to make it easy to specify which notifications are wanted. # One bit is set from each of SC_MOD_* and SC_PERFORMED_*. -enu ModificationFlags=SC_MOD_ SC_PERFORMED_ SC_LAST +enu ModificationFlags=SC_MOD_ SC_PERFORMED_ SC_MULTISTEPUNDOREDO SC_LASTSTEPINUNDOREDO SC_MULTILINEUNDOREDO SC_STARTACTION SC_MODEVENTMASKALL val SC_MOD_INSERTTEXT=0x1 val SC_MOD_DELETETEXT=0x2 val SC_MOD_CHANGESTYLE=0x4 @@ -2143,7 +2345,14 @@ val SC_MOD_CHANGELINESTATE=0x8000 val SC_MOD_CHANGEMARGIN=0x10000 val SC_MOD_CHANGEANNOTATION=0x20000 val SC_MOD_CONTAINER=0x40000 -val SC_MODEVENTMASKALL=0x7FFFF +val SC_MOD_LEXERSTATE=0x80000 +val SC_MODEVENTMASKALL=0xFFFFF + +enu Update=SC_UPDATE_ +val SC_UPDATE_CONTENT=0x1 +val SC_UPDATE_SELECTION=0x2 +val SC_UPDATE_V_SCROLL=0x4 +val SC_UPDATE_H_SCROLL=0x8 # For compatibility, these go through the COMMAND notification rather than NOTIFY # and should have had exactly the same values as the EN_* constants. @@ -2185,6 +2394,7 @@ val SCMOD_SHIFT=1 val SCMOD_CTRL=2 val SCMOD_ALT=4 val SCMOD_SUPER=8 +val SCMOD_META=16 ################################################ # For SciLexer.h @@ -2286,6 +2496,15 @@ val SCLEX_POWERPRO=95 val SCLEX_NIMROD=96 val SCLEX_SML=97 val SCLEX_MARKDOWN=98 +val SCLEX_TXT2TAGS=99 +val SCLEX_A68K=100 +val SCLEX_MODULA=101 +val SCLEX_COFFEESCRIPT=102 +val SCLEX_TCMD=103 +val SCLEX_AVS=104 +val SCLEX_ECL=105 +val SCLEX_OSCRIPT=106 +val SCLEX_VISUALPROLOG=107 # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -2332,6 +2551,10 @@ val SCE_C_WORD2=16 val SCE_C_COMMENTDOCKEYWORD=17 val SCE_C_COMMENTDOCKEYWORDERROR=18 val SCE_C_GLOBALCLASS=19 +val SCE_C_STRINGRAW=20 +val SCE_C_TRIPLEVERBATIM=21 +val SCE_C_HASHQUOTEDSTRING=22 +val SCE_C_PREPROCESSORCOMMENT=23 # Lexical states for SCLEX_D lex D=SCLEX_D SCE_D_ val SCE_D_DEFAULT=0 @@ -2382,10 +2605,10 @@ val SCE_TCL_WORD8=19 val SCE_TCL_COMMENT_BOX=20 val SCE_TCL_BLOCK_COMMENT=21 # Lexical states for SCLEX_HTML, SCLEX_XML -lex HTML=SCLEX_HTML SCE_H -lex XML=SCLEX_XML SCE_H -lex ASP=SCLEX_ASP SCE_H -lex PHP=SCLEX_PHP SCE_H +lex HTML=SCLEX_HTML SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_ +lex XML=SCLEX_XML SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_ +lex ASP=SCLEX_ASP SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_ +lex PHP=SCLEX_PHP SCE_H_ SCE_HJ_ SCE_HJA_ SCE_HB_ SCE_HBA_ SCE_HP_ SCE_HPHP_ SCE_HPA_ val SCE_H_DEFAULT=0 val SCE_H_TAG=1 val SCE_H_TAGUNKNOWN=2 @@ -2546,6 +2769,16 @@ val SCE_PL_POD_VERB=31 val SCE_PL_SUB_PROTOTYPE=40 val SCE_PL_FORMAT_IDENT=41 val SCE_PL_FORMAT=42 +val SCE_PL_STRING_VAR=43 +val SCE_PL_XLAT=44 +val SCE_PL_REGEX_VAR=54 +val SCE_PL_REGSUBST_VAR=55 +val SCE_PL_BACKTICKS_VAR=57 +val SCE_PL_HERE_QQ_VAR=61 +val SCE_PL_HERE_QX_VAR=62 +val SCE_PL_STRING_QQ_VAR=64 +val SCE_PL_STRING_QX_VAR=65 +val SCE_PL_STRING_QR_VAR=66 # Lexical states for SCLEX_RUBY lex Ruby=SCLEX_RUBY SCE_RB_ val SCE_RB_DEFAULT=0 @@ -2620,6 +2853,14 @@ val SCE_L_COMMAND=1 val SCE_L_TAG=2 val SCE_L_MATH=3 val SCE_L_COMMENT=4 +val SCE_L_TAG2=5 +val SCE_L_MATH2=6 +val SCE_L_COMMENT2=7 +val SCE_L_VERBATIM=8 +val SCE_L_SHORTCMD=9 +val SCE_L_SPECIAL=10 +val SCE_L_CMDOPT=11 +val SCE_L_ERROR=12 # Lexical states for SCLEX_LUA lex Lua=SCLEX_LUA SCE_LUA_ val SCE_LUA_DEFAULT=0 @@ -2642,6 +2883,7 @@ val SCE_LUA_WORD5=16 val SCE_LUA_WORD6=17 val SCE_LUA_WORD7=18 val SCE_LUA_WORD8=19 +val SCE_LUA_LABEL=20 # Lexical states for SCLEX_ERRORLIST lex ErrorList=SCLEX_ERRORLIST SCE_ERR_ val SCE_ERR_DEFAULT=0 @@ -2676,6 +2918,19 @@ val SCE_BAT_HIDE=4 val SCE_BAT_COMMAND=5 val SCE_BAT_IDENTIFIER=6 val SCE_BAT_OPERATOR=7 +# Lexical states for SCLEX_TCMD +lex TCMD=SCLEX_TCMD SCE_TCMD_ +val SCE_TCMD_DEFAULT=0 +val SCE_TCMD_COMMENT=1 +val SCE_TCMD_WORD=2 +val SCE_TCMD_LABEL=3 +val SCE_TCMD_HIDE=4 +val SCE_TCMD_COMMAND=5 +val SCE_TCMD_IDENTIFIER=6 +val SCE_TCMD_OPERATOR=7 +val SCE_TCMD_ENVIRONMENT=8 +val SCE_TCMD_EXPANSION=9 +val SCE_TCMD_CLABEL=10 # Lexical states for SCLEX_MAKEFILE lex MakeFile=SCLEX_MAKEFILE SCE_MAKE_ val SCE_MAKE_DEFAULT=0 @@ -2851,6 +3106,7 @@ val SCE_ASM_COMMENTBLOCK=11 val SCE_ASM_CHARACTER=12 val SCE_ASM_STRINGEOL=13 val SCE_ASM_EXTINSTRUCTION=14 +val SCE_ASM_COMMENTDIRECTIVE=15 # Lexical states for SCLEX_FORTRAN lex Fortran=SCLEX_FORTRAN SCE_F_ lex F77=SCLEX_F77 SCE_F_ @@ -2893,6 +3149,8 @@ val SCE_CSS_PSEUDOELEMENT=18 val SCE_CSS_EXTENDED_IDENTIFIER=19 val SCE_CSS_EXTENDED_PSEUDOCLASS=20 val SCE_CSS_EXTENDED_PSEUDOELEMENT=21 +val SCE_CSS_MEDIA=22 +val SCE_CSS_VARIABLE=23 # Lexical states for SCLEX_POV lex POV=SCLEX_POV SCE_POV_ val SCE_POV_DEFAULT=0 @@ -3375,7 +3633,7 @@ val SCE_ST_ASSIGN=14 val SCE_ST_CHARACTER=15 val SCE_ST_SPEC_SEL=16 # Lexical states for SCLEX_FLAGSHIP (clipper) -lex FlagShip=SCLEX_FLAGSHIP SCE_B_ +lex FlagShip=SCLEX_FLAGSHIP SCE_FS_ val SCE_FS_DEFAULT=0 val SCE_FS_COMMENT=1 val SCE_FS_COMMENTLINE=2 @@ -3395,11 +3653,19 @@ val SCE_FS_IDENTIFIER=15 val SCE_FS_DATE=16 val SCE_FS_STRINGEOL=17 val SCE_FS_CONSTANT=18 -val SCE_FS_ASM=19 -val SCE_FS_LABEL=20 -val SCE_FS_ERROR=21 -val SCE_FS_HEXNUMBER=22 -val SCE_FS_BINNUMBER=23 +val SCE_FS_WORDOPERATOR=19 +val SCE_FS_DISABLEDCODE=20 +val SCE_FS_DEFAULT_C=21 +val SCE_FS_COMMENTDOC_C=22 +val SCE_FS_COMMENTLINEDOC_C=23 +val SCE_FS_KEYWORD_C=24 +val SCE_FS_KEYWORD2_C=25 +val SCE_FS_NUMBER_C=26 +val SCE_FS_STRING_C=27 +val SCE_FS_PREPROCESSOR_C=28 +val SCE_FS_OPERATOR_C=29 +val SCE_FS_IDENTIFIER_C=30 +val SCE_FS_STRINGEOL_C=31 # Lexical states for SCLEX_CSOUND lex Csound=SCLEX_CSOUND SCE_CSOUND_ val SCE_CSOUND_DEFAULT=0 @@ -3606,6 +3872,9 @@ val SCE_POWERSHELL_IDENTIFIER=7 val SCE_POWERSHELL_KEYWORD=8 val SCE_POWERSHELL_CMDLET=9 val SCE_POWERSHELL_ALIAS=10 +val SCE_POWERSHELL_FUNCTION=11 +val SCE_POWERSHELL_USER1=12 +val SCE_POWERSHELL_COMMENTSTREAM=13 # Lexical state for SCLEX_MYSQL lex MySQL=SCLEX_MYSQL SCE_MYSQL_ val SCE_MYSQL_DEFAULT=0 @@ -3730,6 +3999,196 @@ val SCE_MARKDOWN_LINK=18 val SCE_MARKDOWN_CODE=19 val SCE_MARKDOWN_CODE2=20 val SCE_MARKDOWN_CODEBK=21 +# Lexical state for SCLEX_TXT2TAGS +lex Txt2tags=SCLEX_TXT2TAGS SCE_TXT2TAGS_ +val SCE_TXT2TAGS_DEFAULT=0 +val SCE_TXT2TAGS_LINE_BEGIN=1 +val SCE_TXT2TAGS_STRONG1=2 +val SCE_TXT2TAGS_STRONG2=3 +val SCE_TXT2TAGS_EM1=4 +val SCE_TXT2TAGS_EM2=5 +val SCE_TXT2TAGS_HEADER1=6 +val SCE_TXT2TAGS_HEADER2=7 +val SCE_TXT2TAGS_HEADER3=8 +val SCE_TXT2TAGS_HEADER4=9 +val SCE_TXT2TAGS_HEADER5=10 +val SCE_TXT2TAGS_HEADER6=11 +val SCE_TXT2TAGS_PRECHAR=12 +val SCE_TXT2TAGS_ULIST_ITEM=13 +val SCE_TXT2TAGS_OLIST_ITEM=14 +val SCE_TXT2TAGS_BLOCKQUOTE=15 +val SCE_TXT2TAGS_STRIKEOUT=16 +val SCE_TXT2TAGS_HRULE=17 +val SCE_TXT2TAGS_LINK=18 +val SCE_TXT2TAGS_CODE=19 +val SCE_TXT2TAGS_CODE2=20 +val SCE_TXT2TAGS_CODEBK=21 +val SCE_TXT2TAGS_COMMENT=22 +val SCE_TXT2TAGS_OPTION=23 +val SCE_TXT2TAGS_PREPROC=24 +val SCE_TXT2TAGS_POSTPROC=25 +# Lexical states for SCLEX_A68K +lex A68k=SCLEX_A68K SCE_A68K_ +val SCE_A68K_DEFAULT=0 +val SCE_A68K_COMMENT=1 +val SCE_A68K_NUMBER_DEC=2 +val SCE_A68K_NUMBER_BIN=3 +val SCE_A68K_NUMBER_HEX=4 +val SCE_A68K_STRING1=5 +val SCE_A68K_OPERATOR=6 +val SCE_A68K_CPUINSTRUCTION=7 +val SCE_A68K_EXTINSTRUCTION=8 +val SCE_A68K_REGISTER=9 +val SCE_A68K_DIRECTIVE=10 +val SCE_A68K_MACRO_ARG=11 +val SCE_A68K_LABEL=12 +val SCE_A68K_STRING2=13 +val SCE_A68K_IDENTIFIER=14 +val SCE_A68K_MACRO_DECLARATION=15 +val SCE_A68K_COMMENT_WORD=16 +val SCE_A68K_COMMENT_SPECIAL=17 +val SCE_A68K_COMMENT_DOXYGEN=18 +# Lexical states for SCLEX_MODULA +lex Modula=SCLEX_MODULA SCE_MODULA_ +val SCE_MODULA_DEFAULT=0 +val SCE_MODULA_COMMENT=1 +val SCE_MODULA_DOXYCOMM=2 +val SCE_MODULA_DOXYKEY=3 +val SCE_MODULA_KEYWORD=4 +val SCE_MODULA_RESERVED=5 +val SCE_MODULA_NUMBER=6 +val SCE_MODULA_BASENUM=7 +val SCE_MODULA_FLOAT=8 +val SCE_MODULA_STRING=9 +val SCE_MODULA_STRSPEC=10 +val SCE_MODULA_CHAR=11 +val SCE_MODULA_CHARSPEC=12 +val SCE_MODULA_PROC=13 +val SCE_MODULA_PRAGMA=14 +val SCE_MODULA_PRGKEY=15 +val SCE_MODULA_OPERATOR=16 +val SCE_MODULA_BADSTR=17 +# Lexical states for SCLEX_COFFEESCRIPT +lex CoffeeScript=SCLEX_COFFEESCRIPT SCE_COFFEESCRIPT_ +val SCE_COFFEESCRIPT_DEFAULT=0 +val SCE_COFFEESCRIPT_COMMENT=1 +val SCE_COFFEESCRIPT_COMMENTLINE=2 +val SCE_COFFEESCRIPT_COMMENTDOC=3 +val SCE_COFFEESCRIPT_NUMBER=4 +val SCE_COFFEESCRIPT_WORD=5 +val SCE_COFFEESCRIPT_STRING=6 +val SCE_COFFEESCRIPT_CHARACTER=7 +val SCE_COFFEESCRIPT_UUID=8 +val SCE_COFFEESCRIPT_PREPROCESSOR=9 +val SCE_COFFEESCRIPT_OPERATOR=10 +val SCE_COFFEESCRIPT_IDENTIFIER=11 +val SCE_COFFEESCRIPT_STRINGEOL=12 +val SCE_COFFEESCRIPT_VERBATIM=13 +val SCE_COFFEESCRIPT_REGEX=14 +val SCE_COFFEESCRIPT_COMMENTLINEDOC=15 +val SCE_COFFEESCRIPT_WORD2=16 +val SCE_COFFEESCRIPT_COMMENTDOCKEYWORD=17 +val SCE_COFFEESCRIPT_COMMENTDOCKEYWORDERROR=18 +val SCE_COFFEESCRIPT_GLOBALCLASS=19 +val SCE_COFFEESCRIPT_STRINGRAW=20 +val SCE_COFFEESCRIPT_TRIPLEVERBATIM=21 +val SCE_COFFEESCRIPT_HASHQUOTEDSTRING=22 +val SCE_COFFEESCRIPT_COMMENTBLOCK=22 +val SCE_COFFEESCRIPT_VERBOSE_REGEX=23 +val SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT=24 +# Lexical states for SCLEX_AVS +lex AVS=SCLEX_AVS SCE_AVS_ +val SCE_AVS_DEFAULT=0 +val SCE_AVS_COMMENTBLOCK=1 +val SCE_AVS_COMMENTBLOCKN=2 +val SCE_AVS_COMMENTLINE=3 +val SCE_AVS_NUMBER=4 +val SCE_AVS_OPERATOR=5 +val SCE_AVS_IDENTIFIER=6 +val SCE_AVS_STRING=7 +val SCE_AVS_TRIPLESTRING=8 +val SCE_AVS_KEYWORD=9 +val SCE_AVS_FILTER=10 +val SCE_AVS_PLUGIN=11 +val SCE_AVS_FUNCTION=12 +val SCE_AVS_CLIPPROP=13 +val SCE_AVS_USERDFN=14 +# Lexical states for SCLEX_ECL +lex ECL=SCLEX_ECL SCE_ECL_ +val SCE_ECL_DEFAULT=0 +val SCE_ECL_COMMENT=1 +val SCE_ECL_COMMENTLINE=2 +val SCE_ECL_NUMBER=3 +val SCE_ECL_STRING=4 +val SCE_ECL_WORD0=5 +val SCE_ECL_OPERATOR=6 +val SCE_ECL_CHARACTER=7 +val SCE_ECL_UUID=8 +val SCE_ECL_PREPROCESSOR=9 +val SCE_ECL_UNKNOWN=10 +val SCE_ECL_IDENTIFIER=11 +val SCE_ECL_STRINGEOL=12 +val SCE_ECL_VERBATIM=13 +val SCE_ECL_REGEX=14 +val SCE_ECL_COMMENTLINEDOC=15 +val SCE_ECL_WORD1=16 +val SCE_ECL_COMMENTDOCKEYWORD=17 +val SCE_ECL_COMMENTDOCKEYWORDERROR=18 +val SCE_ECL_WORD2=19 +val SCE_ECL_WORD3=20 +val SCE_ECL_WORD4=21 +val SCE_ECL_WORD5=22 +val SCE_ECL_COMMENTDOC=23 +val SCE_ECL_ADDED=24 +val SCE_ECL_DELETED=25 +val SCE_ECL_CHANGED=26 +val SCE_ECL_MOVED=27 +# Lexical states for SCLEX_OSCRIPT +lex OScript=SCLEX_OSCRIPT SCE_OSCRIPT_ +val SCE_OSCRIPT_DEFAULT=0 +val SCE_OSCRIPT_LINE_COMMENT=1 +val SCE_OSCRIPT_BLOCK_COMMENT=2 +val SCE_OSCRIPT_DOC_COMMENT=3 +val SCE_OSCRIPT_PREPROCESSOR=4 +val SCE_OSCRIPT_NUMBER=5 +val SCE_OSCRIPT_SINGLEQUOTE_STRING=6 +val SCE_OSCRIPT_DOUBLEQUOTE_STRING=7 +val SCE_OSCRIPT_CONSTANT=8 +val SCE_OSCRIPT_IDENTIFIER=9 +val SCE_OSCRIPT_GLOBAL=10 +val SCE_OSCRIPT_KEYWORD=11 +val SCE_OSCRIPT_OPERATOR=12 +val SCE_OSCRIPT_LABEL=13 +val SCE_OSCRIPT_TYPE=14 +val SCE_OSCRIPT_FUNCTION=15 +val SCE_OSCRIPT_OBJECT=16 +val SCE_OSCRIPT_PROPERTY=17 +val SCE_OSCRIPT_METHOD=18 +# Lexical states for SCLEX_VISUALPROLOG +lex VisualProlog=SCLEX_VISUALPROLOG SCE_VISUALPROLOG_ +val SCE_VISUALPROLOG_DEFAULT=0 +val SCE_VISUALPROLOG_KEY_MAJOR=1 +val SCE_VISUALPROLOG_KEY_MINOR=2 +val SCE_VISUALPROLOG_KEY_DIRECTIVE=3 +val SCE_VISUALPROLOG_COMMENT_BLOCK=4 +val SCE_VISUALPROLOG_COMMENT_LINE=5 +val SCE_VISUALPROLOG_COMMENT_KEY=6 +val SCE_VISUALPROLOG_COMMENT_KEY_ERROR=7 +val SCE_VISUALPROLOG_IDENTIFIER=8 +val SCE_VISUALPROLOG_VARIABLE=9 +val SCE_VISUALPROLOG_ANONYMOUS=10 +val SCE_VISUALPROLOG_NUMBER=11 +val SCE_VISUALPROLOG_OPERATOR=12 +val SCE_VISUALPROLOG_CHARACTER=13 +val SCE_VISUALPROLOG_CHARACTER_TOO_MANY=14 +val SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR=15 +val SCE_VISUALPROLOG_STRING=16 +val SCE_VISUALPROLOG_STRING_ESCAPE=17 +val SCE_VISUALPROLOG_STRING_ESCAPE_ERROR=18 +val SCE_VISUALPROLOG_STRING_EOL_OPEN=19 +val SCE_VISUALPROLOG_STRING_VERBATIM=20 +val SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL=21 +val SCE_VISUALPROLOG_STRING_VERBATIM_EOL=22 # Events @@ -3740,23 +4199,39 @@ evt void SavePointLeft=2003(void) evt void ModifyAttemptRO=2004(void) # GTK+ Specific to work around focus and accelerator problems: evt void Key=2005(int ch, int modifiers) -evt void DoubleClick=2006(void) -evt void UpdateUI=2007(void) -evt void Modified=2008(int position, int modificationType, string text, int length, int linesAdded, int line, int foldLevelNow, int foldLevelPrev) +evt void DoubleClick=2006(int modifiers, int position, int line) +evt void UpdateUI=2007(int updated) +evt void Modified=2008(int position, int modificationType, string text, int length, int linesAdded, int line, int foldLevelNow, int foldLevelPrev, int token, int annotationLinesAdded) evt void MacroRecord=2009(int message, int wParam, int lParam) evt void MarginClick=2010(int modifiers, int position, int margin) evt void NeedShown=2011(int position, int length) evt void Painted=2013(void) -evt void UserListSelection=2014(int listType, string text) +evt void UserListSelection=2014(int listType, string text, int position) evt void URIDropped=2015(string text) -evt void DwellStart=2016(int position) -evt void DwellEnd=2017(int position) +evt void DwellStart=2016(int position, int x, int y) +evt void DwellEnd=2017(int position, int x, int y) evt void Zoom=2018(void) evt void HotSpotClick=2019(int modifiers, int position) evt void HotSpotDoubleClick=2020(int modifiers, int position) evt void CallTipClick=2021(int position) -evt void AutoCSelection=2022(string text) +evt void AutoCSelection=2022(string text, int position) evt void IndicatorClick=2023(int modifiers, int position) evt void IndicatorRelease=2024(int modifiers, int position) evt void AutoCCancelled=2025(void) evt void AutoCCharDeleted=2026(void) +evt void HotSpotReleaseClick=2027(int modifiers, int position) + +cat Deprecated + +# Deprecated in 2.21 +# The SC_CP_DBCS value can be used to indicate a DBCS mode for GTK+. +val SC_CP_DBCS=1 + +# Deprecated in 2.30 + +# In palette mode? +get bool GetUsePalette=2139(,) + +# In palette mode, Scintilla uses the environment's palette calls to display +# more colours. This may lead to ugly displays. +set void SetUsePalette=2039(bool usePalette,) diff --git a/src/stc/scintilla/include/ScintillaWidget.h b/src/stc/scintilla/include/ScintillaWidget.h index c60c4a21b9..021af2a30e 100644 --- a/src/stc/scintilla/include/ScintillaWidget.h +++ b/src/stc/scintilla/include/ScintillaWidget.h @@ -9,13 +9,13 @@ #ifndef SCINTILLAWIDGET_H #define SCINTILLAWIDGET_H -#if PLAT_GTK +#if defined(GTK) #ifdef __cplusplus extern "C" { #endif -#define SCINTILLA(obj) GTK_CHECK_CAST (obj, scintilla_get_type (), ScintillaObject) +#define SCINTILLA(obj) G_TYPE_CHECK_INSTANCE_CAST (obj, scintilla_get_type (), ScintillaObject) #define SCINTILLA_CLASS(klass) GTK_CHECK_CLASS_CAST (klass, scintilla_get_type (), ScintillaClass) #define IS_SCINTILLA(obj) GTK_CHECK_TYPE (obj, scintilla_get_type ()) @@ -34,21 +34,13 @@ struct _ScintillaClass { void (* notify) (ScintillaObject *ttt); }; -#if GLIB_MAJOR_VERSION < 2 -GtkType scintilla_get_type (void); -#else GType scintilla_get_type (void); -#endif GtkWidget* scintilla_new (void); void scintilla_set_id (ScintillaObject *sci, uptr_t id); sptr_t scintilla_send_message (ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam); void scintilla_release_resources(void); -#if GTK_MAJOR_VERSION < 2 -#define SCINTILLA_NOTIFY "notify" -#else #define SCINTILLA_NOTIFY "sci-notify" -#endif #ifdef __cplusplus } diff --git a/src/stc/scintilla/include/WindowAccessor.h b/src/stc/scintilla/include/WindowAccessor.h deleted file mode 100644 index 6f265f6580..0000000000 --- a/src/stc/scintilla/include/WindowAccessor.h +++ /dev/null @@ -1,67 +0,0 @@ -// Scintilla source code edit control -/** @file WindowAccessor.h - ** Implementation of BufferAccess and StylingAccess on a Scintilla - ** rapid easy access to contents of a Scintilla. - **/ -// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -/** - */ - -class WindowAccessor : public Accessor { - // Private so WindowAccessor objects can not be copied - WindowAccessor(const WindowAccessor &source) : Accessor(), props(source.props) {} - WindowAccessor &operator=(const WindowAccessor &) { return *this; } -protected: - WindowID id; - PropertyGet &props; - int lenDoc; - - char styleBuf[bufferSize]; - int validLen; - char chFlags; - char chWhile; - unsigned int startSeg; - - bool InternalIsLeadByte(char ch); - void Fill(int position); -public: - WindowAccessor(WindowID id_, PropertyGet &props_) : - Accessor(), id(id_), props(props_), - lenDoc(-1), validLen(0), chFlags(0), chWhile(0) { - } - ~WindowAccessor(); - bool Match(int pos, const char *s); - char StyleAt(int position); - int GetLine(int position); - int LineStart(int line); - int LevelAt(int line); - int Length(); - void Flush(); - int GetLineState(int line); - int SetLineState(int line, int state); - int GetPropertyInt(const char *key, int defaultValue=0) { - return props.GetInt(key, defaultValue); - } - char *GetProperties() { - return props.ToString(); - } - - void StartAt(unsigned int start, char chMask=31); - void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; }; - unsigned int GetStartSegment() { return startSeg; } - void StartSegment(unsigned int pos); - void ColourTo(unsigned int pos, int chAttr); - void SetLevel(int line, int level); - int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0); - void IndicatorFill(int start, int end, int indicator, int value); -}; - -#ifdef SCI_NAMESPACE -} -#endif diff --git a/src/stc/scintilla/lexers/LexA68k.cxx b/src/stc/scintilla/lexers/LexA68k.cxx new file mode 100644 index 0000000000..970e429c64 --- /dev/null +++ b/src/stc/scintilla/lexers/LexA68k.cxx @@ -0,0 +1,318 @@ +// Scintilla source code edit control +/** @file LexA68k.cxx + ** Lexer for Assembler, just for the MASM syntax + ** Written by Martial Demolins AKA Folco + **/ +// Copyright 2010 Martial Demolins <mdemolins(a)gmail.com> +// The License.txt file describes the conditions under which this software +// may be distributed. + + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +// Return values for GetOperatorType +#define NO_OPERATOR 0 +#define OPERATOR_1CHAR 1 +#define OPERATOR_2CHAR 2 + + +/** + * IsIdentifierStart + * + * Return true if the given char is a valid identifier first char + */ + +static inline bool IsIdentifierStart (const int ch) +{ + return (isalpha(ch) || (ch == '_') || (ch == '\\')); +} + + +/** + * IsIdentifierChar + * + * Return true if the given char is a valid identifier char + */ + +static inline bool IsIdentifierChar (const int ch) +{ + return (isalnum(ch) || (ch == '_') || (ch == '@') || (ch == ':') || (ch == '.')); +} + + +/** + * GetOperatorType + * + * Return: + * NO_OPERATOR if char is not an operator + * OPERATOR_1CHAR if the operator is one char long + * OPERATOR_2CHAR if the operator is two chars long + */ + +static inline int GetOperatorType (const int ch1, const int ch2) +{ + int OpType = NO_OPERATOR; + + if ((ch1 == '+') || (ch1 == '-') || (ch1 == '*') || (ch1 == '/') || (ch1 == '#') || + (ch1 == '(') || (ch1 == ')') || (ch1 == '~') || (ch1 == '&') || (ch1 == '|') || (ch1 == ',')) + OpType = OPERATOR_1CHAR; + + else if ((ch1 == ch2) && (ch1 == '<' || ch1 == '>')) + OpType = OPERATOR_2CHAR; + + return OpType; +} + + +/** + * IsBin + * + * Return true if the given char is 0 or 1 + */ + +static inline bool IsBin (const int ch) +{ + return (ch == '0') || (ch == '1'); +} + + +/** + * IsDoxygenChar + * + * Return true if the char may be part of a Doxygen keyword + */ + +static inline bool IsDoxygenChar (const int ch) +{ + return isalpha(ch) || (ch == '$') || (ch == '[') || (ch == ']') || (ch == '{') || (ch == '}'); +} + + +/** + * ColouriseA68kDoc + * + * Main function, which colourises a 68k source + */ + +static void ColouriseA68kDoc (unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) +{ + + // Get references to keywords lists + WordList &cpuInstruction = *keywordlists[0]; + WordList ®isters = *keywordlists[1]; + WordList &directive = *keywordlists[2]; + WordList &extInstruction = *keywordlists[3]; + WordList &commentSpecial = *keywordlists[4]; + WordList &doxygenKeyword = *keywordlists[5]; + + + // Instanciate a context for our source + StyleContext sc(startPos, length, initStyle, styler); + + + /************************************************************ + * + * Parse the text + * + ************************************************************/ + + for ( ; sc.More(); sc.Forward()) + { + char Buffer[100]; + int OpType; + + // Reset style at beginning of line + if (sc.atLineStart) + sc.SetState(SCE_A68K_DEFAULT); + + + /************************************************************ + * + * Handle current state if we are not in the "default style" + * + ************************************************************/ + + if (sc.state != SCE_A68K_DEFAULT) + { + // Check if current style continue. + // If this case, we loop because there is nothing else to do + if (((sc.state == SCE_A68K_NUMBER_DEC) && isdigit(sc.ch)) // Decimal number + || ((sc.state == SCE_A68K_NUMBER_BIN) && IsBin(sc.ch)) // Binary number + || ((sc.state == SCE_A68K_NUMBER_HEX) && isxdigit(sc.ch)) // Hexa number + || ((sc.state == SCE_A68K_MACRO_ARG) && isdigit(sc.ch)) // Arg of macro + || ((sc.state == SCE_A68K_STRING1) && (sc.ch != '\'')) // String single-quoted + || ((sc.state == SCE_A68K_STRING2) && (sc.ch != '\"')) // String double-quoted + || ((sc.state == SCE_A68K_MACRO_ARG) && isdigit(sc.ch)) // Macro argument + // Label. ' ' and '\t' are needed to handle macro declarations + || ((sc.state == SCE_A68K_LABEL) && (sc.ch != ':') && (sc.ch != ' ') && (sc.ch != '\t')) + || ((sc.state == SCE_A68K_IDENTIFIER) && (sc.ch < 0x80) && IsIdentifierChar(sc.ch)) // Identifier + || ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && (sc.ch < 0x80) && IsDoxygenChar(sc.ch)) // Doxygen keyword + || ((sc.state == SCE_A68K_COMMENT_WORD) && (sc.ch < 0x80) && isalpha(sc.ch))) // Comment current word + { + continue; + } + + // Check if some states terminate at the current char: + // we must include this char in the current style context + else if (((sc.state == SCE_A68K_STRING1) && (sc.ch < 0x80) && (sc.ch == '\'')) // String single-quoted + || ((sc.state == SCE_A68K_STRING2) && (sc.ch < 0x80) && (sc.ch == '\"')) // String double-quoted + || ((sc.state == SCE_A68K_LABEL) && (sc.ch < 0x80) && (sc.ch == ':'))) // Label + { + sc.ForwardSetState(SCE_A68K_DEFAULT); + } + + // Check for special words or Doxygen keywords in comments + else if (sc.state == SCE_A68K_COMMENT) + { + if (sc.ch == '\\') { + sc.SetState(SCE_A68K_COMMENT_DOXYGEN); + } + else if ((sc.ch < 0x80) && isalpha(sc.ch)) { + sc.SetState(SCE_A68K_COMMENT_WORD); + } + continue; + } + + // Check for special words in comment + else if ((sc.state == SCE_A68K_COMMENT_WORD) && (sc.ch < 0x80) && !isalpha(sc.ch)) + { + sc.GetCurrent(Buffer, sizeof(Buffer)); + if (commentSpecial.InList(Buffer)) { + sc.ChangeState(SCE_A68K_COMMENT_SPECIAL); + } + else { + sc.ChangeState(SCE_A68K_COMMENT); + } + sc.SetState(SCE_A68K_COMMENT); + continue; + } + + // Check for Doxygen keywords + else if ((sc.state == SCE_A68K_COMMENT_DOXYGEN) && (sc.ch < 0x80) && !IsDoxygenChar(sc.ch)) + { + sc.GetCurrentLowered(Buffer, sizeof(Buffer)); // Buffer the string of the current context + if (!doxygenKeyword.InList(Buffer)) { + sc.ChangeState(SCE_A68K_COMMENT); + } + sc.SetState(SCE_A68K_COMMENT); + continue; + } + + // Check if we are in the case of a label which terminates without ':' + // It should be a macro declaration, not a label + else if ((sc.state == SCE_A68K_LABEL) && (sc.ch < 0x80) && ((sc.ch == ' ') || (sc.ch == '\t'))) + { + sc.ChangeState(SCE_A68K_MACRO_DECLARATION); + } + + // Check if we are at the end of an identifier + // In this case, colourise it if was a keyword. + else if ((sc.state == SCE_A68K_IDENTIFIER) && !IsIdentifierChar(sc.ch)) + { + sc.GetCurrentLowered(Buffer, sizeof(Buffer)); // Buffer the string of the current context + if (cpuInstruction.InList(Buffer)) { // And check if it belongs to a keyword list + sc.ChangeState(SCE_A68K_CPUINSTRUCTION); + } + else if (extInstruction.InList(Buffer)) { + sc.ChangeState(SCE_A68K_EXTINSTRUCTION); + } + else if (registers.InList(Buffer)) { + sc.ChangeState(SCE_A68K_REGISTER); + } + else if (directive.InList(Buffer)) { + sc.ChangeState(SCE_A68K_DIRECTIVE); + } + } + + // All special contexts are now handled.Come back to default style + sc.SetState(SCE_A68K_DEFAULT); + } + + + /************************************************************ + * + * Check if we must enter a new state + * + ************************************************************/ + + // Label and macro identifiers start at the beginning of a line + // We set both as a label, but if it wasn't one (no ':' at the end), + // it will be changed as a macro identifier. + if (sc.atLineStart && (sc.ch < 0x80) && IsIdentifierStart(sc.ch)) { + sc.SetState(SCE_A68K_LABEL); + } + else if ((sc.ch < 0x80) && (sc.ch == ';')) { // Comment + sc.SetState(SCE_A68K_COMMENT); + } + else if ((sc.ch < 0x80) && isdigit(sc.ch)) { // Decimal numbers haven't prefix + sc.SetState(SCE_A68K_NUMBER_DEC); + } + else if ((sc.ch < 0x80) && (sc.ch == '%')) { // Binary numbers are prefixed with '%' + sc.SetState(SCE_A68K_NUMBER_BIN); + } + else if ((sc.ch < 0x80) && (sc.ch == '$')) { // Hexadecimal numbers are prefixed with '$' + sc.SetState(SCE_A68K_NUMBER_HEX); + } + else if ((sc.ch < 0x80) && (sc.ch == '\'')) { // String (single-quoted) + sc.SetState(SCE_A68K_STRING1); + } + else if ((sc.ch < 0x80) && (sc.ch == '\"')) { // String (double-quoted) + sc.SetState(SCE_A68K_STRING2); + } + else if ((sc.ch < 0x80) && (sc.ch == '\\') && (isdigit(sc.chNext))) { // Replacement symbols in macro + sc.SetState(SCE_A68K_MACRO_ARG); + } + else if ((sc.ch < 0x80) && IsIdentifierStart(sc.ch)) { // An identifier: constant, label, etc... + sc.SetState(SCE_A68K_IDENTIFIER); + } + else { + if (sc.ch < 0x80) { + OpType = GetOperatorType(sc.ch, sc.chNext); // Check if current char is an operator + if (OpType != NO_OPERATOR) { + sc.SetState(SCE_A68K_OPERATOR); + if (OpType == OPERATOR_2CHAR) { // Check if the operator is 2 bytes long + sc.ForwardSetState(SCE_A68K_OPERATOR); // (>> or <<) + } + } + } + } + } // End of for() + sc.Complete(); +} + + +// Names of the keyword lists + +static const char * const a68kWordListDesc[] = +{ + "CPU instructions", + "Registers", + "Directives", + "Extended instructions", + "Comment special words", + "Doxygen keywords", + 0 +}; + +LexerModule lmA68k(SCLEX_A68K, ColouriseA68kDoc, "a68k", 0, a68kWordListDesc); diff --git a/src/stc/scintilla/src/LexAPDL.cxx b/src/stc/scintilla/lexers/LexAPDL.cxx similarity index 98% rename from src/stc/scintilla/src/LexAPDL.cxx rename to src/stc/scintilla/lexers/LexAPDL.cxx index 7bf597b42c..7d65a56153 100644 --- a/src/stc/scintilla/src/LexAPDL.cxx +++ b/src/stc/scintilla/lexers/LexAPDL.cxx @@ -8,18 +8,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexASY.cxx b/src/stc/scintilla/lexers/LexASY.cxx similarity index 97% rename from src/stc/scintilla/src/LexASY.cxx rename to src/stc/scintilla/lexers/LexASY.cxx index 5bf979fd37..9e3470cda3 100644 --- a/src/stc/scintilla/src/LexASY.cxx +++ b/src/stc/scintilla/lexers/LexASY.cxx @@ -4,25 +4,26 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" #include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif -static void ColouriseAsyDoc(unsigned int startPos, int length, int initStyle, +static void ColouriseAsyDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { WordList &keywords = *keywordlists[0]; @@ -118,7 +119,7 @@ static void ColouriseAsyDoc(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_ASY_IDENTIFIER); } else if (sc.Match('/', '*')) { sc.SetState(SCE_ASY_COMMENT); - sc.Forward(); // + sc.Forward(); // } else if (sc.Match('/', '/')) { sc.SetState(SCE_ASY_COMMENTLINE); } else if (sc.ch == '\"') { @@ -162,14 +163,14 @@ static int ParseASYWord(unsigned int pos, Accessor &styler, char *word) length++; ch=styler.SafeGetCharAt(pos+length); } - word[length]=0; + word[length]=0; return length; } static bool IsASYDrawingLine(int line, Accessor &styler) { int pos = styler.LineStart(line); int eol_pos = styler.LineStart(line + 1) - 1; - + int startpos = pos; char buffer[100]=""; @@ -181,11 +182,11 @@ static bool IsASYDrawingLine(int line, Accessor &styler) { if (!drawcommands && ch!=' ') return false; else if (drawcommands) return true; startpos++; - } + } return false; } -static void FoldAsyDoc(unsigned int startPos, int length, int initStyle, +static void FoldAsyDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; @@ -236,7 +237,7 @@ static void FoldAsyDoc(unsigned int startPos, int length, int initStyle, else if (lineCurrent!=0 && IsASYDrawingLine(lineCurrent - 1, styler) && !IsASYDrawingLine(lineCurrent+1, styler)) levelNext--; - } + } if (atEOL) { int levelUse = levelCurrent; diff --git a/src/stc/scintilla/src/LexAU3.cxx b/src/stc/scintilla/lexers/LexAU3.cxx similarity index 93% rename from src/stc/scintilla/src/LexAU3.cxx rename to src/stc/scintilla/lexers/LexAU3.cxx index cfff9279db..e9ab75772f 100644 --- a/src/stc/scintilla/src/LexAU3.cxx +++ b/src/stc/scintilla/lexers/LexAU3.cxx @@ -1,15 +1,15 @@ // Scintilla source code edit control // @file LexAU3.cxx // Lexer for AutoIt3 http://www.hiddensoft.com/autoit3 -// by Jos van der Zande, jvdzande@yahoo.com +// by Jos van der Zande, jvdzande@yahoo.com // // Changes: // March 28, 2004 - Added the standard Folding code // April 21, 2004 - Added Preprosessor Table + Syntax Highlighting // Fixed Number highlighting // Changed default isoperator to IsAOperator to have a better match to AutoIt3 -// Fixed "#comments_start" -> "#comments-start" -// Fixed "#comments_end" -> "#comments-end" +// Fixed "#comments_start" -> "#comments-start" +// Fixed "#comments_end" -> "#comments-end" // Fixed Sendkeys in Strings when not terminated with } // Added support for Sendkey strings that have second parameter e.g. {UP 5} or {a down} // April 26, 2004 - Fixed # pre-processor statement inside of comment block would invalidly change the color. @@ -25,9 +25,9 @@ // Added fold.compact support set with fold.compact=1 // Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1 // it will now only happen when fold.comment=2. -// Sep 5, 2004 - Added logic to handle colourizing words on the last line. +// Sep 5, 2004 - Added logic to handle colourizing words on the last line. // Typed Characters now show as "default" till they match any table. -// Oct 10, 2004 - Added logic to show Comments in "Special" directives. +// Oct 10, 2004 - Added logic to show Comments in "Special" directives. // Nov 1, 2004 - Added better testing for Numbers supporting x and e notation. // Nov 28, 2004 - Added logic to handle continuation lines for syntax highlighting. // Jan 10, 2005 - Added Abbreviations Keyword used for expansion @@ -52,18 +52,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -127,7 +130,7 @@ static int GetSendKey(const char *szLine, char *szKey) } else if (cTemp == ' ') { - // skip other spaces + // skip other spaces } else if (nFlag == 0) { @@ -139,7 +142,7 @@ static int GetSendKey(const char *szLine, char *szKey) // Save second portion into var... szSpecial[nSpecPos++] = cTemp; // check if Second portion is all numbers for repeat fuction - if (isdigit(cTemp) == false) {nSpecNum = 0;} + if (isdigit(cTemp) == false) {nSpecNum = 0;} } } nPos++; // skip to next char @@ -151,7 +154,7 @@ static int GetSendKey(const char *szLine, char *szKey) szKey[nKeyPos] = '\0'; szSpecial[nSpecPos] = '\0'; if (strcmp(szSpecial,"down")== 0 || strcmp(szSpecial,"up")== 0 || - strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 || + strcmp(szSpecial,"on")== 0 || strcmp(szSpecial,"off")== 0 || strcmp(szSpecial,"toggle")== 0 || nSpecNum == 1 ) { nFlag = 0; @@ -160,13 +163,13 @@ static int GetSendKey(const char *szLine, char *szKey) { nFlag = 1; } - return nFlag; // 1 is bad, 0 is good + return nFlag; // 1 is bad, 0 is good -} // GetSendKey() +} // GetSendKey() // // Routine to check the last "none comment" character on a line to see if its a continuation -// +// static bool IsContinuationLine(unsigned int szLine, Accessor &styler) { int nsPos = styler.LineStart(szLine); @@ -192,7 +195,7 @@ static bool IsContinuationLine(unsigned int szLine, Accessor &styler) // // syntax highlighting logic -static void ColouriseAU3Doc(unsigned int startPos, +static void ColouriseAU3Doc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { @@ -214,19 +217,19 @@ static void ColouriseAU3Doc(unsigned int startPos, (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { lineCurrent--; startPos = styler.LineStart(lineCurrent); // get start position - initStyle = 0; // reset the start style to 0 + initStyle = 0; // reset the start style to 0 } } // Set the new length to include it from the start and set the start position length = length + s_startPos - startPos; // correct the total length to process styler.StartAt(startPos); - + StyleContext sc(startPos, length, initStyle, styler); char si; // string indicator "=1 '=2 char ni; // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3 - char ci; // comment indicator 0=not linecomment(;) + char ci; // comment indicator 0=not linecomment(;) char s_save[100]; - si=0; + si=0; ni=0; ci=0; //$$$ @@ -234,11 +237,11 @@ static void ColouriseAU3Doc(unsigned int startPos, char s[100]; sc.GetCurrentLowered(s, sizeof(s)); // ********************************************** - // save the total current word for eof processing - if (IsAWordChar(sc.ch) || sc.ch == '}') + // save the total current word for eof processing + if (IsAWordChar(sc.ch) || sc.ch == '}') { strcpy(s_save,s); - int tp = strlen(s_save); + int tp = static_cast<int>(strlen(s_save)); if (tp < 99) { s_save[tp] = static_cast<char>(tolower(sc.ch)); s_save[tp+1] = '\0'; @@ -254,9 +257,9 @@ static void ColouriseAU3Doc(unsigned int startPos, if (sc.atLineEnd) { ci=0; if (strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0) { - if (sc.atLineEnd) + if (sc.atLineEnd) sc.SetState(SCE_AU3_DEFAULT); - else + else sc.SetState(SCE_AU3_COMMENTBLOCK); } break; @@ -267,9 +270,9 @@ static void ColouriseAU3Doc(unsigned int startPos, sc.SetState(SCE_AU3_COMMENTBLOCK); } // skip rest of the line - if (ci==2) + if (ci==2) break; - // check when first character is detected on the line + // check when first character is detected on the line if (ci==0) { if (IsAWordStart(static_cast<char>(sc.ch)) || IsAOperator(static_cast<char>(sc.ch))) { ci=1; @@ -292,10 +295,10 @@ static void ColouriseAU3Doc(unsigned int startPos, } case SCE_AU3_OPERATOR: { - // check if its a COMobject + // check if its a COMobject if (sc.chPrev == '.' && IsAWordChar(sc.ch)) { sc.SetState(SCE_AU3_COMOBJ); - } + } else { sc.SetState(SCE_AU3_DEFAULT); } @@ -360,7 +363,7 @@ static void ColouriseAU3Doc(unsigned int startPos, sc.SetState(SCE_AU3_DEFAULT); } } - } + } if (sc.atLineEnd) { sc.SetState(SCE_AU3_DEFAULT);} break; @@ -433,7 +436,7 @@ static void ColouriseAU3Doc(unsigned int startPos, case SCE_AU3_STRING: { // check for " to end a double qouted string or - // check for ' to end a single qouted string + // check for ' to end a single qouted string if ((si == 1 && sc.ch == '\"') || (si == 2 && sc.ch == '\'') || (si == 3 && sc.ch == '>')) { sc.ForwardSetState(SCE_AU3_DEFAULT); @@ -445,7 +448,7 @@ static void ColouriseAU3Doc(unsigned int startPos, si=0; // at line end and not found a continuation char then reset to default int lineCurrent = styler.GetLine(sc.currentPos); - if (!IsContinuationLine(lineCurrent,styler)) + if (!IsContinuationLine(lineCurrent,styler)) { sc.SetState(SCE_AU3_DEFAULT); break; @@ -456,27 +459,27 @@ static void ColouriseAU3Doc(unsigned int startPos, sc.SetState(SCE_AU3_SENT);} break; } - + case SCE_AU3_SENT: { - // Send key string ended - if (sc.chPrev == '}' && sc.ch != '}') + // Send key string ended + if (sc.chPrev == '}' && sc.ch != '}') { // set color to SENDKEY when valid sendkey .. else set back to regular string char sk[100]; // split {111 222} and return {111} and check if 222 is valid. // if return code = 1 then invalid 222 so must be string - if (GetSendKey(s,sk)) + if (GetSendKey(s,sk)) { sc.ChangeState(SCE_AU3_STRING); } // if single char between {?} then its ok as sendkey for a single character - else if (strlen(sk) == 3) + else if (strlen(sk) == 3) { sc.ChangeState(SCE_AU3_SENT); } // if sendkey {111} is in table then ok as sendkey - else if (keywords4.InList(sk)) + else if (keywords4.InList(sk)) { sc.ChangeState(SCE_AU3_SENT); } @@ -492,9 +495,9 @@ static void ColouriseAU3Doc(unsigned int startPos, int nPos = 0; int nState = 1; char cTemp; - while (!(nState == 2) && ((cTemp = s[nPos]) != '\0')) + while (!(nState == 2) && ((cTemp = s[nPos]) != '\0')) { - if (cTemp == '{' && nState == 1) + if (cTemp == '{' && nState == 1) { nState = 2; } @@ -509,14 +512,14 @@ static void ColouriseAU3Doc(unsigned int startPos, sc.ChangeState(SCE_AU3_STRING); sc.SetState(SCE_AU3_STRING); } - // If invalid character found then assume its a regular string + // If invalid character found then assume its a regular string if (nState == 0) { sc.ChangeState(SCE_AU3_STRING); sc.SetState(SCE_AU3_STRING); } } // check if next portion is again a sendkey - if (sc.atLineEnd) + if (sc.atLineEnd) { sc.ChangeState(SCE_AU3_STRING); sc.SetState(SCE_AU3_DEFAULT); @@ -547,14 +550,14 @@ static void ColouriseAU3Doc(unsigned int startPos, else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);} else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);} //else if (sc.ch == '_') {sc.SetState(SCE_AU3_KEYWORD);} - else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);} // string after #include + else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);} // string after #include else if (sc.ch == '\"') { sc.SetState(SCE_AU3_STRING); si = 1; } else if (sc.ch == '\'') { sc.SetState(SCE_AU3_STRING); si = 2; } - else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) + else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { sc.SetState(SCE_AU3_NUMBER); ni = 0; @@ -566,7 +569,7 @@ static void ColouriseAU3Doc(unsigned int startPos, } //for (; sc.More(); sc.Forward()) //************************************* - // Colourize the last word correctly + // Colourize the last word correctly //************************************* if (sc.state == SCE_AU3_KEYWORD) { @@ -610,24 +613,24 @@ static void ColouriseAU3Doc(unsigned int startPos, } if (sc.state == SCE_AU3_SENT) { - // Send key string ended - if (sc.chPrev == '}' && sc.ch != '}') + // Send key string ended + if (sc.chPrev == '}' && sc.ch != '}') { // set color to SENDKEY when valid sendkey .. else set back to regular string char sk[100]; // split {111 222} and return {111} and check if 222 is valid. // if return code = 1 then invalid 222 so must be string - if (GetSendKey(s_save,sk)) + if (GetSendKey(s_save,sk)) { sc.ChangeState(SCE_AU3_STRING); } // if single char between {?} then its ok as sendkey for a single character - else if (strlen(sk) == 3) + else if (strlen(sk) == 3) { sc.ChangeState(SCE_AU3_SENT); } // if sendkey {111} is in table then ok as sendkey - else if (keywords4.InList(sk)) + else if (keywords4.InList(sk)) { sc.ChangeState(SCE_AU3_SENT); } @@ -638,7 +641,7 @@ static void ColouriseAU3Doc(unsigned int startPos, sc.SetState(SCE_AU3_STRING); } // check if next portion is again a sendkey - if (sc.atLineEnd) + if (sc.atLineEnd) { sc.ChangeState(SCE_AU3_STRING); sc.SetState(SCE_AU3_DEFAULT); @@ -655,7 +658,7 @@ static bool IsStreamCommentStyle(int style) { // // Routine to find first none space on the current line and return its Style -// needed for comment lines not starting on pos 1 +// needed for comment lines not starting on pos 1 static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) { int nsPos = styler.LineStart(szLine); @@ -687,7 +690,7 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc startPos = styler.LineStart(lineCurrent); } } - // vars for style of previous/current/next lines + // vars for style of previous/current/next lines int style = GetStyleFirstWord(lineCurrent,styler); int stylePrev = 0; // find the first previous line without continuation character at the end @@ -712,7 +715,7 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc if (lineCurrent > 0) levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; int levelNext = levelCurrent; - // + // int visibleChars = 0; char chNext = styler.SafeGetCharAt(startPos); char chPrev = ' '; @@ -737,7 +740,7 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc } } } - // start the capture of the first word + // start the capture of the first word if (!(FirstWordStart)) { if (IsAWordChar(ch) || IsAWordStart(ch) || ch == ';') { FirstWordStart = true; @@ -749,7 +752,7 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc if (ThenFoundLast) { if (IsAWordChar(ch)) { ThenFoundLast = false; - } + } } // find out if the word "then" is the last on a "if" line if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { @@ -770,21 +773,21 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc } } } - // End of Line found so process the information + // End of Line found so process the information if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { // ************************** // Folding logic for Keywords // ************************** // if a keyword is found on the current line and the line doesn't end with _ (continuation) // and we are not inside a commentblock. - if (szKeywordlen > 0 && (!(chPrev == '_')) && + if (szKeywordlen > 0 && (!(chPrev == '_')) && ((!(IsStreamCommentStyle(style)) || foldInComment)) ) { szKeyword[szKeywordlen] = '\0'; // only fold "if" last keyword is "then" (else its a one line if) if (strcmp(szKeyword,"if") == 0 && ThenFoundLast) { levelNext++; } - // create new fold for these words + // create new fold for these words if (strcmp(szKeyword,"do") == 0 || strcmp(szKeyword,"for") == 0 || strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0|| strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) { @@ -797,12 +800,12 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc } // end the fold for these words before the current line if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 || - strcmp(szKeyword,"next") == 0 || strcmp(szKeyword,"until") == 0 || + strcmp(szKeyword,"next") == 0 || strcmp(szKeyword,"until") == 0 || strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){ levelNext--; levelCurrent--; } - // end the fold for these words before the current line and Start new fold + // end the fold for these words before the current line and Start new fold if (strcmp(szKeyword,"case") == 0 || strcmp(szKeyword,"else") == 0 || strcmp(szKeyword,"elseif") == 0 ) { levelCurrent--; @@ -841,16 +844,16 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc // Start of a comment block if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { levelNext++; - } + } // fold till the last line for normal comment lines - else if (IsStreamCommentStyle(stylePrev) + else if (IsStreamCommentStyle(stylePrev) && !(styleNext == SCE_AU3_COMMENT) - && stylePrev == SCE_AU3_COMMENT + && stylePrev == SCE_AU3_COMMENT && style == SCE_AU3_COMMENT) { levelNext--; } // fold till the one but last line for Blockcomment lines - else if (IsStreamCommentStyle(stylePrev) + else if (IsStreamCommentStyle(stylePrev) && !(styleNext == SCE_AU3_COMMENTBLOCK) && style == SCE_AU3_COMMENTBLOCK) { levelNext--; diff --git a/src/stc/scintilla/src/LexAVE.cxx b/src/stc/scintilla/lexers/LexAVE.cxx similarity index 97% rename from src/stc/scintilla/src/LexAVE.cxx rename to src/stc/scintilla/lexers/LexAVE.cxx index 2b7029b1ac..373173ca20 100644 --- a/src/stc/scintilla/src/LexAVE.cxx +++ b/src/stc/scintilla/lexers/LexAVE.cxx @@ -9,18 +9,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> -#include <stdarg.h> #include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -42,7 +45,7 @@ inline bool IsAWordStart(const int ch) { } inline bool isAveOperator(char ch) { - if (isalnum(ch)) + if (isascii(ch) && isalnum(ch)) return false; // '.' left out as it is used to make up numbers if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || diff --git a/src/stc/scintilla/lexers/LexAVS.cxx b/src/stc/scintilla/lexers/LexAVS.cxx new file mode 100644 index 0000000000..82e4345790 --- /dev/null +++ b/src/stc/scintilla/lexers/LexAVS.cxx @@ -0,0 +1,293 @@ +// Scintilla source code edit control +/** @file LexAVS.cxx + ** Lexer for AviSynth. + **/ +// Copyright 2012 by Bruno Barbieri <brunorex@gmail.com> +// Heavily based on LexPOV by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordStart(int ch) { + return isalpha(ch) || (ch != ' ' && ch != '\n' && ch != '(' && ch != '.' && ch != ','); +} + +static inline bool IsANumberChar(int ch) { + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. + return (ch < 0x80) && + (isdigit(ch) || ch == '.' || ch == '-' || ch == '+'); +} + +static void ColouriseAvsDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &filters = *keywordlists[1]; + WordList &plugins = *keywordlists[2]; + WordList &functions = *keywordlists[3]; + WordList &clipProperties = *keywordlists[4]; + WordList &userDefined = *keywordlists[5]; + + int currentLine = styler.GetLine(startPos); + // Initialize the block comment nesting level, if we are inside such a comment. + int blockCommentLevel = 0; + if (initStyle == SCE_AVS_COMMENTBLOCK || initStyle == SCE_AVS_COMMENTBLOCKN) { + blockCommentLevel = styler.GetLineState(currentLine - 1); + } + + // Do not leak onto next line + if (initStyle == SCE_AVS_COMMENTLINE) { + initStyle = SCE_AVS_DEFAULT; + } + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + currentLine = styler.GetLine(sc.currentPos); + if (sc.state == SCE_AVS_COMMENTBLOCK || sc.state == SCE_AVS_COMMENTBLOCKN) { + // Inside a block comment, we set the line state + styler.SetLineState(currentLine, blockCommentLevel); + } else { + // Reset the line state + styler.SetLineState(currentLine, 0); + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_AVS_OPERATOR) { + sc.SetState(SCE_AVS_DEFAULT); + } else if (sc.state == SCE_AVS_NUMBER) { + // We stop the number definition on non-numerical non-dot non-sign char + if (!IsANumberChar(sc.ch)) { + sc.SetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_AVS_KEYWORD); + } else if (filters.InList(s)) { + sc.ChangeState(SCE_AVS_FILTER); + } else if (plugins.InList(s)) { + sc.ChangeState(SCE_AVS_PLUGIN); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_AVS_FUNCTION); + } else if (clipProperties.InList(s)) { + sc.ChangeState(SCE_AVS_CLIPPROP); + } else if (userDefined.InList(s)) { + sc.ChangeState(SCE_AVS_USERDFN); + } + sc.SetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_COMMENTBLOCK) { + if (sc.Match('/', '*')) { + blockCommentLevel++; + sc.Forward(); + } else if (sc.Match('*', '/') && blockCommentLevel > 0) { + blockCommentLevel--; + sc.Forward(); + if (blockCommentLevel == 0) { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } + } else if (sc.state == SCE_AVS_COMMENTBLOCKN) { + if (sc.Match('[', '*')) { + blockCommentLevel++; + sc.Forward(); + } else if (sc.Match('*', ']') && blockCommentLevel > 0) { + blockCommentLevel--; + sc.Forward(); + if (blockCommentLevel == 0) { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } + } else if (sc.state == SCE_AVS_COMMENTLINE) { + if (sc.atLineEnd) { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_STRING) { + if (sc.ch == '\"') { + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } else if (sc.state == SCE_AVS_TRIPLESTRING) { + if (sc.Match("\"\"\"")) { + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_AVS_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_AVS_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_AVS_NUMBER); + } else if (IsADigit(sc.ch) || (sc.ch == ',' && IsADigit(sc.chNext))) { + sc.Forward(); + sc.SetState(SCE_AVS_NUMBER); + } else if (sc.Match('/', '*')) { + blockCommentLevel = 1; + sc.SetState(SCE_AVS_COMMENTBLOCK); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('[', '*')) { + blockCommentLevel = 1; + sc.SetState(SCE_AVS_COMMENTBLOCKN); + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.ch == '#') { + sc.SetState(SCE_AVS_COMMENTLINE); + } else if (sc.ch == '\"') { + if (sc.Match("\"\"\"")) { + sc.SetState(SCE_AVS_TRIPLESTRING); + } else { + sc.SetState(SCE_AVS_STRING); + } + } else if (isoperator(static_cast<char>(sc.ch))) { + sc.SetState(SCE_AVS_OPERATOR); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_AVS_IDENTIFIER); + } + } + } + + // End of file: complete any pending changeState + if (sc.state == SCE_AVS_IDENTIFIER) { + if (!IsAWordChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + + if (keywords.InList(s)) { + sc.ChangeState(SCE_AVS_KEYWORD); + } else if (filters.InList(s)) { + sc.ChangeState(SCE_AVS_FILTER); + } else if (plugins.InList(s)) { + sc.ChangeState(SCE_AVS_PLUGIN); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_AVS_FUNCTION); + } else if (clipProperties.InList(s)) { + sc.ChangeState(SCE_AVS_CLIPPROP); + } else if (userDefined.InList(s)) { + sc.ChangeState(SCE_AVS_USERDFN); + } + sc.SetState(SCE_AVS_DEFAULT); + } + } + + sc.Complete(); +} + +static void FoldAvsDoc( + unsigned int startPos, + int length, + int initStyle, + WordList *[], + Accessor &styler) { + + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (foldComment && style == SCE_AVS_COMMENTBLOCK) { + if (stylePrev != SCE_AVS_COMMENTBLOCK) { + levelCurrent++; + } else if ((styleNext != SCE_AVS_COMMENTBLOCK) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + + if (foldComment && style == SCE_AVS_COMMENTBLOCKN) { + if (stylePrev != SCE_AVS_COMMENTBLOCKN) { + levelCurrent++; + } else if ((styleNext != SCE_AVS_COMMENTBLOCKN) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelCurrent--; + } + } + + if (style == SCE_AVS_OPERATOR) { + if (ch == '{') { + levelCurrent++; + } else if (ch == '}') { + levelCurrent--; + } + } + + if (atEOL) { + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + + if (!isspacechar(ch)) + visibleChars++; + } + // Fill in the real level of the next line, keeping the current flags as they will be filled in later + int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK; + styler.SetLevel(lineCurrent, levelPrev | flagsNext); +} + +static const char * const avsWordLists[] = { + "Keywords", + "Filters", + "Plugins", + "Functions", + "Clip properties", + "User defined functions", + 0, +}; + +LexerModule lmAVS(SCLEX_AVS, ColouriseAvsDoc, "avs", FoldAvsDoc, avsWordLists); diff --git a/src/stc/scintilla/src/LexAbaqus.cxx b/src/stc/scintilla/lexers/LexAbaqus.cxx similarity index 99% rename from src/stc/scintilla/src/LexAbaqus.cxx rename to src/stc/scintilla/lexers/LexAbaqus.cxx index 10e8b76b1e..134170071a 100644 --- a/src/stc/scintilla/src/LexAbaqus.cxx +++ b/src/stc/scintilla/lexers/LexAbaqus.cxx @@ -10,18 +10,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexAda.cxx b/src/stc/scintilla/lexers/LexAda.cxx similarity index 98% rename from src/stc/scintilla/src/LexAda.cxx rename to src/stc/scintilla/lexers/LexAda.cxx index 654bfbebad..49eb2c68b0 100644 --- a/src/stc/scintilla/src/LexAda.cxx +++ b/src/stc/scintilla/lexers/LexAda.cxx @@ -6,19 +6,24 @@ // The License.txt file describes the conditions under which this software may be distributed. #include <stdlib.h> -#include <ctype.h> #include <string.h> #include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> #include <string> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "PropSet.h" -#include "KeyWords.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/lexers/LexAsm.cxx b/src/stc/scintilla/lexers/LexAsm.cxx new file mode 100644 index 0000000000..78874de860 --- /dev/null +++ b/src/stc/scintilla/lexers/LexAsm.cxx @@ -0,0 +1,460 @@ +// Scintilla source code edit control +/** @file LexAsm.cxx + ** Lexer for Assembler, just for the MASM syntax + ** Written by The Black Horus + ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10 + ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" <dlchnr(at)gmx(dot)net> + **/ +// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include <string> +#include <map> +#include <set> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || + ch == '_' || ch == '?'); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || + ch == '%' || ch == '@' || ch == '$' || ch == '?'); +} + +static inline bool IsAsmOperator(const int ch) { + if ((ch < 0x80) && (isalnum(ch))) + return false; + // '.' left out as it is used to make up numbers + if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || + ch == '(' || ch == ')' || ch == '=' || ch == '^' || + ch == '[' || ch == ']' || ch == '<' || ch == '&' || + ch == '>' || ch == ',' || ch == '|' || ch == '~' || + ch == '%' || ch == ':') + return true; + return false; +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_ASM_COMMENTDIRECTIVE || style == SCE_ASM_COMMENTBLOCK; +} + +static inline int LowerCase(int c) { + if (c >= 'A' && c <= 'Z') + return 'a' + c - 'A'; + return c; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerAsm +struct OptionsAsm { + std::string delimiter; + bool fold; + bool foldSyntaxBased; + bool foldCommentMultiline; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + OptionsAsm() { + delimiter = ""; + fold = false; + foldSyntaxBased = true; + foldCommentMultiline = false; + foldCommentExplicit = false; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + } +}; + +static const char * const asmWordListDesc[] = { + "CPU instructions", + "FPU instructions", + "Registers", + "Directives", + "Directive operands", + "Extended instructions", + "Directives4Foldstart", + "Directives4Foldend", + 0 +}; + +struct OptionSetAsm : public OptionSet<OptionsAsm> { + OptionSetAsm() { + DefineProperty("lexer.asm.comment.delimiter", &OptionsAsm::delimiter, + "Character used for COMMENT directive's delimiter, replacing the standard \"~\"."); + + DefineProperty("fold", &OptionsAsm::fold); + + DefineProperty("fold.asm.syntax.based", &OptionsAsm::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.asm.comment.multiline", &OptionsAsm::foldCommentMultiline, + "Set this property to 1 to enable folding multi-line comments."); + + DefineProperty("fold.asm.comment.explicit", &OptionsAsm::foldCommentExplicit, + "This option enables folding explicit fold points when using the Asm lexer. " + "Explicit fold points allows adding extra folding by placing a ;{ comment at the start and a ;} " + "at the end of a section that should fold."); + + DefineProperty("fold.asm.explicit.start", &OptionsAsm::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard ;{."); + + DefineProperty("fold.asm.explicit.end", &OptionsAsm::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard ;}."); + + DefineProperty("fold.asm.explicit.anywhere", &OptionsAsm::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.compact", &OptionsAsm::foldCompact); + + DefineWordListSets(asmWordListDesc); + } +}; + +class LexerAsm : public ILexer { + WordList cpuInstruction; + WordList mathInstruction; + WordList registers; + WordList directive; + WordList directiveOperand; + WordList extInstruction; + WordList directives4foldstart; + WordList directives4foldend; + OptionsAsm options; + OptionSetAsm osAsm; +public: + LexerAsm() { + } + virtual ~LexerAsm() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osAsm.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osAsm.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osAsm.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osAsm.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + + static ILexer *LexerFactoryAsm() { + return new LexerAsm(); + } +}; + +int SCI_METHOD LexerAsm::PropertySet(const char *key, const char *val) { + if (osAsm.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerAsm::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &cpuInstruction; + break; + case 1: + wordListN = &mathInstruction; + break; + case 2: + wordListN = ®isters; + break; + case 3: + wordListN = &directive; + break; + case 4: + wordListN = &directiveOperand; + break; + case 5: + wordListN = &extInstruction; + break; + case 6: + wordListN = &directives4foldstart; + break; + case 7: + wordListN = &directives4foldend; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerAsm::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + // Do not leak onto next line + if (initStyle == SCE_ASM_STRINGEOL) + initStyle = SCE_ASM_DEFAULT; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) + { + + // Prevent SCE_ASM_STRINGEOL from leaking back to previous line + if (sc.atLineStart && (sc.state == SCE_ASM_STRING)) { + sc.SetState(SCE_ASM_STRING); + } else if (sc.atLineStart && (sc.state == SCE_ASM_CHARACTER)) { + sc.SetState(SCE_ASM_CHARACTER); + } + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continue; + } + } + + // Determine if the current state should terminate. + if (sc.state == SCE_ASM_OPERATOR) { + if (!IsAsmOperator(sc.ch)) { + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_NUMBER) { + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_IDENTIFIER) { + if (!IsAWordChar(sc.ch) ) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + bool IsDirective = false; + + if (cpuInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_CPUINSTRUCTION); + } else if (mathInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_MATHINSTRUCTION); + } else if (registers.InList(s)) { + sc.ChangeState(SCE_ASM_REGISTER); + } else if (directive.InList(s)) { + sc.ChangeState(SCE_ASM_DIRECTIVE); + IsDirective = true; + } else if (directiveOperand.InList(s)) { + sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND); + } else if (extInstruction.InList(s)) { + sc.ChangeState(SCE_ASM_EXTINSTRUCTION); + } + sc.SetState(SCE_ASM_DEFAULT); + if (IsDirective && !strcmp(s, "comment")) { + char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; + while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + if (sc.ch == delimiter) { + sc.SetState(SCE_ASM_COMMENTDIRECTIVE); + } + } + } + } else if (sc.state == SCE_ASM_COMMENTDIRECTIVE) { + char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0]; + if (sc.ch == delimiter) { + while (!sc.atLineEnd) { + sc.Forward(); + } + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_COMMENT ) { + if (sc.atLineEnd) { + sc.SetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_STRING) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_ASM_STRINGEOL); + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + } else if (sc.state == SCE_ASM_CHARACTER) { + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_ASM_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_ASM_STRINGEOL); + sc.ForwardSetState(SCE_ASM_DEFAULT); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_ASM_DEFAULT) { + if (sc.ch == ';'){ + sc.SetState(SCE_ASM_COMMENT); + } else if (isascii(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && isascii(sc.chNext) && isdigit(sc.chNext)))) { + sc.SetState(SCE_ASM_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_ASM_IDENTIFIER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_ASM_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_ASM_CHARACTER); + } else if (IsAsmOperator(sc.ch)) { + sc.SetState(SCE_ASM_OPERATOR); + } + } + + } + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "else". + +void SCI_METHOD LexerAsm::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + char word[100]; + int wordlen = 0; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (options.foldCommentMultiline && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (options.foldCommentExplicit && ((style == SCE_ASM_COMMENT) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if (ch == ';') { + if (chNext == '{') { + levelNext++; + } else if (chNext == '}') { + levelNext--; + } + } + } + } + if (options.foldSyntaxBased && (style == SCE_ASM_DIRECTIVE)) { + word[wordlen++] = static_cast<char>(LowerCase(ch)); + if (wordlen == 100) { // prevent overflow + word[0] = '\0'; + wordlen = 1; + } + if (styleNext != SCE_ASM_DIRECTIVE) { // reading directive ready + word[wordlen] = '\0'; + wordlen = 0; + if (directives4foldstart.InList(word)) { + levelNext++; + } else if (directives4foldend.InList(word)){ + levelNext--; + } + } + } + if (!IsASpace(ch)) + visibleChars++; + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + } + } +} + +LexerModule lmAsm(SCLEX_ASM, LexerAsm::LexerFactoryAsm, "asm", asmWordListDesc); + diff --git a/src/stc/scintilla/src/LexAsn1.cxx b/src/stc/scintilla/lexers/LexAsn1.cxx similarity index 97% rename from src/stc/scintilla/src/LexAsn1.cxx rename to src/stc/scintilla/lexers/LexAsn1.cxx index 36f1d5dc2e..3545b3fa9a 100644 --- a/src/stc/scintilla/src/LexAsn1.cxx +++ b/src/stc/scintilla/lexers/LexAsn1.cxx @@ -5,20 +5,23 @@ // Copyright 2004 by Herr Pfarrer rpfarrer <at> yahoo <dot> de // Last Updated: 20/07/2004 // The License.txt file describes the conditions under which this software may be distributed. + #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexBaan.cxx b/src/stc/scintilla/lexers/LexBaan.cxx similarity index 97% rename from src/stc/scintilla/src/LexBaan.cxx rename to src/stc/scintilla/lexers/LexBaan.cxx index a6847db71a..3784f3c310 100644 --- a/src/stc/scintilla/src/LexBaan.cxx +++ b/src/stc/scintilla/lexers/LexBaan.cxx @@ -8,18 +8,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexBash.cxx b/src/stc/scintilla/lexers/LexBash.cxx similarity index 63% rename from src/stc/scintilla/src/LexBash.cxx rename to src/stc/scintilla/lexers/LexBash.cxx index 5801278bec..8cd6cc570e 100644 --- a/src/stc/scintilla/src/LexBash.cxx +++ b/src/stc/scintilla/lexers/LexBash.cxx @@ -2,44 +2,53 @@ /** @file LexBash.cxx ** Lexer for Bash. **/ -// Copyright 2004-2008 by Neil Hodgson <neilh@scintilla.org> +// Copyright 2004-2010 by Neil Hodgson <neilh@scintilla.org> // Adapted from LexPerl by Kein-Hong Man 2004 // The License.txt file describes the conditions under which this software may be distributed. #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" #include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif -#define HERE_DELIM_MAX 256 +#define HERE_DELIM_MAX 256 // define this if you want 'invalid octals' to be marked as errors // usually, this is not a good idea, permissive lexing is better #undef PEDANTIC_OCTAL -#define BASH_BASE_ERROR 65 -#define BASH_BASE_DECIMAL 66 -#define BASH_BASE_HEX 67 +#define BASH_BASE_ERROR 65 +#define BASH_BASE_DECIMAL 66 +#define BASH_BASE_HEX 67 #ifdef PEDANTIC_OCTAL -#define BASH_BASE_OCTAL 68 -#define BASH_BASE_OCTAL_ERROR 69 +#define BASH_BASE_OCTAL 68 +#define BASH_BASE_OCTAL_ERROR 69 #endif +// state constants for parts of a bash command segment +#define BASH_CMD_BODY 0 +#define BASH_CMD_START 1 +#define BASH_CMD_WORD 2 +#define BASH_CMD_TEST 3 +#define BASH_CMD_ARITH 4 +#define BASH_CMD_DELIM 5 + static inline int translateBashDigit(int ch) { if (ch >= '0' && ch <= '9') { return ch - '0'; @@ -80,11 +89,15 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { WordList &keywords = *keywordlists[0]; + WordList cmdDelimiter, bashStruct, bashStruct_in; + cmdDelimiter.Set("| || |& & && ; ;; ( ) { }"); + bashStruct.Set("if elif fi while until else then do done esac eval"); + bashStruct_in.Set("for case select"); CharacterSet setWordStart(CharacterSet::setAlpha, "_"); // note that [+-] are often parts of identifiers in shell scripts CharacterSet setWord(CharacterSet::setAlphaNum, "._+-"); - CharacterSet setBashOperator(CharacterSet::setNone, "^&\\%()-+=|{}[]:;>,*/<?!.~@"); + CharacterSet setBashOperator(CharacterSet::setNone, "^&%()-+=|{}[]:;>,*/<?!.~@"); CharacterSet setSingleCharOp(CharacterSet::setNone, "rwxoRWXOezsfdlpSbctugkTBMACahGLNn"); CharacterSet setParam(CharacterSet::setAlphaNum, "$_"); CharacterSet setHereDoc(CharacterSet::setAlpha, "_\\-+!"); @@ -144,46 +157,115 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, int numBase = 0; int digit; unsigned int endPos = startPos + length; + int cmdState = BASH_CMD_START; + int testExprType = 0; - // Backtrack to beginning of style if required... - // If in a long distance lexical state, backtrack to find quote characters - if (initStyle == SCE_SH_HERE_Q) { - while ((startPos > 1) && (styler.StyleAt(startPos) != SCE_SH_HERE_DELIM)) { - startPos--; - } - startPos = styler.LineStart(styler.GetLine(startPos)); - initStyle = styler.StyleAt(startPos - 1); - } - // Bash strings can be multi-line with embedded newlines, so backtrack. - // Bash numbers have additional state during lexing, so backtrack too. - if (initStyle == SCE_SH_STRING - || initStyle == SCE_SH_BACKTICKS - || initStyle == SCE_SH_CHARACTER - || initStyle == SCE_SH_NUMBER - || initStyle == SCE_SH_IDENTIFIER - || initStyle == SCE_SH_COMMENTLINE) { - while ((startPos > 1) && (styler.StyleAt(startPos - 1) == initStyle)) { - startPos--; - } - initStyle = SCE_SH_DEFAULT; + // Always backtracks to the start of a line that is not a continuation + // of the previous line (i.e. start of a bash command segment) + int ln = styler.GetLine(startPos); + for (;;) { + startPos = styler.LineStart(ln); + if (ln == 0 || styler.GetLineState(ln) == BASH_CMD_START) + break; + ln--; } + initStyle = SCE_SH_DEFAULT; StyleContext sc(startPos, endPos - startPos, initStyle, styler); for (; sc.More(); sc.Forward()) { + // handle line continuation, updates per-line stored state + if (sc.atLineStart) { + ln = styler.GetLine(sc.currentPos); + if (sc.state == SCE_SH_STRING + || sc.state == SCE_SH_BACKTICKS + || sc.state == SCE_SH_CHARACTER + || sc.state == SCE_SH_HERE_Q + || sc.state == SCE_SH_COMMENTLINE + || sc.state == SCE_SH_PARAM) { + // force backtrack while retaining cmdState + styler.SetLineState(ln, BASH_CMD_BODY); + } else { + if (ln > 0) { + if ((sc.GetRelative(-3) == '\\' && sc.GetRelative(-2) == '\r' && sc.chPrev == '\n') + || sc.GetRelative(-2) == '\\') { // handle '\' line continuation + // retain last line's state + } else + cmdState = BASH_CMD_START; + } + styler.SetLineState(ln, cmdState); + } + } + + // controls change of cmdState at the end of a non-whitespace element + // states BODY|TEST|ARITH persist until the end of a command segment + // state WORD persist, but ends with 'in' or 'do' construct keywords + int cmdStateNew = BASH_CMD_BODY; + if (cmdState == BASH_CMD_TEST || cmdState == BASH_CMD_ARITH || cmdState == BASH_CMD_WORD) + cmdStateNew = cmdState; + int stylePrev = sc.state; + // Determine if the current state should terminate. switch (sc.state) { case SCE_SH_OPERATOR: sc.SetState(SCE_SH_DEFAULT); + if (cmdState == BASH_CMD_DELIM) // if command delimiter, start new command + cmdStateNew = BASH_CMD_START; + else if (sc.chPrev == '\\') // propagate command state if line continued + cmdStateNew = cmdState; break; case SCE_SH_WORD: // "." never used in Bash variable names but used in file names if (!setWord.Contains(sc.ch)) { - char s[1000]; + char s[500]; + char s2[10]; sc.GetCurrent(s, sizeof(s)); - if (s[0] != '-' && // for file operators - !keywords.InList(s)) { + // allow keywords ending in a whitespace or command delimiter + s2[0] = static_cast<char>(sc.ch); + s2[1] = '\0'; + bool keywordEnds = IsASpace(sc.ch) || cmdDelimiter.InList(s2); + // 'in' or 'do' may be construct keywords + if (cmdState == BASH_CMD_WORD) { + if (strcmp(s, "in") == 0 && keywordEnds) + cmdStateNew = BASH_CMD_BODY; + else if (strcmp(s, "do") == 0 && keywordEnds) + cmdStateNew = BASH_CMD_START; + else + sc.ChangeState(SCE_SH_IDENTIFIER); + sc.SetState(SCE_SH_DEFAULT); + break; + } + // a 'test' keyword starts a test expression + if (strcmp(s, "test") == 0) { + if (cmdState == BASH_CMD_START && keywordEnds) { + cmdStateNew = BASH_CMD_TEST; + testExprType = 0; + } else + sc.ChangeState(SCE_SH_IDENTIFIER); + } + // detect bash construct keywords + else if (bashStruct.InList(s)) { + if (cmdState == BASH_CMD_START && keywordEnds) + cmdStateNew = BASH_CMD_START; + else + sc.ChangeState(SCE_SH_IDENTIFIER); + } + // 'for'|'case'|'select' needs 'in'|'do' to be highlighted later + else if (bashStruct_in.InList(s)) { + if (cmdState == BASH_CMD_START && keywordEnds) + cmdStateNew = BASH_CMD_WORD; + else + sc.ChangeState(SCE_SH_IDENTIFIER); + } + // disambiguate option items and file test operators + else if (s[0] == '-') { + if (cmdState != BASH_CMD_TEST) + sc.ChangeState(SCE_SH_IDENTIFIER); + } + // disambiguate keywords and identifiers + else if (cmdState != BASH_CMD_START + || !(keywords.InList(s) && keywordEnds)) { sc.ChangeState(SCE_SH_IDENTIFIER); } sc.SetState(SCE_SH_DEFAULT); @@ -248,14 +330,8 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_SH_DEFAULT); break; case SCE_SH_COMMENTLINE: - if (sc.ch == '\\' && (sc.chNext == '\r' || sc.chNext == '\n')) { - // comment continuation - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - } else if (sc.atLineEnd) { - sc.ForwardSetState(SCE_SH_DEFAULT); + if (sc.atLineEnd && sc.chPrev != '\\') { + sc.SetState(SCE_SH_DEFAULT); } break; case SCE_SH_HERE_DELIM: @@ -294,23 +370,14 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, HereDoc.State = 1; } } else if (HereDoc.State == 1) { // collect the delimiter - if (HereDoc.Quoted) { // a quoted here-doc delimiter - if (sc.ch == HereDoc.Quote) { // closing quote => end of delimiter - sc.ForwardSetState(SCE_SH_DEFAULT); - } else { - if (sc.ch == '\\' && sc.chNext == HereDoc.Quote) { // escaped quote - sc.Forward(); - } - HereDoc.Append(sc.ch); - } - } else { // an unquoted here-doc delimiter - if (setHereDoc2.Contains(sc.ch)) { - HereDoc.Append(sc.ch); - } else if (sc.ch == '\\') { - // skip escape prefix - } else { - sc.SetState(SCE_SH_DEFAULT); - } + if (setHereDoc2.Contains(sc.ch) || sc.chPrev == '\\') { + HereDoc.Append(sc.ch); + } else if (HereDoc.Quoted && sc.ch == HereDoc.Quote) { // closing quote => end of delimiter + sc.ForwardSetState(SCE_SH_DEFAULT); + } else if (sc.ch == '\\') { + // skip escape prefix + } else { + sc.SetState(SCE_SH_DEFAULT); } if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { // force blowup sc.SetState(SCE_SH_ERROR); @@ -339,8 +406,8 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, if (s[strlen(s) - 1] == '\r') s[strlen(s) - 1] = '\0'; if (strcmp(HereDoc.Delimiter, s) == 0) { - if ((prefixws > 0 && HereDoc.Indent) || // indentation rule - (prefixws == 0 && !HereDoc.Indent)) { + if ((prefixws == 0) || // indentation rule + (prefixws > 0 && HereDoc.Indent)) { sc.SetState(SCE_SH_DEFAULT); break; } @@ -358,7 +425,6 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, } break; case SCE_SH_STRING: // delimited styles - case SCE_SH_CHARACTER: case SCE_SH_BACKTICKS: case SCE_SH_PARAM: if (sc.ch == '\\' && Quote.Up != '\\') { @@ -372,6 +438,14 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, Quote.Count++; } break; + case SCE_SH_CHARACTER: // singly-quoted strings + if (sc.ch == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + sc.ForwardSetState(SCE_SH_DEFAULT); + } + } + break; } // Must check end of HereDoc state 1 before default state is handled @@ -391,10 +465,17 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_SH_HERE_Q); } + // update cmdState about the current command segment + if (stylePrev != SCE_SH_DEFAULT && sc.state == SCE_SH_DEFAULT) { + cmdState = cmdStateNew; + } // Determine if a new state should be entered. if (sc.state == SCE_SH_DEFAULT) { - if (sc.ch == '\\') { // escaped character + if (sc.ch == '\\') { + // Bash can escape any non-newline as a literal sc.SetState(SCE_SH_IDENTIFIER); + if (sc.chNext == '\r' || sc.chNext == '\n') + sc.SetState(SCE_SH_OPERATOR); } else if (IsADigit(sc.ch)) { sc.SetState(SCE_SH_NUMBER); numBase = BASH_BASE_DECIMAL; @@ -424,19 +505,20 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_SH_BACKTICKS); Quote.Start(sc.ch); } else if (sc.ch == '$') { + if (sc.Match("$((")) { + sc.SetState(SCE_SH_OPERATOR); // handle '((' later + continue; + } sc.SetState(SCE_SH_SCALAR); sc.Forward(); if (sc.ch == '{') { sc.ChangeState(SCE_SH_PARAM); } else if (sc.ch == '\'') { - sc.ChangeState(SCE_SH_CHARACTER); + sc.ChangeState(SCE_SH_STRING); } else if (sc.ch == '"') { sc.ChangeState(SCE_SH_STRING); } else if (sc.ch == '(' || sc.ch == '`') { sc.ChangeState(SCE_SH_BACKTICKS); - if (sc.chNext == '(') { // $(( is lexed as operator - sc.ChangeState(SCE_SH_OPERATOR); - } } else { continue; // scalar has no delimiter pair } @@ -453,9 +535,66 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_SH_WORD); sc.Forward(); } else if (setBashOperator.Contains(sc.ch)) { + char s[10]; + bool isCmdDelim = false; sc.SetState(SCE_SH_OPERATOR); + // handle opening delimiters for test/arithmetic expressions - ((,[[,[ + if (cmdState == BASH_CMD_START + || cmdState == BASH_CMD_BODY) { + if (sc.Match('(', '(')) { + cmdState = BASH_CMD_ARITH; + sc.Forward(); + } else if (sc.Match('[', '[') && IsASpace(sc.GetRelative(2))) { + cmdState = BASH_CMD_TEST; + testExprType = 1; + sc.Forward(); + } else if (sc.ch == '[' && IsASpace(sc.chNext)) { + cmdState = BASH_CMD_TEST; + testExprType = 2; + } + } + // special state -- for ((x;y;z)) in ... looping + if (cmdState == BASH_CMD_WORD && sc.Match('(', '(')) { + cmdState = BASH_CMD_ARITH; + sc.Forward(); + continue; + } + // handle command delimiters in command START|BODY|WORD state, also TEST if 'test' + if (cmdState == BASH_CMD_START + || cmdState == BASH_CMD_BODY + || cmdState == BASH_CMD_WORD + || (cmdState == BASH_CMD_TEST && testExprType == 0)) { + s[0] = static_cast<char>(sc.ch); + if (setBashOperator.Contains(sc.chNext)) { + s[1] = static_cast<char>(sc.chNext); + s[2] = '\0'; + isCmdDelim = cmdDelimiter.InList(s); + if (isCmdDelim) + sc.Forward(); + } + if (!isCmdDelim) { + s[1] = '\0'; + isCmdDelim = cmdDelimiter.InList(s); + } + if (isCmdDelim) { + cmdState = BASH_CMD_DELIM; + continue; + } + } + // handle closing delimiters for test/arithmetic expressions - )),]],] + if (cmdState == BASH_CMD_ARITH && sc.Match(')', ')')) { + cmdState = BASH_CMD_BODY; + sc.Forward(); + } else if (cmdState == BASH_CMD_TEST && IsASpace(sc.chPrev)) { + if (sc.Match(']', ']') && testExprType == 1) { + sc.Forward(); + cmdState = BASH_CMD_BODY; + } else if (sc.ch == ']' && testExprType == 2) { + cmdState = BASH_CMD_BODY; + } + } } - } + }// sc.state } sc.Complete(); } @@ -507,6 +646,14 @@ static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[], levelCurrent--; } } + // Here Document folding + if (style == SCE_SH_HERE_DELIM) { + if (ch == '<' && chNext == '<') { + levelCurrent++; + } + } else if (style == SCE_SH_HERE_Q && styler.StyleAt(i+1) == SCE_PL_DEFAULT) { + levelCurrent--; + } if (atEOL) { int lev = levelPrev; if (visibleChars == 0 && foldCompact) diff --git a/src/stc/scintilla/src/LexBasic.cxx b/src/stc/scintilla/lexers/LexBasic.cxx similarity index 57% rename from src/stc/scintilla/src/LexBasic.cxx rename to src/stc/scintilla/lexers/LexBasic.cxx index 1c5d7b4259..bc8fcee472 100644 --- a/src/stc/scintilla/src/LexBasic.cxx +++ b/src/stc/scintilla/lexers/LexBasic.cxx @@ -1,6 +1,7 @@ // Scintilla source code edit control /** @file LexBasic.cxx ** Lexer for BlitzBasic and PureBasic. + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" <dlchnr(at)gmx(dot)net> **/ // Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. @@ -19,18 +20,24 @@ #include <stdlib.h> #include <string.h> #include <stdio.h> -#include <ctype.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include <string> +#include <map> -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -86,8 +93,213 @@ static int LowerCase(int c) return c; } -static void ColouriseBasicDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler, char comment_char) { +static int CheckBlitzFoldPoint(char const *token, int &level) { + if (!strcmp(token, "function") || + !strcmp(token, "type")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "end function") || + !strcmp(token, "end type")) { + return -1; + } + return 0; +} + +static int CheckPureFoldPoint(char const *token, int &level) { + if (!strcmp(token, "procedure") || + !strcmp(token, "enumeration") || + !strcmp(token, "interface") || + !strcmp(token, "structure")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "endprocedure") || + !strcmp(token, "endenumeration") || + !strcmp(token, "endinterface") || + !strcmp(token, "endstructure")) { + return -1; + } + return 0; +} + +static int CheckFreeFoldPoint(char const *token, int &level) { + if (!strcmp(token, "function") || + !strcmp(token, "sub") || + !strcmp(token, "type")) { + level |= SC_FOLDLEVELHEADERFLAG; + return 1; + } + if (!strcmp(token, "end function") || + !strcmp(token, "end sub") || + !strcmp(token, "end type")) { + return -1; + } + return 0; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerBasic +struct OptionsBasic { + bool fold; + bool foldSyntaxBased; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + OptionsBasic() { + fold = false; + foldSyntaxBased = true; + foldCommentExplicit = false; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + } +}; + +static const char * const blitzbasicWordListDesc[] = { + "BlitzBasic Keywords", + "user1", + "user2", + "user3", + 0 +}; + +static const char * const purebasicWordListDesc[] = { + "PureBasic Keywords", + "PureBasic PreProcessor Keywords", + "user defined 1", + "user defined 2", + 0 +}; + +static const char * const freebasicWordListDesc[] = { + "FreeBasic Keywords", + "FreeBasic PreProcessor Keywords", + "user defined 1", + "user defined 2", + 0 +}; + +struct OptionSetBasic : public OptionSet<OptionsBasic> { + OptionSetBasic(const char * const wordListDescriptions[]) { + DefineProperty("fold", &OptionsBasic::fold); + + DefineProperty("fold.basic.syntax.based", &OptionsBasic::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.basic.comment.explicit", &OptionsBasic::foldCommentExplicit, + "This option enables folding explicit fold points when using the Basic lexer. " + "Explicit fold points allows adding extra folding by placing a ;{ (BB/PB) or '{ (FB) comment at the start " + "and a ;} (BB/PB) or '} (FB) at the end of a section that should be folded."); + + DefineProperty("fold.basic.explicit.start", &OptionsBasic::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard ;{ (BB/PB) or '{ (FB)."); + + DefineProperty("fold.basic.explicit.end", &OptionsBasic::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard ;} (BB/PB) or '} (FB)."); + + DefineProperty("fold.basic.explicit.anywhere", &OptionsBasic::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.compact", &OptionsBasic::foldCompact); + + DefineWordListSets(wordListDescriptions); + } +}; + +class LexerBasic : public ILexer { + char comment_char; + int (*CheckFoldPoint)(char const *, int &); + WordList keywordlists[4]; + OptionsBasic options; + OptionSetBasic osBasic; +public: + LexerBasic(char comment_char_, int (*CheckFoldPoint_)(char const *, int &), const char * const wordListDescriptions[]) : + comment_char(comment_char_), + CheckFoldPoint(CheckFoldPoint_), + osBasic(wordListDescriptions) { + } + virtual ~LexerBasic() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osBasic.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osBasic.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osBasic.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osBasic.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + static ILexer *LexerFactoryBlitzBasic() { + return new LexerBasic(';', CheckBlitzFoldPoint, blitzbasicWordListDesc); + } + static ILexer *LexerFactoryPureBasic() { + return new LexerBasic(';', CheckPureFoldPoint, purebasicWordListDesc); + } + static ILexer *LexerFactoryFreeBasic() { + return new LexerBasic('\'', CheckFreeFoldPoint, freebasicWordListDesc ); + } +}; + +int SCI_METHOD LexerBasic::PropertySet(const char *key, const char *val) { + if (osBasic.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerBasic::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywordlists[0]; + break; + case 1: + wordListN = &keywordlists[1]; + break; + case 2: + wordListN = &keywordlists[2]; + break; + case 3: + wordListN = &keywordlists[3]; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerBasic::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + bool wasfirst = true, isfirst = true; // true if first token in a line styler.StartAt(startPos); @@ -111,7 +323,7 @@ static void ColouriseBasicDoc(unsigned int startPos, int length, int initStyle, }; sc.GetCurrentLowered(s, sizeof(s)); for (int i = 0; i < 4; i++) { - if (keywordlists[i]->InList(s)) { + if (keywordlists[i].InList(s)) { sc.ChangeState(kstates[i]); } } @@ -202,66 +414,30 @@ static void ColouriseBasicDoc(unsigned int startPos, int length, int initStyle, sc.Complete(); } -static int CheckBlitzFoldPoint(char const *token, int &level) { - if (!strcmp(token, "function") || - !strcmp(token, "type")) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "end function") || - !strcmp(token, "end type")) { - return -1; - } - return 0; -} -static int CheckPureFoldPoint(char const *token, int &level) { - if (!strcmp(token, "procedure") || - !strcmp(token, "enumeration") || - !strcmp(token, "interface") || - !strcmp(token, "structure")) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "endprocedure") || - !strcmp(token, "endenumeration") || - !strcmp(token, "endinterface") || - !strcmp(token, "endstructure")) { - return -1; - } - return 0; -} +void SCI_METHOD LexerBasic::Fold(unsigned int startPos, int length, int /* initStyle */, IDocument *pAccess) { -static int CheckFreeFoldPoint(char const *token, int &level) { - if (!strcmp(token, "function") || - !strcmp(token, "sub") || - !strcmp(token, "type")) { - level |= SC_FOLDLEVELHEADERFLAG; - return 1; - } - if (!strcmp(token, "end function") || - !strcmp(token, "end sub") || - !strcmp(token, "end type")) { - return -1; - } - return 0; -} + if (!options.fold) + return; + + LexAccessor styler(pAccess); -static void FoldBasicDoc(unsigned int startPos, int length, - Accessor &styler, int (*CheckFoldPoint)(char const *, int &)) { int line = styler.GetLine(startPos); int level = styler.LevelAt(line); int go = 0, done = 0; int endPos = startPos + length; char word[256]; int wordlen = 0; - int i; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + int cNext = styler[startPos]; + // Scan for tokens at the start of the line (they may include // whitespace, for tokens like "End Function" - for (i = startPos; i < endPos; i++) { - int c = styler.SafeGetCharAt(i); - if (!done && !go) { + for (int i = startPos; i < endPos; i++) { + int c = cNext; + cNext = styler.SafeGetCharAt(i + 1); + bool atEOL = (c == '\r' && cNext != '\n') || (c == '\n'); + if (options.foldSyntaxBased && !done && !go) { if (wordlen) { // are we scanning a token already? word[wordlen] = static_cast<char>(LowerCase(c)); if (!IsIdentifier(c)) { // done with token @@ -291,8 +467,27 @@ static void FoldBasicDoc(unsigned int startPos, int length, } } } - if (c == '\n') { // line end - if (!done && wordlen == 0 && foldCompact) // line was only space + if (options.foldCommentExplicit && ((styler.StyleAt(i) == SCE_B_COMMENT) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + level |= SC_FOLDLEVELHEADERFLAG; + go = 1; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + go = -1; + } + } else { + if (c == comment_char) { + if (cNext == '{') { + level |= SC_FOLDLEVELHEADERFLAG; + go = 1; + } else if (cNext == '}') { + go = -1; + } + } + } + } + if (atEOL) { // line end + if (!done && wordlen == 0 && options.foldCompact) // line was only space level |= SC_FOLDLEVELWHITEFLAG; if (level != styler.LevelAt(line)) styler.SetLevel(line, level); @@ -308,66 +503,8 @@ static void FoldBasicDoc(unsigned int startPos, int length, } } -static void ColouriseBlitzBasicDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';'); -} - -static void ColourisePureBasicDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';'); -} - -static void ColouriseFreeBasicDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, '\''); -} - -static void FoldBlitzBasicDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - FoldBasicDoc(startPos, length, styler, CheckBlitzFoldPoint); -} - -static void FoldPureBasicDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - FoldBasicDoc(startPos, length, styler, CheckPureFoldPoint); -} - -static void FoldFreeBasicDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - FoldBasicDoc(startPos, length, styler, CheckFreeFoldPoint); -} - -static const char * const blitzbasicWordListDesc[] = { - "BlitzBasic Keywords", - "user1", - "user2", - "user3", - 0 -}; - -static const char * const purebasicWordListDesc[] = { - "PureBasic Keywords", - "PureBasic PreProcessor Keywords", - "user defined 1", - "user defined 2", - 0 -}; - -static const char * const freebasicWordListDesc[] = { - "FreeBasic Keywords", - "FreeBasic PreProcessor Keywords", - "user defined 1", - "user defined 2", - 0 -}; - -LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, ColouriseBlitzBasicDoc, "blitzbasic", - FoldBlitzBasicDoc, blitzbasicWordListDesc); - -LexerModule lmPureBasic(SCLEX_PUREBASIC, ColourisePureBasicDoc, "purebasic", - FoldPureBasicDoc, purebasicWordListDesc); +LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, LexerBasic::LexerFactoryBlitzBasic, "blitzbasic", blitzbasicWordListDesc); -LexerModule lmFreeBasic(SCLEX_FREEBASIC, ColouriseFreeBasicDoc, "freebasic", - FoldFreeBasicDoc, freebasicWordListDesc); +LexerModule lmPureBasic(SCLEX_PUREBASIC, LexerBasic::LexerFactoryPureBasic, "purebasic", purebasicWordListDesc); +LexerModule lmFreeBasic(SCLEX_FREEBASIC, LexerBasic::LexerFactoryFreeBasic, "freebasic", freebasicWordListDesc); diff --git a/src/stc/scintilla/src/LexBullant.cxx b/src/stc/scintilla/lexers/LexBullant.cxx similarity index 96% rename from src/stc/scintilla/src/LexBullant.cxx rename to src/stc/scintilla/lexers/LexBullant.cxx index cc60cd2fc6..bb5c9c4a86 100644 --- a/src/stc/scintilla/src/LexBullant.cxx +++ b/src/stc/scintilla/lexers/LexBullant.cxx @@ -3,24 +3,29 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif static int classifyWordBullant(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) { char s[100]; + s[0] = '\0'; for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) { s[i] = static_cast<char>(tolower(styler[start + i])); s[i + 1] = '\0'; @@ -111,7 +116,7 @@ static void ColouriseBullantDoc(unsigned int startPos, int length, int initStyle } blockChange=0; */ } - if (!isspace(ch)) + if (!(isascii(ch) && isspace(ch))) visibleChars++; if (styler.IsLeadByte(ch)) { diff --git a/src/stc/scintilla/src/LexCLW.cxx b/src/stc/scintilla/lexers/LexCLW.cxx similarity index 97% rename from src/stc/scintilla/src/LexCLW.cxx rename to src/stc/scintilla/lexers/LexCLW.cxx index 624ef0f2ba..c1dea607c3 100644 --- a/src/stc/scintilla/src/LexCLW.cxx +++ b/src/stc/scintilla/lexers/LexCLW.cxx @@ -10,16 +10,19 @@ #include <string.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> #include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -60,10 +63,10 @@ inline bool IsALabelStart(const int iChar) { // Is a label character inline bool IsALabelCharacter(const int iChar) { - return(isalnum(iChar) || iChar == '_' || iChar == ':'); + return(isalnum(iChar) || iChar == '_' || iChar == ':'); } -// Is the character is a ! and the the next character is not a ! +// Is the character is a ! and the the next character is not a ! inline bool IsACommentStart(const int iChar) { return(iChar == '!'); @@ -126,7 +129,7 @@ inline bool SetNumericConstantState(StyleContext &scDoc) { break; default : break; - } + } } // If points found (can be more than one for improper formatted number if (iPoints > 0) { @@ -186,12 +189,12 @@ static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitS WordList &wlLabelReservedWords = *wlKeywords[7]; // Clarion Reserved Keywords (Labels) WordList &wlProcLabelReservedWords = *wlKeywords[8]; // Clarion Reserved Keywords (Procedure Labels) - const char wlProcReservedKeywordList[] = + const char wlProcReservedKeywordList[] = "PROCEDURE FUNCTION"; WordList wlProcReservedKeywords; wlProcReservedKeywords.Set(wlProcReservedKeywordList); - const char wlCompilerKeywordList[] = + const char wlCompilerKeywordList[] = "COMPILE OMIT"; WordList wlCompilerKeywords; wlCompilerKeywords.Set(wlCompilerKeywordList); @@ -243,7 +246,7 @@ static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitS // change the label to error state scDoc.ChangeState(SCE_CLW_ERROR); } - // Else if UPPERCASE label string is + // Else if UPPERCASE label string is else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) { char cWord[512]; // Word buffer // Get the next word from the current position @@ -368,13 +371,13 @@ static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitS // Increment the parenthese level iParenthesesLevel++; } - // Else if the character is a ) (close parenthese) + // Else if the character is a ) (close parenthese) else if (scDoc.ch == ')') { // If the parenthese level is set to zero // parentheses matched if (!iParenthesesLevel) { scDoc.SetState(SCE_CLW_DEFAULT); - } + } // Else parenthese level is greater than zero // still looking for matching parentheses else { @@ -399,7 +402,7 @@ static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitS || IsAHexCharacter(scDoc.ch, bCaseSensitive) || scDoc.ch == '.' || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) { - // If the number was a real + // If the number was a real if (SetNumericConstantState(scDoc)) { // Colour the matched string to the real constant state scDoc.ChangeState(SCE_CLW_REAL_CONSTANT); @@ -461,7 +464,7 @@ static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitS } // Default Handling else { - // If in default state + // If in default state if (scDoc.state == SCE_CLW_DEFAULT) { // If is a letter could be a possible statement if (isalpha(scDoc.ch)) { @@ -477,10 +480,10 @@ static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitS else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') { // then set the state to comment. scDoc.SetState(SCE_CLW_COMMENT); - } + } // else if the character is a ' (single quote) else if (scDoc.ch == '\'') { - // If the character is also a ' (single quote) + // If the character is also a ' (single quote) // Embedded Apostrophe if (scDoc.chNext == '\'') { // Move forward colouring it as default state @@ -490,7 +493,7 @@ static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitS // move to the next character and then set the state to comment. scDoc.ForwardSetState(SCE_CLW_STRING); } - } + } // else the character is an @ (ampersand) else if (scDoc.ch == '@') { // Case insensitive. @@ -509,7 +512,7 @@ static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitS scDoc.SetState(SCE_CLW_PICTURE_STRING); } } - } + } } } } @@ -616,7 +619,7 @@ static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, iStyle = iStyleNext; iStyleNext = accStyler.StyleAt(uiPos + 1); bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n'); - + if (iStylePrev == SCE_CLW_DEFAULT) { if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) { // Store last word start point. @@ -647,7 +650,7 @@ static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, iLevelPrev = iLevelCurrent; iVisibleChars = 0; } - + if (!isspacechar(chChar)) iVisibleChars++; } diff --git a/src/stc/scintilla/src/LexCOBOL.cxx b/src/stc/scintilla/lexers/LexCOBOL.cxx similarity index 93% rename from src/stc/scintilla/src/LexCOBOL.cxx rename to src/stc/scintilla/lexers/LexCOBOL.cxx index d061d5c674..b3bc011d60 100644 --- a/src/stc/scintilla/src/LexCOBOL.cxx +++ b/src/stc/scintilla/lexers/LexCOBOL.cxx @@ -10,18 +10,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" #include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -90,11 +93,11 @@ static int classifyWordCOBOL(unsigned int start, unsigned int end, /*WordList &k getRange(start, end, styler, s, sizeof(s)); char chAttr = SCE_C_IDENTIFIER; - if (isdigit(s[0]) || (s[0] == '.')) { + if (isdigit(s[0]) || (s[0] == '.') || (s[0] == 'v')) { chAttr = SCE_C_NUMBER; char *p = s + 1; while (*p) { - if (!isdigit(*p) && isCOBOLwordchar(*p)) { + if ((!isdigit(*p) && (*p) != 'v') && isCOBOLwordchar(*p)) { chAttr = SCE_C_IDENTIFIER; break; } @@ -202,9 +205,17 @@ static void ColouriseCOBOLDoc(unsigned int startPos, int length, int initStyle, } if (state == SCE_C_DEFAULT) { - if (isCOBOLwordstart(ch) || (ch == '$' && isalpha(chNext))) { + if (isCOBOLwordstart(ch) || (ch == '$' && isascii(chNext) && isalpha(chNext))) { ColourTo(styler, i-1, state); state = SCE_C_IDENTIFIER; + } else if (column == 6 && ch == '*') { + // Cobol comment line: asterisk in column 7. + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; + } else if (ch == '*' && chNext == '>') { + // Cobol inline comment: asterisk, followed by greater than. + ColourTo(styler, i-1, state); + state = SCE_C_COMMENTLINE; } else if (column == 0 && ch == '*' && chNext != '*') { ColourTo(styler, i-1, state); state = SCE_C_COMMENTLINE; diff --git a/src/stc/scintilla/lexers/LexCPP.cxx b/src/stc/scintilla/lexers/LexCPP.cxx new file mode 100644 index 0000000000..d6efa7ee01 --- /dev/null +++ b/src/stc/scintilla/lexers/LexCPP.cxx @@ -0,0 +1,1209 @@ +// Scintilla source code edit control +/** @file LexCPP.cxx + ** Lexer for C++, C, Java, and JavaScript. + ** Further folding features and configuration properties added by "Udo Lechner" <dlchnr(at)gmx(dot)net> + **/ +// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> + +#include <string> +#include <vector> +#include <map> +#include <algorithm> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "SparseState.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool IsSpaceEquiv(int state) { + return (state <= SCE_C_COMMENTDOC) || + // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE + (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) || + (state == SCE_C_COMMENTDOCKEYWORDERROR); +} + +// Preconditions: sc.currentPos points to a character after '+' or '-'. +// The test for pos reaching 0 should be redundant, +// and is in only for safety measures. +// Limitation: this code will give the incorrect answer for code like +// a = b+++/ptn/... +// Putting a space between the '++' post-inc operator and the '+' binary op +// fixes this, and is highly recommended for readability anyway. +static bool FollowsPostfixOperator(StyleContext &sc, LexAccessor &styler) { + int pos = (int) sc.currentPos; + while (--pos > 0) { + char ch = styler[pos]; + if (ch == '+' || ch == '-') { + return styler[pos - 1] == ch; + } + } + return false; +} + +static bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) { + // Don't look at styles, so no need to flush. + int pos = (int) sc.currentPos; + int currentLine = styler.GetLine(pos); + int lineStartPos = styler.LineStart(currentLine); + char ch; + while (--pos > lineStartPos) { + ch = styler.SafeGetCharAt(pos); + if (ch != ' ' && ch != '\t') { + break; + } + } + const char *retBack = "nruter"; + const char *s = retBack; + while (*s + && pos >= lineStartPos + && styler.SafeGetCharAt(pos) == *s) { + s++; + pos--; + } + return !*s; +} + +static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) { + std::string restOfLine; + int i =0; + char ch = styler.SafeGetCharAt(start, '\n'); + while ((ch != '\r') && (ch != '\n')) { + if (allowSpace || (ch != ' ')) + restOfLine += ch; + i++; + ch = styler.SafeGetCharAt(start + i, '\n'); + } + return restOfLine; +} + +static bool IsStreamCommentStyle(int style) { + return style == SCE_C_COMMENT || + style == SCE_C_COMMENTDOC || + style == SCE_C_COMMENTDOCKEYWORD || + style == SCE_C_COMMENTDOCKEYWORDERROR; +} + +static std::vector<std::string> Tokenize(const std::string &s) { + // Break into space separated tokens + std::string word; + std::vector<std::string> tokens; + for (const char *cp = s.c_str(); *cp; cp++) { + if ((*cp == ' ') || (*cp == '\t')) { + if (!word.empty()) { + tokens.push_back(word); + word = ""; + } + } else { + word += *cp; + } + } + if (!word.empty()) { + tokens.push_back(word); + } + return tokens; +} + +struct PPDefinition { + int line; + std::string key; + std::string value; + PPDefinition(int line_, const std::string &key_, const std::string &value_) : + line(line_), key(key_), value(value_) { + } +}; + +class LinePPState { + int state; + int ifTaken; + int level; + bool ValidLevel() const { + return level >= 0 && level < 32; + } + int maskLevel() const { + return 1 << level; + } +public: + LinePPState() : state(0), ifTaken(0), level(-1) { + } + bool IsInactive() const { + return state != 0; + } + bool CurrentIfTaken() { + return (ifTaken & maskLevel()) != 0; + } + void StartSection(bool on) { + level++; + if (ValidLevel()) { + if (on) { + state &= ~maskLevel(); + ifTaken |= maskLevel(); + } else { + state |= maskLevel(); + ifTaken &= ~maskLevel(); + } + } + } + void EndSection() { + if (ValidLevel()) { + state &= ~maskLevel(); + ifTaken &= ~maskLevel(); + } + level--; + } + void InvertCurrentLevel() { + if (ValidLevel()) { + state ^= maskLevel(); + ifTaken |= maskLevel(); + } + } +}; + +// Hold the preprocessor state for each line seen. +// Currently one entry per line but could become sparse with just one entry per preprocessor line. +class PPStates { + std::vector<LinePPState> vlls; +public: + LinePPState ForLine(int line) { + if ((line > 0) && (vlls.size() > static_cast<size_t>(line))) { + return vlls[line]; + } else { + return LinePPState(); + } + } + void Add(int line, LinePPState lls) { + vlls.resize(line+1); + vlls[line] = lls; + } +}; + +// An individual named option for use in an OptionSet + +// Options used for LexerCPP +struct OptionsCPP { + bool stylingWithinPreprocessor; + bool identifiersAllowDollars; + bool trackPreprocessor; + bool updatePreprocessor; + bool triplequotedStrings; + bool hashquotedStrings; + bool fold; + bool foldSyntaxBased; + bool foldComment; + bool foldCommentMultiline; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldPreprocessor; + bool foldCompact; + bool foldAtElse; + OptionsCPP() { + stylingWithinPreprocessor = false; + identifiersAllowDollars = true; + trackPreprocessor = true; + updatePreprocessor = true; + triplequotedStrings = false; + hashquotedStrings = false; + fold = false; + foldSyntaxBased = true; + foldComment = false; + foldCommentMultiline = true; + foldCommentExplicit = true; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldPreprocessor = false; + foldCompact = false; + foldAtElse = false; + } +}; + +static const char *const cppWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Documentation comment keywords", + "Global classes and typedefs", + "Preprocessor definitions", + 0, +}; + +struct OptionSetCPP : public OptionSet<OptionsCPP> { + OptionSetCPP() { + DefineProperty("styling.within.preprocessor", &OptionsCPP::stylingWithinPreprocessor, + "For C++ code, determines whether all preprocessor code is styled in the " + "preprocessor style (0, the default) or only from the initial # to the end " + "of the command word(1)."); + + DefineProperty("lexer.cpp.allow.dollars", &OptionsCPP::identifiersAllowDollars, + "Set to 0 to disallow the '$' character in identifiers with the cpp lexer."); + + DefineProperty("lexer.cpp.track.preprocessor", &OptionsCPP::trackPreprocessor, + "Set to 1 to interpret #if/#else/#endif to grey out code that is not active."); + + DefineProperty("lexer.cpp.update.preprocessor", &OptionsCPP::updatePreprocessor, + "Set to 1 to update preprocessor definitions when #define found."); + + DefineProperty("lexer.cpp.triplequoted.strings", &OptionsCPP::triplequotedStrings, + "Set to 1 to enable highlighting of triple-quoted strings."); + + DefineProperty("lexer.cpp.hashquoted.strings", &OptionsCPP::hashquotedStrings, + "Set to 1 to enable highlighting of hash-quoted strings."); + + DefineProperty("fold", &OptionsCPP::fold); + + DefineProperty("fold.cpp.syntax.based", &OptionsCPP::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.comment", &OptionsCPP::foldComment, + "This option enables folding multi-line comments and explicit fold points when using the C++ lexer. " + "Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} " + "at the end of a section that should fold."); + + DefineProperty("fold.cpp.comment.multiline", &OptionsCPP::foldCommentMultiline, + "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + + DefineProperty("fold.cpp.comment.explicit", &OptionsCPP::foldCommentExplicit, + "Set this property to 0 to disable folding explicit fold points when fold.comment=1."); + + DefineProperty("fold.cpp.explicit.start", &OptionsCPP::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard //{."); + + DefineProperty("fold.cpp.explicit.end", &OptionsCPP::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard //}."); + + DefineProperty("fold.cpp.explicit.anywhere", &OptionsCPP::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); + + DefineProperty("fold.preprocessor", &OptionsCPP::foldPreprocessor, + "This option enables folding preprocessor directives when using the C++ lexer. " + "Includes C#'s explicit #region and #endregion folding directives."); + + DefineProperty("fold.compact", &OptionsCPP::foldCompact); + + DefineProperty("fold.at.else", &OptionsCPP::foldAtElse, + "This option enables C++ folding on a \"} else {\" line of an if statement."); + + DefineWordListSets(cppWordLists); + } +}; + +class LexerCPP : public ILexer { + bool caseSensitive; + CharacterSet setWord; + CharacterSet setNegationOp; + CharacterSet setArithmethicOp; + CharacterSet setRelOp; + CharacterSet setLogicalOp; + PPStates vlls; + std::vector<PPDefinition> ppDefineHistory; + WordList keywords; + WordList keywords2; + WordList keywords3; + WordList keywords4; + WordList ppDefinitions; + std::map<std::string, std::string> preprocessorDefinitionsStart; + OptionsCPP options; + OptionSetCPP osCPP; + SparseState<std::string> rawStringTerminators; + enum { activeFlag = 0x40 }; +public: + LexerCPP(bool caseSensitive_) : + caseSensitive(caseSensitive_), + setWord(CharacterSet::setAlphaNum, "._", 0x80, true), + setNegationOp(CharacterSet::setNone, "!"), + setArithmethicOp(CharacterSet::setNone, "+-/*%"), + setRelOp(CharacterSet::setNone, "=!<>"), + setLogicalOp(CharacterSet::setNone, "|&") { + } + virtual ~LexerCPP() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osCPP.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osCPP.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osCPP.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osCPP.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + + static ILexer *LexerFactoryCPP() { + return new LexerCPP(true); + } + static ILexer *LexerFactoryCPPInsensitive() { + return new LexerCPP(false); + } + static int MaskActive(int style) { + return style & ~activeFlag; + } + void EvaluateTokens(std::vector<std::string> &tokens); + bool EvaluateExpression(const std::string &expr, const std::map<std::string, std::string> &preprocessorDefinitions); +}; + +int SCI_METHOD LexerCPP::PropertySet(const char *key, const char *val) { + if (osCPP.PropertySet(&options, key, val)) { + if (strcmp(key, "lexer.cpp.allow.dollars") == 0) { + setWord = CharacterSet(CharacterSet::setAlphaNum, "._", 0x80, true); + if (options.identifiersAllowDollars) { + setWord.Add('$'); + } + } + return 0; + } + return -1; +} + +int SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &keywords3; + break; + case 3: + wordListN = &keywords4; + break; + case 4: + wordListN = &ppDefinitions; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + if (n == 4) { + // Rebuild preprocessorDefinitions + preprocessorDefinitionsStart.clear(); + for (int nDefinition = 0; nDefinition < ppDefinitions.len; nDefinition++) { + char *cpDefinition = ppDefinitions.words[nDefinition]; + char *cpEquals = strchr(cpDefinition, '='); + if (cpEquals) { + std::string name(cpDefinition, cpEquals - cpDefinition); + std::string val(cpEquals+1); + preprocessorDefinitionsStart[name] = val; + } else { + std::string name(cpDefinition); + std::string val("1"); + preprocessorDefinitionsStart[name] = val; + } + } + } + } + } + return firstModification; +} + +// Functor used to truncate history +struct After { + int line; + After(int line_) : line(line_) {} + bool operator()(PPDefinition &p) const { + return p.line > line; + } +}; + +void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); + CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); + + CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + + if (options.identifiersAllowDollars) { + setWordStart.Add('$'); + } + + int chPrevNonWhite = ' '; + int visibleChars = 0; + bool lastWordWasUUID = false; + int styleBeforeDCKeyword = SCE_C_DEFAULT; + bool continuationLine = false; + bool isIncludePreprocessor = false; + + int lineCurrent = styler.GetLine(startPos); + if ((MaskActive(initStyle) == SCE_C_PREPROCESSOR) || + (MaskActive(initStyle) == SCE_C_COMMENTLINE) || + (MaskActive(initStyle) == SCE_C_COMMENTLINEDOC)) { + // Set continuationLine if last character of previous line is '\' + if (lineCurrent > 0) { + int chBack = styler.SafeGetCharAt(startPos-1, 0); + int chBack2 = styler.SafeGetCharAt(startPos-2, 0); + int lineEndChar = '!'; + if (chBack2 == '\r' && chBack == '\n') { + lineEndChar = styler.SafeGetCharAt(startPos-3, 0); + } else if (chBack == '\n' || chBack == '\r') { + lineEndChar = chBack2; + } + continuationLine = lineEndChar == '\\'; + } + } + + // look back to set chPrevNonWhite properly for better regex colouring + if (startPos > 0) { + int back = startPos; + while (--back && IsSpaceEquiv(MaskActive(styler.StyleAt(back)))) + ; + if (MaskActive(styler.StyleAt(back)) == SCE_C_OPERATOR) { + chPrevNonWhite = styler.SafeGetCharAt(back); + } + } + + StyleContext sc(startPos, length, initStyle, styler, 0x7f); + LinePPState preproc = vlls.ForLine(lineCurrent); + + bool definitionsChanged = false; + + // Truncate ppDefineHistory before current line + + if (!options.updatePreprocessor) + ppDefineHistory.clear(); + + std::vector<PPDefinition>::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(), After(lineCurrent-1)); + if (itInvalid != ppDefineHistory.end()) { + ppDefineHistory.erase(itInvalid, ppDefineHistory.end()); + definitionsChanged = true; + } + + std::map<std::string, std::string> preprocessorDefinitions = preprocessorDefinitionsStart; + for (std::vector<PPDefinition>::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) { + preprocessorDefinitions[itDef->key] = itDef->value; + } + + std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1); + SparseState<std::string> rawSTNew(lineCurrent); + + int activitySet = preproc.IsInactive() ? activeFlag : 0; + + for (; sc.More();) { + + if (sc.atLineStart) { + // Using MaskActive() is not needed in the following statement. + // Inside inactive preprocessor declaration, state will be reset anyway at the end of this block. + if ((sc.state == SCE_C_STRING) || (sc.state == SCE_C_CHARACTER)) { + // Prevent SCE_C_STRINGEOL from leaking back to previous line which + // ends with a line continuation by locking in the state upto this position. + sc.SetState(sc.state); + } + if ((MaskActive(sc.state) == SCE_C_PREPROCESSOR) && (!continuationLine)) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + lastWordWasUUID = false; + isIncludePreprocessor = false; + if (preproc.IsInactive()) { + activitySet = activeFlag; + sc.SetState(sc.state | activitySet); + } + } + + if (sc.atLineEnd) { + lineCurrent++; + vlls.Add(lineCurrent, preproc); + if (rawStringTerminator != "") { + rawSTNew.Set(lineCurrent-1, rawStringTerminator); + } + } + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + lineCurrent++; + vlls.Add(lineCurrent, preproc); + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continuationLine = true; + sc.Forward(); + continue; + } + } + + const bool atLineEndBeforeSwitch = sc.atLineEnd; + + // Determine if the current state should terminate. + switch (MaskActive(sc.state)) { + case SCE_C_OPERATOR: + sc.SetState(SCE_C_DEFAULT|activitySet); + break; + case SCE_C_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (!(setWord.Contains(sc.ch) || ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_IDENTIFIER: + if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { + char s[1000]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (keywords.InList(s)) { + lastWordWasUUID = strcmp(s, "uuid") == 0; + sc.ChangeState(SCE_C_WORD|activitySet); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_C_WORD2|activitySet); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_C_GLOBALCLASS|activitySet); + } + const bool literalString = sc.ch == '\"'; + if (literalString || sc.ch == '\'') { + size_t lenS = strlen(s); + const bool raw = literalString && sc.chPrev == 'R'; + if (raw) + s[lenS--] = '\0'; + bool valid = + (lenS == 0) || + ((lenS == 1) && ((s[0] == 'L') || (s[0] == 'u') || (s[0] == 'U'))) || + ((lenS == 2) && literalString && (s[0] == 'u') && (s[1] == '8')); + if (valid) { + if (literalString) + sc.ChangeState((raw ? SCE_C_STRINGRAW : SCE_C_STRING)|activitySet); + else + sc.ChangeState(SCE_C_CHARACTER|activitySet); + } + } + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_PREPROCESSOR: + if (options.stylingWithinPreprocessor) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + } else { + if (sc.Match('/', '*')) { + sc.SetState(SCE_C_PREPROCESSORCOMMENT|activitySet); + sc.Forward(); // Eat the * + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + } + break; + case SCE_C_PREPROCESSORCOMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_PREPROCESSOR|activitySet); + continue; // Without advancing in case of '\'. + } + break; + case SCE_C_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD|activitySet); + } + } + break; + case SCE_C_COMMENTLINE: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_COMMENTLINEDOC: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD|activitySet); + } + } + break; + case SCE_C_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } else if (!setDoxygen.Contains(sc.ch)) { + char s[100]; + if (caseSensitive) { + sc.GetCurrent(s, sizeof(s)); + } else { + sc.GetCurrentLowered(s, sizeof(s)); + } + if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet); + } + sc.SetState(styleBeforeDCKeyword|activitySet); + } + break; + case SCE_C_STRING: + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL|activitySet); + } else if (isIncludePreprocessor) { + if (sc.ch == '>') { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + isIncludePreprocessor = false; + } + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_HASHQUOTEDSTRING: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_STRINGRAW: + if (sc.Match(rawStringTerminator.c_str())) { + for (size_t termPos=rawStringTerminator.size(); termPos; termPos--) + sc.Forward(); + sc.SetState(SCE_C_DEFAULT|activitySet); + rawStringTerminator = ""; + } + break; + case SCE_C_CHARACTER: + if (sc.atLineEnd) { + sc.ChangeState(SCE_C_STRINGEOL|activitySet); + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_REGEX: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '/') { + sc.Forward(); + while ((sc.ch < 0x80) && islower(sc.ch)) + sc.Forward(); // gobble regex flags + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (sc.ch == '\\') { + // Gobble up the quoted character + if (sc.chNext == '\\' || sc.chNext == '/') { + sc.Forward(); + } + } + break; + case SCE_C_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_VERBATIM: + if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_C_DEFAULT|activitySet); + } + } + break; + case SCE_C_TRIPLEVERBATIM: + if (sc.Match("\"\"\"")) { + while (sc.Match('"')) { + sc.Forward(); + } + sc.SetState(SCE_C_DEFAULT|activitySet); + } + break; + case SCE_C_UUID: + if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { + sc.SetState(SCE_C_DEFAULT|activitySet); + } + } + + if (sc.atLineEnd && !atLineEndBeforeSwitch) { + // State exit processing consumed characters up to end of line. + lineCurrent++; + vlls.Add(lineCurrent, preproc); + } + + // Determine if a new state should be entered. + if (MaskActive(sc.state) == SCE_C_DEFAULT) { + if (sc.Match('@', '\"')) { + sc.SetState(SCE_C_VERBATIM|activitySet); + sc.Forward(); + } else if (options.triplequotedStrings && sc.Match("\"\"\"")) { + sc.SetState(SCE_C_TRIPLEVERBATIM|activitySet); + sc.Forward(2); + } else if (options.hashquotedStrings && sc.Match('#', '\"')) { + sc.SetState(SCE_C_HASHQUOTEDSTRING|activitySet); + sc.Forward(); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID|activitySet); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_NUMBER|activitySet); + } + } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID|activitySet); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_IDENTIFIER|activitySet); + } + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style + sc.SetState(SCE_C_COMMENTDOC|activitySet); + } else { + sc.SetState(SCE_C_COMMENT|activitySet); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('/', '/')) { + if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) + // Support of Qt/Doxygen doc. style + sc.SetState(SCE_C_COMMENTLINEDOC|activitySet); + else + sc.SetState(SCE_C_COMMENTLINE|activitySet); + } else if (sc.ch == '/' + && (setOKBeforeRE.Contains(chPrevNonWhite) + || followsReturnKeyword(sc, styler)) + && (!setCouldBePostOp.Contains(chPrevNonWhite) + || !FollowsPostfixOperator(sc, styler))) { + sc.SetState(SCE_C_REGEX|activitySet); // JavaScript's RegEx + } else if (sc.ch == '\"') { + if (sc.chPrev == 'R') { + styler.Flush(); + if (MaskActive(styler.StyleAt(sc.currentPos - 1)) == SCE_C_STRINGRAW) { + sc.SetState(SCE_C_STRINGRAW|activitySet); + rawStringTerminator = ")"; + for (int termPos = sc.currentPos + 1;; termPos++) { + char chTerminator = styler.SafeGetCharAt(termPos, '('); + if (chTerminator == '(') + break; + rawStringTerminator += chTerminator; + } + rawStringTerminator += '\"'; + } else { + sc.SetState(SCE_C_STRING|activitySet); + } + } else { + sc.SetState(SCE_C_STRING|activitySet); + } + isIncludePreprocessor = false; // ensure that '>' won't end the string + } else if (isIncludePreprocessor && sc.ch == '<') { + sc.SetState(SCE_C_STRING|activitySet); + } else if (sc.ch == '\'') { + sc.SetState(SCE_C_CHARACTER|activitySet); + } else if (sc.ch == '#' && visibleChars == 0) { + // Preprocessor commands are alone on their line + sc.SetState(SCE_C_PREPROCESSOR|activitySet); + // Skip whitespace between # and preprocessor word + do { + sc.Forward(); + } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); + if (sc.atLineEnd) { + sc.SetState(SCE_C_DEFAULT|activitySet); + } else if (sc.Match("include")) { + isIncludePreprocessor = true; + } else { + if (options.trackPreprocessor) { + if (sc.Match("ifdef") || sc.Match("ifndef")) { + bool isIfDef = sc.Match("ifdef"); + int i = isIfDef ? 5 : 6; + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + i + 1, false); + bool foundDef = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end(); + preproc.StartSection(isIfDef == foundDef); + } else if (sc.Match("if")) { + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true); + bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions); + preproc.StartSection(ifGood); + } else if (sc.Match("else")) { + if (!preproc.CurrentIfTaken()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } else if (!preproc.IsInactive()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } + } else if (sc.Match("elif")) { + // Ensure only one chosen out of #if .. #elif .. #elif .. #else .. #endif + if (!preproc.CurrentIfTaken()) { + // Similar to #if + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 2, true); + bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions); + if (ifGood) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } + } else if (!preproc.IsInactive()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } + } else if (sc.Match("endif")) { + preproc.EndSection(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + sc.ChangeState(SCE_C_PREPROCESSOR|activitySet); + } else if (sc.Match("define")) { + if (options.updatePreprocessor && !preproc.IsInactive()) { + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); + if (restOfLine.find(")") == std::string::npos) { // Don't handle macros with arguments + std::vector<std::string> tokens = Tokenize(restOfLine); + std::string key; + std::string value("1"); + if (tokens.size() >= 1) { + key = tokens[0]; + if (tokens.size() >= 2) { + value = tokens[1]; + } + preprocessorDefinitions[key] = value; + ppDefineHistory.push_back(PPDefinition(lineCurrent, key, value)); + definitionsChanged = true; + } + } + } + } + } + } + } else if (isoperator(static_cast<char>(sc.ch))) { + sc.SetState(SCE_C_OPERATOR|activitySet); + } + } + + if (!IsASpace(sc.ch) && !IsSpaceEquiv(MaskActive(sc.state))) { + chPrevNonWhite = sc.ch; + visibleChars++; + } + continuationLine = false; + sc.Forward(); + } + const bool rawStringsChanged = rawStringTerminators.Merge(rawSTNew, lineCurrent); + if (definitionsChanged || rawStringsChanged) + styler.ChangeLexerState(startPos, startPos + length); + sc.Complete(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". + +void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = MaskActive(styler.StyleAt(startPos)); + int style = MaskActive(initStyle); + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = MaskActive(styler.StyleAt(i + 1)); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (options.foldComment && options.foldCommentExplicit && ((style == SCE_C_COMMENTLINE) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + } + if (options.foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { + if (ch == '#') { + unsigned int j = i + 1; + while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelNext++; + } else if (styler.Match(j, "end")) { + levelNext--; + } + } + } + if (options.foldSyntaxBased && (style == SCE_C_OPERATOR)) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (!IsASpace(ch)) + visibleChars++; + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + if (options.foldSyntaxBased && options.foldAtElse) { + levelUse = levelMinCurrent; + } + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + } + } +} + +void LexerCPP::EvaluateTokens(std::vector<std::string> &tokens) { + + // Evaluate defined() statements to either 0 or 1 + for (size_t i=0; (i+2)<tokens.size();) { + if ((tokens[i] == "defined") && (tokens[i+1] == "(")) { + const char *val = "0"; + if (tokens[i+2] == ")") { + // defined() + tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 3); + } else if (((i+3)<tokens.size()) && (tokens[i+3] == ")")) { + // defined(<int>) + tokens.erase(tokens.begin() + i + 1, tokens.begin() + i + 4); + val = "1"; + } + tokens[i] = val; + } else { + i++; + } + } + + // Find bracketed subexpressions and recurse on them + std::vector<std::string>::iterator itBracket = std::find(tokens.begin(), tokens.end(), "("); + std::vector<std::string>::iterator itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); + while ((itBracket != tokens.end()) && (itEndBracket != tokens.end()) && (itEndBracket > itBracket)) { + std::vector<std::string> inBracket(itBracket + 1, itEndBracket); + EvaluateTokens(inBracket); + + // The insertion is done before the removal because there were failures with the opposite approach + tokens.insert(itBracket, inBracket.begin(), inBracket.end()); + itBracket = std::find(tokens.begin(), tokens.end(), "("); + itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); + tokens.erase(itBracket, itEndBracket + 1); + + itBracket = std::find(tokens.begin(), tokens.end(), "("); + itEndBracket = std::find(tokens.begin(), tokens.end(), ")"); + } + + // Evaluate logical negations + for (size_t j=0; (j+1)<tokens.size();) { + if (setNegationOp.Contains(tokens[j][0])) { + int isTrue = atoi(tokens[j+1].c_str()); + if (tokens[j] == "!") + isTrue = !isTrue; + std::vector<std::string>::iterator itInsert = + tokens.erase(tokens.begin() + j, tokens.begin() + j + 2); + tokens.insert(itInsert, isTrue ? "1" : "0"); + } else { + j++; + } + } + + // Evaluate expressions in precedence order + enum precedence { precArithmetic, precRelative, precLogical }; + for (int prec=precArithmetic; prec <= precLogical; prec++) { + // Looking at 3 tokens at a time so end at 2 before end + for (size_t k=0; (k+2)<tokens.size();) { + char chOp = tokens[k+1][0]; + if ( + ((prec==precArithmetic) && setArithmethicOp.Contains(chOp)) || + ((prec==precRelative) && setRelOp.Contains(chOp)) || + ((prec==precLogical) && setLogicalOp.Contains(chOp)) + ) { + int valA = atoi(tokens[k].c_str()); + int valB = atoi(tokens[k+2].c_str()); + int result = 0; + if (tokens[k+1] == "+") + result = valA + valB; + else if (tokens[k+1] == "-") + result = valA - valB; + else if (tokens[k+1] == "*") + result = valA * valB; + else if (tokens[k+1] == "/") + result = valA / (valB ? valB : 1); + else if (tokens[k+1] == "%") + result = valA % (valB ? valB : 1); + else if (tokens[k+1] == "<") + result = valA < valB; + else if (tokens[k+1] == "<=") + result = valA <= valB; + else if (tokens[k+1] == ">") + result = valA > valB; + else if (tokens[k+1] == ">=") + result = valA >= valB; + else if (tokens[k+1] == "==") + result = valA == valB; + else if (tokens[k+1] == "!=") + result = valA != valB; + else if (tokens[k+1] == "||") + result = valA || valB; + else if (tokens[k+1] == "&&") + result = valA && valB; + char sResult[30]; + sprintf(sResult, "%d", result); + std::vector<std::string>::iterator itInsert = + tokens.erase(tokens.begin() + k, tokens.begin() + k + 3); + tokens.insert(itInsert, sResult); + } else { + k++; + } + } + } +} + +bool LexerCPP::EvaluateExpression(const std::string &expr, const std::map<std::string, std::string> &preprocessorDefinitions) { + // Break into tokens, replacing with definitions + std::string word; + std::vector<std::string> tokens; + const char *cp = expr.c_str(); + for (;;) { + if (setWord.Contains(*cp)) { + word += *cp; + } else { + std::map<std::string, std::string>::const_iterator it = preprocessorDefinitions.find(word); + if (it != preprocessorDefinitions.end()) { + tokens.push_back(it->second); + } else if (!word.empty() && ((word[0] >= '0' && word[0] <= '9') || (word == "defined"))) { + tokens.push_back(word); + } + word = ""; + if (!*cp) { + break; + } + if ((*cp != ' ') && (*cp != '\t')) { + std::string op(cp, 1); + if (setRelOp.Contains(*cp)) { + if (setRelOp.Contains(cp[1])) { + op += cp[1]; + cp++; + } + } else if (setLogicalOp.Contains(*cp)) { + if (setLogicalOp.Contains(cp[1])) { + op += cp[1]; + cp++; + } + } + tokens.push_back(op); + } + } + cp++; + } + + EvaluateTokens(tokens); + + // "0" or "" -> false else true + bool isFalse = tokens.empty() || + ((tokens.size() == 1) && ((tokens[0] == "") || tokens[0] == "0")); + return !isFalse; +} + +LexerModule lmCPP(SCLEX_CPP, LexerCPP::LexerFactoryCPP, "cpp", cppWordLists); +LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, LexerCPP::LexerFactoryCPPInsensitive, "cppnocase", cppWordLists); diff --git a/src/stc/scintilla/src/LexCSS.cxx b/src/stc/scintilla/lexers/LexCSS.cxx similarity index 61% rename from src/stc/scintilla/src/LexCSS.cxx rename to src/stc/scintilla/lexers/LexCSS.cxx index 3b139cdcdd..036bb2e0ab 100644 --- a/src/stc/scintilla/src/LexCSS.cxx +++ b/src/stc/scintilla/lexers/LexCSS.cxx @@ -3,24 +3,33 @@ ** Lexer for Cascading Style Sheets ** Written by Jakub Vrána ** Improved by Philippe Lhoste (CSS2) + ** Improved by Ross McKay (SCSS mode; see http://sass-lang.com/ ) **/ // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. +// TODO: handle SCSS nested properties like font: { weight: bold; size: 1em; } +// TODO: handle SCSS interpolation: #{} +// TODO: add features for Less if somebody feels like contributing; http://lesscss.org/ +// TODO: refactor this monster so that the next poor slob can read it! + #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -48,6 +57,22 @@ inline bool IsCssOperator(const int ch) { return false; } +// look behind (from start of document to our start position) to determine current nesting level +inline int NestingLevelLookBehind(unsigned int startPos, Accessor &styler) { + int ch; + int nestingLevel = 0; + + for (unsigned int i = 0; i < startPos; i++) { + ch = styler.SafeGetCharAt(i); + if (ch == '{') + nestingLevel++; + else if (ch == '}') + nestingLevel--; + } + + return nestingLevel; +} + static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) { WordList &css1Props = *keywordlists[0]; WordList &pseudoClasses = *keywordlists[1]; @@ -62,11 +87,47 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo int lastState = -1; // before operator int lastStateC = -1; // before comment + int lastStateS = -1; // before single-quoted/double-quoted string + int lastStateVar = -1; // before variable (SCSS) + int lastStateVal = -1; // before value (SCSS) int op = ' '; // last operator int opPrev = ' '; // last operator + bool insideParentheses = false; // true if currently in a CSS url() or similar construct + + // property lexer.css.scss.language + // Set to 1 for Sassy CSS (.scss) + bool isScssDocument = styler.GetPropertyInt("lexer.css.scss.language") != 0; + + // property lexer.css.less.language + // Set to 1 for Less CSS (.less) + bool isLessDocument = styler.GetPropertyInt("lexer.css.less.language") != 0; + + // property lexer.css.hss.language + // Set to 1 for HSS (.hss) + bool isHssDocument = styler.GetPropertyInt("lexer.css.hss.language") != 0; + + // SCSS/LESS/HSS have the concept of variable + bool hasVariables = isScssDocument || isLessDocument || isHssDocument; + char varPrefix = 0; + if (hasVariables) + varPrefix = isLessDocument ? '@' : '$'; + + // SCSS/LESS/HSS support single-line comments + typedef enum _CommentModes { eCommentBlock = 0, eCommentLine = 1} CommentMode; + CommentMode comment_mode = eCommentBlock; + bool hasSingleLineComments = isScssDocument || isLessDocument || isHssDocument; + + // must keep track of nesting level in document types that support it (SCSS/LESS/HSS) + bool hasNesting = false; + int nestingLevel = 0; + if (isScssDocument || isLessDocument || isHssDocument) { + hasNesting = true; + nestingLevel = NestingLevelLookBehind(startPos, styler); + } + // "the loop" for (; sc.More(); sc.Forward()) { - if (sc.state == SCE_CSS_COMMENT && sc.Match('*', '/')) { + if (sc.state == SCE_CSS_COMMENT && ((comment_mode == eCommentBlock && sc.Match('*', '/')) || (comment_mode == eCommentLine && sc.atLineEnd))) { if (lastStateC == -1) { // backtrack to get last state: // comments are like whitespace, so we must return to the previous state @@ -90,8 +151,12 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo if (i == 0) lastStateC = SCE_CSS_DEFAULT; } - sc.Forward(); - sc.ForwardSetState(lastStateC); + if (comment_mode == eCommentBlock) { + sc.Forward(); + sc.ForwardSetState(lastStateC); + } else /* eCommentLine */ { + sc.SetState(lastStateC); + } } if (sc.state == SCE_CSS_COMMENT) @@ -105,7 +170,7 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo i--; if ((sc.currentPos - i) % 2 == 1) continue; - sc.ForwardSetState(SCE_CSS_VALUE); + sc.ForwardSetState(lastStateS); } if (sc.state == SCE_CSS_OPERATOR) { @@ -121,7 +186,7 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo } switch (op) { case '@': - if (lastState == SCE_CSS_DEFAULT) + if (lastState == SCE_CSS_DEFAULT || hasNesting) sc.SetState(SCE_CSS_DIRECTIVE); break; case '>': @@ -140,15 +205,33 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo sc.SetState(SCE_CSS_TAG); break; case '{': - if (lastState == SCE_CSS_DIRECTIVE) + nestingLevel++; + switch (lastState) { + case SCE_CSS_MEDIA: sc.SetState(SCE_CSS_DEFAULT); - else if (lastState == SCE_CSS_TAG) + break; + case SCE_CSS_TAG: + case SCE_CSS_DIRECTIVE: sc.SetState(SCE_CSS_IDENTIFIER); + break; + } break; case '}': - if (lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT || - lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || lastState == SCE_CSS_IDENTIFIER3) - sc.SetState(SCE_CSS_DEFAULT); + if (--nestingLevel < 0) + nestingLevel = 0; + switch (lastState) { + case SCE_CSS_DEFAULT: + case SCE_CSS_VALUE: + case SCE_CSS_IMPORTANT: + case SCE_CSS_IDENTIFIER: + case SCE_CSS_IDENTIFIER2: + case SCE_CSS_IDENTIFIER3: + if (hasNesting) + sc.SetState(nestingLevel > 0 ? SCE_CSS_IDENTIFIER : SCE_CSS_DEFAULT); + else + sc.SetState(SCE_CSS_DEFAULT); + break; + } break; case '(': if (lastState == SCE_CSS_PSEUDOCLASS) @@ -163,14 +246,28 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo sc.SetState(SCE_CSS_TAG); break; case ':': - if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || - lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_EXTENDED_PSEUDOCLASS || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS || - lastState == SCE_CSS_PSEUDOELEMENT || lastState == SCE_CSS_EXTENDED_PSEUDOELEMENT) + switch (lastState) { + case SCE_CSS_TAG: + case SCE_CSS_DEFAULT: + case SCE_CSS_CLASS: + case SCE_CSS_ID: + case SCE_CSS_PSEUDOCLASS: + case SCE_CSS_EXTENDED_PSEUDOCLASS: + case SCE_CSS_UNKNOWN_PSEUDOCLASS: + case SCE_CSS_PSEUDOELEMENT: + case SCE_CSS_EXTENDED_PSEUDOELEMENT: sc.SetState(SCE_CSS_PSEUDOCLASS); - else if (lastState == SCE_CSS_IDENTIFIER || lastState == SCE_CSS_IDENTIFIER2 || - lastState == SCE_CSS_IDENTIFIER3 || lastState == SCE_CSS_EXTENDED_IDENTIFIER || - lastState == SCE_CSS_UNKNOWN_IDENTIFIER) + break; + case SCE_CSS_IDENTIFIER: + case SCE_CSS_IDENTIFIER2: + case SCE_CSS_IDENTIFIER3: + case SCE_CSS_EXTENDED_IDENTIFIER: + case SCE_CSS_UNKNOWN_IDENTIFIER: + case SCE_CSS_VARIABLE: sc.SetState(SCE_CSS_VALUE); + lastStateVal = lastState; + break; + } break; case '.': if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT || lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || @@ -189,10 +286,40 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo sc.SetState(SCE_CSS_DEFAULT); break; case ';': - if (lastState == SCE_CSS_DIRECTIVE) - sc.SetState(SCE_CSS_DEFAULT); - else if (lastState == SCE_CSS_VALUE || lastState == SCE_CSS_IMPORTANT) - sc.SetState(SCE_CSS_IDENTIFIER); + switch (lastState) { + case SCE_CSS_DIRECTIVE: + if (hasNesting) { + sc.SetState(nestingLevel > 0 ? SCE_CSS_IDENTIFIER : SCE_CSS_DEFAULT); + } else { + sc.SetState(SCE_CSS_DEFAULT); + } + break; + case SCE_CSS_VALUE: + case SCE_CSS_IMPORTANT: + // data URLs can have semicolons; simplistically check for wrapping parentheses and move along + if (insideParentheses) { + sc.SetState(lastState); + } else { + if (lastStateVal == SCE_CSS_VARIABLE) { + sc.SetState(SCE_CSS_DEFAULT); + } else { + sc.SetState(SCE_CSS_IDENTIFIER); + } + } + break; + case SCE_CSS_VARIABLE: + if (lastStateVar == SCE_CSS_VALUE) { + // data URLs can have semicolons; simplistically check for wrapping parentheses and move along + if (insideParentheses) { + sc.SetState(SCE_CSS_VALUE); + } else { + sc.SetState(SCE_CSS_IDENTIFIER); + } + } else { + sc.SetState(SCE_CSS_DEFAULT); + } + break; + } break; case '!': if (lastState == SCE_CSS_VALUE) @@ -201,14 +328,77 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo } } - if (IsAWordChar(sc.ch)) { - if (sc.state == SCE_CSS_DEFAULT) - sc.SetState(SCE_CSS_TAG); + if (sc.ch == '*' && sc.state == SCE_CSS_DEFAULT) { + sc.SetState(SCE_CSS_TAG); continue; } - if (sc.ch == '*' && sc.state == SCE_CSS_DEFAULT) { - sc.SetState(SCE_CSS_TAG); + // check for inside parentheses (whether part of an "operator" or not) + if (sc.ch == '(') + insideParentheses = true; + else if (sc.ch == ')') + insideParentheses = false; + + // SCSS special modes + if (hasVariables) { + // variable name + if (sc.ch == varPrefix) { + switch (sc.state) { + case SCE_CSS_DEFAULT: + if (isLessDocument) // give priority to pseudo elements + break; + case SCE_CSS_VALUE: + lastStateVar = sc.state; + sc.SetState(SCE_CSS_VARIABLE); + continue; + } + } + if (sc.state == SCE_CSS_VARIABLE) { + if (IsAWordChar(sc.ch)) { + // still looking at the variable name + continue; + } + if (lastStateVar == SCE_CSS_VALUE) { + // not looking at the variable name any more, and it was part of a value + sc.SetState(SCE_CSS_VALUE); + } + } + + // nested rule parent selector + if (sc.ch == '&') { + switch (sc.state) { + case SCE_CSS_DEFAULT: + case SCE_CSS_IDENTIFIER: + sc.SetState(SCE_CSS_TAG); + continue; + } + } + } + + // nesting rules that apply to SCSS and Less + if (hasNesting) { + // check for nested rule selector + if (sc.state == SCE_CSS_IDENTIFIER && (IsAWordChar(sc.ch) || sc.ch == ':' || sc.ch == '.' || sc.ch == '#')) { + // look ahead to see whether { comes before next ; and } + unsigned int endPos = startPos + length; + int ch; + + for (unsigned int i = sc.currentPos; i < endPos; i++) { + ch = styler.SafeGetCharAt(i); + if (ch == ';' || ch == '}') + break; + if (ch == '{') { + sc.SetState(SCE_CSS_DEFAULT); + continue; + } + } + } + + } + + if (IsAWordChar(sc.ch)) { + if (sc.state == SCE_CSS_DEFAULT) + sc.SetState(SCE_CSS_TAG); continue; } @@ -219,7 +409,8 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo sc.state == SCE_CSS_PSEUDOCLASS || sc.state == SCE_CSS_PSEUDOELEMENT || sc.state == SCE_CSS_EXTENDED_PSEUDOCLASS || sc.state == SCE_CSS_EXTENDED_PSEUDOELEMENT || sc.state == SCE_CSS_UNKNOWN_PSEUDOCLASS || - sc.state == SCE_CSS_IMPORTANT + sc.state == SCE_CSS_IMPORTANT || + sc.state == SCE_CSS_DIRECTIVE )) { char s[100]; sc.GetCurrentLowered(s, sizeof(s)); @@ -263,6 +454,10 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo if (strcmp(s2, "important") != 0) sc.ChangeState(SCE_CSS_VALUE); break; + case SCE_CSS_DIRECTIVE: + if (op == '@' && strcmp(s2, "media") == 0) + sc.ChangeState(SCE_CSS_MEDIA); + break; } } @@ -278,14 +473,23 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo if (sc.Match('/', '*')) { lastStateC = sc.state; + comment_mode = eCommentBlock; + sc.SetState(SCE_CSS_COMMENT); + sc.Forward(); + } else if (hasSingleLineComments && sc.Match('/', '/') && !insideParentheses) { + // note that we've had to treat ([...]// as the start of a URL not a comment, e.g. url(http://example.com), url(//example.com) + lastStateC = sc.state; + comment_mode = eCommentLine; sc.SetState(SCE_CSS_COMMENT); sc.Forward(); - } else if (sc.state == SCE_CSS_VALUE && (sc.ch == '\"' || sc.ch == '\'')) { + } else if ((sc.state == SCE_CSS_VALUE || sc.state == SCE_CSS_ATTRIBUTE) + && (sc.ch == '\"' || sc.ch == '\'')) { + lastStateS = sc.state; sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING)); } else if (IsCssOperator(sc.ch) && (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']') && (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!') - && (sc.state != SCE_CSS_DIRECTIVE || sc.ch == ';' || sc.ch == '{') + && ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_MEDIA) || sc.ch == ';' || sc.ch == '{') ) { if (sc.state != SCE_CSS_OPERATOR) lastState = sc.state; diff --git a/src/stc/scintilla/src/LexCaml.cxx b/src/stc/scintilla/lexers/LexCaml.cxx similarity index 97% rename from src/stc/scintilla/src/LexCaml.cxx rename to src/stc/scintilla/lexers/LexCaml.cxx index 0d11622593..f576e3e234 100644 --- a/src/stc/scintilla/src/LexCaml.cxx +++ b/src/stc/scintilla/lexers/LexCaml.cxx @@ -20,19 +20,22 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" #include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" // Since the Microsoft __iscsym[f] funcs are not ANSI... inline int iscaml(int c) {return isalnum(c) || c == '_';} @@ -51,9 +54,13 @@ using namespace Scintilla; /* (actually seems to work!) */ +#include <string> #include "WindowAccessor.h" #include "ExternalLexer.h" +#undef EXT_LEXER_DECL +#define EXT_LEXER_DECL __declspec( dllexport ) __stdcall + #if PLAT_WIN #include <windows.h> #endif @@ -430,13 +437,11 @@ void ColouriseCamlDoc( static #endif /* BUILD_AS_EXTERNAL_LEXER */ void FoldCamlDoc( - unsigned int startPos, int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) + unsigned int, int, + int, + WordList *[], + Accessor &) { - // below useless evaluation(s) to supress "not used" warnings - startPos || length || initStyle || keywordlists[0] || styler.Length(); } static const char * const camlWordListDesc[] = { diff --git a/src/stc/scintilla/src/LexCmake.cxx b/src/stc/scintilla/lexers/LexCmake.cxx similarity index 98% rename from src/stc/scintilla/src/LexCmake.cxx rename to src/stc/scintilla/lexers/LexCmake.cxx index 1f51f474e8..70e9dee984 100644 --- a/src/stc/scintilla/src/LexCmake.cxx +++ b/src/stc/scintilla/lexers/LexCmake.cxx @@ -5,21 +5,25 @@ // Copyright 2007 by Cristian Adam <cristian [dot] adam [at] gmx [dot] net> // based on the NSIS lexer // The License.txt file describes the conditions under which this software may be distributed. + #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "CharClassify.h" -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif diff --git a/src/stc/scintilla/lexers/LexCoffeeScript.cxx b/src/stc/scintilla/lexers/LexCoffeeScript.cxx new file mode 100644 index 0000000000..96d5d2d96f --- /dev/null +++ b/src/stc/scintilla/lexers/LexCoffeeScript.cxx @@ -0,0 +1,571 @@ +// Scintilla source code edit control +/** @file LexCoffeeScript.cxx + ** Lexer for CoffeeScript. + **/ +// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org> +// Based on the Scintilla C++ Lexer +// Written by Eric Promislow <ericp@activestate.com> in 2011 for the Komodo IDE +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static bool IsSpaceEquiv(int state) { + return (state <= SCE_C_COMMENTDOC + // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE + || state == SCE_C_COMMENTLINEDOC + || state == SCE_C_COMMENTDOCKEYWORD + || state == SCE_C_COMMENTDOCKEYWORDERROR + || state == SCE_COFFEESCRIPT_COMMENTBLOCK + || state == SCE_COFFEESCRIPT_VERBOSE_REGEX + || state == SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT + || state == SCE_C_WORD + || state == SCE_C_REGEX); +} + +// Preconditions: sc.currentPos points to a character after '+' or '-'. +// The test for pos reaching 0 should be redundant, +// and is in only for safety measures. +// Limitation: this code will give the incorrect answer for code like +// a = b+++/ptn/... +// Putting a space between the '++' post-inc operator and the '+' binary op +// fixes this, and is highly recommended for readability anyway. +static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) { + int pos = (int) sc.currentPos; + while (--pos > 0) { + char ch = styler[pos]; + if (ch == '+' || ch == '-') { + return styler[pos - 1] == ch; + } + } + return false; +} + +static bool followsReturnKeyword(StyleContext &sc, Accessor &styler) { + // Don't look at styles, so no need to flush. + int pos = (int) sc.currentPos; + int currentLine = styler.GetLine(pos); + int lineStartPos = styler.LineStart(currentLine); + char ch; + while (--pos > lineStartPos) { + ch = styler.SafeGetCharAt(pos); + if (ch != ' ' && ch != '\t') { + break; + } + } + const char *retBack = "nruter"; + const char *s = retBack; + while (*s + && pos >= lineStartPos + && styler.SafeGetCharAt(pos) == *s) { + s++; + pos--; + } + return !*s; +} + +static void ColouriseCoffeeScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + + // property styling.within.preprocessor + // For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default) + // or only from the initial # to the end of the command word(1). + bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; + + CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); + CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); + + CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + + // property lexer.cpp.allow.dollars + // Set to 0 to disallow the '$' character in identifiers with the cpp lexer. + if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) { + setWordStart.Add('$'); + setWord.Add('$'); + } + + int chPrevNonWhite = ' '; + int visibleChars = 0; + bool lastWordWasUUID = false; + int styleBeforeDCKeyword = SCE_C_DEFAULT; + bool continuationLine = false; + bool isIncludePreprocessor = false; + + if (initStyle == SCE_C_PREPROCESSOR) { + // Set continuationLine if last character of previous line is '\' + int lineCurrent = styler.GetLine(startPos); + if (lineCurrent > 0) { + int chBack = styler.SafeGetCharAt(startPos-1, 0); + int chBack2 = styler.SafeGetCharAt(startPos-2, 0); + int lineEndChar = '!'; + if (chBack2 == '\r' && chBack == '\n') { + lineEndChar = styler.SafeGetCharAt(startPos-3, 0); + } else if (chBack == '\n' || chBack == '\r') { + lineEndChar = chBack2; + } + continuationLine = lineEndChar == '\\'; + } + } + + // look back to set chPrevNonWhite properly for better regex colouring + int endPos = startPos + length; + if (startPos > 0) { + unsigned int back = startPos; + styler.Flush(); + while (back > 0 && IsSpaceEquiv(styler.StyleAt(--back))) + ; + if (styler.StyleAt(back) == SCE_C_OPERATOR) { + chPrevNonWhite = styler.SafeGetCharAt(back); + } + if (startPos != back) { + initStyle = styler.StyleAt(back); + } + startPos = back; + } + + StyleContext sc(startPos, endPos - startPos, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + // Reset states to begining of colourise so no surprises + // if different sets of lines lexed. + visibleChars = 0; + lastWordWasUUID = false; + isIncludePreprocessor = false; + } + + // Handle line continuation generically. + if (sc.ch == '\\') { + if (sc.chNext == '\n' || sc.chNext == '\r') { + sc.Forward(); + if (sc.ch == '\r' && sc.chNext == '\n') { + sc.Forward(); + } + continuationLine = true; + continue; + } + } + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_C_OPERATOR: + sc.SetState(SCE_C_DEFAULT); + break; + case SCE_C_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (!setWord.Contains(sc.ch)) { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_IDENTIFIER: + if (!setWord.Contains(sc.ch) || (sc.ch == '.') || (sc.ch == '$')) { + char s[1000]; + sc.GetCurrent(s, sizeof(s)); + if (keywords.InList(s)) { + lastWordWasUUID = strcmp(s, "uuid") == 0; + sc.ChangeState(SCE_C_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_C_WORD2); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_C_GLOBALCLASS); + } + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_PREPROCESSOR: + if (sc.atLineStart && !continuationLine) { + sc.SetState(SCE_C_DEFAULT); + } else if (stylingWithinPreprocessor) { + if (IsASpace(sc.ch)) { + sc.SetState(SCE_C_DEFAULT); + } + } else { + if (sc.Match('/', '*') || sc.Match('/', '/')) { + sc.SetState(SCE_C_DEFAULT); + } + } + break; + case SCE_C_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD); + } + } + break; + case SCE_C_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_COMMENTLINEDOC: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; + sc.SetState(SCE_C_COMMENTDOCKEYWORD); + } + } + break; + case SCE_C_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (!setDoxygen.Contains(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { + sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_C_STRING: + if (isIncludePreprocessor) { + if (sc.ch == '>') { + sc.ForwardSetState(SCE_C_DEFAULT); + isIncludePreprocessor = false; + } + } else if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_CHARACTER: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\'') { + sc.ForwardSetState(SCE_C_DEFAULT); + } + break; + case SCE_C_REGEX: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '/') { + sc.Forward(); + while ((sc.ch < 0x80) && islower(sc.ch)) + sc.Forward(); // gobble regex flags + sc.SetState(SCE_C_DEFAULT); + } else if (sc.ch == '\\') { + // Gobble up the quoted character + if (sc.chNext == '\\' || sc.chNext == '/') { + sc.Forward(); + } + } + break; + case SCE_C_STRINGEOL: + if (sc.atLineStart) { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_C_VERBATIM: + if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_C_DEFAULT); + } + } + break; + case SCE_C_UUID: + if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { + sc.SetState(SCE_C_DEFAULT); + } + break; + case SCE_COFFEESCRIPT_COMMENTBLOCK: + if (sc.Match("###")) { + sc.ChangeState(SCE_C_COMMENT); + sc.Forward(); + sc.Forward(); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(); + } + break; + case SCE_COFFEESCRIPT_VERBOSE_REGEX: + if (sc.Match("///")) { + sc.Forward(); + sc.Forward(); + sc.ChangeState(SCE_C_REGEX); + sc.ForwardSetState(SCE_C_DEFAULT); + } else if (sc.Match('#')) { + sc.ChangeState(SCE_C_REGEX); + sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT); + } else if (sc.ch == '\\') { + sc.Forward(); + } + break; + case SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT: + if (sc.atLineStart) { + sc.ChangeState(SCE_C_COMMENT); + sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX); + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_C_DEFAULT) { + if (sc.Match('@', '\"')) { + sc.SetState(SCE_C_VERBATIM); + sc.Forward(); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_NUMBER); + } + } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@') || (sc.ch == '$')) { + if (lastWordWasUUID) { + sc.SetState(SCE_C_UUID); + lastWordWasUUID = false; + } else { + sc.SetState(SCE_C_IDENTIFIER); + } + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style + sc.SetState(SCE_C_COMMENTDOC); + } else { + sc.SetState(SCE_C_COMMENT); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match("///")) { + sc.SetState(SCE_COFFEESCRIPT_VERBOSE_REGEX); + } else if (sc.ch == '/' + && (setOKBeforeRE.Contains(chPrevNonWhite) + || followsReturnKeyword(sc, styler)) + && (!setCouldBePostOp.Contains(chPrevNonWhite) + || !FollowsPostfixOperator(sc, styler))) { + sc.SetState(SCE_C_REGEX); // JavaScript's RegEx + } else if (sc.ch == '\"') { + sc.SetState(SCE_C_STRING); + isIncludePreprocessor = false; // ensure that '>' won't end the string + } else if (isIncludePreprocessor && sc.ch == '<') { + sc.SetState(SCE_C_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_C_CHARACTER); + } else if (sc.ch == '#') { + if (sc.Match("###")) { + sc.SetState(SCE_COFFEESCRIPT_COMMENTBLOCK); + } else { + sc.SetState(SCE_C_COMMENTLINE); + } + } else if (isoperator(static_cast<char>(sc.ch))) { + sc.SetState(SCE_C_OPERATOR); + } + } + + if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) { + chPrevNonWhite = sc.ch; + visibleChars++; + } + continuationLine = false; + } + // Change temporary coffeescript states into standard C ones. + switch (sc.state) { + case SCE_COFFEESCRIPT_COMMENTBLOCK: + sc.ChangeState(SCE_C_COMMENT); + break; + case SCE_COFFEESCRIPT_VERBOSE_REGEX: + sc.ChangeState(SCE_C_REGEX); + break; + case SCE_COFFEESCRIPT_VERBOSE_REGEX_COMMENT: + sc.ChangeState(SCE_C_COMMENTLINE); + break; + } + sc.Complete(); +} + +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + if (ch == '#') + return true; + else if (ch == '/' + && i < eol_pos - 1 + && styler[i + 1] == '*') + return true; + else if (ch != ' ' && ch != '\t') + return false; + } + return false; +} + +static void FoldCoffeeScriptDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) { + // A simplified version of FoldPyDoc + const int maxPos = startPos + length; + const int maxLines = styler.GetLine(maxPos - 1); // Requested last line + const int docLines = styler.GetLine(styler.Length() - 1); // Available last line + + // property fold.coffeescript.comment + const bool foldComment = styler.GetPropertyInt("fold.coffeescript.comment") != 0; + + const bool foldCompact = styler.GetPropertyInt("fold.compact") != 0; + + // Backtrack to previous non-blank line so we can determine indent level + // for any white space lines + // and so we can fix any preceding fold level (which is why we go back + // at least one line in all cases) + int spaceFlags = 0; + int lineCurrent = styler.GetLine(startPos); + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + while (lineCurrent > 0) { + lineCurrent--; + indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG) + && !IsCommentLine(lineCurrent, styler)) + break; + } + int indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + + // Set up initial loop state + int prevComment = 0; + if (lineCurrent >= 1) + prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); + + // Process all characters to end of requested range + // or comment that hangs over the end of the range. Cap processing in all cases + // to end of document (in case of comment at end). + while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevComment)) { + + // Gather info + int lev = indentCurrent; + int lineNext = lineCurrent + 1; + int indentNext = indentCurrent; + if (lineNext <= docLines) { + // Information about next line is only available if not at end of document + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + } + const int comment = foldComment && IsCommentLine(lineCurrent, styler); + const int comment_start = (comment && !prevComment && (lineNext <= docLines) && + IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE)); + const int comment_continue = (comment && prevComment); + if (!comment) + indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; + if (indentNext & SC_FOLDLEVELWHITEFLAG) + indentNext = SC_FOLDLEVELWHITEFLAG | indentCurrentLevel; + + if (comment_start) { + // Place fold point at start of a block of comments + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (comment_continue) { + // Add level to rest of lines in the block + lev = lev + 1; + } + + // Skip past any blank lines for next indent level info; we skip also + // comments (all comments, not just those starting in column 0) + // which effectively folds them into surrounding code rather + // than screwing up folding. + + while ((lineNext < docLines) && + ((indentNext & SC_FOLDLEVELWHITEFLAG) || + (lineNext <= docLines && IsCommentLine(lineNext, styler)))) { + + lineNext++; + indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); + } + + const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; + const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments); + + // Now set all the indent levels on the lines we skipped + // Do this from end to start. Once we encounter one line + // which is indented more than the line after the end of + // the comment-block, use the level of the block before + + int skipLine = lineNext; + int skipLevel = levelAfterComments; + + while (--skipLine > lineCurrent) { + int skipLineIndent = styler.IndentAmount(skipLine, &spaceFlags, NULL); + + if (foldCompact) { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments) + skipLevel = levelBeforeComments; + + int whiteFlag = skipLineIndent & SC_FOLDLEVELWHITEFLAG; + + styler.SetLevel(skipLine, skipLevel | whiteFlag); + } else { + if ((skipLineIndent & SC_FOLDLEVELNUMBERMASK) > levelAfterComments && + !(skipLineIndent & SC_FOLDLEVELWHITEFLAG) && + !IsCommentLine(skipLine, styler)) + skipLevel = levelBeforeComments; + + styler.SetLevel(skipLine, skipLevel); + } + } + + // Set fold header on non-comment line + if (!comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) + lev |= SC_FOLDLEVELHEADERFLAG; + } + + // Keep track of block comment state of previous line + prevComment = comment_start || comment_continue; + + // Set fold level for this line and move to next line + styler.SetLevel(lineCurrent, lev); + indentCurrent = indentNext; + lineCurrent = lineNext; + } +} + +static const char *const csWordLists[] = { + "Keywords", + 0, +}; + +LexerModule lmCoffeeScript(SCLEX_COFFEESCRIPT, ColouriseCoffeeScriptDoc, "coffeescript", FoldCoffeeScriptDoc, csWordLists); diff --git a/src/stc/scintilla/src/LexConf.cxx b/src/stc/scintilla/lexers/LexConf.cxx similarity index 88% rename from src/stc/scintilla/src/LexConf.cxx rename to src/stc/scintilla/lexers/LexConf.cxx index 969275f925..23ed5a6c83 100644 --- a/src/stc/scintilla/src/LexConf.cxx +++ b/src/stc/scintilla/lexers/LexConf.cxx @@ -2,7 +2,7 @@ /** @file LexConf.cxx ** Lexer for Apache Configuration Files. ** - ** First working version contributed by Ahmad Zawawi <zeus_go64@hotmail.com> on October 28, 2000. + ** First working version contributed by Ahmad Zawawi <ahmad.zawawi@gmail.com> on October 28, 2000. ** i created this lexer because i needed something pretty when dealing ** when Apache Configuration files... **/ @@ -11,18 +11,22 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -70,17 +74,17 @@ static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *k } else if( ch == '"') { state = SCE_CONF_STRING; styler.ColourTo(i,SCE_CONF_STRING); - } else if( ispunct(ch) ) { + } else if( isascii(ch) && ispunct(ch) ) { // signals an operator... // no state jump necessary for this // simple case... styler.ColourTo(i,SCE_CONF_OPERATOR); - } else if( isalpha(ch) ) { + } else if( isascii(ch) && isalpha(ch) ) { // signals the start of an identifier bufferCount = 0; buffer[bufferCount++] = static_cast<char>(tolower(ch)); state = SCE_CONF_IDENTIFIER; - } else if( isdigit(ch) ) { + } else if( isascii(ch) && isdigit(ch) ) { // signals the start of a number bufferCount = 0; buffer[bufferCount++] = ch; @@ -107,7 +111,7 @@ static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *k // if we find a non-alphanumeric char, // we simply go to default state // else we're still dealing with an extension... - if( isalnum(ch) || (ch == '_') || + if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '$') || (ch == '/') || (ch == '.') || (ch == '*') ) { @@ -129,7 +133,7 @@ static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *k case SCE_CONF_IDENTIFIER: // stay in CONF_IDENTIFIER state until we find a non-alphanumeric - if( isalnum(ch) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) { + if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '*')) { buffer[bufferCount++] = static_cast<char>(tolower(ch)); } else { state = SCE_CONF_DEFAULT; @@ -154,7 +158,7 @@ static void ColouriseConfDoc(unsigned int startPos, int length, int, WordList *k case SCE_CONF_NUMBER: // stay in CONF_NUMBER state until we find a non-numeric - if( isdigit(ch) || ch == '.') { + if( (isascii(ch) && isdigit(ch)) || ch == '.') { buffer[bufferCount++] = ch; } else { state = SCE_CONF_DEFAULT; diff --git a/src/stc/scintilla/src/LexCrontab.cxx b/src/stc/scintilla/lexers/LexCrontab.cxx similarity index 94% rename from src/stc/scintilla/src/LexCrontab.cxx rename to src/stc/scintilla/lexers/LexCrontab.cxx index 62044c3709..08abc71917 100644 --- a/src/stc/scintilla/src/LexCrontab.cxx +++ b/src/stc/scintilla/lexers/LexCrontab.cxx @@ -9,18 +9,22 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -94,12 +98,12 @@ static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordLi // signals an asterisk // no state jump necessary for this simple case... styler.ColourTo(i,SCE_NNCRONTAB_ASTERISK); - } else if( isalpha(ch) || ch == '<' ) { + } else if( (isascii(ch) && isalpha(ch)) || ch == '<' ) { // signals the start of an identifier bufferCount = 0; buffer[bufferCount++] = ch; state = SCE_NNCRONTAB_IDENTIFIER; - } else if( isdigit(ch) ) { + } else if( isascii(ch) && isdigit(ch) ) { // signals the start of a number bufferCount = 0; buffer[bufferCount++] = ch; @@ -167,7 +171,7 @@ static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordLi case SCE_NNCRONTAB_IDENTIFIER: // stay in CONF_IDENTIFIER state until we find a non-alphanumeric - if( isalnum(ch) || (ch == '_') || (ch == '-') || (ch == '/') || + if( (isascii(ch) && isalnum(ch)) || (ch == '_') || (ch == '-') || (ch == '/') || (ch == '$') || (ch == '.') || (ch == '<') || (ch == '>') || (ch == '@') ) { buffer[bufferCount++] = ch; @@ -196,7 +200,7 @@ static void ColouriseNncrontabDoc(unsigned int startPos, int length, int, WordLi case SCE_NNCRONTAB_NUMBER: // stay in CONF_NUMBER state until we find a non-numeric - if( isdigit(ch) /* || ch == '.' */ ) { + if( isascii(ch) && isdigit(ch) /* || ch == '.' */ ) { buffer[bufferCount++] = ch; } else { state = SCE_NNCRONTAB_DEFAULT; diff --git a/src/stc/scintilla/src/LexCsound.cxx b/src/stc/scintilla/lexers/LexCsound.cxx similarity index 96% rename from src/stc/scintilla/src/LexCsound.cxx rename to src/stc/scintilla/lexers/LexCsound.cxx index 4162c9b3aa..8e5880c90f 100644 --- a/src/stc/scintilla/src/LexCsound.cxx +++ b/src/stc/scintilla/lexers/LexCsound.cxx @@ -8,18 +8,22 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> -#include "Platform.h" +#include <assert.h> +#include <ctype.h> -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -35,7 +39,7 @@ static inline bool IsAWordStart(const int ch) { } static inline bool IsCsoundOperator(char ch) { - if (isalnum(ch)) + if (isascii(ch) && isalnum(ch)) return false; // '.' left out as it is used to make up numbers if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || @@ -72,7 +76,7 @@ static void ColouriseCsoundDoc(unsigned int startPos, int length, int initStyle, continue; } } - + // Determine if the current state should terminate. if (sc.state == SCE_CSOUND_OPERATOR) { if (!IsCsoundOperator(static_cast<char>(sc.ch))) { @@ -119,7 +123,7 @@ static void ColouriseCsoundDoc(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_CSOUND_DEFAULT); } } - + // Determine if a new state should be entered. if (sc.state == SCE_CSOUND_DEFAULT) { if (sc.ch == ';'){ @@ -146,7 +150,7 @@ static void ColouriseCsoundDoc(unsigned int startPos, int length, int initStyle, sc.Complete(); } -static void FoldCsoundInstruments(unsigned int startPos, int length, int /* initStyle */, WordList *[], +static void FoldCsoundInstruments(unsigned int startPos, int length, int /* initStyle */, WordList *[], Accessor &styler) { unsigned int lengthDoc = startPos + length; int visibleChars = 0; diff --git a/src/stc/scintilla/src/LexD.cxx b/src/stc/scintilla/lexers/LexD.cxx similarity index 64% rename from src/stc/scintilla/src/LexD.cxx rename to src/stc/scintilla/lexers/LexD.cxx index 4c4bcb343e..32e3c86efb 100644 --- a/src/stc/scintilla/src/LexD.cxx +++ b/src/stc/scintilla/lexers/LexD.cxx @@ -2,25 +2,32 @@ ** Lexer for D. ** ** Copyright (c) 2006 by Waldemar Augustyn <waldemar@wdmsys.com> + ** Converted to lexer object and added further folding features/properties by "Udo Lechner" <dlchnr(at)gmx(dot)net> **/ // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include <string> +#include <map> -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -55,17 +62,187 @@ static bool IsStringSuffix(int ch) { return ch == 'c' || ch == 'w' || ch == 'd'; } +static bool IsStreamCommentStyle(int style) { + return style == SCE_D_COMMENT || + style == SCE_D_COMMENTDOC || + style == SCE_D_COMMENTDOCKEYWORD || + style == SCE_D_COMMENTDOCKEYWORDERROR; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerD +struct OptionsD { + bool fold; + bool foldSyntaxBased; + bool foldComment; + bool foldCommentMultiline; + bool foldCommentExplicit; + std::string foldExplicitStart; + std::string foldExplicitEnd; + bool foldExplicitAnywhere; + bool foldCompact; + int foldAtElseInt; + bool foldAtElse; + OptionsD() { + fold = false; + foldSyntaxBased = true; + foldComment = false; + foldCommentMultiline = true; + foldCommentExplicit = true; + foldExplicitStart = ""; + foldExplicitEnd = ""; + foldExplicitAnywhere = false; + foldCompact = true; + foldAtElseInt = -1; + foldAtElse = false; + } +}; + +static const char * const dWordLists[] = { + "Primary keywords and identifiers", + "Secondary keywords and identifiers", + "Documentation comment keywords", + "Type definitions and aliases", + "Keywords 5", + "Keywords 6", + "Keywords 7", + 0, + }; + +struct OptionSetD : public OptionSet<OptionsD> { + OptionSetD() { + DefineProperty("fold", &OptionsD::fold); + + DefineProperty("fold.d.syntax.based", &OptionsD::foldSyntaxBased, + "Set this property to 0 to disable syntax based folding."); + + DefineProperty("fold.comment", &OptionsD::foldComment); + + DefineProperty("fold.d.comment.multiline", &OptionsD::foldCommentMultiline, + "Set this property to 0 to disable folding multi-line comments when fold.comment=1."); + + DefineProperty("fold.d.comment.explicit", &OptionsD::foldCommentExplicit, + "Set this property to 0 to disable folding explicit fold points when fold.comment=1."); + + DefineProperty("fold.d.explicit.start", &OptionsD::foldExplicitStart, + "The string to use for explicit fold start points, replacing the standard //{."); + + DefineProperty("fold.d.explicit.end", &OptionsD::foldExplicitEnd, + "The string to use for explicit fold end points, replacing the standard //}."); + + DefineProperty("fold.d.explicit.anywhere", &OptionsD::foldExplicitAnywhere, + "Set this property to 1 to enable explicit fold points anywhere, not just in line comments."); -static void ColouriseDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler, bool caseSensitive) { + DefineProperty("fold.compact", &OptionsD::foldCompact); - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; //doxygen - WordList &keywords4 = *keywordlists[3]; - WordList &keywords5 = *keywordlists[4]; - WordList &keywords6 = *keywordlists[5]; - WordList &keywords7 = *keywordlists[6]; + DefineProperty("lexer.d.fold.at.else", &OptionsD::foldAtElseInt, + "This option enables D folding on a \"} else {\" line of an if statement."); + + DefineProperty("fold.at.else", &OptionsD::foldAtElse); + + DefineWordListSets(dWordLists); + } +}; + +class LexerD : public ILexer { + bool caseSensitive; + WordList keywords; + WordList keywords2; + WordList keywords3; + WordList keywords4; + WordList keywords5; + WordList keywords6; + WordList keywords7; + OptionsD options; + OptionSetD osD; +public: + LexerD(bool caseSensitive_) : + caseSensitive(caseSensitive_) { + } + virtual ~LexerD() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osD.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osD.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osD.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osD.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + + static ILexer *LexerFactoryD() { + return new LexerD(true); + } + static ILexer *LexerFactoryDInsensitive() { + return new LexerD(false); + } +}; + +int SCI_METHOD LexerD::PropertySet(const char *key, const char *val) { + if (osD.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerD::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &keywords3; + break; + case 3: + wordListN = &keywords4; + break; + case 4: + wordListN = &keywords5; + break; + case 5: + wordListN = &keywords6; + break; + case 6: + wordListN = &keywords7; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerD::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); int styleBeforeDCKeyword = SCE_D_DEFAULT; @@ -290,24 +467,17 @@ static void ColouriseDoc(unsigned int startPos, int length, int initStyle, sc.Complete(); } -static bool IsStreamCommentStyle(int style) { - return style == SCE_D_COMMENT || - style == SCE_D_COMMENTDOC || - style == SCE_D_COMMENTDOCKEYWORD || - style == SCE_D_COMMENTDOCKEYWORDERROR; -} - // Store both the current line's fold level and the next lines in the // level store to make it easy to pick up with each increment // and to make it possible to fiddle the current level for "} else {". -static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - - // property lexer.d.fold.at.else - // This option enables D folding on a "} else {" line of an if statement. - bool foldAtElse = styler.GetPropertyInt("lexer.d.fold.at.else", - styler.GetPropertyInt("fold.at.else", 0)) != 0; + +void SCI_METHOD LexerD::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + + if (!options.fold) + return; + + LexAccessor styler(pAccess); + unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos); @@ -319,6 +489,8 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor & char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); int style = initStyle; + bool foldAtElse = options.foldAtElseInt >= 0 ? options.foldAtElseInt != 0 : options.foldAtElse; + const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty(); for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); @@ -326,7 +498,7 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor & style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { + if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev)) { levelNext++; } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { @@ -334,7 +506,25 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor & levelNext--; } } - if (style == SCE_D_OPERATOR) { + if (options.foldComment && options.foldCommentExplicit && ((style == SCE_D_COMMENTLINE) || options.foldExplicitAnywhere)) { + if (userDefinedFoldMarkers) { + if (styler.Match(i, options.foldExplicitStart.c_str())) { + levelNext++; + } else if (styler.Match(i, options.foldExplicitEnd.c_str())) { + levelNext--; + } + } else { + if ((ch == '/') && (chNext == '/')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + if (chNext2 == '{') { + levelNext++; + } else if (chNext2 == '}') { + levelNext--; + } + } + } + } + if (options.foldSyntaxBased && (style == SCE_D_OPERATOR)) { if (ch == '{') { // Measure the minimum before a '{' to allow // folding on "} else {" @@ -346,19 +536,19 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor & levelNext--; } } - if (atEOL) { - if (foldComment) { // Handle nested comments + if (atEOL || (i == endPos-1)) { + if (options.foldComment && options.foldCommentMultiline) { // Handle nested comments int nc; nc = styler.GetLineState(lineCurrent); nc -= lineCurrent>0? styler.GetLineState(lineCurrent-1): 0; levelNext += nc; } int levelUse = levelCurrent; - if (foldAtElse) { + if (options.foldSyntaxBased && foldAtElse) { levelUse = levelMinCurrent; } int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) + if (visibleChars == 0 && options.foldCompact) lev |= SC_FOLDLEVELWHITEFLAG; if (levelUse < levelNext) lev |= SC_FOLDLEVELHEADERFLAG; @@ -375,25 +565,4 @@ static void FoldDoc(unsigned int startPos, int length, int initStyle, Accessor & } } -static void FoldDDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - FoldDoc(startPos, length, initStyle, styler); -} - -static const char * const dWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "Documentation comment keywords", - "Type definitions and aliases", - "Keywords 5", - "Keywords 6", - "Keywords 7", - 0, - }; - -static void ColouriseDDoc(unsigned int startPos, int length, - int initStyle, WordList *keywordlists[], Accessor &styler) { - ColouriseDoc(startPos, length, initStyle, keywordlists, styler, true); -} - -LexerModule lmD(SCLEX_D, ColouriseDDoc, "d", FoldDDoc, dWordLists); +LexerModule lmD(SCLEX_D, LexerD::LexerFactoryD, "d", dWordLists); diff --git a/src/stc/scintilla/src/LexCPP.cxx b/src/stc/scintilla/lexers/LexECL.cxx similarity index 52% rename from src/stc/scintilla/src/LexCPP.cxx rename to src/stc/scintilla/lexers/LexECL.cxx index 9577afbdaf..cf15a62a55 100644 --- a/src/stc/scintilla/src/LexCPP.cxx +++ b/src/stc/scintilla/lexers/LexECL.cxx @@ -1,8 +1,8 @@ // Scintilla source code edit control -/** @file LexCPP.cxx - ** Lexer for C++, C, Java, and JavaScript. +/** @file LexECL.cxx + ** Lexer for ECL. **/ -// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. #include <stdlib.h> @@ -10,82 +10,76 @@ #include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> -#include "Platform.h" +#ifdef _MSC_VER +#pragma warning(disable: 4786) +#endif +#ifdef __BORLANDC__ +// Borland C++ displays warnings in vector header without this +#pragma option -w-ccc -w-rch +#endif -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" +#include <string> +#include <vector> +#include <map> +#include <algorithm> + +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" #include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + +#define SET_LOWER "abcdefghijklmnopqrstuvwxyz" +#define SET_UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +#define SET_DIGITS "0123456789" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif static bool IsSpaceEquiv(int state) { - return (state <= SCE_C_COMMENTDOC) || - // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE - (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) || - (state == SCE_C_COMMENTDOCKEYWORDERROR); + return (state <= SCE_ECL_COMMENTDOC) || + // including SCE_ECL_DEFAULT, SCE_ECL_COMMENT, SCE_ECL_COMMENTLINE + (state == SCE_ECL_COMMENTLINEDOC) || (state == SCE_ECL_COMMENTDOCKEYWORD) || + (state == SCE_ECL_COMMENTDOCKEYWORDERROR); } -// Preconditions: sc.currentPos points to a character after '+' or '-'. -// The test for pos reaching 0 should be redundant, -// and is in only for safety measures. -// Limitation: this code will give the incorrect answer for code like -// a = b+++/ptn/... -// Putting a space between the '++' post-inc operator and the '+' binary op -// fixes this, and is highly recommended for readability anyway. -static bool FollowsPostfixOperator(StyleContext &sc, Accessor &styler) { - int pos = (int) sc.currentPos; - while (--pos > 0) { - char ch = styler[pos]; - if (ch == '+' || ch == '-') { - return styler[pos - 1] == ch; - } - } - return false; -} - -static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler, bool caseSensitive) { - - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - - // property styling.within.preprocessor - // For C++ code, determines whether all preprocessor code is styled in the preprocessor style (0, the default) - // or only from the initial # to the end of the command word(1). - bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0; - - CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); - CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); - - CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); - +static void ColouriseEclDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], + Accessor &styler) { + WordList &keywords0 = *keywordlists[0]; + WordList &keywords1 = *keywordlists[1]; + WordList &keywords2 = *keywordlists[2]; + WordList &keywords3 = *keywordlists[3]; //Value Types + WordList &keywords4 = *keywordlists[4]; + WordList &keywords5 = *keywordlists[5]; + WordList &keywords6 = *keywordlists[6]; //Javadoc Tags + WordList cplusplus; + cplusplus.Set("beginc endc"); + + bool stylingWithinPreprocessor = false; + + CharacterSet setOKBeforeRE(CharacterSet::setNone, "(=,"); + CharacterSet setDoxygen(CharacterSet::setLower, "$@\\&<>#{}[]"); CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); - - // property lexer.cpp.allow.dollars - // Set to 0 to disallow the '$' character in identifiers with the cpp lexer. - if (styler.GetPropertyInt("lexer.cpp.allow.dollars", 1) != 0) { - setWordStart.Add('$'); - setWord.Add('$'); - } + CharacterSet setQualified(CharacterSet::setNone, "uUxX"); int chPrevNonWhite = ' '; int visibleChars = 0; bool lastWordWasUUID = false; - int styleBeforeDCKeyword = SCE_C_DEFAULT; + int styleBeforeDCKeyword = SCE_ECL_DEFAULT; bool continuationLine = false; - bool isIncludePreprocessor = false; - if (initStyle == SCE_C_PREPROCESSOR) { + if (initStyle == SCE_ECL_PREPROCESSOR) { // Set continuationLine if last character of previous line is '\' int lineCurrent = styler.GetLine(startPos); if (lineCurrent > 0) { @@ -106,7 +100,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo int back = startPos; while (--back && IsSpaceEquiv(styler.StyleAt(back))) ; - if (styler.StyleAt(back) == SCE_C_OPERATOR) { + if (styler.StyleAt(back) == SCE_ECL_OPERATOR) { chPrevNonWhite = styler.SafeGetCharAt(back); } } @@ -114,18 +108,16 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo StyleContext sc(startPos, length, initStyle, styler); for (; sc.More(); sc.Forward()) { - if (sc.atLineStart) { - if (sc.state == SCE_C_STRING) { - // Prevent SCE_C_STRINGEOL from leaking back to previous line which + if (sc.state == SCE_ECL_STRING) { + // Prevent SCE_ECL_STRINGEOL from leaking back to previous line which // ends with a line continuation by locking in the state upto this position. - sc.SetState(SCE_C_STRING); + sc.SetState(SCE_ECL_STRING); } // Reset states to begining of colourise so no surprises // if different sets of lines lexed. visibleChars = 0; lastWordWasUUID = false; - isIncludePreprocessor = false; } // Handle line continuation generically. @@ -142,134 +134,145 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo // Determine if the current state should terminate. switch (sc.state) { - case SCE_C_OPERATOR: - sc.SetState(SCE_C_DEFAULT); + case SCE_ECL_ADDED: + case SCE_ECL_DELETED: + case SCE_ECL_CHANGED: + case SCE_ECL_MOVED: + if (sc.atLineStart) + sc.SetState(SCE_ECL_DEFAULT); break; - case SCE_C_NUMBER: + case SCE_ECL_OPERATOR: + sc.SetState(SCE_ECL_DEFAULT); + break; + case SCE_ECL_NUMBER: // We accept almost anything because of hex. and number suffixes if (!setWord.Contains(sc.ch)) { - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } break; - case SCE_C_IDENTIFIER: + case SCE_ECL_IDENTIFIER: if (!setWord.Contains(sc.ch) || (sc.ch == '.')) { char s[1000]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (keywords.InList(s)) { + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords0.InList(s)) { lastWordWasUUID = strcmp(s, "uuid") == 0; - sc.ChangeState(SCE_C_WORD); + sc.ChangeState(SCE_ECL_WORD0); + } else if (keywords1.InList(s)) { + sc.ChangeState(SCE_ECL_WORD1); } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_C_WORD2); + sc.ChangeState(SCE_ECL_WORD2); } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_C_GLOBALCLASS); + sc.ChangeState(SCE_ECL_WORD4); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_ECL_WORD5); + } + else //Data types are of from KEYWORD## + { + int i = static_cast<int>(strlen(s)) - 1; + while(i >= 0 && (isdigit(s[i]) || s[i] == '_')) + --i; + + char s2[1000]; + strncpy(s2, s, i + 1); + s2[i + 1] = 0; + if (keywords3.InList(s2)) { + sc.ChangeState(SCE_ECL_WORD3); + } } - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } break; - case SCE_C_PREPROCESSOR: + case SCE_ECL_PREPROCESSOR: if (sc.atLineStart && !continuationLine) { - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } else if (stylingWithinPreprocessor) { if (IsASpace(sc.ch)) { - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } } else { if (sc.Match('/', '*') || sc.Match('/', '/')) { - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } } break; - case SCE_C_COMMENT: + case SCE_ECL_COMMENT: if (sc.Match('*', '/')) { sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); + sc.ForwardSetState(SCE_ECL_DEFAULT); } break; - case SCE_C_COMMENTDOC: + case SCE_ECL_COMMENTDOC: if (sc.Match('*', '/')) { sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); + sc.ForwardSetState(SCE_ECL_DEFAULT); } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support // Verify that we have the conditions to mark a comment-doc-keyword if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_C_COMMENTDOC; - sc.SetState(SCE_C_COMMENTDOCKEYWORD); + styleBeforeDCKeyword = SCE_ECL_COMMENTDOC; + sc.SetState(SCE_ECL_COMMENTDOCKEYWORD); } } break; - case SCE_C_COMMENTLINE: + case SCE_ECL_COMMENTLINE: if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } break; - case SCE_C_COMMENTLINEDOC: + case SCE_ECL_COMMENTLINEDOC: if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support // Verify that we have the conditions to mark a comment-doc-keyword if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC; - sc.SetState(SCE_C_COMMENTDOCKEYWORD); + styleBeforeDCKeyword = SCE_ECL_COMMENTLINEDOC; + sc.SetState(SCE_ECL_COMMENTDOCKEYWORD); } } break; - case SCE_C_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) { - sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + case SCE_ECL_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_ECL_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_ECL_COMMENTDOCKEYWORDERROR); sc.Forward(); - sc.ForwardSetState(SCE_C_DEFAULT); + sc.ForwardSetState(SCE_ECL_DEFAULT); } else if (!setDoxygen.Contains(sc.ch)) { - char s[100]; - if (caseSensitive) { - sc.GetCurrent(s, sizeof(s)); - } else { - sc.GetCurrentLowered(s, sizeof(s)); - } - if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) { - sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR); + char s[1000]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!IsASpace(sc.ch) || !keywords6.InList(s+1)) { + sc.ChangeState(SCE_ECL_COMMENTDOCKEYWORDERROR); } sc.SetState(styleBeforeDCKeyword); } break; - case SCE_C_STRING: + case SCE_ECL_STRING: if (sc.atLineEnd) { - sc.ChangeState(SCE_C_STRINGEOL); - } else if (isIncludePreprocessor) { - if (sc.ch == '>') { - sc.ForwardSetState(SCE_C_DEFAULT); - isIncludePreprocessor = false; - } + sc.ChangeState(SCE_ECL_STRINGEOL); } else if (sc.ch == '\\') { if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { sc.Forward(); } } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_C_DEFAULT); + sc.ForwardSetState(SCE_ECL_DEFAULT); } break; - case SCE_C_CHARACTER: + case SCE_ECL_CHARACTER: if (sc.atLineEnd) { - sc.ChangeState(SCE_C_STRINGEOL); + sc.ChangeState(SCE_ECL_STRINGEOL); } else if (sc.ch == '\\') { if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { sc.Forward(); } } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_C_DEFAULT); + sc.ForwardSetState(SCE_ECL_DEFAULT); } break; - case SCE_C_REGEX: + case SCE_ECL_REGEX: if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } else if (sc.ch == '/') { sc.Forward(); while ((sc.ch < 0x80) && islower(sc.ch)) sc.Forward(); // gobble regex flags - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } else if (sc.ch == '\\') { // Gobble up the quoted character if (sc.chNext == '\\' || sc.chNext == '/') { @@ -277,82 +280,85 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo } } break; - case SCE_C_STRINGEOL: + case SCE_ECL_STRINGEOL: if (sc.atLineStart) { - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } break; - case SCE_C_VERBATIM: + case SCE_ECL_VERBATIM: if (sc.ch == '\"') { if (sc.chNext == '\"') { sc.Forward(); } else { - sc.ForwardSetState(SCE_C_DEFAULT); + sc.ForwardSetState(SCE_ECL_DEFAULT); } } break; - case SCE_C_UUID: + case SCE_ECL_UUID: if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') { - sc.SetState(SCE_C_DEFAULT); + sc.SetState(SCE_ECL_DEFAULT); } + break; } // Determine if a new state should be entered. - if (sc.state == SCE_C_DEFAULT) { - if (sc.Match('@', '\"')) { - sc.SetState(SCE_C_VERBATIM); + int lineCurrent = styler.GetLine(sc.currentPos); + int lineState = styler.GetLineState(lineCurrent); + if (sc.state == SCE_ECL_DEFAULT) { + if (lineState) { + sc.SetState(lineState); + } + else if (sc.Match('@', '\"')) { + sc.SetState(SCE_ECL_VERBATIM); + sc.Forward(); + } else if (setQualified.Contains(sc.ch) && sc.chNext == '\'') { + sc.SetState(SCE_ECL_CHARACTER); sc.Forward(); } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { if (lastWordWasUUID) { - sc.SetState(SCE_C_UUID); + sc.SetState(SCE_ECL_UUID); lastWordWasUUID = false; } else { - sc.SetState(SCE_C_NUMBER); + sc.SetState(SCE_ECL_NUMBER); } } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) { if (lastWordWasUUID) { - sc.SetState(SCE_C_UUID); + sc.SetState(SCE_ECL_UUID); lastWordWasUUID = false; } else { - sc.SetState(SCE_C_IDENTIFIER); + sc.SetState(SCE_ECL_IDENTIFIER); } } else if (sc.Match('/', '*')) { if (sc.Match("/**") || sc.Match("/*!")) { // Support of Qt/Doxygen doc. style - sc.SetState(SCE_C_COMMENTDOC); + sc.SetState(SCE_ECL_COMMENTDOC); } else { - sc.SetState(SCE_C_COMMENT); + sc.SetState(SCE_ECL_COMMENT); } sc.Forward(); // Eat the * so it isn't used for the end of the comment } else if (sc.Match('/', '/')) { if ((sc.Match("///") && !sc.Match("////")) || sc.Match("//!")) // Support of Qt/Doxygen doc. style - sc.SetState(SCE_C_COMMENTLINEDOC); + sc.SetState(SCE_ECL_COMMENTLINEDOC); else - sc.SetState(SCE_C_COMMENTLINE); - } else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite) && - (!setCouldBePostOp.Contains(chPrevNonWhite) || !FollowsPostfixOperator(sc, styler))) { - sc.SetState(SCE_C_REGEX); // JavaScript's RegEx - } else if (sc.ch == '\"') { - sc.SetState(SCE_C_STRING); - isIncludePreprocessor = false; // ensure that '>' won't end the string - } else if (isIncludePreprocessor && sc.ch == '<') { - sc.SetState(SCE_C_STRING); + sc.SetState(SCE_ECL_COMMENTLINE); + } else if (sc.ch == '/' && setOKBeforeRE.Contains(chPrevNonWhite)) { + sc.SetState(SCE_ECL_REGEX); // JavaScript's RegEx +// } else if (sc.ch == '\"') { +// sc.SetState(SCE_ECL_STRING); } else if (sc.ch == '\'') { - sc.SetState(SCE_C_CHARACTER); + sc.SetState(SCE_ECL_CHARACTER); } else if (sc.ch == '#' && visibleChars == 0) { // Preprocessor commands are alone on their line - sc.SetState(SCE_C_PREPROCESSOR); + sc.SetState(SCE_ECL_PREPROCESSOR); // Skip whitespace between # and preprocessor word do { sc.Forward(); } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More()); if (sc.atLineEnd) { - sc.SetState(SCE_C_DEFAULT); - } else if (sc.Match("include")) { - isIncludePreprocessor = true; + sc.SetState(SCE_ECL_DEFAULT); } } else if (isoperator(static_cast<char>(sc.ch))) { - sc.SetState(SCE_C_OPERATOR); + sc.SetState(SCE_ECL_OPERATOR); } } @@ -363,38 +369,39 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo continuationLine = false; } sc.Complete(); + } static bool IsStreamCommentStyle(int style) { - return style == SCE_C_COMMENT || - style == SCE_C_COMMENTDOC || - style == SCE_C_COMMENTDOCKEYWORD || - style == SCE_C_COMMENTDOCKEYWORDERROR; + return style == SCE_ECL_COMMENT || + style == SCE_ECL_COMMENTDOC || + style == SCE_ECL_COMMENTDOCKEYWORD || + style == SCE_ECL_COMMENTDOCKEYWORDERROR; +} + +bool MatchNoCase(Accessor & styler, unsigned int & pos, const char *s) { + int i=0; + for (; *s; i++) { + char compare_char = tolower(*s); + char styler_char = tolower(styler.SafeGetCharAt(pos+i)); + if (compare_char != styler_char) + return false; + s++; + } + pos+=i-1; + return true; } + // Store both the current line's fold level and the next lines in the // level store to make it easy to pick up with each increment // and to make it possible to fiddle the current level for "} else {". -static void FoldCppDoc(unsigned int startPos, int length, int initStyle, +static void FoldEclDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { - - // property fold.comment - // This option enables folding multi-line comments and explicit fold points when using the C++ lexer. - // Explicit fold points allows adding extra folding by placing a //{ comment at the start and a //} - // at the end of a section that should fold. - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - - // property fold.preprocessor - // This option enables folding preprocessor directives when using the C++ lexer. - // Includes C#'s explicit #region and #endregion folding directives. - bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; - - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - - // property fold.at.else - // This option enables C++ folding on a "} else {" line of an if statement. - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; - + bool foldComment = true; + bool foldPreprocessor = true; + bool foldCompact = true; + bool foldAtElse = true; unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos); @@ -414,14 +421,14 @@ static void FoldCppDoc(unsigned int startPos, int length, int initStyle, styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) { + if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_ECL_COMMENTLINEDOC)) { levelNext++; - } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) { + } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_ECL_COMMENTLINEDOC) && !atEOL) { // Comments don't end at end of line and the next character may be unstyled. levelNext--; } } - if (foldComment && (style == SCE_C_COMMENTLINE)) { + if (foldComment && (style == SCE_ECL_COMMENTLINE)) { if ((ch == '/') && (chNext == '/')) { char chNext2 = styler.SafeGetCharAt(i + 2); if (chNext2 == '{') { @@ -431,20 +438,20 @@ static void FoldCppDoc(unsigned int startPos, int length, int initStyle, } } } - if (foldPreprocessor && (style == SCE_C_PREPROCESSOR)) { + if (foldPreprocessor && (style == SCE_ECL_PREPROCESSOR)) { if (ch == '#') { unsigned int j = i + 1; while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { j++; } - if (styler.Match(j, "region") || styler.Match(j, "if")) { + if (MatchNoCase(styler, j, "region") || MatchNoCase(styler, j, "if")) { levelNext++; - } else if (styler.Match(j, "end")) { + } else if (MatchNoCase(styler, j, "endregion") || MatchNoCase(styler, j, "end")) { levelNext--; } } } - if (style == SCE_C_OPERATOR) { + if (style == SCE_ECL_OPERATOR) { if (ch == '{') { // Measure the minimum before a '{' to allow // folding on "} else {" @@ -456,8 +463,15 @@ static void FoldCppDoc(unsigned int startPos, int length, int initStyle, levelNext--; } } - if (!IsASpace(ch)) - visibleChars++; + if (style == SCE_ECL_WORD2) { + if (MatchNoCase(styler, i, "record") || MatchNoCase(styler, i, "transform") || MatchNoCase(styler, i, "type") || MatchNoCase(styler, i, "function") || + MatchNoCase(styler, i, "module") || MatchNoCase(styler, i, "service") || MatchNoCase(styler, i, "interface") || MatchNoCase(styler, i, "ifblock") || + MatchNoCase(styler, i, "macro") || MatchNoCase(styler, i, "beginc++")) { + levelNext++; + } else if (MatchNoCase(styler, i, "endmacro") || MatchNoCase(styler, i, "endc++") || MatchNoCase(styler, i, "end")) { + levelNext--; + } + } if (atEOL || (i == endPos-1)) { int levelUse = levelCurrent; if (foldAtElse) { @@ -480,27 +494,19 @@ static void FoldCppDoc(unsigned int startPos, int length, int initStyle, } visibleChars = 0; } + if (!IsASpace(ch)) + visibleChars++; } } -static const char * const cppWordLists[] = { - "Primary keywords and identifiers", - "Secondary keywords and identifiers", - "Documentation comment keywords", - "Unused", - "Global classes and typedefs", - 0, - }; - -static void ColouriseCppDocSensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, true); -} - -static void ColouriseCppDocInsensitive(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - ColouriseCppDoc(startPos, length, initStyle, keywordlists, styler, false); -} - -LexerModule lmCPP(SCLEX_CPP, ColouriseCppDocSensitive, "cpp", FoldCppDoc, cppWordLists); -LexerModule lmCPPNoCase(SCLEX_CPPNOCASE, ColouriseCppDocInsensitive, "cppnocase", FoldCppDoc, cppWordLists); +static const char * const EclWordListDesc[] = { + "Keywords", + 0 +}; + +LexerModule lmECL( + SCLEX_ECL, + ColouriseEclDoc, + "ecl", + FoldEclDoc, + EclWordListDesc); diff --git a/src/stc/scintilla/src/LexEScript.cxx b/src/stc/scintilla/lexers/LexEScript.cxx similarity index 98% rename from src/stc/scintilla/src/LexEScript.cxx rename to src/stc/scintilla/lexers/LexEScript.cxx index 295aaec531..9a7560e1e4 100644 --- a/src/stc/scintilla/src/LexEScript.cxx +++ b/src/stc/scintilla/lexers/LexEScript.cxx @@ -9,15 +9,18 @@ #include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -198,7 +201,7 @@ static void FoldESCRIPTDoc(unsigned int startPos, int length, int initStyle, Wor styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - + if (foldComment && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev)) { levelCurrent++; diff --git a/src/stc/scintilla/src/LexEiffel.cxx b/src/stc/scintilla/lexers/LexEiffel.cxx similarity index 98% rename from src/stc/scintilla/src/LexEiffel.cxx rename to src/stc/scintilla/lexers/LexEiffel.cxx index 03dea5e73d..067801ca8d 100644 --- a/src/stc/scintilla/src/LexEiffel.cxx +++ b/src/stc/scintilla/lexers/LexEiffel.cxx @@ -7,18 +7,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> -#include <stdarg.h> #include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexErlang.cxx b/src/stc/scintilla/lexers/LexErlang.cxx similarity index 98% rename from src/stc/scintilla/src/LexErlang.cxx rename to src/stc/scintilla/lexers/LexErlang.cxx index 45577bda4c..5f52258594 100644 --- a/src/stc/scintilla/src/LexErlang.cxx +++ b/src/stc/scintilla/lexers/LexErlang.cxx @@ -4,24 +4,28 @@ /** @file LexErlang.cxx ** Lexer for Erlang. ** Enhanced by Etienne 'Lenain' Girondel (lenaing@gmail.com) - ** Originally wrote by Peter-Henry Mander, + ** Originally wrote by Peter-Henry Mander, ** based on Matlab lexer by José Fonseca. **/ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -152,7 +156,7 @@ static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle, // Try to match documentation comment sc.GetCurrent(cur, sizeof(cur)); - if (parse_state == COMMENT_DOC_MACRO + if (parse_state == COMMENT_DOC_MACRO && erlangDocMacro.InList(cur)) { sc.ChangeState(SCE_ERLANG_COMMENT_DOC_MACRO); while (sc.ch != '}' && !sc.atLineEnd) @@ -340,7 +344,7 @@ static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle, case NUMERAL_BASE_VALUE : { if (!is_radix(radix_digits,sc.ch)) { radix_digits = 0; - + if (!isalnum(sc.ch)) sc.ChangeState(SCE_ERLANG_NUMBER); @@ -380,7 +384,7 @@ static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle, /* Preprocessor --------------------------------------------------*/ case PREPROCESSOR : { if (!IsAWordChar(sc.ch)) { - + sc.GetCurrent(cur, sizeof(cur)); if (erlangPreproc.InList(cur)) { style = SCE_ERLANG_PREPROC; @@ -421,7 +425,7 @@ static void ColouriseErlangDoc(unsigned int startPos, int length, int initStyle, } break; case SCE_ERLANG_OPERATOR : { if (sc.chPrev == '.') { - if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' + if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') { sc.ForwardSetState(SCE_ERLANG_DEFAULT); } else if (sc.ch == '\'') { diff --git a/src/stc/scintilla/lexers/LexFlagship.cxx b/src/stc/scintilla/lexers/LexFlagship.cxx new file mode 100644 index 0000000000..b8568b05af --- /dev/null +++ b/src/stc/scintilla/lexers/LexFlagship.cxx @@ -0,0 +1,354 @@ +// Scintilla source code edit control +/** @file LexFlagShip.cxx + ** Lexer for Harbour and FlagShip. + ** (Syntactically compatible to other xBase dialects, like Clipper, dBase, Clip, FoxPro etc.) + **/ +// Copyright 2005 by Randy Butler +// Copyright 2010 by Xavi <jarabal/at/gmail.com> (Harbour) +// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Extended to accept accented characters +static inline bool IsAWordChar(int ch) +{ + return ch >= 0x80 || + (isalnum(ch) || ch == '_'); +} + +static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) +{ + + WordList &keywords = *keywordlists[0]; + WordList &keywords2 = *keywordlists[1]; + WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; + + // property lexer.flagship.styling.within.preprocessor + // For Harbour code, determines whether all preprocessor code is styled in the preprocessor style (0) or only from the + // initial # to the end of the command word(1, the default). It also determines how to present text, dump, and disabled code. + bool stylingWithinPreprocessor = styler.GetPropertyInt("lexer.flagship.styling.within.preprocessor", 1) != 0; + + CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + int visibleChars = 0; + int closeStringChar = 0; + int styleBeforeDCKeyword = SCE_FS_DEFAULT; + bool bEnableCode = initStyle < SCE_FS_DISABLEDCODE; + + StyleContext sc(startPos, length, initStyle, styler); + + for (; sc.More(); sc.Forward()) { + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_FS_OPERATOR: + case SCE_FS_OPERATOR_C: + case SCE_FS_WORDOPERATOR: + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + break; + case SCE_FS_IDENTIFIER: + case SCE_FS_IDENTIFIER_C: + if (!IsAWordChar(sc.ch)) { + char s[64]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords.InList(s)) { + sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD : SCE_FS_KEYWORD_C); + } else if (keywords2.InList(s)) { + sc.ChangeState(bEnableCode ? SCE_FS_KEYWORD2 : SCE_FS_KEYWORD2_C); + } else if (bEnableCode && keywords3.InList(s)) { + sc.ChangeState(SCE_FS_KEYWORD3); + } else if (bEnableCode && keywords4.InList(s)) { + sc.ChangeState(SCE_FS_KEYWORD4); + }// Else, it is really an identifier... + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_NUMBER: + if (!IsAWordChar(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_NUMBER_C: + if (!IsAWordChar(sc.ch) && sc.ch != '.') { + sc.SetState(SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_CONSTANT: + if (!IsAWordChar(sc.ch)) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_STRING: + case SCE_FS_STRING_C: + if (sc.ch == closeStringChar) { + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.atLineEnd) { + sc.ChangeState(bEnableCode ? SCE_FS_STRINGEOL : SCE_FS_STRINGEOL_C); + } + break; + case SCE_FS_STRINGEOL: + case SCE_FS_STRINGEOL_C: + if (sc.atLineStart) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_COMMENTDOC: + case SCE_FS_COMMENTDOC_C: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C; + sc.SetState(SCE_FS_COMMENTDOCKEYWORD); + } + } + break; + case SCE_FS_COMMENT: + case SCE_FS_COMMENTLINE: + if (sc.atLineStart) { + sc.SetState(SCE_FS_DEFAULT); + } + break; + case SCE_FS_COMMENTLINEDOC: + case SCE_FS_COMMENTLINEDOC_C: + if (sc.atLineStart) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C; + sc.SetState(SCE_FS_COMMENTDOCKEYWORD); + } + } + break; + case SCE_FS_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_FS_COMMENTDOC || styleBeforeDCKeyword == SCE_FS_COMMENTDOC_C) && + sc.Match('*', '/')) { + sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (!setDoxygen.Contains(sc.ch)) { + char s[64]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!IsASpace(sc.ch) || !keywords5.InList(s + 1)) { + sc.ChangeState(SCE_FS_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_FS_PREPROCESSOR: + case SCE_FS_PREPROCESSOR_C: + if (sc.atLineEnd) { + if (!(sc.chPrev == ';' || sc.GetRelative(-2) == ';')) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + } else if (stylingWithinPreprocessor) { + if (IsASpaceOrTab(sc.ch)) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + } else if (sc.Match('/', '*') || sc.Match('/', '/') || sc.Match('&', '&')) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } + break; + case SCE_FS_DISABLEDCODE: + if (sc.ch == '#' && visibleChars == 0) { + sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); + do { // Skip whitespace between # and preprocessor word + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("pragma")) { + sc.Forward(6); + do { // Skip more whitespace until keyword + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { + bEnableCode = true; + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(sc.ch == '_' ? 8 : 6); + sc.ForwardSetState(SCE_FS_DEFAULT); + } else { + sc.ChangeState(SCE_FS_DISABLEDCODE); + } + } else { + sc.ChangeState(SCE_FS_DISABLEDCODE); + } + } + break; + case SCE_FS_DATE: + if (sc.ch == '}') { + sc.ForwardSetState(SCE_FS_DEFAULT); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_FS_STRINGEOL); + } + } + + // Determine if a new state should be entered. + if (sc.state == SCE_FS_DEFAULT || sc.state == SCE_FS_DEFAULT_C) { + if (bEnableCode && + (sc.MatchIgnoreCase(".and.") || sc.MatchIgnoreCase(".not."))) { + sc.SetState(SCE_FS_WORDOPERATOR); + sc.Forward(4); + } else if (bEnableCode && sc.MatchIgnoreCase(".or.")) { + sc.SetState(SCE_FS_WORDOPERATOR); + sc.Forward(3); + } else if (bEnableCode && + (sc.MatchIgnoreCase(".t.") || sc.MatchIgnoreCase(".f.") || + (!IsAWordChar(sc.GetRelative(3)) && sc.MatchIgnoreCase("nil")))) { + sc.SetState(SCE_FS_CONSTANT); + sc.Forward(2); + } else if (sc.Match('/', '*')) { + sc.SetState(bEnableCode ? SCE_FS_COMMENTDOC : SCE_FS_COMMENTDOC_C); + sc.Forward(); + } else if (bEnableCode && sc.Match('&', '&')) { + sc.SetState(SCE_FS_COMMENTLINE); + sc.Forward(); + } else if (sc.Match('/', '/')) { + sc.SetState(bEnableCode ? SCE_FS_COMMENTLINEDOC : SCE_FS_COMMENTLINEDOC_C); + sc.Forward(); + } else if (bEnableCode && sc.ch == '*' && visibleChars == 0) { + sc.SetState(SCE_FS_COMMENT); + } else if (sc.ch == '\"' || sc.ch == '\'') { + sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); + closeStringChar = sc.ch; + } else if (closeStringChar == '>' && sc.ch == '<') { + sc.SetState(bEnableCode ? SCE_FS_STRING : SCE_FS_STRING_C); + } else if (sc.ch == '#' && visibleChars == 0) { + sc.SetState(bEnableCode ? SCE_FS_PREPROCESSOR : SCE_FS_PREPROCESSOR_C); + do { // Skip whitespace between # and preprocessor word + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.atLineEnd) { + sc.SetState(bEnableCode ? SCE_FS_DEFAULT : SCE_FS_DEFAULT_C); + } else if (sc.MatchIgnoreCase("include")) { + if (stylingWithinPreprocessor) { + closeStringChar = '>'; + } + } else if (sc.MatchIgnoreCase("pragma")) { + sc.Forward(6); + do { // Skip more whitespace until keyword + sc.Forward(); + } while (IsASpaceOrTab(sc.ch) && sc.More()); + if (sc.MatchIgnoreCase("begindump") || sc.MatchIgnoreCase("__cstream")) { + bEnableCode = false; + if (stylingWithinPreprocessor) { + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(8); + sc.ForwardSetState(SCE_FS_DEFAULT_C); + } else { + sc.SetState(SCE_FS_DISABLEDCODE); + } + } else if (sc.MatchIgnoreCase("enddump") || sc.MatchIgnoreCase("__endtext")) { + bEnableCode = true; + sc.SetState(SCE_FS_DISABLEDCODE); + sc.Forward(sc.ch == '_' ? 8 : 6); + sc.ForwardSetState(SCE_FS_DEFAULT); + } + } + } else if (bEnableCode && sc.ch == '{') { + int p = 0; + int chSeek; + unsigned int endPos(startPos + length); + do { // Skip whitespace + chSeek = sc.GetRelative(++p); + } while (IsASpaceOrTab(chSeek) && (sc.currentPos + p < endPos)); + if (chSeek == '^') { + sc.SetState(SCE_FS_DATE); + } else { + sc.SetState(SCE_FS_OPERATOR); + } + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(bEnableCode ? SCE_FS_NUMBER : SCE_FS_NUMBER_C); + } else if (IsAWordChar(sc.ch)) { + sc.SetState(bEnableCode ? SCE_FS_IDENTIFIER : SCE_FS_IDENTIFIER_C); + } else if (isoperator(static_cast<char>(sc.ch)) || (bEnableCode && sc.ch == '@')) { + sc.SetState(bEnableCode ? SCE_FS_OPERATOR : SCE_FS_OPERATOR_C); + } + } + + if (sc.atLineEnd) { + visibleChars = 0; + closeStringChar = 0; + } + if (!IsASpace(sc.ch)) { + visibleChars++; + } + } + sc.Complete(); +} + +static void FoldFlagShipDoc(unsigned int startPos, int length, int, + WordList *[], Accessor &styler) +{ + + int endPos = startPos + length; + + // Backtrack to previous line in case need to fix its fold status + int lineCurrent = styler.GetLine(startPos); + if (startPos > 0 && lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + int spaceFlags = 0; + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags); + char chNext = styler[startPos]; + for (int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos-1)) { + int lev = indentCurrent; + int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags); + if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { + int spaceFlags2 = 0; + int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2); + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { + lev |= SC_FOLDLEVELHEADERFLAG; + } + } + } + indentCurrent = indentNext; + styler.SetLevel(lineCurrent, lev); + lineCurrent++; + } + } +} + +static const char * const FSWordListDesc[] = { + "Keywords Commands", + "Std Library Functions", + "Procedure, return, exit", + "Class (oop)", + "Doxygen keywords", + 0 +}; + +LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc); diff --git a/src/stc/scintilla/src/LexForth.cxx b/src/stc/scintilla/lexers/LexForth.cxx similarity index 96% rename from src/stc/scintilla/src/LexForth.cxx rename to src/stc/scintilla/lexers/LexForth.cxx index e52543fa55..0e9875cebb 100644 --- a/src/stc/scintilla/src/LexForth.cxx +++ b/src/stc/scintilla/lexers/LexForth.cxx @@ -7,18 +7,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -130,7 +133,7 @@ static void ColouriseForthDoc(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_FORTH_NUMBER); while(sc.More() && isascii(sc.chNext) && (sc.chNext == '0' || sc.chNext == '1')) sc.Forward(); - } else if ( isascii(sc.ch) && + } else if ( isascii(sc.ch) && (isxdigit(sc.ch) || ((sc.ch == '.' || sc.ch == '-') && isascii(sc.chNext) && isxdigit(sc.chNext)) ) ){ sc.SetState(SCE_FORTH_NUMBER); @@ -173,4 +176,4 @@ static const char * const forthWordLists[] = { LexerModule lmForth(SCLEX_FORTH, ColouriseForthDoc, "forth", FoldForthDoc, forthWordLists); - + diff --git a/src/stc/scintilla/src/LexFortran.cxx b/src/stc/scintilla/lexers/LexFortran.cxx similarity index 91% rename from src/stc/scintilla/src/LexFortran.cxx rename to src/stc/scintilla/lexers/LexFortran.cxx index 0b3f2777c9..bfbe301a20 100644 --- a/src/stc/scintilla/src/LexFortran.cxx +++ b/src/stc/scintilla/lexers/LexFortran.cxx @@ -8,18 +8,23 @@ /***************************************/ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> /***************************************/ -#include "Platform.h" -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +/***************************************/ + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -82,7 +87,7 @@ static void ColouriseFortranDoc(unsigned int startPos, int length, int initStyle /***********************************************/ // Handle the fix format generically int toLineStart = sc.currentPos - posLineStart; - if (isFixFormat && (toLineStart < 6 || toLineStart > 72)) { + if (isFixFormat && (toLineStart < 6 || toLineStart >= 72)) { if ((toLineStart == 0 && (tolower(sc.ch) == 'c' || sc.ch == '*')) || sc.ch == '!') { if (sc.MatchIgnoreCase("cdec$") || sc.MatchIgnoreCase("*dec$") || sc.MatchIgnoreCase("!dec$") || sc.MatchIgnoreCase("cdir$") || sc.MatchIgnoreCase("*dir$") || sc.MatchIgnoreCase("!dir$") || @@ -94,7 +99,7 @@ static void ColouriseFortranDoc(unsigned int startPos, int length, int initStyle } while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end - } else if (toLineStart > 72) { + } else if (toLineStart >= 72) { sc.SetState(SCE_F_COMMENT); while (!sc.atLineEnd && sc.More()) sc.Forward(); // Until line end } else if (toLineStart < 5) { @@ -103,17 +108,27 @@ static void ColouriseFortranDoc(unsigned int startPos, int length, int initStyle else sc.SetState(SCE_F_DEFAULT); } else if (toLineStart == 5) { - if (!IsASpace(sc.ch) && sc.ch != '0') { + //if (!IsASpace(sc.ch) && sc.ch != '0') { + if (sc.ch != '\r' && sc.ch != '\n') { sc.SetState(SCE_F_CONTINUATION); - sc.ForwardSetState(prevState); + if (!IsASpace(sc.ch) && sc.ch != '0') + sc.ForwardSetState(prevState); } else sc.SetState(SCE_F_DEFAULT); } continue; } /***************************************/ + // Hanndle preprocessor directives + if (sc.ch == '#' && numNonBlank == 1) + { + sc.SetState(SCE_F_PREPROCESSOR); + while (!sc.atLineEnd && sc.More()) + sc.Forward(); // Until line end + } + /***************************************/ // Handle line continuation generically. - if (!isFixFormat && sc.ch == '&') { + if (!isFixFormat && sc.ch == '&' && sc.state != SCE_F_COMMENT) { char chTemp = ' '; int j = 1; while (IsABlank(chTemp) && j<132) { @@ -247,7 +262,8 @@ static int classifyFoldPointFortran(const char* s, const char* prevWord, const c || strcmp(s, "function") == 0 || strcmp(s, "interface") == 0 || strcmp(s, "module") == 0 || strcmp(s, "program") == 0 || strcmp(s, "subroutine") == 0 || strcmp(s, "then") == 0 - || (strcmp(s, "type") == 0 && chNextNonBlank != '(') ){ + || (strcmp(s, "type") == 0 && chNextNonBlank != '(') + || strcmp(s, "critical") == 0){ if (strcmp(prevWord, "end") == 0) lev = 0; else @@ -260,12 +276,14 @@ static int classifyFoldPointFortran(const char* s, const char* prevWord, const c || strcmp(s, "endfunction") == 0 || strcmp(s, "endinterface") == 0 || strcmp(s, "endmodule") == 0 || strcmp(s, "endprogram") == 0 || strcmp(s, "endsubroutine") == 0 || strcmp(s, "endtype") == 0 - || strcmp(s, "endwhere") == 0 - || strcmp(s, "procedure") == 0 ) { // Take care of the module procedure statement + || strcmp(s, "endwhere") == 0 || strcmp(s, "endcritical") == 0 + || (strcmp(s, "procedure") == 0 && strcmp(prevWord, "module") == 0) ) { // Take care of the "module procedure" statement lev = -1; } else if (strcmp(prevWord, "end") == 0 && strcmp(s, "if") == 0){ // end if lev = 0; - } + } else if (strcmp(prevWord, "type") == 0 && strcmp(s, "is") == 0){ // type is + lev = -1; + } return lev; } // Folding the code @@ -307,7 +325,7 @@ static void FoldFortranDoc(unsigned int startPos, int length, int initStyle, styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); // - if (stylePrev == SCE_F_DEFAULT && (style == SCE_F_WORD || style == SCE_F_LABEL)) { + if (((isFixFormat && stylePrev == SCE_F_CONTINUATION) || stylePrev == SCE_F_DEFAULT || stylePrev == SCE_F_OPERATOR) && (style == SCE_F_WORD || style == SCE_F_LABEL)) { // Store last word and label start point. lastStart = i; } diff --git a/src/stc/scintilla/src/LexGAP.cxx b/src/stc/scintilla/lexers/LexGAP.cxx similarity index 97% rename from src/stc/scintilla/src/LexGAP.cxx rename to src/stc/scintilla/lexers/LexGAP.cxx index 25bd33b900..fb30660986 100644 --- a/src/stc/scintilla/src/LexGAP.cxx +++ b/src/stc/scintilla/lexers/LexGAP.cxx @@ -8,25 +8,28 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif static inline bool IsGAPOperator(char ch) { - if (isalnum(ch)) return false; + if (isascii(ch) && isalnum(ch)) return false; if (ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '^' || ch == ',' || ch == '!' || ch == '.' || ch == '=' || ch == '<' || ch == '>' || ch == '(' || diff --git a/src/stc/scintilla/src/LexGui4Cli.cxx b/src/stc/scintilla/lexers/LexGui4Cli.cxx similarity index 98% rename from src/stc/scintilla/src/LexGui4Cli.cxx rename to src/stc/scintilla/lexers/LexGui4Cli.cxx index 1c92de72e7..13cf9ea86f 100644 --- a/src/stc/scintilla/src/LexGui4Cli.cxx +++ b/src/stc/scintilla/lexers/LexGui4Cli.cxx @@ -23,18 +23,21 @@ val SCE_GC_OPERATOR=9 #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexHTML.cxx b/src/stc/scintilla/lexers/LexHTML.cxx similarity index 89% rename from src/stc/scintilla/src/LexHTML.cxx rename to src/stc/scintilla/lexers/LexHTML.cxx index 6038326e3e..fe5e8c8577 100644 --- a/src/stc/scintilla/src/LexHTML.cxx +++ b/src/stc/scintilla/lexers/LexHTML.cxx @@ -7,19 +7,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" #include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -54,15 +56,8 @@ inline bool IsOperator(int ch) { return false; } -static inline int MakeLowerCase(int ch) { - if (ch < 'A' || ch > 'Z') - return ch; - else - return ch - 'A' + 'a'; -} - static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) { - size_t i = 0; + unsigned int i = 0; for (; (i < end - start + 1) && (i < len-1); i++) { s[i] = static_cast<char>(MakeLowerCase(styler[start + i])); } @@ -71,17 +66,17 @@ static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int en static const char *GetNextWord(Accessor &styler, unsigned int start, char *s, size_t sLen) { - size_t i = 0; + unsigned int i = 0; for (; i < sLen-1; i++) { char ch = static_cast<char>(styler.SafeGetCharAt(start + i)); if ((i == 0) && !IsAWordStart(ch)) break; - if ((i > 0) && !IsAWordChar(ch)) + if ((i > 0) && !IsAWordChar(ch)) break; s[i] = ch; } s[i] = '\0'; - + return s; } @@ -266,28 +261,29 @@ static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &k static int classifyTagHTML(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, bool &tagDontFold, bool caseSensitive, bool isXml, bool allowScripts) { - char s[30 + 2]; + char withSpace[30 + 2] = " "; + const char *s = withSpace + 1; // Copy after the '<' - unsigned int i = 0; + unsigned int i = 1; for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) { char ch = styler[cPos]; if ((ch != '<') && (ch != '/')) { - s[i++] = caseSensitive ? ch : static_cast<char>(MakeLowerCase(ch)); + withSpace[i++] = caseSensitive ? ch : static_cast<char>(MakeLowerCase(ch)); } } //The following is only a quick hack, to see if this whole thing would work //we first need the tagname with a trailing space... - s[i] = ' '; - s[i+1] = '\0'; + withSpace[i] = ' '; + withSpace[i+1] = '\0'; // if the current language is XML, I can fold any tag // if the current language is HTML, I don't want to fold certain tags (input, meta, etc.) //...to find it in the list of no-container-tags - tagDontFold = (!isXml) && (NULL != strstr("meta link img area br hr input ", s)); + tagDontFold = (!isXml) && (NULL != strstr(" area base basefont br col command embed frame hr img input isindex keygen link meta param source track wbr ", withSpace)); //now we can remove the trailing space - s[i] = '\0'; + withSpace[i] = '\0'; // No keywords -> all are known char chAttr = SCE_H_TAGUNKNOWN; @@ -323,19 +319,19 @@ static int classifyTagHTML(unsigned int start, unsigned int end, static void classifyWordHTJS(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, script_mode inScriptType) { + char s[30 + 1]; + unsigned int i = 0; + for (; i < end - start + 1 && i < 30; i++) { + s[i] = styler[start + i]; + } + s[i] = '\0'; + char chAttr = SCE_HJ_WORD; - bool wordIsNumber = IsADigit(styler[start]) || (styler[start] == '.'); - if (wordIsNumber) + bool wordIsNumber = IsADigit(s[0]) || ((s[0] == '.') && IsADigit(s[1])); + if (wordIsNumber) { chAttr = SCE_HJ_NUMBER; - else { - char s[30 + 1]; - unsigned int i = 0; - for (; i < end - start + 1 && i < 30; i++) { - s[i] = styler[start + i]; - } - s[i] = '\0'; - if (keywords.InList(s)) - chAttr = SCE_HJ_KEYWORD; + } else if (keywords.InList(s)) { + chAttr = SCE_HJ_KEYWORD; } styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); } @@ -361,7 +357,7 @@ static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keyw return SCE_HB_DEFAULT; } -static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType) { +static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord, script_mode inScriptType, bool isMako) { bool wordIsNumber = IsADigit(styler[start]); char s[30 + 1]; unsigned int i = 0; @@ -378,6 +374,8 @@ static void classifyWordHTPy(unsigned int start, unsigned int end, WordList &key chAttr = SCE_HP_NUMBER; else if (keywords.InList(s)) chAttr = SCE_HP_WORD; + else if (isMako && 0 == strcmp(s, "block")) + chAttr = SCE_HP_WORD; styler.ColourTo(end, statePrintForState(chAttr, inScriptType)); strcpy(prevWord, s); } @@ -494,12 +492,15 @@ static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType if (strlen(blockType) == 0) { return ((ch == '%') && (chNext == '>')); } else if ((0 == strcmp(blockType, "inherit")) || - (0 == strcmp(blockType, "namespace")) || + (0 == strcmp(blockType, "namespace")) || (0 == strcmp(blockType, "include")) || (0 == strcmp(blockType, "page"))) { return ((ch == '/') && (chNext == '>')); } else if (0 == strcmp(blockType, "%")) { - return isLineEnd(ch); + if (ch == '/' && isLineEnd(chNext)) + return 1; + else + return isLineEnd(ch); } else if (0 == strcmp(blockType, "{")) { return ch == '}'; } else { @@ -507,6 +508,18 @@ static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType } } +static bool isDjangoBlockEnd(const int ch, const int chNext, const char *blockType) { + if (strlen(blockType) == 0) { + return 0; + } else if (0 == strcmp(blockType, "%")) { + return ((ch == '%') && (chNext == '}')); + } else if (0 == strcmp(blockType, "{")) { + return ((ch == '}') && (chNext == '}')); + } else { + return 0; + } +} + static bool isPHPStringState(int state) { return (state == SCE_HPHP_HSTRING) || @@ -575,20 +588,22 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty styler.StartAt(startPos, static_cast<char>(STYLE_MAX)); char prevWord[200]; prevWord[0] = '\0'; - char nextWord[200]; - nextWord[0] = '\0'; char phpStringDelimiter[200]; // PHP is not limited in length, we are phpStringDelimiter[0] = '\0'; int StateToPrint = initStyle; int state = stateForPrintState(StateToPrint); char makoBlockType[200]; makoBlockType[0] = '\0'; + int makoComment = 0; + char djangoBlockType[2]; + djangoBlockType[0] = '\0'; - // If inside a tag, it may be a script tag, so reread from the start to ensure any language tags are seen + // If inside a tag, it may be a script tag, so reread from the start of line starting tag to ensure any language tags are seen if (InTagState(state)) { while ((startPos > 0) && (InTagState(styler.StyleAt(startPos - 1)))) { - startPos--; - length++; + int backLineStart = styler.LineStart(styler.GetLine(startPos-1)); + length += startPos - backLineStart; + startPos = backLineStart; } state = SCE_H_DEFAULT; } @@ -607,13 +622,13 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty int lineCurrent = styler.GetLine(startPos); int lineState; if (lineCurrent > 0) { - lineState = styler.GetLineState(lineCurrent); + lineState = styler.GetLineState(lineCurrent-1); } else { // Default client and ASP scripting language is JavaScript lineState = eScriptJS << 8; - // property asp.default.language - // Script in ASP code is initially assumed to be in JavaScript. + // property asp.default.language + // Script in ASP code is initially assumed to be in JavaScript. // To change this to VBScript set asp.default.language to 2. Python is 3. lineState |= styler.GetPropertyInt("asp.default.language", eScriptJS) << 4; } @@ -630,44 +645,49 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty if (inScriptType == eNonHtmlScript && state == SCE_H_COMMENT) { scriptLanguage = eScriptComment; } + script_type beforeLanguage = ScriptOfState(beforePreProc); - // property fold.html - // Folding is turned on or off for HTML and XML files with this option. + // property fold.html + // Folding is turned on or off for HTML and XML files with this option. // The fold option must also be on for folding to occur. const bool foldHTML = styler.GetPropertyInt("fold.html", 0) != 0; const bool fold = foldHTML && styler.GetPropertyInt("fold", 0); - // property fold.html.preprocessor - // Folding is turned on or off for scripts embedded in HTML files with this option. + // property fold.html.preprocessor + // Folding is turned on or off for scripts embedded in HTML files with this option. // The default is on. const bool foldHTMLPreprocessor = foldHTML && styler.GetPropertyInt("fold.html.preprocessor", 1); const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - // property fold.hypertext.comment - // Allow folding for comments in scripts embedded in HTML. - // The default is off. + // property fold.hypertext.comment + // Allow folding for comments in scripts embedded in HTML. + // The default is off. const bool foldComment = fold && styler.GetPropertyInt("fold.hypertext.comment", 0) != 0; - // property fold.hypertext.heredoc - // Allow folding for heredocs in scripts embedded in HTML. - // The default is off. + // property fold.hypertext.heredoc + // Allow folding for heredocs in scripts embedded in HTML. + // The default is off. const bool foldHeredoc = fold && styler.GetPropertyInt("fold.hypertext.heredoc", 0) != 0; - // property html.tags.case.sensitive - // For XML and HTML, setting this property to 1 will make tags match in a case - // sensitive way which is the expected behaviour for XML and XHTML. + // property html.tags.case.sensitive + // For XML and HTML, setting this property to 1 will make tags match in a case + // sensitive way which is the expected behaviour for XML and XHTML. const bool caseSensitive = styler.GetPropertyInt("html.tags.case.sensitive", 0) != 0; - // property lexer.xml.allow.scripts - // Set to 0 to disable scripts in XML. + // property lexer.xml.allow.scripts + // Set to 0 to disable scripts in XML. const bool allowScripts = styler.GetPropertyInt("lexer.xml.allow.scripts", 1) != 0; - // property lexer.html.mako - // Set to 1 to enable the mako template language. + // property lexer.html.mako + // Set to 1 to enable the mako template language. const bool isMako = styler.GetPropertyInt("lexer.html.mako", 0) != 0; + // property lexer.html.django + // Set to 1 to enable the django template language. + const bool isDjango = styler.GetPropertyInt("lexer.html.django", 0) != 0; + const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true); const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true); const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true); @@ -732,15 +752,25 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty if ((state != SCE_HPHP_COMMENT) && (state != SCE_HPHP_COMMENTLINE) && (state != SCE_HJ_COMMENT) && (state != SCE_HJ_COMMENTLINE) && (state != SCE_HJ_COMMENTDOC) && (!isStringState(state))) { //Platform::DebugPrintf("state=%d, StateToPrint=%d, initStyle=%d\n", state, StateToPrint, initStyle); //if ((state == SCE_HPHP_OPERATOR) || (state == SCE_HPHP_DEFAULT) || (state == SCE_HJ_SYMBOLS) || (state == SCE_HJ_START) || (state == SCE_HJ_DEFAULT)) { - if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) { - levelCurrent += ((ch == '{') || (ch == '/')) ? 1 : -1; + if (ch == '#') { + int j = i + 1; + while ((j < lengthDoc) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { + j++; + } + if (styler.Match(j, "region") || styler.Match(j, "if")) { + levelCurrent++; + } else if (styler.Match(j, "end")) { + levelCurrent--; + } + } else if ((ch == '{') || (ch == '}') || (foldComment && (ch == '/') && (chNext == '*'))) { + levelCurrent += (((ch == '{') || (ch == '/')) ? 1 : -1); } } else if (((state == SCE_HPHP_COMMENT) || (state == SCE_HJ_COMMENT)) && foldComment && (ch == '*') && (chNext == '/')) { levelCurrent--; } break; case eScriptPython: - if (state != SCE_HP_COMMENTLINE) { + if (state != SCE_HP_COMMENTLINE && !isMako) { if ((ch == ':') && ((chNext == '\n') || (chNext == '\r' && chNext2 == '\n'))) { levelCurrent++; } else if ((ch == '\n') && !((chNext == '\r') && (chNext2 == '\n')) && (chNext != '\n')) { @@ -785,8 +815,6 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty visibleChars = 0; levelPrev = levelCurrent; } - lineCurrent++; - lineStartVisibleChars = 0; styler.SetLineState(lineCurrent, ((inScriptType & 0x03) << 0) | ((tagOpened & 0x01) << 2) | @@ -794,13 +822,27 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty ((aspScript & 0x0F) << 4) | ((clientScript & 0x0F) << 8) | ((beforePreProc & 0xFF) << 12)); + lineCurrent++; + lineStartVisibleChars = 0; } + // handle start of Mako comment line + if (isMako && ch == '#' && chNext == '#') { + makoComment = 1; + } + + // handle end of Mako comment line + else if (isMako && makoComment && (ch == '\r' || ch == '\n')) { + makoComment = 0; + styler.ColourTo(i, SCE_HP_COMMENTLINE); + state = SCE_HP_DEFAULT; + } + // Allow falling through to mako handling code if newline is going to end a block if (((ch == '\r' && chNext != '\n') || (ch == '\n')) && (!isMako || (0 != strcmp(makoBlockType, "%")))) { } - + // generic end of script processing else if ((inScriptType == eNonHtmlScript) && (ch == '<') && (chNext == '/')) { // Check if it's the end of the script tag (or any other HTML tag) @@ -857,10 +899,12 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty else if ((state != SCE_H_ASPAT) && !isPHPStringState(state) && (state != SCE_HPHP_COMMENT) && + (state != SCE_HPHP_COMMENTLINE) && (ch == '<') && (chNext == '?') && - !IsScriptCommentState(state) ) { - scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, eScriptPHP); + !IsScriptCommentState(state)) { + beforeLanguage = scriptLanguage; + scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, isXml ? eScriptXML : eScriptPHP); if (scriptLanguage != eScriptPHP && isStringState(state)) continue; styler.ColourTo(i - 1, StateToPrint); beforePreProc = state; @@ -886,13 +930,14 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty } // handle the start Mako template Python code - else if (isMako && scriptLanguage == eScriptNone && ((ch == '<' && chNext == '%') || + else if (isMako && scriptLanguage == eScriptNone && ((ch == '<' && chNext == '%') || (lineStartVisibleChars == 1 && ch == '%') || + (lineStartVisibleChars == 1 && ch == '/' && chNext == '%') || (ch == '$' && chNext == '{') || (ch == '<' && chNext == '/' && chNext2 == '%'))) { - if (ch == '%') + if (ch == '%' || ch == '/') strcpy(makoBlockType, "%"); - else if (ch == '$') + else if (ch == '$') strcpy(makoBlockType, "{"); else if (chNext == '/') GetNextWord(styler, i+3, makoBlockType, sizeof(makoBlockType)); @@ -915,12 +960,10 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty state = SCE_HP_START; scriptLanguage = eScriptPython; styler.ColourTo(i, SCE_H_ASP); - if (foldHTMLPreprocessor && ch == '<') - levelCurrent++; - - if (ch != '%' && ch != '$') { - i += strlen(makoBlockType); - visibleChars += strlen(makoBlockType); + + if (ch != '%' && ch != '$' && ch != '/') { + i += static_cast<int>(strlen(makoBlockType)); + visibleChars += static_cast<int>(strlen(makoBlockType)); if (keywords4.InList(makoBlockType)) styler.ColourTo(i, SCE_HP_WORD); else @@ -931,8 +974,62 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty continue; } + // handle the start/end of Django comment + else if (isDjango && state != SCE_H_COMMENT && (ch == '{' && chNext == '#')) { + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + beforeLanguage = scriptLanguage; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + i += 1; + visibleChars += 1; + scriptLanguage = eScriptComment; + state = SCE_H_COMMENT; + styler.ColourTo(i, SCE_H_ASP); + ch = static_cast<unsigned char>(styler.SafeGetCharAt(i)); + continue; + } else if (isDjango && state == SCE_H_COMMENT && (ch == '#' && chNext == '}')) { + styler.ColourTo(i - 1, StateToPrint); + i += 1; + visibleChars += 1; + styler.ColourTo(i, SCE_H_ASP); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = beforeLanguage; + continue; + } + + // handle the start Django template code + else if (isDjango && scriptLanguage != eScriptPython && (ch == '{' && (chNext == '%' || chNext == '{'))) { + if (chNext == '%') + strcpy(djangoBlockType, "%"); + else + strcpy(djangoBlockType, "{"); + styler.ColourTo(i - 1, StateToPrint); + beforePreProc = state; + if (inScriptType == eNonHtmlScript) + inScriptType = eNonHtmlScriptPreProc; + else + inScriptType = eNonHtmlPreProc; + + i += 1; + visibleChars += 1; + state = SCE_HP_START; + beforeLanguage = scriptLanguage; + scriptLanguage = eScriptPython; + styler.ColourTo(i, SCE_H_ASP); + + ch = static_cast<unsigned char>(styler.SafeGetCharAt(i)); + continue; + } + // handle the start of ASP pre-processor = Non-HTML - else if (!isMako && !isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) { + else if (!isMako && !isDjango && !isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) { styler.ColourTo(i - 1, StateToPrint); beforePreProc = state; if (inScriptType == eNonHtmlScript) @@ -977,7 +1074,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty (ch == '!') && (StateToPrint != SCE_H_CDATA) && (!IsCommentState(StateToPrint)) && - (!IsScriptCommentState(StateToPrint)) ) { + (!IsScriptCommentState(StateToPrint))) { beforePreProc = state; styler.ColourTo(i - 2, StateToPrint); if ((chNext == '-') && (chNext2 == '-')) { @@ -992,14 +1089,14 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty state = SCE_H_SGML_COMMAND; // wait for a pending command } // fold whole tag (-- when closing the tag) - if (foldHTMLPreprocessor || (state == SCE_H_COMMENT)) + if (foldHTMLPreprocessor || state == SCE_H_COMMENT || state == SCE_H_CDATA) levelCurrent++; continue; } // handle the end of Mako Python code - else if (isMako && - ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + else if (isMako && + ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && (scriptLanguage != eScriptNone) && stateAllowsTermination(state) && isMakoBlockEnd(ch, chNext, makoBlockType)) { if (state == SCE_H_ASPAT) { @@ -1007,7 +1104,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty styler.GetStartSegment(), i - 1, aspScript); } if (state == SCE_HP_WORD) { - classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType); + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); } else { styler.ColourTo(i - 1, StateToPrint); } @@ -1015,7 +1112,11 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty i++; visibleChars++; } - if (0 != strcmp(makoBlockType, "%")) { + else if (0 == strcmp(makoBlockType, "%") && ch == '/') { + i++; + visibleChars++; + } + if (0 != strcmp(makoBlockType, "%") || ch == '/') { styler.ColourTo(i, SCE_H_ASP); } state = beforePreProc; @@ -1023,15 +1124,38 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty inScriptType = eNonHtmlScript; else inScriptType = eHtml; - if (foldHTMLPreprocessor && ch != '\n' && ch != '\r') { - levelCurrent--; - } scriptLanguage = eScriptNone; continue; } + // handle the end of Django template code + else if (isDjango && + ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + (scriptLanguage != eScriptNone) && stateAllowsTermination(state) && + isDjangoBlockEnd(ch, chNext, djangoBlockType)) { + if (state == SCE_H_ASPAT) { + aspScript = segIsScriptingIndicator(styler, + styler.GetStartSegment(), i - 1, aspScript); + } + if (state == SCE_HP_WORD) { + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); + } else { + styler.ColourTo(i - 1, StateToPrint); + } + i += 1; + visibleChars += 1; + styler.ColourTo(i, SCE_H_ASP); + state = beforePreProc; + if (inScriptType == eNonHtmlScriptPreProc) + inScriptType = eNonHtmlScript; + else + inScriptType = eHtml; + scriptLanguage = beforeLanguage; + continue; + } + // handle the end of a pre-processor = Non-HTML - else if ((!isMako && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && + else if ((!isMako && !isDjango && ((inScriptType == eNonHtmlPreProc) || (inScriptType == eNonHtmlScriptPreProc)) && (((scriptLanguage != eScriptNone) && stateAllowsTermination(state))) && (((ch == '%') || (ch == '?')) && (chNext == '>'))) || ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) { @@ -1048,7 +1172,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty classifyWordHTVB(styler.GetStartSegment(), i - 1, keywords3, styler, inScriptType); break; case SCE_HP_WORD: - classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType); + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); break; case SCE_HPHP_WORD: classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler); @@ -1081,7 +1205,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) { levelCurrent--; } - scriptLanguage = eScriptNone; + scriptLanguage = beforeLanguage; continue; } ///////////////////////////////////// @@ -1461,6 +1585,10 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty state = SCE_HJ_COMMENTDOC; else state = SCE_HJ_COMMENT; + if (chNext2 == '/') { + // Eat the * so it isn't used for the end of the comment + i++; + } } else if (ch == '/' && chNext == '/') { styler.ColourTo(i - 1, StateToPrint); state = SCE_HJ_COMMENTLINE; @@ -1564,7 +1692,9 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty i += 2; } else if (isLineEnd(ch)) { styler.ColourTo(i - 1, StateToPrint); - state = SCE_HJ_STRINGEOL; + if (chPrev != '\\' && (chPrev2 != '\\' || chPrev != '\r' || ch != '\n')) { + state = SCE_HJ_STRINGEOL; + } } break; case SCE_HJ_STRINGEOL: @@ -1708,7 +1838,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty break; case SCE_HP_WORD: if (!IsAWordChar(ch)) { - classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType); + classifyWordHTPy(styler.GetStartSegment(), i - 1, keywords4, styler, prevWord, inScriptType, isMako); state = SCE_HP_DEFAULT; if (ch == '#') { state = SCE_HP_COMMENTLINE; @@ -1859,7 +1989,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty styler.ColourTo(i, StateToPrint); state = SCE_HPHP_DEFAULT; } else if (isLineEnd(chPrev)) { - const int psdLength = strlen(phpStringDelimiter); + const int psdLength = static_cast<int>(strlen(phpStringDelimiter)); const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); if (isLineEnd(chAfterPsd) || @@ -1882,7 +2012,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty state = SCE_HPHP_DEFAULT; } } else if (isLineEnd(chPrev) && styler.Match(i, phpStringDelimiter)) { - const int psdLength = strlen(phpStringDelimiter); + const int psdLength = static_cast<int>(strlen(phpStringDelimiter)); const char chAfterPsd = styler.SafeGetCharAt(i + psdLength); const char chAfterPsd2 = styler.SafeGetCharAt(i + psdLength + 1); if (isLineEnd(chAfterPsd) || @@ -1997,14 +2127,15 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty classifyWordHTVB(styler.GetStartSegment(), lengthDoc - 1, keywords3, styler, inScriptType); break; case SCE_HP_WORD: - classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywords4, styler, prevWord, inScriptType); + classifyWordHTPy(styler.GetStartSegment(), lengthDoc - 1, keywords4, styler, prevWord, inScriptType, isMako); break; case SCE_HPHP_WORD: classifyWordHTPHP(styler.GetStartSegment(), lengthDoc - 1, keywords5, styler); break; default: StateToPrint = statePrintForState(state, inScriptType); - styler.ColourTo(lengthDoc - 1, StateToPrint); + if (static_cast<int>(styler.GetStartSegment()) < lengthDoc) + styler.ColourTo(lengthDoc - 1, StateToPrint); break; } diff --git a/src/stc/scintilla/lexers/LexHaskell.cxx b/src/stc/scintilla/lexers/LexHaskell.cxx new file mode 100644 index 0000000000..37d85d0cfb --- /dev/null +++ b/src/stc/scintilla/lexers/LexHaskell.cxx @@ -0,0 +1,368 @@ +/****************************************************************** + * LexHaskell.cxx + * + * A haskell lexer for the scintilla code control. + * Some stuff "lended" from LexPython.cxx and LexCPP.cxx. + * External lexer stuff inspired from the caml external lexer. + * + * Written by Tobias Engvall - tumm at dtek dot chalmers dot se + * + * Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com + * + * TODO: + * * Implement a folder :) + * * Nice Character-lexing (stuff inside '\''), LexPython has + * this. + * + * + *****************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#ifdef BUILD_AS_EXTERNAL_LEXER + +#include "ExternalLexer.h" +#include "WindowAccessor.h" + +#define BUILD_EXTERNAL_LEXER 0 + +#endif + +#define HA_MODE_DEFAULT 0 +#define HA_MODE_IMPORT1 1 +#define HA_MODE_IMPORT2 2 +#define HA_MODE_IMPORT3 3 +#define HA_MODE_MODULE 4 +#define HA_MODE_FFI 5 +#define HA_MODE_TYPE 6 + +static inline bool IsNewline(const int ch) { + return (ch == '\n' || ch == '\r'); +} + +static inline bool IsWhitespace(const int ch) { + return ( ch == ' ' + || ch == '\t' + || IsNewline(ch) ); +} + +static inline bool IsAWordStart(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '_'); +} + +static inline bool IsAWordChar(const int ch) { + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); +} + +static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) { + + WordList &keywords = *keywordlists[0]; + WordList &ffi = *keywordlists[1]; + + StyleContext sc(startPos, length, initStyle, styler); + + int lineCurrent = styler.GetLine(startPos); + int state = lineCurrent ? styler.GetLineState(lineCurrent-1) + : HA_MODE_DEFAULT; + int mode = state & 0xF; + int xmode = state >> 4; + + while (sc.More()) { + // Check for state end + + // Operator + if (sc.state == SCE_HA_OPERATOR) { + if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) { + sc.Forward(); + } else { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } + } + // String + else if (sc.state == SCE_HA_STRING) { + if (sc.ch == '\"') { + sc.Forward(); + styler.ColourTo(sc.currentPos-1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(2); + } else if (sc.atLineEnd) { + styler.ColourTo(sc.currentPos-1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } else { + sc.Forward(); + } + } + // Char + else if (sc.state == SCE_HA_CHARACTER) { + if (sc.ch == '\'') { + sc.Forward(); + styler.ColourTo(sc.currentPos-1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } else if (sc.ch == '\\') { + sc.Forward(2); + } else if (sc.atLineEnd) { + styler.ColourTo(sc.currentPos-1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } else { + sc.Forward(); + } + } + // Number + else if (sc.state == SCE_HA_NUMBER) { + if (IsADigit(sc.ch, xmode)) { + sc.Forward(); + } else if ((xmode == 10) && + (sc.ch == 'e' || sc.ch == 'E') && + (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-')) { + sc.Forward(); + if (sc.ch == '+' || sc.ch == '-') + sc.Forward(); + } else { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } + } + // Identifier + else if (sc.state == SCE_HA_IDENTIFIER) { + if (IsAWordChar(sc.ch)) { + sc.Forward(); + } else { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + int style = sc.state; + int new_mode = 0; + if (keywords.InList(s)) { + style = SCE_HA_KEYWORD; + } else if (isupper(s[0])) { + if (mode >= HA_MODE_IMPORT1 && mode <= HA_MODE_IMPORT3) { + style = SCE_HA_MODULE; + new_mode = HA_MODE_IMPORT2; + } else if (mode == HA_MODE_MODULE) + style = SCE_HA_MODULE; + else + style = SCE_HA_CAPITAL; + } else if (mode == HA_MODE_IMPORT1 && + strcmp(s,"qualified") == 0) { + style = SCE_HA_KEYWORD; + new_mode = HA_MODE_IMPORT1; + } else if (mode == HA_MODE_IMPORT2) { + if (strcmp(s,"as") == 0) { + style = SCE_HA_KEYWORD; + new_mode = HA_MODE_IMPORT3; + } else if (strcmp(s,"hiding") == 0) { + style = SCE_HA_KEYWORD; + } + } else if (mode == HA_MODE_FFI) { + if (ffi.InList(s)) { + style = SCE_HA_KEYWORD; + new_mode = HA_MODE_FFI; + } + } + else if (mode == HA_MODE_TYPE) { + if (strcmp(s,"family") == 0) + style = SCE_HA_KEYWORD; + } + styler.ColourTo(sc.currentPos - 1, style); + if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI) + new_mode = HA_MODE_IMPORT1; + else if (strcmp(s,"module") == 0) + new_mode = HA_MODE_MODULE; + else if (strcmp(s,"foreign") == 0) + new_mode = HA_MODE_FFI; + else if (strcmp(s,"type") == 0) + new_mode = HA_MODE_TYPE; + sc.ChangeState(SCE_HA_DEFAULT); + mode = new_mode; + } + } + + // Comments + // Oneliner + else if (sc.state == SCE_HA_COMMENTLINE) { + if (sc.atLineEnd) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } else { + sc.Forward(); + } + } + // Nested + else if (sc.state == SCE_HA_COMMENTBLOCK) { + if (sc.Match("{-")) { + sc.Forward(2); + xmode++; + } + else if (sc.Match("-}")) { + sc.Forward(2); + xmode--; + if (xmode == 0) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_HA_DEFAULT); + } + } else { + if (sc.atLineEnd) { + // Remember the line state for future incremental lexing + styler.SetLineState(lineCurrent, (xmode << 4) | mode); + lineCurrent++; + } + sc.Forward(); + } + } + // New state? + if (sc.state == SCE_HA_DEFAULT) { + // Digit + if (IsADigit(sc.ch) || + (sc.ch == '.' && IsADigit(sc.chNext)) || + (sc.ch == '-' && IsADigit(sc.chNext))) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.ChangeState(SCE_HA_NUMBER); + if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { + // Match anything starting with "0x" or "0X", too + sc.Forward(2); + xmode = 16; + } else if (sc.ch == '0' && (sc.chNext == 'O' || sc.chNext == 'o')) { + // Match anything starting with "0x" or "0X", too + sc.Forward(2); + xmode = 8; + } else { + sc.Forward(); + xmode = 10; + } + mode = HA_MODE_DEFAULT; + } + // Comment line + else if (sc.Match("--")) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(2); + sc.ChangeState(SCE_HA_COMMENTLINE); + // Comment block + } + else if (sc.Match("{-")) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(2); + sc.ChangeState(SCE_HA_COMMENTBLOCK); + xmode = 1; + } + // String + else if (sc.Match('\"')) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); + sc.ChangeState(SCE_HA_STRING); + } + // Character + else if (sc.Match('\'')) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); + sc.ChangeState(SCE_HA_CHARACTER); + } + else if (sc.ch == '(' || sc.ch == ')' || + sc.ch == '{' || sc.ch == '}' || + sc.ch == '[' || sc.ch == ']') { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); + styler.ColourTo(sc.currentPos - 1, SCE_HA_OPERATOR); + mode = HA_MODE_DEFAULT; + } + // Operator + else if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); + sc.ChangeState(SCE_HA_OPERATOR); + mode = HA_MODE_DEFAULT; + } + // Keyword + else if (IsAWordStart(sc.ch)) { + styler.ColourTo(sc.currentPos - 1, sc.state); + sc.Forward(); + sc.ChangeState(SCE_HA_IDENTIFIER); + } else { + if (sc.atLineEnd) { + // Remember the line state for future incremental lexing + styler.SetLineState(lineCurrent, (xmode << 4) | mode); + lineCurrent++; + } + sc.Forward(); + } + } + } + sc.Complete(); +} + +// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet. +// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com +#ifdef BUILD_EXTERNAL_LEXER +static const char* LexerName = "haskell"; + +void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle, + char *words[], WindowID window, char *props) +{ + PropSetSimple ps; + ps.SetMultiple(props); + WindowAccessor wa(window, ps); + + int nWL = 0; + for (; words[nWL]; nWL++) ; + WordList** wl = new WordList* [nWL + 1]; + int i = 0; + for (; i<nWL; i++) + { + wl[i] = new WordList(); + wl[i]->Set(words[i]); + } + wl[i] = 0; + + ColorizeHaskellDoc(startPos, length, initStyle, wl, wa); + wa.Flush(); + for (i=nWL-1;i>=0;i--) + delete wl[i]; + delete [] wl; +} + +void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle, + char *words[], WindowID window, char *props) +{ + +} + +int EXT_LEXER_DECL GetLexerCount() +{ + return 1; +} + +void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength) +{ + if (buflength > 0) { + buflength--; + int n = strlen(LexerName); + if (n > buflength) + n = buflength; + memcpy(name, LexerName, n), name[n] = '\0'; + } +} +#endif + +LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell"); diff --git a/src/stc/scintilla/src/LexInno.cxx b/src/stc/scintilla/lexers/LexInno.cxx similarity index 94% rename from src/stc/scintilla/src/LexInno.cxx rename to src/stc/scintilla/lexers/LexInno.cxx index 6d1102c654..a0f5b3271a 100644 --- a/src/stc/scintilla/src/LexInno.cxx +++ b/src/stc/scintilla/lexers/LexInno.cxx @@ -7,19 +7,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "CharClassify.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -34,7 +36,6 @@ static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *k char *buffer = new char[length]; int bufferCount = 0; bool isBOL, isEOL, isWS, isBOLWS = 0; - bool isCode = false; bool isCStyleComment = false; WordList §ionKeywords = *keywordLists[0]; @@ -44,6 +45,10 @@ static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *k WordList &pascalKeywords = *keywordLists[4]; WordList &userKeywords = *keywordLists[5]; + int curLine = styler.GetLine(startPos); + int curLineState = curLine > 0 ? styler.GetLineState(curLine - 1) : 0; + bool isCode = (curLineState == 1); + // Go through all provided text segment // using the hand-written state machine shown below styler.StartAt(startPos); @@ -64,6 +69,12 @@ static void ColouriseInnoDoc(unsigned int startPos, int length, int, WordList *k isEOL = (ch == '\n' || ch == '\r'); isWS = (ch == ' ' || ch == '\t'); + if ((ch == '\r' && chNext != '\n') || (ch == '\n')) { + // Remember the line state for future incremental lexing + curLine = styler.GetLine(i); + styler.SetLineState(curLine, (isCode ? 1 : 0)); + } + switch(state) { case SCE_INNO_DEFAULT: if (!isCode && ch == ';' && isBOLWS) { diff --git a/src/stc/scintilla/src/LexKix.cxx b/src/stc/scintilla/lexers/LexKix.cxx similarity index 96% rename from src/stc/scintilla/src/LexKix.cxx rename to src/stc/scintilla/lexers/LexKix.cxx index 06e7c1791f..32af263fdf 100644 --- a/src/stc/scintilla/src/LexKix.cxx +++ b/src/stc/scintilla/lexers/LexKix.cxx @@ -7,18 +7,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexLisp.cxx b/src/stc/scintilla/lexers/LexLisp.cxx similarity index 97% rename from src/stc/scintilla/src/LexLisp.cxx rename to src/stc/scintilla/lexers/LexLisp.cxx index e1d06cbac4..08f765ad63 100644 --- a/src/stc/scintilla/src/LexLisp.cxx +++ b/src/stc/scintilla/lexers/LexLisp.cxx @@ -8,18 +8,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" #include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -44,7 +47,7 @@ static inline bool isLispwordstart(char ch) { static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) { - PLATFORM_ASSERT(end >= start); + assert(end >= start); char s[100]; unsigned int i; bool digit_flag = true; @@ -139,7 +142,7 @@ static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, W } } } else if (state == SCE_LISP_MACRO_DISPATCH) { - if (!isdigit(ch)) { + if (!(isascii(ch) && isdigit(ch))) { if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) { state = SCE_LISP_DEFAULT; } else { diff --git a/src/stc/scintilla/src/LexLout.cxx b/src/stc/scintilla/lexers/LexLout.cxx similarity index 97% rename from src/stc/scintilla/src/LexLout.cxx rename to src/stc/scintilla/lexers/LexLout.cxx index 492e4ed6d6..985b93b49c 100644 --- a/src/stc/scintilla/src/LexLout.cxx +++ b/src/stc/scintilla/lexers/LexLout.cxx @@ -7,18 +7,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexLua.cxx b/src/stc/scintilla/lexers/LexLua.cxx similarity index 75% rename from src/stc/scintilla/src/LexLua.cxx rename to src/stc/scintilla/lexers/LexLua.cxx index a1e579f269..9e48efcd92 100644 --- a/src/stc/scintilla/src/LexLua.cxx +++ b/src/stc/scintilla/lexers/LexLua.cxx @@ -9,19 +9,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> -#include <stdarg.h> #include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" #include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -57,10 +59,11 @@ static void ColouriseLuaDoc( // Accepts accented characters CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); + CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); // Not exactly following number definition (several dots are seen as OK, etc.) - // but probably enough in most cases. - CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefABCDEF"); + // but probably enough in most cases. [pP] is for hex floats. + CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefpABCDEFP"); + CharacterSet setExponent(CharacterSet::setNone, "eEpP"); CharacterSet setLuaOperator(CharacterSet::setNone, "*/-+()={}~[];<>,.^%:#"); CharacterSet setEscapeSkip(CharacterSet::setNone, "\"'\\"); @@ -68,12 +71,16 @@ static void ColouriseLuaDoc( // Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level, // if we are inside such a string. Block comment was introduced in Lua 5.0, // blocks with separators [=[ ... ]=] in Lua 5.1. + // Continuation of a string (\z whitespace escaping) is controlled by stringWs. int nestLevel = 0; int sepCount = 0; - if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) { + int stringWs = 0; + if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT || + initStyle == SCE_LUA_STRING || initStyle == SCE_LUA_CHARACTER) { int lineState = styler.GetLineState(currentLine - 1); - nestLevel = lineState >> 8; + nestLevel = lineState >> 9; sepCount = lineState & 0xFF; + stringWs = lineState & 0x100; } // Do not leak onto next line @@ -93,8 +100,10 @@ static void ColouriseLuaDoc( switch (sc.state) { case SCE_LUA_LITERALSTRING: case SCE_LUA_COMMENT: - // Inside a literal string or block comment, we set the line state - styler.SetLineState(currentLine, (nestLevel << 8) | sepCount); + case SCE_LUA_STRING: + case SCE_LUA_CHARACTER: + // Inside a literal string, block comment or string, we set the line state + styler.SetLineState(currentLine, (nestLevel << 9) | stringWs | sepCount); break; default: // Reset the line state @@ -121,21 +130,91 @@ static void ColouriseLuaDoc( // Determine if the current state should terminate. if (sc.state == SCE_LUA_OPERATOR) { + if (sc.ch == ':' && sc.chPrev == ':') { // :: <label> :: forward scan + sc.Forward(); + int ln = 0, maxln = startPos + length - sc.currentPos; + int c; + while (ln < maxln) { // determine line extent + c = sc.GetRelative(ln); + if (c == '\r' || c == '\n') + break; + ln++; + } + maxln = ln; ln = 0; + while (ln < maxln) { // skip over spaces/tabs + if (!IsASpaceOrTab(sc.GetRelative(ln))) + break; + ln++; + } + int ws1 = ln; + if (setWordStart.Contains(sc.GetRelative(ln))) { + int i = 0; + char s[100]; + while (ln < maxln) { // get potential label + c = sc.GetRelative(ln); + if (!setWord.Contains(c)) + break; + if (i < 90) + s[i++] = c; + ln++; + } + s[i] = '\0'; int lbl = ln; + if (!keywords.InList(s)) { + while (ln < maxln) { // skip over spaces/tabs + if (!IsASpaceOrTab(sc.GetRelative(ln))) + break; + ln++; + } + int ws2 = ln - lbl; + if (sc.GetRelative(ln) == ':' && sc.GetRelative(ln + 1) == ':') { + // final :: found, complete valid label construct + sc.ChangeState(SCE_LUA_LABEL); + if (ws1) { + sc.SetState(SCE_LUA_DEFAULT); + sc.Forward(ws1); + } + sc.SetState(SCE_LUA_LABEL); + sc.Forward(lbl - ws1); + if (ws2) { + sc.SetState(SCE_LUA_DEFAULT); + sc.Forward(ws2); + } + sc.SetState(SCE_LUA_LABEL); + sc.Forward(2); + } + } + } + } sc.SetState(SCE_LUA_DEFAULT); } else if (sc.state == SCE_LUA_NUMBER) { - // We stop the number definition on non-numerical non-dot non-eE non-sign non-hexdigit char + // We stop the number definition on non-numerical non-dot non-eEpP non-sign non-hexdigit char if (!setNumber.Contains(sc.ch)) { sc.SetState(SCE_LUA_DEFAULT); } else if (sc.ch == '-' || sc.ch == '+') { - if (sc.chPrev != 'E' && sc.chPrev != 'e') + if (!setExponent.Contains(sc.chPrev)) sc.SetState(SCE_LUA_DEFAULT); } } else if (sc.state == SCE_LUA_IDENTIFIER) { - if (!setWord.Contains(sc.ch) || sc.Match('.', '.')) { + if (!(setWord.Contains(sc.ch) || sc.ch == '.') || sc.Match('.', '.')) { char s[100]; sc.GetCurrent(s, sizeof(s)); if (keywords.InList(s)) { sc.ChangeState(SCE_LUA_WORD); + if (strcmp(s, "goto") == 0) { // goto <label> forward scan + sc.SetState(SCE_LUA_DEFAULT); + while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) + sc.Forward(); + if (setWordStart.Contains(sc.ch)) { + sc.SetState(SCE_LUA_LABEL); + sc.Forward(); + while (setWord.Contains(sc.ch)) + sc.Forward(); + sc.GetCurrent(s, sizeof(s)); + if (keywords.InList(s)) + sc.ChangeState(SCE_LUA_WORD); + } + sc.SetState(SCE_LUA_DEFAULT); + } } else if (keywords2.InList(s)) { sc.ChangeState(SCE_LUA_WORD2); } else if (keywords3.InList(s)) { @@ -158,24 +237,38 @@ static void ColouriseLuaDoc( sc.ForwardSetState(SCE_LUA_DEFAULT); } } else if (sc.state == SCE_LUA_STRING) { + if (stringWs) { + if (!IsASpace(sc.ch)) + stringWs = 0; + } if (sc.ch == '\\') { if (setEscapeSkip.Contains(sc.chNext)) { sc.Forward(); + } else if (sc.chNext == 'z') { + sc.Forward(); + stringWs = 0x100; } } else if (sc.ch == '\"') { sc.ForwardSetState(SCE_LUA_DEFAULT); - } else if (sc.atLineEnd) { + } else if (stringWs == 0 && sc.atLineEnd) { sc.ChangeState(SCE_LUA_STRINGEOL); sc.ForwardSetState(SCE_LUA_DEFAULT); } } else if (sc.state == SCE_LUA_CHARACTER) { + if (stringWs) { + if (!IsASpace(sc.ch)) + stringWs = 0; + } if (sc.ch == '\\') { if (setEscapeSkip.Contains(sc.chNext)) { sc.Forward(); + } else if (sc.chNext == 'z') { + sc.Forward(); + stringWs = 0x100; } } else if (sc.ch == '\'') { sc.ForwardSetState(SCE_LUA_DEFAULT); - } else if (sc.atLineEnd) { + } else if (stringWs == 0 && sc.atLineEnd) { sc.ChangeState(SCE_LUA_STRINGEOL); sc.ForwardSetState(SCE_LUA_DEFAULT); } @@ -212,8 +305,10 @@ static void ColouriseLuaDoc( sc.SetState(SCE_LUA_IDENTIFIER); } else if (sc.ch == '\"') { sc.SetState(SCE_LUA_STRING); + stringWs = 0; } else if (sc.ch == '\'') { sc.SetState(SCE_LUA_CHARACTER); + stringWs = 0; } else if (sc.ch == '[') { sepCount = LongDelimCheck(sc); if (sepCount == 0) { @@ -244,7 +339,7 @@ static void ColouriseLuaDoc( } } - if (setWord.Contains(sc.chPrev)) { + if (setWord.Contains(sc.chPrev) || sc.chPrev == '.') { char s[100]; sc.GetCurrent(s, sizeof(s)); if (keywords.InList(s)) { diff --git a/src/stc/scintilla/src/LexMMIXAL.cxx b/src/stc/scintilla/lexers/LexMMIXAL.cxx similarity index 96% rename from src/stc/scintilla/src/LexMMIXAL.cxx rename to src/stc/scintilla/lexers/LexMMIXAL.cxx index a00f35ca03..43361d4297 100644 --- a/src/stc/scintilla/src/LexMMIXAL.cxx +++ b/src/stc/scintilla/lexers/LexMMIXAL.cxx @@ -9,18 +9,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -32,10 +35,10 @@ static inline bool IsAWordChar(const int ch) { } inline bool isMMIXALOperator(char ch) { - if (isalnum(ch)) + if (isascii(ch) && isalnum(ch)) return false; if (ch == '+' || ch == '-' || ch == '|' || ch == '^' || - ch == '*' || ch == '/' || ch == '/' || + ch == '*' || ch == '/' || ch == '%' || ch == '<' || ch == '>' || ch == '&' || ch == '~' || ch == '$' || ch == ',' || ch == '(' || ch == ')' || diff --git a/src/stc/scintilla/src/LexMPT.cxx b/src/stc/scintilla/lexers/LexMPT.cxx similarity index 91% rename from src/stc/scintilla/src/LexMPT.cxx rename to src/stc/scintilla/lexers/LexMPT.cxx index b0099ff862..b3eed34422 100644 --- a/src/stc/scintilla/src/LexMPT.cxx +++ b/src/stc/scintilla/lexers/LexMPT.cxx @@ -7,21 +7,26 @@ // Copyright 2003 by Marius Gheorghe <mgheorghe@cabletest.com> // The License.txt file describes the conditions under which this software may be distributed. +#include <stdlib.h> #include <string.h> #include <stdio.h> +#include <stdarg.h> +#include <assert.h> #include <ctype.h> -#include <stdlib.h> #include <string> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -32,7 +37,7 @@ static int GetLotLineState(std::string &line) { // Now finds the first non-blank character unsigned i; // Declares counter here to make it persistent after the for loop for (i = 0; i < line.length(); ++i) { - if (!isspace(line[i])) + if (!(isascii(line[i]) && isspace(line[i]))) break; } @@ -66,7 +71,7 @@ static int GetLotLineState(std::string &line) { return SCE_LOT_ABORT; } else { - return i ? SCE_LOT_PASS : SCE_LOT_DEFAULT; + return i ? SCE_LOT_PASS : SCE_LOT_DEFAULT; } } } @@ -135,10 +140,10 @@ static void FoldLotDoc(unsigned int startPos, int length, int, WordList *[], Acc if (ch == '\r' && chNext == '\n') { // TO DO: // Should really get the state of the previous line from the styler - int stylePrev = style; + int stylePrev = style; style = styleNext; styleNext = styler.StyleAt(i + 2); - + switch (style) { /* case SCE_LOT_SET: @@ -147,7 +152,7 @@ static void FoldLotDoc(unsigned int startPos, int length, int, WordList *[], Acc */ case SCE_LOT_FAIL: /* - if (stylePrev != SCE_LOT_FAIL) + if (stylePrev != SCE_LOT_FAIL) lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; else lev = SC_FOLDLEVELBASE + 1; @@ -156,7 +161,7 @@ static void FoldLotDoc(unsigned int startPos, int length, int, WordList *[], Acc break; default: - if (lineCurrent == 0 || stylePrev == SCE_LOT_FAIL) + if (lineCurrent == 0 || stylePrev == SCE_LOT_FAIL) lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; else lev = SC_FOLDLEVELBASE + 1; @@ -166,7 +171,7 @@ static void FoldLotDoc(unsigned int startPos, int length, int, WordList *[], Acc break; } - if (lev != styler.LevelAt(lineCurrent)) + if (lev != styler.LevelAt(lineCurrent)) styler.SetLevel(lineCurrent, lev); lineCurrent++; diff --git a/src/stc/scintilla/src/LexMSSQL.cxx b/src/stc/scintilla/lexers/LexMSSQL.cxx similarity index 98% rename from src/stc/scintilla/src/LexMSSQL.cxx rename to src/stc/scintilla/lexers/LexMSSQL.cxx index 4a3f3bed83..ce600394c5 100644 --- a/src/stc/scintilla/src/LexMSSQL.cxx +++ b/src/stc/scintilla/lexers/LexMSSQL.cxx @@ -7,18 +7,22 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif diff --git a/src/stc/scintilla/src/LexMagik.cxx b/src/stc/scintilla/lexers/LexMagik.cxx similarity index 98% rename from src/stc/scintilla/src/LexMagik.cxx rename to src/stc/scintilla/lexers/LexMagik.cxx index c6f6585b3b..992080dd8a 100644 --- a/src/stc/scintilla/src/LexMagik.cxx +++ b/src/stc/scintilla/lexers/LexMagik.cxx @@ -8,18 +8,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -230,7 +233,7 @@ static void ColouriseMagikDoc(unsigned int startPos, int length, int initStyle, } if(characters.InList(keyword)) { - sc.Forward(strlen(keyword)); + sc.Forward(static_cast<int>(strlen(keyword))); } else { sc.Forward(); } diff --git a/src/stc/scintilla/src/LexMarkdown.cxx b/src/stc/scintilla/lexers/LexMarkdown.cxx similarity index 89% rename from src/stc/scintilla/src/LexMarkdown.cxx rename to src/stc/scintilla/lexers/LexMarkdown.cxx index f7fc48f40f..a926977074 100644 --- a/src/stc/scintilla/src/LexMarkdown.cxx +++ b/src/stc/scintilla/lexers/LexMarkdown.cxx @@ -2,31 +2,31 @@ * LexMarkdown.cxx * * A simple Markdown lexer for scintilla. - * + * * Includes highlighting for some extra features from the - * Pandoc implementation; strikeout, using '#.' as a default + * Pandoc implementation; strikeout, using '#.' as a default * ordered list item marker, and delimited code blocks. - * + * * Limitations: - * + * * Standard indented code blocks are not highlighted at all, - * as it would conflict with other indentation schemes. Use + * as it would conflict with other indentation schemes. Use * delimited code blocks for blanket highlighting of an * entire code block. Embedded HTML is not highlighted either. * Blanket HTML highlighting has issues, because some Markdown * implementations allow Markdown markup inside of the HTML. Also, - * there is a following blank line issue that can't be ignored, - * explained in the next paragraph. Embedded HTML and code - * blocks would be better supported with language specific + * there is a following blank line issue that can't be ignored, + * explained in the next paragraph. Embedded HTML and code + * blocks would be better supported with language specific * highlighting. - * + * * The highlighting aims to accurately reflect correct syntax, * but a few restrictions are relaxed. Delimited code blocks are - * highlighted, even if the line following the code block is not blank. + * highlighted, even if the line following the code block is not blank. * Requiring a blank line after a block, breaks the highlighting * in certain cases, because of the way Scintilla ends up calling * the lexer. - * + * * Written by Jon Strait - jstrait@moonloop.net * * The License.txt file describes the conditions under which this @@ -34,20 +34,22 @@ * *****************************************************************/ -#include <stdlib.h> +#include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -74,7 +76,7 @@ static bool FollowToLineEnd(const int ch, const int state, const unsigned int en else return false; } -// Set the state on text section from current to length characters, +// Set the state on text section from current to length characters, // then set the rest until the newline to default, except for any characters matching token static void SetStateAndZoom(const int state, const int length, const int token, StyleContext &sc) { sc.SetState(state); @@ -100,9 +102,9 @@ static void SetStateAndZoom(const int state, const int length, const int token, static bool HasPrevLineContent(StyleContext &sc) { int i = 0; // Go back to the previous newline - while ((--i + sc.currentPos) && !IsNewline(sc.GetRelative(i))) + while ((--i + (int)sc.currentPos) >= 0 && !IsNewline(sc.GetRelative(i))) ; - while (--i + sc.currentPos) { + while ((--i + (int)sc.currentPos) >= 0) { if (IsNewline(sc.GetRelative(i))) break; if (!IsASpaceOrTab(sc.GetRelative(i))) @@ -111,17 +113,21 @@ static bool HasPrevLineContent(StyleContext &sc) { return false; } +static bool AtTermStart(StyleContext &sc) { + return sc.currentPos == 0 || isspacechar(sc.chPrev); +} + static bool IsValidHrule(const unsigned int endPos, StyleContext &sc) { int c, count = 1; unsigned int i = 0; while (++i) { c = sc.GetRelative(i); - if (c == sc.ch) + if (c == sc.ch) ++count; // hit a terminating character else if (!IsASpaceOrTab(c) || sc.currentPos + i == endPos) { // Are we a valid HRULE - if ((IsNewline(c) || sc.currentPos + i == endPos) && + if ((IsNewline(c) || sc.currentPos + i == endPos) && count >= 3 && !HasPrevLineContent(sc)) { sc.SetState(SCE_MARKDOWN_HRULE); sc.Forward(i); @@ -145,7 +151,7 @@ static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle // Useful in the corner case of having to start at the beginning file position // in the default state. bool freezeCursor = false; - + StyleContext sc(startPos, length, initStyle, styler); while (sc.More()) { @@ -154,18 +160,18 @@ static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle sc.Forward(); continue; } - + // A blockquotes resets the line semantics if (sc.state == SCE_MARKDOWN_BLOCKQUOTE) sc.SetState(SCE_MARKDOWN_LINE_BEGIN); - + // Conditional state-based actions if (sc.state == SCE_MARKDOWN_CODE2) { if (sc.Match("``") && sc.GetRelative(-2) != ' ') { sc.Forward(2); sc.SetState(SCE_MARKDOWN_DEFAULT); } - } + } else if (sc.state == SCE_MARKDOWN_CODE) { if (sc.ch == '`' && sc.chPrev != ' ') sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); @@ -201,14 +207,14 @@ static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle sc.Forward(2); sc.SetState(SCE_MARKDOWN_DEFAULT); } - } - else if (sc.state == SCE_MARKDOWN_STRONG2) { - if (sc.Match("__") && sc.chPrev != ' ') { + } + else if (sc.state == SCE_MARKDOWN_STRONG2) { + if (sc.Match("__") && sc.chPrev != ' ') { sc.Forward(2); sc.SetState(SCE_MARKDOWN_DEFAULT); } } - // Emphasis + // Emphasis else if (sc.state == SCE_MARKDOWN_EM1) { if (sc.ch == '*' && sc.chPrev != ' ') sc.ForwardSetState(SCE_MARKDOWN_DEFAULT); @@ -281,7 +287,7 @@ static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle sc.SetState(SCE_MARKDOWN_PRECHAR); } } - + // The header lasts until the newline else if (sc.state == SCE_MARKDOWN_HEADER1 || sc.state == SCE_MARKDOWN_HEADER2 || sc.state == SCE_MARKDOWN_HEADER3 || sc.state == SCE_MARKDOWN_HEADER4 || @@ -289,7 +295,7 @@ static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle if (IsNewline(sc.ch)) sc.SetState(SCE_MARKDOWN_LINE_BEGIN); } - + // New state only within the initial whitespace if (sc.state == SCE_MARKDOWN_PRECHAR) { // Blockquote @@ -300,8 +306,8 @@ static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle else if (!HasPrevLineContent(sc) && (sc.chPrev == '\t' || precharCount >= 4)) sc.SetState(SCE_MARKDOWN_CODEBK); */ - // HRule - Total of three or more hyphens, asterisks, or underscores - // on a line by themselves + // HRule - Total of three or more hyphens, asterisks, or underscores + // on a line by themselves else if ((sc.ch == '-' || sc.ch == '*' || sc.ch == '_') && IsValidHrule(endPos, sc)) ; // Unordered list @@ -314,7 +320,7 @@ static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle int digitCount = 0; while (IsADigit(sc.GetRelative(++digitCount))) ; - if (sc.GetRelative(digitCount) == '.' && + if (sc.GetRelative(digitCount) == '.' && IsASpaceOrTab(sc.GetRelative(digitCount + 1))) { sc.SetState(SCE_MARKDOWN_OLIST_ITEM); sc.Forward(digitCount + 1); @@ -332,7 +338,7 @@ static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle else ++precharCount; } - + // New state anywhere in doc if (sc.state == SCE_MARKDOWN_DEFAULT) { if (sc.atLineStart && sc.ch == '#') { @@ -371,35 +377,38 @@ static void ColorizeMarkdownDoc(unsigned int startPos, int length, int initStyle } } // Code - also a special case for alternate inside spacing - if (sc.Match("``") && sc.GetRelative(3) != ' ') { + if (sc.Match("``") && sc.GetRelative(3) != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_CODE2); sc.Forward(); } - else if (sc.ch == '`' && sc.chNext != ' ') { + else if (sc.ch == '`' && sc.chNext != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_CODE); } // Strong - else if (sc.Match("**") && sc.GetRelative(2) != ' ') { + else if (sc.Match("**") && sc.GetRelative(2) != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_STRONG1); sc.Forward(); } - else if (sc.Match("__") && sc.GetRelative(2) != ' ') { + else if (sc.Match("__") && sc.GetRelative(2) != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_STRONG2); sc.Forward(); } // Emphasis - else if (sc.ch == '*' && sc.chNext != ' ') + else if (sc.ch == '*' && sc.chNext != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_EM1); - else if (sc.ch == '_' && sc.chNext != ' ') + } + else if (sc.ch == '_' && sc.chNext != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_EM2); + } // Strikeout - else if (sc.Match("~~") && sc.GetRelative(2) != ' ') { + else if (sc.Match("~~") && sc.GetRelative(2) != ' ' && AtTermStart(sc)) { sc.SetState(SCE_MARKDOWN_STRIKEOUT); sc.Forward(); } // Beginning of line - else if (IsNewline(sc.ch)) + else if (IsNewline(sc.ch)) { sc.SetState(SCE_MARKDOWN_LINE_BEGIN); + } } // Advance if not holding back the cursor for this iteration. if (!freezeCursor) diff --git a/src/stc/scintilla/src/LexMatlab.cxx b/src/stc/scintilla/lexers/LexMatlab.cxx similarity index 96% rename from src/stc/scintilla/src/LexMatlab.cxx rename to src/stc/scintilla/lexers/LexMatlab.cxx index 4e467bd2ff..68915af0e9 100644 --- a/src/stc/scintilla/src/LexMatlab.cxx +++ b/src/stc/scintilla/lexers/LexMatlab.cxx @@ -12,18 +12,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -103,12 +106,12 @@ static void ColouriseMatlabOctaveDoc( transpose = true; } } else if (sc.state == SCE_MATLAB_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_MATLAB_DEFAULT); + if (sc.ch == '\'') { + if (sc.chNext == '\'') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_MATLAB_DEFAULT); + } } } else if (sc.state == SCE_MATLAB_DOUBLEQUOTESTRING) { if (sc.ch == '\\') { diff --git a/src/stc/scintilla/src/LexMetapost.cxx b/src/stc/scintilla/lexers/LexMetapost.cxx similarity index 98% rename from src/stc/scintilla/src/LexMetapost.cxx rename to src/stc/scintilla/lexers/LexMetapost.cxx index 6afc9d8265..d049521cf8 100644 --- a/src/stc/scintilla/src/LexMetapost.cxx +++ b/src/stc/scintilla/lexers/LexMetapost.cxx @@ -14,18 +14,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" #include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -326,11 +329,11 @@ static const char * const metapostWordListDesc[] = { static int classifyFoldPointMetapost(const char* s,WordList *keywordlists[]) { WordList& keywordsStart=*keywordlists[3]; WordList& keywordsStop1=*keywordlists[4]; - + if (keywordsStart.InList(s)) {return 1;} else if (keywordsStop1.InList(s)) {return -1;} return 0; - + } static int ParseMetapostWord(unsigned int pos, Accessor &styler, char *word) @@ -344,11 +347,11 @@ static int ParseMetapostWord(unsigned int pos, Accessor &styler, char *word) length++; ch=styler.SafeGetCharAt(pos+length); } - word[length]=0; + word[length]=0; return length; } - -static void FoldMetapostDoc(unsigned int startPos, int length, int, WordList *keywordlists[], Accessor &styler) + +static void FoldMetapostDoc(unsigned int startPos, int length, int, WordList *keywordlists[], Accessor &styler) { bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; unsigned int endPos = startPos+length; @@ -357,9 +360,9 @@ static void FoldMetapostDoc(unsigned int startPos, int length, int, WordList *ke int levelPrev=styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; int levelCurrent=levelPrev; char chNext=styler[startPos]; - + char buffer[100]=""; - + for (unsigned int i=startPos; i < endPos; i++) { char ch=chNext; chNext=styler.SafeGetCharAt(i+1); @@ -371,7 +374,7 @@ static void FoldMetapostDoc(unsigned int startPos, int length, int, WordList *ke ParseMetapostWord(i, styler, buffer); levelCurrent += classifyFoldPointMetapost(buffer,keywordlists); } - + if (atEOL) { int lev = levelPrev; if (visibleChars == 0 && foldCompact) diff --git a/src/stc/scintilla/lexers/LexModula.cxx b/src/stc/scintilla/lexers/LexModula.cxx new file mode 100644 index 0000000000..cc5847fd68 --- /dev/null +++ b/src/stc/scintilla/lexers/LexModula.cxx @@ -0,0 +1,743 @@ +// -*- coding: utf-8 -*- +// Scintilla source code edit control +/** + * @file LexModula.cxx + * @author Dariusz "DKnoto" Knociński + * @date 2011/02/03 + * @brief Lexer for Modula-2/3 documents. + */ +// The License.txt file describes the conditions under which this software may +// be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#ifdef DEBUG_LEX_MODULA +#define DEBUG_STATE( p, c )\ + fprintf( stderr, "Unknown state: currentPos = %d, char = '%c'\n", p, c ); +#else +#define DEBUG_STATE( p, c ) +#endif + +static inline bool IsDigitOfBase( unsigned ch, unsigned base ) { + if( ch < '0' || ch > 'f' ) return false; + if( base <= 10 ) { + if( ch >= ( '0' + base ) ) return false; + } else { + if( ch > '9' ) { + unsigned nb = base - 10; + if( ( ch < 'A' ) || ( ch >= ( 'A' + nb ) ) ) { + if( ( ch < 'a' ) || ( ch >= ( 'a' + nb ) ) ) { + return false; + } + } + } + } + return true; +} + +static inline unsigned IsOperator( StyleContext & sc, WordList & op ) { + int i; + char s[3]; + + s[0] = sc.ch; + s[1] = sc.chNext; + s[2] = 0; + for( i = 0; i < op.len; i++ ) { + if( ( strlen( op.words[i] ) == 2 ) && + ( s[0] == op.words[i][0] && s[1] == op.words[i][1] ) ) { + return 2; + } + } + s[1] = 0; + for( i = 0; i < op.len; i++ ) { + if( ( strlen( op.words[i] ) == 1 ) && + ( s[0] == op.words[i][0] ) ) { + return 1; + } + } + return 0; +} + +static inline bool IsEOL( Accessor &styler, unsigned curPos ) { + unsigned ch = styler.SafeGetCharAt( curPos ); + if( ( ch == '\r' && styler.SafeGetCharAt( curPos + 1 ) == '\n' ) || + ( ch == '\n' ) ) { + return true; + } + return false; +} + +static inline bool checkStatement( + Accessor &styler, + int &curPos, + const char *stt, bool spaceAfter = true ) { + int len = static_cast<int>(strlen( stt )); + int i; + for( i = 0; i < len; i++ ) { + if( styler.SafeGetCharAt( curPos + i ) != stt[i] ) { + return false; + } + } + if( spaceAfter ) { + if( ! isspace( styler.SafeGetCharAt( curPos + i ) ) ) { + return false; + } + } + curPos += ( len - 1 ); + return true; +} + +static inline bool checkEndSemicolon( + Accessor &styler, + int &curPos, int endPos ) +{ + const char *stt = "END"; + int len = static_cast<int>(strlen( stt )); + int i; + for( i = 0; i < len; i++ ) { + if( styler.SafeGetCharAt( curPos + i ) != stt[i] ) { + return false; + } + } + while( isspace( styler.SafeGetCharAt( curPos + i ) ) ) { + i++; + if( ( curPos + i ) >= endPos ) return false; + } + if( styler.SafeGetCharAt( curPos + i ) != ';' ) { + return false; + } + curPos += ( i - 1 ); + return true; +} + +static inline bool checkKeyIdentOper( + + Accessor &styler, + int &curPos, int endPos, + const char *stt, const char etk ) { + int newPos = curPos; + if( ! checkStatement( styler, newPos, stt ) ) + return false; + newPos++; + if( newPos >= endPos ) + return false; + if( ! isspace( styler.SafeGetCharAt( newPos ) ) ) + return false; + newPos++; + if( newPos >= endPos ) + return false; + while( isspace( styler.SafeGetCharAt( newPos ) ) ) { + newPos++; + if( newPos >= endPos ) + return false; + } + if( ! isalpha( styler.SafeGetCharAt( newPos ) ) ) + return false; + newPos++; + if( newPos >= endPos ) + return false; + char ch; + ch = styler.SafeGetCharAt( newPos ); + while( isalpha( ch ) || isdigit( ch ) || ch == '_' ) { + newPos++; + if( newPos >= endPos ) return false; + ch = styler.SafeGetCharAt( newPos ); + } + while( isspace( styler.SafeGetCharAt( newPos ) ) ) { + newPos++; + if( newPos >= endPos ) return false; + } + if( styler.SafeGetCharAt( newPos ) != etk ) + return false; + curPos = newPos; + return true; +} + +static void FoldModulaDoc( unsigned int startPos, + int length, + int , WordList *[], + Accessor &styler) +{ + int curLine = styler.GetLine(startPos); + int curLevel = SC_FOLDLEVELBASE; + int endPos = startPos + length; + if( curLine > 0 ) + curLevel = styler.LevelAt( curLine - 1 ) >> 16; + int curPos = startPos; + int style = styler.StyleAt( curPos ); + int visChars = 0; + int nextLevel = curLevel; + + while( curPos < endPos ) { + if( ! isspace( styler.SafeGetCharAt( curPos ) ) ) visChars++; + + switch( style ) { + case SCE_MODULA_COMMENT: + if( checkStatement( styler, curPos, "(*" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "*)" ) ) + nextLevel--; + break; + + case SCE_MODULA_DOXYCOMM: + if( checkStatement( styler, curPos, "(**", false ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "*)" ) ) + nextLevel--; + break; + + case SCE_MODULA_KEYWORD: + if( checkStatement( styler, curPos, "IF" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "BEGIN" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "TRY" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "LOOP" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "FOR" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "WHILE" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "REPEAT" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "UNTIL" ) ) + nextLevel--; + else + if( checkStatement( styler, curPos, "WITH" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "CASE" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "TYPECASE" ) ) + nextLevel++; + else + if( checkStatement( styler, curPos, "LOCK" ) ) + nextLevel++; + else + if( checkKeyIdentOper( styler, curPos, endPos, "PROCEDURE", '(' ) ) + nextLevel++; + else + if( checkKeyIdentOper( styler, curPos, endPos, "END", ';' ) ) { + int cln = curLine; + int clv_old = curLevel; + int pos; + char ch; + int clv_new; + while( cln > 0 ) { + clv_new = styler.LevelAt( cln - 1 ) >> 16; + if( clv_new < clv_old ) { + nextLevel--; + pos = styler.LineStart( cln ); + while( ( ch = styler.SafeGetCharAt( pos ) ) != '\n' ) { + if( ch == 'P' ) { + if( styler.StyleAt(pos) == SCE_MODULA_KEYWORD ) { + if( checkKeyIdentOper( styler, pos, endPos, + "PROCEDURE", '(' ) ) { + break; + } + } + } + pos++; + } + clv_old = clv_new; + } + cln--; + } + } + else + if( checkKeyIdentOper( styler, curPos, endPos, "END", '.' ) ) + nextLevel--; + else + if( checkEndSemicolon( styler, curPos, endPos ) ) + nextLevel--; + else { + while( styler.StyleAt( curPos + 1 ) == SCE_MODULA_KEYWORD ) + curPos++; + } + break; + + default: + break; + } + + if( IsEOL( styler, curPos ) || ( curPos == endPos - 1 ) ) { + int efectiveLevel = curLevel | nextLevel << 16; + if( visChars == 0 ) + efectiveLevel |= SC_FOLDLEVELWHITEFLAG; + if( curLevel < nextLevel ) + efectiveLevel |= SC_FOLDLEVELHEADERFLAG; + if( efectiveLevel != styler.LevelAt(curLine) ) { + styler.SetLevel(curLine, efectiveLevel ); + } + curLine++; + curLevel = nextLevel; + if( IsEOL( styler, curPos ) && ( curPos == endPos - 1 ) ) { + styler.SetLevel( curLine, ( curLevel | curLevel << 16) + | SC_FOLDLEVELWHITEFLAG); + } + visChars = 0; + } + curPos++; + style = styler.StyleAt( curPos ); + } +} + +static inline bool skipWhiteSpaces( StyleContext & sc ) { + while( isspace( sc.ch ) ) { + sc.SetState( SCE_MODULA_DEFAULT ); + if( sc.More() ) + sc.Forward(); + else + return false; + } + return true; +} + +static void ColouriseModulaDoc( unsigned int startPos, + int length, + int initStyle, + WordList *wl[], + Accessor &styler ) { + WordList& keyWords = *wl[0]; + WordList& reservedWords = *wl[1]; + WordList& operators = *wl[2]; + WordList& pragmaWords = *wl[3]; + WordList& escapeCodes = *wl[4]; + WordList& doxyKeys = *wl[5]; + + const int BUFLEN = 128; + + char buf[BUFLEN]; + int i, kl; + + int charPos = 0; + + StyleContext sc( startPos, length, initStyle, styler ); + + while( sc.More() ) { + switch( sc.state ) { + case SCE_MODULA_DEFAULT: + if( ! skipWhiteSpaces( sc ) ) break; + + if( sc.ch == '(' && sc.chNext == '*' ) { + if( sc.GetRelative(2) == '*' ) { + sc.SetState( SCE_MODULA_DOXYCOMM ); + sc.Forward(); + } else { + sc.SetState( SCE_MODULA_COMMENT ); + } + sc.Forward(); + } + else + if( isalpha( sc.ch ) ) { + if( isupper( sc.ch ) && isupper( sc.chNext ) ) { + for( i = 0; i < BUFLEN - 1; i++ ) { + buf[i] = sc.GetRelative(i); + if( !isalpha( buf[i] ) && !(buf[i] == '_') ) + break; + } + kl = i; + buf[kl] = 0; + + if( keyWords.InList( buf ) ) { + sc.SetState( SCE_MODULA_KEYWORD ); + sc.Forward( kl ); + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } + else + if( reservedWords.InList( buf ) ) { + sc.SetState( SCE_MODULA_RESERVED ); + sc.Forward( kl ); + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } else { + /** check procedure identifier */ + } + } else { + for( i = 0; i < BUFLEN - 1; i++ ) { + buf[i] = sc.GetRelative(i); + if( !isalpha( buf[i] ) && + !isdigit( buf[i] ) && + !(buf[i] == '_') ) + break; + } + kl = i; + buf[kl] = 0; + + sc.SetState( SCE_MODULA_DEFAULT ); + sc.Forward( kl ); + continue; + } + } + else + if( isdigit( sc.ch ) ) { + sc.SetState( SCE_MODULA_NUMBER ); + continue; + } + else + if( sc.ch == '\"' ) { + sc.SetState( SCE_MODULA_STRING ); + } + else + if( sc.ch == '\'' ) { + charPos = sc.currentPos; + sc.SetState( SCE_MODULA_CHAR ); + } + else + if( sc.ch == '<' && sc.chNext == '*' ) { + sc.SetState( SCE_MODULA_PRAGMA ); + sc.Forward(); + } else { + unsigned len = IsOperator( sc, operators ); + if( len > 0 ) { + sc.SetState( SCE_MODULA_OPERATOR ); + sc.Forward( len ); + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } else { + DEBUG_STATE( sc.currentPos, sc.ch ); + } + } + break; + + case SCE_MODULA_COMMENT: + if( sc.ch == '*' && sc.chNext == ')' ) { + sc.Forward( 2 ); + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } + break; + + case SCE_MODULA_DOXYCOMM: + switch( sc.ch ) { + case '*': + if( sc.chNext == ')' ) { + sc.Forward( 2 ); + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } + break; + + case '@': + if( islower( sc.chNext ) ) { + for( i = 0; i < BUFLEN - 1; i++ ) { + buf[i] = sc.GetRelative(i+1); + if( isspace( buf[i] ) ) break; + } + buf[i] = 0; + kl = i; + + if( doxyKeys.InList( buf ) ) { + sc.SetState( SCE_MODULA_DOXYKEY ); + sc.Forward( kl + 1 ); + sc.SetState( SCE_MODULA_DOXYCOMM ); + } + } + break; + + default: + break; + } + break; + + case SCE_MODULA_NUMBER: + { + buf[0] = sc.ch; + for( i = 1; i < BUFLEN - 1; i++ ) { + buf[i] = sc.GetRelative(i); + if( ! isdigit( buf[i] ) ) + break; + } + kl = i; + buf[kl] = 0; + + switch( sc.GetRelative(kl) ) { + case '_': + { + int base = atoi( buf ); + if( base < 2 || base > 16 ) { + sc.SetState( SCE_MODULA_BADSTR ); + } else { + int imax; + + kl++; + for( i = 0; i < BUFLEN - 1; i++ ) { + buf[i] = sc.GetRelative(kl+i); + if( ! IsDigitOfBase( buf[i], 16 ) ) { + break; + } + } + imax = i; + for( i = 0; i < imax; i++ ) { + if( ! IsDigitOfBase( buf[i], base ) ) { + sc.SetState( SCE_MODULA_BADSTR ); + break; + } + } + kl += imax; + } + sc.SetState( SCE_MODULA_BASENUM ); + for( i = 0; i < kl; i++ ) { + sc.Forward(); + } + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } + break; + + case '.': + if( sc.GetRelative(kl+1) == '.' ) { + kl--; + for( i = 0; i < kl; i++ ) { + sc.Forward(); + } + sc.Forward(); + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } else { + bool doNext = false; + + kl++; + + buf[0] = sc.GetRelative(kl); + if( isdigit( buf[0] ) ) { + for( i = 0;; i++ ) { + if( !isdigit(sc.GetRelative(kl+i)) ) + break; + } + kl += i; + buf[0] = sc.GetRelative(kl); + + switch( buf[0] ) + { + case 'E': + case 'e': + case 'D': + case 'd': + case 'X': + case 'x': + kl++; + buf[0] = sc.GetRelative(kl); + if( buf[0] == '-' || buf[0] == '+' ) { + kl++; + } + buf[0] = sc.GetRelative(kl); + if( isdigit( buf[0] ) ) { + for( i = 0;; i++ ) { + if( !isdigit(sc.GetRelative(kl+i)) ) { + buf[0] = sc.GetRelative(kl+i); + break; + } + } + kl += i; + doNext = true; + } else { + sc.SetState( SCE_MODULA_BADSTR ); + } + break; + + default: + doNext = true; + break; + } + } else { + sc.SetState( SCE_MODULA_BADSTR ); + } + + if( doNext ) { + if( ! isspace( buf[0] ) && + buf[0] != ')' && + buf[0] != '>' && + buf[0] != '<' && + buf[0] != '=' && + buf[0] != '#' && + buf[0] != '+' && + buf[0] != '-' && + buf[0] != '*' && + buf[0] != '/' && + buf[0] != ',' && + buf[0] != ';' + ) { + sc.SetState( SCE_MODULA_BADSTR ); + } else { + kl--; + } + } + } + sc.SetState( SCE_MODULA_FLOAT ); + for( i = 0; i < kl; i++ ) { + sc.Forward(); + } + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + break; + + default: + for( i = 0; i < kl; i++ ) { + sc.Forward(); + } + break; + } + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } + break; + + case SCE_MODULA_STRING: + if( sc.ch == '\"' ) { + sc.Forward(); + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } else { + if( sc.ch == '\\' ) { + i = 1; + if( IsDigitOfBase( sc.chNext, 8 ) ) { + for( i = 1; i < BUFLEN - 1; i++ ) { + if( ! IsDigitOfBase(sc.GetRelative(i+1), 8 ) ) + break; + } + if( i == 3 ) { + sc.SetState( SCE_MODULA_STRSPEC ); + } else { + sc.SetState( SCE_MODULA_BADSTR ); + } + } else { + buf[0] = sc.chNext; + buf[1] = 0; + + if( escapeCodes.InList( buf ) ) { + sc.SetState( SCE_MODULA_STRSPEC ); + } else { + sc.SetState( SCE_MODULA_BADSTR ); + } + } + sc.Forward(i+1); + sc.SetState( SCE_MODULA_STRING ); + continue; + } + } + break; + + case SCE_MODULA_CHAR: + if( sc.ch == '\'' ) { + sc.Forward(); + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } + else + if( ( sc.currentPos - charPos ) == 1 ) { + if( sc.ch == '\\' ) { + i = 1; + if( IsDigitOfBase( sc.chNext, 8 ) ) { + for( i = 1; i < BUFLEN - 1; i++ ) { + if( ! IsDigitOfBase(sc.GetRelative(i+1), 8 ) ) + break; + } + if( i == 3 ) { + sc.SetState( SCE_MODULA_CHARSPEC ); + } else { + sc.SetState( SCE_MODULA_BADSTR ); + } + } else { + buf[0] = sc.chNext; + buf[1] = 0; + + if( escapeCodes.InList( buf ) ) { + sc.SetState( SCE_MODULA_CHARSPEC ); + } else { + sc.SetState( SCE_MODULA_BADSTR ); + } + } + sc.Forward(i+1); + sc.SetState( SCE_MODULA_CHAR ); + continue; + } + } else { + sc.SetState( SCE_MODULA_BADSTR ); + sc.Forward(); + sc.SetState( SCE_MODULA_CHAR ); + continue; + } + break; + + case SCE_MODULA_PRAGMA: + if( sc.ch == '*' && sc.chNext == '>' ) { + sc.Forward(); + sc.Forward(); + sc.SetState( SCE_MODULA_DEFAULT ); + continue; + } + else + if( isupper( sc.ch ) && isupper( sc.chNext ) ) { + buf[0] = sc.ch; + buf[1] = sc.chNext; + for( i = 2; i < BUFLEN - 1; i++ ) { + buf[i] = sc.GetRelative(i); + if( !isupper( buf[i] ) ) + break; + } + kl = i; + buf[kl] = 0; + if( pragmaWords.InList( buf ) ) { + sc.SetState( SCE_MODULA_PRGKEY ); + sc.Forward( kl ); + sc.SetState( SCE_MODULA_PRAGMA ); + continue; + } + } + break; + + default: + break; + } + sc.Forward(); + } + sc.Complete(); +} + +static const char *const modulaWordListDesc[] = +{ + "Keywords", + "ReservedKeywords", + "Operators", + "PragmaKeyswords", + "EscapeCodes", + "DoxygeneKeywords", + 0 +}; + +LexerModule lmModula( SCLEX_MODULA, ColouriseModulaDoc, "modula", FoldModulaDoc, + modulaWordListDesc); diff --git a/src/stc/scintilla/src/LexMySQL.cxx b/src/stc/scintilla/lexers/LexMySQL.cxx similarity index 77% rename from src/stc/scintilla/src/LexMySQL.cxx rename to src/stc/scintilla/lexers/LexMySQL.cxx index e8496ceea2..305fa74517 100644 --- a/src/stc/scintilla/src/LexMySQL.cxx +++ b/src/stc/scintilla/lexers/LexMySQL.cxx @@ -12,18 +12,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -113,12 +116,12 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, if (!IsAWordChar(sc.ch)) { CheckForKeyword(sc, keywordlists); - + // Additional check for function keywords needed. // A function name must be followed by an opening parenthesis. if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(') sc.ChangeState(SCE_MYSQL_DEFAULT); - + sc.SetState(SCE_MYSQL_DEFAULT); } break; @@ -137,7 +140,7 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, if (keywordlists[4]->InList(&s[2])) sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE); delete [] s; - + sc.SetState(SCE_MYSQL_DEFAULT); } break; @@ -232,7 +235,7 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, if (sc.Match('/', '*')) { sc.SetState(SCE_MYSQL_COMMENT); - + // Skip comment introducer and check for hidden command. sc.Forward(2); if (sc.ch == '!') @@ -247,7 +250,7 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, // Special MySQL single line comment. sc.SetState(SCE_MYSQL_COMMENTLINE); sc.Forward(2); - + // Check the third character too. It must be a space or EOL. if (sc.ch != ' ' && sc.ch != '\n' && sc.ch != '\r') sc.ChangeState(SCE_MYSQL_OPERATOR); @@ -258,7 +261,7 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, } } } - + // Do a final check for keywords if we currently have an identifier, to highlight them // also at the end of a line. if (sc.state == SCE_MYSQL_IDENTIFIER) @@ -270,7 +273,7 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(') sc.ChangeState(SCE_MYSQL_DEFAULT); } - + sc.Complete(); } @@ -321,9 +324,9 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL int styleNext = styler.StyleAt(startPos); int style = initStyle; - bool endFound = false; - bool whenFound = false; - bool elseFound = false; + bool endPending = false; + bool whenPending = false; + bool elseIfPending = false; char nextChar = styler.SafeGetCharAt(startPos); for (unsigned int i = startPos; length > 0; i++, length--) @@ -374,18 +377,42 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL } break; case SCE_MYSQL_HIDDENCOMMAND: + if (endPending) + { + // A conditional command is not a white space so it should end the current block + // before opening a new one. + endPending = false; + levelNext--; + if (levelNext < SC_FOLDLEVELBASE) + levelNext = SC_FOLDLEVELBASE; + } if (style != stylePrev) levelNext++; else if (style != styleNext) + { levelNext--; + if (levelNext < SC_FOLDLEVELBASE) + levelNext = SC_FOLDLEVELBASE; + } break; case SCE_MYSQL_OPERATOR: + if (endPending) + { + endPending = false; + levelNext--; + if (levelNext < SC_FOLDLEVELBASE) + levelNext = SC_FOLDLEVELBASE; + } if (currentChar == '(') levelNext++; else if (currentChar == ')') + { levelNext--; + if (levelNext < SC_FOLDLEVELBASE) + levelNext = SC_FOLDLEVELBASE; + } break; case SCE_MYSQL_MAJORKEYWORD: case SCE_MYSQL_KEYWORD: @@ -394,110 +421,98 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL // Reserved and other keywords. if (style != stylePrev) { - bool beginFound = MatchIgnoreCase(styler, i, "begin"); - bool ifFound = MatchIgnoreCase(styler, i, "if"); - bool thenFound = MatchIgnoreCase(styler, i, "then"); - bool whileFound = MatchIgnoreCase(styler, i, "while"); - bool loopFound = MatchIgnoreCase(styler, i, "loop"); - bool repeatFound = MatchIgnoreCase(styler, i, "repeat"); - - if (!foldOnlyBegin && endFound && (ifFound || whileFound || loopFound)) + // END decreases the folding level, regardless which keyword follows. + bool endFound = MatchIgnoreCase(styler, i, "end"); + if (endPending) { - endFound = false; levelNext--; if (levelNext < SC_FOLDLEVELBASE) levelNext = SC_FOLDLEVELBASE; - - // Note that "else" is special here. It may or may not be followed by an "if .. then", - // but in any case the level stays the same. When followed by an "if .. then" the level - // will be increased later, if not, then at eol. } else - if (!foldOnlyBegin && MatchIgnoreCase(styler, i, "else")) + if (!endFound) { - levelNext--; - elseFound = true; - } - else - if (!foldOnlyBegin && thenFound) - { - if (whenFound) - whenFound = false; - else - levelNext++; - } + if (MatchIgnoreCase(styler, i, "begin")) + levelNext++; else - if (ifFound) - elseFound = false; - else - if (MatchIgnoreCase(styler, i, "when")) - whenFound = true; + { + if (!foldOnlyBegin) + { + bool whileFound = MatchIgnoreCase(styler, i, "while"); + bool loopFound = MatchIgnoreCase(styler, i, "loop"); + bool repeatFound = MatchIgnoreCase(styler, i, "repeat"); + bool caseFound = MatchIgnoreCase(styler, i, "case"); + + if (whileFound || loopFound || repeatFound || caseFound) + levelNext++; else { - if (beginFound) - levelNext++; - else - if (!foldOnlyBegin && (loopFound || repeatFound || whileFound)) + // IF alone does not increase the fold level as it is also used in non-block'ed + // code like DROP PROCEDURE blah IF EXISTS. + // Instead THEN opens the new level (if not part of an ELSEIF or WHEN (case) branch). + if (MatchIgnoreCase(styler, i, "then")) + { + if (!elseIfPending && !whenPending) + levelNext++; + else { - if (endFound) - endFound = false; - else - levelNext++; + elseIfPending = false; + whenPending = false; } - else - if (MatchIgnoreCase(styler, i, "end")) - { - // Multiple "end" in a row are counted multiple times! - if (endFound) - { - levelNext--; - if (levelNext < SC_FOLDLEVELBASE) - levelNext = SC_FOLDLEVELBASE; - } - endFound = true; - whenFound = false; - } + } + else + { + // Neither of if/then/while/loop/repeat/case, so check for + // sub parts of IF and CASE. + if (MatchIgnoreCase(styler, i, "elseif")) + elseIfPending = true; + if (MatchIgnoreCase(styler, i, "when")) + whenPending = true; + } } + } + } + } + + // Keep the current end state for the next round. + endPending = endFound; + } + break; + + default: + if (!isspace(currentChar) && endPending) + { + // END followed by a non-whitespace character (not covered by other cases like identifiers) + // also should end a folding block. Typical case: END followed by self defined delimiter. + levelNext--; + if (levelNext < SC_FOLDLEVELBASE) + levelNext = SC_FOLDLEVELBASE; } break; } - // Handle the case of a trailing end without an if / while etc, as in the case of a begin. - if (endFound) - { - endFound = false; - levelNext--; - if (levelNext < SC_FOLDLEVELBASE) - levelNext = SC_FOLDLEVELBASE; - } - - if (atEOL) + if (atEOL) { - if (elseFound) - { - levelNext++; - elseFound = false; - } - - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) - styler.SetLevel(lineCurrent, lev); + // Apply the new folding level to this line. + // Leave pending states as they are otherwise a line break will de-sync + // code folding and valid syntax. + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) + styler.SetLevel(lineCurrent, lev); - lineCurrent++; - levelCurrent = levelNext; - visibleChars = 0; - endFound = false; - whenFound = false; - } - + lineCurrent++; + levelCurrent = levelNext; + visibleChars = 0; + } + if (!isspacechar(currentChar)) - visibleChars++; - } + visibleChars++; + } } //-------------------------------------------------------------------------------------------------- diff --git a/src/stc/scintilla/src/LexNimrod.cxx b/src/stc/scintilla/lexers/LexNimrod.cxx similarity index 96% rename from src/stc/scintilla/src/LexNimrod.cxx rename to src/stc/scintilla/lexers/LexNimrod.cxx index 8c4d043606..08b76fe694 100644 --- a/src/stc/scintilla/src/LexNimrod.cxx +++ b/src/stc/scintilla/lexers/LexNimrod.cxx @@ -9,18 +9,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -113,7 +116,7 @@ static int scanNumber(Accessor &styler, int pos) { if (ch == '_' || (ch >= '0' && ch <= '1')) ++pos; else break; } - } else if (ch == '0' && + } else if (ch == '0' && (ch2 == 'o' || ch2 == 'O' || ch2 == 'c' || ch2 == 'C')) { /* octal number: */ pos += 2; @@ -203,7 +206,7 @@ static void ColouriseNimrodDoc(unsigned int startPos, int length, int initStyle, case '#': { bool doccomment = (styler.SafeGetCharAt(pos+1) == '#'); while (pos < max && !isNewLine(styler.SafeGetCharAt(pos, LF))) pos++; - if (doccomment) + if (doccomment) styler.ColourTo(pos, SCE_C_COMMENTLINEDOC); else styler.ColourTo(pos, SCE_P_COMMENTLINE); @@ -280,7 +283,7 @@ static bool IsQuoteLine(int line, Accessor &styler) { } -static void FoldNimrodDoc(unsigned int startPos, int length, +static void FoldNimrodDoc(unsigned int startPos, int length, int /*initStyle - unused*/, WordList *[], Accessor &styler) { const int maxPos = startPos + length; @@ -311,7 +314,7 @@ static void FoldNimrodDoc(unsigned int startPos, int length, int prev_state = SCE_P_DEFAULT & 31; if (lineCurrent >= 1) prev_state = styler.StyleAt(startPos - 1) & 31; - int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) || + int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) || (prev_state == SCE_P_TRIPLEDOUBLE)); int prevComment = 0; if (lineCurrent >= 1) @@ -320,7 +323,7 @@ static void FoldNimrodDoc(unsigned int startPos, int length, // Process all characters to end of requested range or end of any triple quote // or comment that hangs over the end of the range. Cap processing in all cases // to end of document (in case of unclosed quote or comment at end). - while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || + while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevQuote || prevComment)) { // Gather info @@ -338,7 +341,7 @@ static void FoldNimrodDoc(unsigned int startPos, int length, const int quote_continue = (quote && prevQuote); const int comment = foldComment && IsCommentLine(lineCurrent, styler); const int comment_start = (comment && !prevComment && (lineNext <= docLines) && - IsCommentLine(lineNext, styler) && + IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE)); const int comment_continue = (comment && prevComment); if ((!quote || !prevQuote) && !comment) @@ -377,8 +380,8 @@ static void FoldNimrodDoc(unsigned int startPos, int length, } const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; - const int levelBeforeComments = - Platform::Maximum(indentCurrentLevel,levelAfterComments); + const int levelBeforeComments = + Maximum(indentCurrentLevel,levelAfterComments); // Now set all the indent levels on the lines we skipped // Do this from end to start. Once we encounter one line @@ -401,7 +404,7 @@ static void FoldNimrodDoc(unsigned int startPos, int length, // Set fold header on non-quote/non-comment line if (!quote && !comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) { - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < + if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) lev |= SC_FOLDLEVELHEADERFLAG; } diff --git a/src/stc/scintilla/src/LexNsis.cxx b/src/stc/scintilla/lexers/LexNsis.cxx similarity index 99% rename from src/stc/scintilla/src/LexNsis.cxx rename to src/stc/scintilla/lexers/LexNsis.cxx index 43ddc47061..599ccfbbf0 100644 --- a/src/stc/scintilla/src/LexNsis.cxx +++ b/src/stc/scintilla/lexers/LexNsis.cxx @@ -5,21 +5,25 @@ // Copyright 2003 - 2005 by Angelo Mandato <angelo [at] spaceblue [dot] com> // Last Updated: 03/13/2005 // The License.txt file describes the conditions under which this software may be distributed. + #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "CharClassify.h" -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -138,6 +142,7 @@ static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel bIgnoreCase = true; char s[20]; // The key word we are looking for has atmost 13 characters + s[0] = '\0'; for (unsigned int i = 0; i < end - start + 1 && i < 19; i++) { s[i] = static_cast<char>( styler[ start + i ] ); diff --git a/src/stc/scintilla/lexers/LexOScript.cxx b/src/stc/scintilla/lexers/LexOScript.cxx new file mode 100644 index 0000000000..9daff34d5a --- /dev/null +++ b/src/stc/scintilla/lexers/LexOScript.cxx @@ -0,0 +1,548 @@ +// Scintilla source code edit control +/** @file LexOScript.cxx + ** Lexer for OScript sources; ocx files and/or OSpace dumps. + ** OScript is a programming language used to develop applications for the + ** Livelink server platform. + **/ +// Written by Ferdinand Prantl <prantlf@gmail.com>, inspired by the code from +// LexVB.cxx and LexPascal.cxx. The License.txt file describes the conditions +// under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// ----------------------------------------- +// Functions classifying a single character. + +// This function is generic and should be probably moved to CharSet.h where +// IsAlphaNumeric the others reside. +inline bool IsAlpha(int ch) { + return (ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'); +} + +static inline bool IsIdentifierChar(int ch) { + // Identifiers cannot contain non-ASCII letters; a word with non-English + // language-specific characters cannot be an identifier. + return IsAlphaNumeric(ch) || ch == '_'; +} + +static inline bool IsIdentifierStart(int ch) { + // Identifiers cannot contain non-ASCII letters; a word with non-English + // language-specific characters cannot be an identifier. + return IsAlpha(ch) || ch == '_'; +} + +static inline bool IsNumberChar(int ch, int chNext) { + // Numeric constructs are not checked for lexical correctness. They are + // expected to look like +1.23-E9 but actually any bunch of the following + // characters will be styled as number. + // KNOWN PROBLEM: if you put + or - operators immediately after a number + // and the next operand starts with the letter E, the operator will not be + // recognized and it will be styled together with the preceding number. + // This should not occur; at least not often. The coding style recommends + // putting spaces around operators. + return IsADigit(ch) || toupper(ch) == 'E' || ch == '.' || + ((ch == '-' || ch == '+') && toupper(chNext) == 'E'); +} + +// This function checks for the start or a natural number without any symbols +// or operators as a prefix; the IsPrefixedNumberStart should be called +// immediately after this one to cover all possible numeric constructs. +static inline bool IsNaturalNumberStart(int ch) { + return IsADigit(ch) != 0; +} + +static inline bool IsPrefixedNumberStart(int ch, int chNext) { + // KNOWN PROBLEM: if you put + or - operators immediately before a number + // the operator will not be recognized and it will be styled together with + // the succeeding number. This should not occur; at least not often. The + // coding style recommends putting spaces around operators. + return (ch == '.' || ch == '-' || ch == '+') && IsADigit(chNext); +} + +static inline bool IsOperator(int ch) { + return strchr("%^&*()-+={}[]:;<>,/?!.~|\\", ch) != NULL; +} + +// --------------------------------------------------------------- +// Functions classifying a token currently processed in the lexer. + +// Checks if the current line starts with the preprocessor directive used +// usually to introduce documentation comments: #ifdef DOC. This method is +// supposed to be called if the line has been recognized as a preprocessor +// directive already. +static bool IsDocCommentStart(StyleContext &sc) { + // Check the line back to its start only if the end looks promising. + if (sc.LengthCurrent() == 10 && !IsAlphaNumeric(sc.ch)) { + char s[11]; + sc.GetCurrentLowered(s, sizeof(s)); + return strcmp(s, "#ifdef doc") == 0; + } + return false; +} + +// Checks if the current line starts with the preprocessor directive that +// is complementary to the #ifdef DOC start: #endif. This method is supposed +// to be called if the current state point to the documentation comment. +// QUESTIONAL ASSUMPTION: The complete #endif directive is not checked; just +// the starting #e. However, there is no other preprocessor directive with +// the same starting letter and thus this optimization should always work. +static bool IsDocCommentEnd(StyleContext &sc) { + return sc.ch == '#' && sc.chNext == 'e'; +} + +class IdentifierClassifier { + WordList &keywords; // Passed from keywords property. + WordList &constants; // Passed from keywords2 property. + WordList &operators; // Passed from keywords3 property. + WordList &types; // Passed from keywords4 property. + WordList &functions; // Passed from keywords5 property. + WordList &objects; // Passed from keywords6 property. + + IdentifierClassifier(IdentifierClassifier const&); + IdentifierClassifier& operator=(IdentifierClassifier const&); + +public: + IdentifierClassifier(WordList *keywordlists[]) : + keywords(*keywordlists[0]), constants(*keywordlists[1]), + operators(*keywordlists[2]), types(*keywordlists[3]), + functions(*keywordlists[4]), objects(*keywordlists[5]) + {} + + void ClassifyIdentifier(StyleContext &sc) { + // Opening parenthesis following an identifier makes it a possible + // function call. + // KNOWN PROBLEM: If some whitespace is inserted between the + // identifier and the parenthesis they will not be able to be + // recognized as a function call. This should not occur; at + // least not often. Such coding style would be weird. + if (sc.Match('(')) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + // Before an opening brace can be control statements and + // operators too; function call is the last option. + if (keywords.InList(s)) { + sc.ChangeState(SCE_OSCRIPT_KEYWORD); + } else if (operators.InList(s)) { + sc.ChangeState(SCE_OSCRIPT_OPERATOR); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_OSCRIPT_FUNCTION); + } else { + sc.ChangeState(SCE_OSCRIPT_METHOD); + } + sc.SetState(SCE_OSCRIPT_OPERATOR); + } else { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + // A dot following an identifier means an access to an object + // member. The related object identifier can be special. + // KNOWN PROBLEM: If there is whitespace between the identifier + // and the following dot, the identifier will not be recognized + // as an object in an object member access. If it is one of the + // listed static objects it will not be styled. + if (sc.Match('.') && objects.InList(s)) { + sc.ChangeState(SCE_OSCRIPT_OBJECT); + sc.SetState(SCE_OSCRIPT_OPERATOR); + } else { + if (keywords.InList(s)) { + sc.ChangeState(SCE_OSCRIPT_KEYWORD); + } else if (constants.InList(s)) { + sc.ChangeState(SCE_OSCRIPT_CONSTANT); + } else if (operators.InList(s)) { + sc.ChangeState(SCE_OSCRIPT_OPERATOR); + } else if (types.InList(s)) { + sc.ChangeState(SCE_OSCRIPT_TYPE); + } else if (functions.InList(s)) { + sc.ChangeState(SCE_OSCRIPT_FUNCTION); + } + sc.SetState(SCE_OSCRIPT_DEFAULT); + } + } + } +}; + +// ------------------------------------------------ +// Function colourising an excerpt of OScript code. + +static void ColouriseOScriptDoc(unsigned int startPos, int length, + int initStyle, WordList *keywordlists[], + Accessor &styler) { + // I wonder how whole-line styles ended by EOLN can escape the resetting + // code in the loop below and overflow to the next line. Let us make sure + // that a new line does not start with them carried from the previous one. + // NOTE: An overflowing string is intentionally not checked; it reminds + // the developer that the string must be ended on the same line. + if (initStyle == SCE_OSCRIPT_LINE_COMMENT || + initStyle == SCE_OSCRIPT_PREPROCESSOR) { + initStyle = SCE_OSCRIPT_DEFAULT; + } + + styler.StartAt(startPos); + StyleContext sc(startPos, length, initStyle, styler); + IdentifierClassifier identifierClassifier(keywordlists); + + // It starts with true at the beginning of a line and changes to false as + // soon as the first non-whitespace character has been processed. + bool isFirstToken = true; + // It starts with true at the beginning of a line and changes to false as + // soon as the first identifier on the line is passed by. + bool isFirstIdentifier = true; + // It becomes false when #ifdef DOC (the preprocessor directive often + // used to start a documentation comment) is encountered and remain false + // until the end of the documentation block is not detected. This is done + // by checking for the complementary #endif preprocessor directive. + bool endDocComment = false; + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineStart) { + isFirstToken = true; + isFirstIdentifier = true; + // Detect the current state is neither whitespace nor identifier. It + // means that no next identifier can be the first token on the line. + } else if (isFirstIdentifier && sc.state != SCE_OSCRIPT_DEFAULT && + sc.state != SCE_OSCRIPT_IDENTIFIER) { + isFirstIdentifier = false; + } + + // Check if the current state should be changed. + if (sc.state == SCE_OSCRIPT_OPERATOR) { + // Multiple-symbol operators are marked by single characters. + sc.SetState(SCE_OSCRIPT_DEFAULT); + } else if (sc.state == SCE_OSCRIPT_IDENTIFIER) { + if (!IsIdentifierChar(sc.ch)) { + // Colon after an identifier makes it a label if it is the + // first token on the line. + // KNOWN PROBLEM: If some whitespace is inserted between the + // identifier and the colon they will not be recognized as a + // label. This should not occur; at least not often. It would + // make the code structure less legible and examples in the + // Livelink documentation do not show it. + if (sc.Match(':') && isFirstIdentifier) { + sc.ChangeState(SCE_OSCRIPT_LABEL); + sc.ForwardSetState(SCE_OSCRIPT_DEFAULT); + } else { + identifierClassifier.ClassifyIdentifier(sc); + } + // Avoid a sequence of two words be mistaken for a label. A + // switch case would be an example. + isFirstIdentifier = false; + } + } else if (sc.state == SCE_OSCRIPT_GLOBAL) { + if (!IsIdentifierChar(sc.ch)) { + sc.SetState(SCE_OSCRIPT_DEFAULT); + } + } else if (sc.state == SCE_OSCRIPT_PROPERTY) { + if (!IsIdentifierChar(sc.ch)) { + // Any member access introduced by the dot operator is + // initially marked as a property access. If an opening + // parenthesis is detected later it is changed to method call. + // KNOWN PROBLEM: The same as at the function call recognition + // for SCE_OSCRIPT_IDENTIFIER above. + if (sc.Match('(')) { + sc.ChangeState(SCE_OSCRIPT_METHOD); + } + sc.SetState(SCE_OSCRIPT_DEFAULT); + } + } else if (sc.state == SCE_OSCRIPT_NUMBER) { + if (!IsNumberChar(sc.ch, sc.chNext)) { + sc.SetState(SCE_OSCRIPT_DEFAULT); + } + } else if (sc.state == SCE_OSCRIPT_SINGLEQUOTE_STRING) { + if (sc.ch == '\'') { + // Two consequential apostrophes convert to a single one. + if (sc.chNext == '\'') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_OSCRIPT_DEFAULT); + } + } else if (sc.atLineEnd) { + sc.ForwardSetState(SCE_OSCRIPT_DEFAULT); + } + } else if (sc.state == SCE_OSCRIPT_DOUBLEQUOTE_STRING) { + if (sc.ch == '\"') { + // Two consequential quotation marks convert to a single one. + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_OSCRIPT_DEFAULT); + } + } else if (sc.atLineEnd) { + sc.ForwardSetState(SCE_OSCRIPT_DEFAULT); + } + } else if (sc.state == SCE_OSCRIPT_BLOCK_COMMENT) { + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_OSCRIPT_DEFAULT); + } + } else if (sc.state == SCE_OSCRIPT_LINE_COMMENT) { + if (sc.atLineEnd) { + sc.ForwardSetState(SCE_OSCRIPT_DEFAULT); + } + } else if (sc.state == SCE_OSCRIPT_PREPROCESSOR) { + if (IsDocCommentStart(sc)) { + sc.ChangeState(SCE_OSCRIPT_DOC_COMMENT); + endDocComment = false; + } else if (sc.atLineEnd) { + sc.ForwardSetState(SCE_OSCRIPT_DEFAULT); + } + } else if (sc.state == SCE_OSCRIPT_DOC_COMMENT) { + // KNOWN PROBLEM: The first line detected that would close a + // conditional preprocessor block (#endif) the documentation + // comment block will end. (Nested #if-#endif blocks are not + // supported. Hopefully it will not occur often that a line + // within the text block would stat with #endif. + if (isFirstToken && IsDocCommentEnd(sc)) { + endDocComment = true; + } else if (sc.atLineEnd && endDocComment) { + sc.ForwardSetState(SCE_OSCRIPT_DEFAULT); + } + } + + // Check what state starts with the current character. + if (sc.state == SCE_OSCRIPT_DEFAULT) { + if (sc.Match('\'')) { + sc.SetState(SCE_OSCRIPT_SINGLEQUOTE_STRING); + } else if (sc.Match('\"')) { + sc.SetState(SCE_OSCRIPT_DOUBLEQUOTE_STRING); + } else if (sc.Match('/', '/')) { + sc.SetState(SCE_OSCRIPT_LINE_COMMENT); + sc.Forward(); + } else if (sc.Match('/', '*')) { + sc.SetState(SCE_OSCRIPT_BLOCK_COMMENT); + sc.Forward(); + } else if (isFirstToken && sc.Match('#')) { + sc.SetState(SCE_OSCRIPT_PREPROCESSOR); + } else if (sc.Match('$')) { + // Both process-global ($xxx) and thread-global ($$xxx) + // variables are handled as one global. + sc.SetState(SCE_OSCRIPT_GLOBAL); + } else if (IsNaturalNumberStart(sc.ch)) { + sc.SetState(SCE_OSCRIPT_NUMBER); + } else if (IsPrefixedNumberStart(sc.ch, sc.chNext)) { + sc.SetState(SCE_OSCRIPT_NUMBER); + sc.Forward(); + } else if (sc.Match('.') && IsIdentifierStart(sc.chNext)) { + // Every object member access is marked as a property access + // initially. The decision between property and method is made + // after parsing the identifier and looking what comes then. + // KNOWN PROBLEM: If there is whitespace between the following + // identifier and the dot, the dot will not be recognized + // as a member accessing operator. In turn, the identifier + // will not be recognizable as a property or a method too. + sc.SetState(SCE_OSCRIPT_OPERATOR); + sc.Forward(); + sc.SetState(SCE_OSCRIPT_PROPERTY); + } else if (IsIdentifierStart(sc.ch)) { + sc.SetState(SCE_OSCRIPT_IDENTIFIER); + } else if (IsOperator(sc.ch)) { + sc.SetState(SCE_OSCRIPT_OPERATOR); + } + } + + if (isFirstToken && !IsASpaceOrTab(sc.ch)) { + isFirstToken = false; + } + } + + sc.Complete(); +} + +// ------------------------------------------ +// Functions supporting OScript code folding. + +static inline bool IsBlockComment(int style) { + return style == SCE_OSCRIPT_BLOCK_COMMENT; +} + +static bool IsLineComment(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eolPos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eolPos; i++) { + char ch = styler[i]; + char chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + if (ch == '/' && chNext == '/' && style == SCE_OSCRIPT_LINE_COMMENT) { + return true; + } else if (!IsASpaceOrTab(ch)) { + return false; + } + } + return false; +} + +static inline bool IsPreprocessor(int style) { + return style == SCE_OSCRIPT_PREPROCESSOR || + style == SCE_OSCRIPT_DOC_COMMENT; +} + +static void GetRangeLowered(unsigned int start, unsigned int end, + Accessor &styler, char *s, unsigned int len) { + unsigned int i = 0; + while (i < end - start + 1 && i < len - 1) { + s[i] = static_cast<char>(tolower(styler[start + i])); + i++; + } + s[i] = '\0'; +} + +static void GetForwardWordLowered(unsigned int start, Accessor &styler, + char *s, unsigned int len) { + unsigned int i = 0; + while (i < len - 1 && IsAlpha(styler.SafeGetCharAt(start + i))) { + s[i] = static_cast<char>(tolower(styler.SafeGetCharAt(start + i))); + i++; + } + s[i] = '\0'; +} + +static void UpdatePreprocessorFoldLevel(int &levelCurrent, + unsigned int startPos, Accessor &styler) { + char s[7]; // Size of the longest possible keyword + null. + GetForwardWordLowered(startPos, styler, s, sizeof(s)); + + if (strcmp(s, "ifdef") == 0 || + strcmp(s, "ifndef") == 0) { + levelCurrent++; + } else if (strcmp(s, "endif") == 0) { + levelCurrent--; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; + } + } +} + +static void UpdateKeywordFoldLevel(int &levelCurrent, unsigned int lastStart, + unsigned int currentPos, Accessor &styler) { + char s[9]; + GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s)); + + if (strcmp(s, "if") == 0 || strcmp(s, "for") == 0 || + strcmp(s, "switch") == 0 || strcmp(s, "function") == 0 || + strcmp(s, "while") == 0 || strcmp(s, "repeat") == 0) { + levelCurrent++; + } else if (strcmp(s, "end") == 0 || strcmp(s, "until") == 0) { + levelCurrent--; + if (levelCurrent < SC_FOLDLEVELBASE) { + levelCurrent = SC_FOLDLEVELBASE; + } + } +} + +// ------------------------------ +// Function folding OScript code. + +static void FoldOScriptDoc(unsigned int startPos, int length, int initStyle, + WordList *[], Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; + bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; + int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK; + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + int lastStart = 0; + + for (int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atLineEnd = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + if (foldComment && IsBlockComment(style)) { + if (!IsBlockComment(stylePrev)) { + levelCurrent++; + } else if (!IsBlockComment(styleNext) && !atLineEnd) { + // Comments do not end at end of line and the next character + // may not be styled. + levelCurrent--; + } + } + if (foldComment && atLineEnd && IsLineComment(lineCurrent, styler)) { + if (!IsLineComment(lineCurrent - 1, styler) && + IsLineComment(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsLineComment(lineCurrent - 1, styler) && + !IsLineComment(lineCurrent+1, styler)) + levelCurrent--; + } + if (foldPreprocessor) { + if (ch == '#' && IsPreprocessor(style)) { + UpdatePreprocessorFoldLevel(levelCurrent, i + 1, styler); + } + } + + if (stylePrev != SCE_OSCRIPT_KEYWORD && style == SCE_OSCRIPT_KEYWORD) { + lastStart = i; + } + if (stylePrev == SCE_OSCRIPT_KEYWORD) { + if(IsIdentifierChar(ch) && !IsIdentifierChar(chNext)) { + UpdateKeywordFoldLevel(levelCurrent, lastStart, i, styler); + } + } + + if (!IsASpace(ch)) + visibleChars++; + + if (atLineEnd) { + int level = levelPrev; + if (visibleChars == 0 && foldCompact) + level |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + level |= SC_FOLDLEVELHEADERFLAG; + if (level != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, level); + } + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; + } + } + + // If we did not reach EOLN in the previous loop, store the line level and + // whitespace information. The rest will be filled in later. + int lev = levelPrev; + if (visibleChars == 0 && foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + styler.SetLevel(lineCurrent, lev); +} + +// -------------------------------------------- +// Declaration of the OScript lexer descriptor. + +static const char * const oscriptWordListDesc[] = { + "Keywords and reserved words", + "Literal constants", + "Literal operators", + "Built-in value and reference types", + "Built-in global functions", + "Built-in static objects", + 0 +}; + +LexerModule lmOScript(SCLEX_OSCRIPT, ColouriseOScriptDoc, "oscript", FoldOScriptDoc, oscriptWordListDesc); diff --git a/src/stc/scintilla/src/LexOpal.cxx b/src/stc/scintilla/lexers/LexOpal.cxx similarity index 93% rename from src/stc/scintilla/src/LexOpal.cxx rename to src/stc/scintilla/lexers/LexOpal.cxx index 221f955974..320fe9bee0 100644 --- a/src/stc/scintilla/src/LexOpal.cxx +++ b/src/stc/scintilla/lexers/LexOpal.cxx @@ -6,18 +6,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" #include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -92,7 +95,7 @@ inline bool HandleString( unsigned int & cur, unsigned int one_too_much, Accesso inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail ) { char ch; - + if( could_fail ) { cur++; @@ -101,7 +104,7 @@ inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, A styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); return false; // STOP } - + ch = styler.SafeGetCharAt( cur ); if( ch != '*' ) { @@ -110,7 +113,7 @@ inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, A return true; } } - + // Wait for comment close cur++; bool star_found = false; @@ -121,7 +124,7 @@ inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, A styler.ColourTo( cur - 1, SCE_OPAL_COMMENT_BLOCK ); return false; // STOP } - + ch = styler.SafeGetCharAt( cur ); if( star_found ) { @@ -155,7 +158,7 @@ inline bool HandleCommentBlock( unsigned int & cur, unsigned int one_too_much, A inline bool HandleCommentLine( unsigned int & cur, unsigned int one_too_much, Accessor & styler, bool could_fail ) { char ch; - + if( could_fail ) { cur++; @@ -164,7 +167,7 @@ inline bool HandleCommentLine( unsigned int & cur, unsigned int one_too_much, Ac styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); return false; // STOP } - + ch = styler.SafeGetCharAt( cur ); if( ch != '-' ) { @@ -179,7 +182,7 @@ inline bool HandleCommentLine( unsigned int & cur, unsigned int one_too_much, Ac styler.ColourTo( cur - 1, SCE_OPAL_DEFAULT ); return false; // STOP } - + ch = styler.SafeGetCharAt( cur ); if( ( ch != ' ' ) && ( ch != '\t' ) ) { @@ -224,7 +227,7 @@ inline bool HandleCommentLine( unsigned int & cur, unsigned int one_too_much, Ac { if( ch == '\015' ) { - fifteen_found = true; + fifteen_found = true; } else if( ch == '\012' ) { @@ -259,7 +262,7 @@ inline bool HandleSpace( unsigned int & cur, unsigned int one_too_much, Accessor styler.ColourTo( cur - 1, SCE_OPAL_SPACE ); return false; } - + ch = styler.SafeGetCharAt( cur ); switch( ch ) { @@ -269,7 +272,7 @@ inline bool HandleSpace( unsigned int & cur, unsigned int one_too_much, Accessor case '\012': cur++; break; - + default: styler.ColourTo( cur - 1, SCE_OPAL_SPACE ); styler.StartSegment( cur ); @@ -292,7 +295,7 @@ inline bool HandleInteger( unsigned int & cur, unsigned int one_too_much, Access } ch = styler.SafeGetCharAt( cur ); - if( !isdigit( ch ) ) + if( !( isascii( ch ) && isdigit( ch ) ) ) { styler.ColourTo( cur - 1, SCE_OPAL_INTEGER ); styler.StartSegment( cur ); @@ -311,10 +314,10 @@ inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor { ch = styler.SafeGetCharAt( cur ); if( ( ch != '_' ) && ( ch != '-' ) && - !islower( ch ) && !isupper( ch ) && !isdigit( ch ) ) break; + !( isascii( ch ) && ( islower( ch ) || isupper( ch ) || isdigit( ch ) ) ) ) break; cur++; - if( cur >= one_too_much ) + if( cur >= one_too_much ) { break; } @@ -323,7 +326,7 @@ inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor const int ide_len = cur - beg + 1; char * ide = new char[ ide_len ]; getRange( beg, cur, styler, ide, ide_len ); - + WordList & keywords = *keywordlists[ 0 ]; WordList & classwords = *keywordlists[ 1 ]; @@ -338,8 +341,8 @@ inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor } else { - styler.StartSegment( cur ); - return true; + styler.StartSegment( cur ); + return true; } } else if( classwords.InList( ide ) ) // Sort @@ -353,8 +356,8 @@ inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor } else { - styler.StartSegment( cur ); - return true; + styler.StartSegment( cur ); + return true; } } else if( !strcmp( ide, "true" ) || !strcmp( ide, "false" ) ) // Bool const @@ -368,8 +371,8 @@ inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor } else { - styler.StartSegment( cur ); - return true; + styler.StartSegment( cur ); + return true; } } else // Unknown keyword @@ -384,7 +387,7 @@ inline bool HandleWord( unsigned int & cur, unsigned int one_too_much, Accessor else { styler.StartSegment( cur ); - return true; + return true; } } @@ -400,7 +403,7 @@ inline bool HandleSkip( unsigned int & cur, unsigned int one_too_much, Accessor } else { - styler.StartSegment( cur ); + styler.StartSegment( cur ); return true; } } @@ -444,11 +447,11 @@ static void ColouriseOpalDoc( unsigned int startPos, int length, int initStyle, if( !HandleString( cur, one_too_much, styler ) ) return; state = SCE_OPAL_DEFAULT; break; - + default: // SCE_OPAL_DEFAULT: { char ch = styler.SafeGetCharAt( cur ); - + switch( ch ) { // String @@ -483,20 +486,20 @@ static void ColouriseOpalDoc( unsigned int startPos, int length, int initStyle, case '\012': if( !HandleSpace( cur, one_too_much, styler ) ) return; break; - + default: { // Integer - if( isdigit( ch ) ) + if( isascii( ch ) && isdigit( ch ) ) { if( !HandleInteger( cur, one_too_much, styler ) ) return; } // Keyword - else if( islower( ch ) || isupper( ch ) ) + else if( isascii( ch ) && ( islower( ch ) || isupper( ch ) ) ) { if( !HandleWord( cur, one_too_much, styler, keywordlists ) ) return; - + } // Skip diff --git a/src/stc/scintilla/src/LexOthers.cxx b/src/stc/scintilla/lexers/LexOthers.cxx similarity index 83% rename from src/stc/scintilla/src/LexOthers.cxx rename to src/stc/scintilla/lexers/LexOthers.cxx index 75458f6d59..259059fd9f 100644 --- a/src/stc/scintilla/src/LexOthers.cxx +++ b/src/stc/scintilla/lexers/LexOthers.cxx @@ -8,19 +8,22 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "CharClassify.h" -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -37,6 +40,10 @@ static bool Is1To9(char ch) { return (ch >= '1') && (ch <= '9'); } +static bool IsAlphabetic(int ch) { + return isascii(ch) && isalpha(ch); +} + static inline bool AtEOL(Accessor &styler, unsigned int i) { return (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); @@ -51,7 +58,7 @@ static bool IsBOperator(char ch) { // Tests for BATCH Separators static bool IsBSeparator(char ch) { return (ch == '\\') || (ch == '.') || (ch == ';') || - (ch == '\"') || (ch == '\'') || (ch == '/') || (ch == ')'); + (ch == '\"') || (ch == '\'') || (ch == '/'); } static void ColouriseBatchLine( @@ -101,7 +108,7 @@ static void ColouriseBatchLine( } return; // Check for Drive Change (Drive Change is internal command) - return if found - } else if ((isalpha(lineBuffer[offset])) && + } else if ((IsAlphabetic(lineBuffer[offset])) && (lineBuffer[offset + 1] == ':') && ((isspacechar(lineBuffer[offset + 2])) || (((lineBuffer[offset + 2] == '\\')) && @@ -493,6 +500,10 @@ static void ColouriseBatchDoc( } } +#define DIFF_BUFFER_START_SIZE 16 +// Note that ColouriseDiffLine analyzes only the first DIFF_BUFFER_START_SIZE +// characters of each line to classify the line. + static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) { // It is needed to remember the current state to recognize starting // comment lines before the first "diff " or "--- ". If a real @@ -502,7 +513,7 @@ static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) { styler.ColourTo(endLine, SCE_DIFF_COMMAND); } else if (0 == strncmp(lineBuffer, "Index: ", 7)) { // For subversion's diff styler.ColourTo(endLine, SCE_DIFF_COMMAND); - } else if (0 == strncmp(lineBuffer, "---", 3)) { + } else if (0 == strncmp(lineBuffer, "---", 3) && lineBuffer[3] != '-') { // In a context diff, --- appears in both the header and the position markers if (lineBuffer[3] == ' ' && atoi(lineBuffer + 4) && !strchr(lineBuffer, '/')) styler.ColourTo(endLine, SCE_DIFF_POSITION); @@ -549,20 +560,27 @@ static void ColouriseDiffLine(char *lineBuffer, int endLine, Accessor &styler) { } static void ColouriseDiffDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { - char lineBuffer[1024]; + char lineBuffer[DIFF_BUFFER_START_SIZE]; styler.StartAt(startPos); styler.StartSegment(startPos); unsigned int linePos = 0; for (unsigned int i = startPos; i < startPos + length; i++) { - lineBuffer[linePos++] = styler[i]; - if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { - // End of line (or of line buffer) met, colourise it - lineBuffer[linePos] = '\0'; + if (AtEOL(styler, i)) { + if (linePos < DIFF_BUFFER_START_SIZE) { + lineBuffer[linePos] = 0; + } ColouriseDiffLine(lineBuffer, i, styler); linePos = 0; + } else if (linePos < DIFF_BUFFER_START_SIZE - 1) { + lineBuffer[linePos++] = styler[i]; + } else if (linePos == DIFF_BUFFER_START_SIZE - 1) { + lineBuffer[linePos++] = 0; } } if (linePos > 0) { // Last line does not have ending characters + if (linePos < DIFF_BUFFER_START_SIZE) { + lineBuffer[linePos] = 0; + } ColouriseDiffLine(lineBuffer, startPos + length - 1, styler); } } @@ -723,10 +741,10 @@ static void ColourisePropsDoc(unsigned int startPos, int length, int, WordList * unsigned int linePos = 0; unsigned int startLine = startPos; - // property lexer.props.allow.initial.spaces - // For properties files, set to 0 to style all lines that start with whitespace in the default style. - // This is not suitable for SciTE .properties files which use indentation for flow control but - // can be used for RFC2822 text where indentation is used for continuation lines. + // property lexer.props.allow.initial.spaces + // For properties files, set to 0 to style all lines that start with whitespace in the default style. + // This is not suitable for SciTE .properties files which use indentation for flow control but + // can be used for RFC2822 text where indentation is used for continuation lines. bool allowInitialSpaces = styler.GetPropertyInt("lexer.props.allow.initial.spaces", 1) != 0; for (unsigned int i = startPos; i < startPos + length; i++) { @@ -847,13 +865,17 @@ static void ColouriseMakeLine( styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR); return; } + int varCount = 0; while (i < lengthLine) { if (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(') { styler.ColourTo(startLine + i - 1, state); state = SCE_MAKE_IDENTIFIER; + varCount++; } else if (state == SCE_MAKE_IDENTIFIER && lineBuffer[i] == ')') { - styler.ColourTo(startLine + i, state); - state = SCE_MAKE_DEFAULT; + if (--varCount == 0) { + styler.ColourTo(startLine + i, state); + state = SCE_MAKE_DEFAULT; + } } // skip identifier and target styling if this is a command line @@ -922,8 +944,8 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin // Command or return status return SCE_ERR_CMD; } else if (lineBuffer[0] == '<') { - // Diff removal, but not interested. Trapped to avoid hitting CTAG cases. - return SCE_ERR_DEFAULT; + // Diff removal. + return SCE_ERR_DIFF_DELETION; } else if (lineBuffer[0] == '!') { return SCE_ERR_DIFF_CHANGED; } else if (lineBuffer[0] == '+') { @@ -961,17 +983,17 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin } else if (strstart(lineBuffer, "Warning ")) { // Borland warning message return SCE_ERR_BORLAND; - } else if (strstr(lineBuffer, "at line " ) && - (strstr(lineBuffer, "at line " ) < (lineBuffer + lengthLine)) && + } else if (strstr(lineBuffer, "at line ") && + (strstr(lineBuffer, "at line ") < (lineBuffer + lengthLine)) && strstr(lineBuffer, "file ") && (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) { // Lua 4 error message return SCE_ERR_LUA; - } else if (strstr(lineBuffer, " at " ) && - (strstr(lineBuffer, " at " ) < (lineBuffer + lengthLine)) && + } else if (strstr(lineBuffer, " at ") && + (strstr(lineBuffer, " at ") < (lineBuffer + lengthLine)) && strstr(lineBuffer, " line ") && (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) && - (strstr(lineBuffer, " at " ) < (strstr(lineBuffer, " line ")))) { + (strstr(lineBuffer, " at ") < (strstr(lineBuffer, " line ")))) { // perl error message return SCE_ERR_PERL; } else if ((memcmp(lineBuffer, " at ", 6) == 0) && @@ -1004,7 +1026,7 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin bool initialTab = (lineBuffer[0] == '\t'); bool initialColonPart = false; enum { stInitial, - stGccStart, stGccDigit, stGcc, + stGccStart, stGccDigit, stGccColumn, stGcc, stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet, stCtagsStart, stCtagsStartString, stCtagsStringDollar, stCtags, stUnrecognized @@ -1036,12 +1058,18 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin state = Is1To9(ch) ? stGccDigit : stUnrecognized; } else if (state == stGccDigit) { // <filename>:<line> if (ch == ':') { - state = stGcc; // :9.*: is GCC + state = stGccColumn; // :9.*: is GCC startValue = i + 1; - break; } else if (!Is0To9(ch)) { state = stUnrecognized; } + } else if (state == stGccColumn) { // <filename>:<line>:<column> + if (!Is0To9(ch)) { + state = stGcc; + if (ch == ':') + startValue = i + 1; + break; + } } else if (state == stMsStart) { // <filename>( state = Is0To9(ch) ? stMsDigit : stUnrecognized; } else if (state == stMsDigit) { // <filename>(<line> @@ -1065,7 +1093,7 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i. else numstep = 2; // otherwise add 2. - for (j = i + numstep; j < lengthLine && isalpha(lineBuffer[j]) && chPos < sizeof(word) - 1; j++) + for (j = i + numstep; j < lengthLine && IsAlphabetic(lineBuffer[j]) && chPos < sizeof(word) - 1; j++) word[chPos++] = lineBuffer[j]; word[chPos] = 0; if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") || @@ -1131,11 +1159,11 @@ static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordLi styler.StartSegment(startPos); unsigned int linePos = 0; - // property lexer.errorlist.value.separate - // For lines in the output pane that are matches from Find in Files or GCC-style - // diagnostics, style the path and line number separately from the rest of the - // line with style 21 used for the rest of the line. - // This allows matched text to be more easily distinguished from its location. + // property lexer.errorlist.value.separate + // For lines in the output pane that are matches from Find in Files or GCC-style + // diagnostics, style the path and line number separately from the rest of the + // line with style 21 used for the rest of the line. + // This allows matched text to be more easily distinguished from its location. bool valueSeparate = styler.GetPropertyInt("lexer.errorlist.value.separate", 0) != 0; for (unsigned int i = startPos; i < startPos + length; i++) { lineBuffer[linePos++] = styler[i]; @@ -1151,21 +1179,71 @@ static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordLi } } -static int isSpecial(char s) { - return (s == '\\') || (s == ',') || (s == ';') || (s == '\'') || (s == ' ') || - (s == '\"') || (s == '`') || (s == '^') || (s == '~'); +static bool latexIsSpecial(int ch) { + return (ch == '#') || (ch == '$') || (ch == '%') || (ch == '&') || (ch == '_') || + (ch == '{') || (ch == '}') || (ch == ' '); +} + +static bool latexIsBlank(int ch) { + return (ch == ' ') || (ch == '\t'); } -static int isTag(int start, Accessor &styler) { - char s[6]; - unsigned int i = 0, e = 1; - while (i < 5 && e) { - s[i] = styler[start + i]; +static bool latexIsBlankAndNL(int ch) { + return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'); +} + +static bool latexIsLetter(int ch) { + return isascii(ch) && isalpha(ch); +} + +static bool latexIsTagValid(int &i, int l, Accessor &styler) { + while (i < l) { + if (styler.SafeGetCharAt(i) == '{') { + while (i < l) { + i++; + if (styler.SafeGetCharAt(i) == '}') { + return true; + } else if (!latexIsLetter(styler.SafeGetCharAt(i)) && + styler.SafeGetCharAt(i)!='*') { + return false; + } + } + } else if (!latexIsBlank(styler.SafeGetCharAt(i))) { + return false; + } i++; - e = styler[start + i] != '{'; + } + return false; +} + +static bool latexNextNotBlankIs(int i, int l, Accessor &styler, char needle) { + char ch; + while (i < l) { + ch = styler.SafeGetCharAt(i); + if (!latexIsBlankAndNL(ch) && ch != '*') { + if (ch == needle) + return true; + else + return false; + } + i++; + } + return false; +} + +static bool latexLastWordIs(int start, Accessor &styler, const char *needle) { + unsigned int i = 0; + unsigned int l = static_cast<unsigned int>(strlen(needle)); + int ini = start-l+1; + char s[32]; + + while (i < l && i < 32) { + s[i] = styler.SafeGetCharAt(ini + i); + i++; } s[i] = '\0'; - return (strcmp(s, "begin") == 0) || (strcmp(s, "end") == 0); + + return (strcmp(s, needle) == 0); } static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, @@ -1174,39 +1252,51 @@ static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, styler.StartAt(startPos); int state = initStyle; - char chNext = styler[startPos]; + char chNext = styler.SafeGetCharAt(startPos); styler.StartSegment(startPos); int lengthDoc = startPos + length; + char chVerbatimDelim = '\0'; for (int i = startPos; i < lengthDoc; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); if (styler.IsLeadByte(ch)) { - chNext = styler.SafeGetCharAt(i + 2); i++; + chNext = styler.SafeGetCharAt(i + 1); continue; } + switch (state) { case SCE_L_DEFAULT : switch (ch) { case '\\' : styler.ColourTo(i - 1, state); - if (isSpecial(styler[i + 1])) { - styler.ColourTo(i + 1, SCE_L_COMMAND); - i++; - chNext = styler.SafeGetCharAt(i + 1); + if (latexIsSpecial(chNext)) { + state = SCE_L_SPECIAL; } else { - if (isTag(i + 1, styler)) - state = SCE_L_TAG; - else + if (latexIsLetter(chNext)) { state = SCE_L_COMMAND; + } else { + if (chNext == '(' || chNext == '[') { + styler.ColourTo(i-1, state); + styler.ColourTo(i+1, SCE_L_SHORTCMD); + state = SCE_L_MATH; + if (chNext == '[') + state = SCE_L_MATH2; + i++; + chNext = styler.SafeGetCharAt(i+1); + } else { + state = SCE_L_SHORTCMD; + } + } } break; case '$' : styler.ColourTo(i - 1, state); state = SCE_L_MATH; if (chNext == '$') { + state = SCE_L_MATH2; i++; chNext = styler.SafeGetCharAt(i + 1); } @@ -1217,29 +1307,124 @@ static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, break; } break; + case SCE_L_ERROR: + styler.ColourTo(i-1, state); + state = SCE_L_DEFAULT; + break; + case SCE_L_SPECIAL: + case SCE_L_SHORTCMD: + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + break; case SCE_L_COMMAND : - if (chNext == '[' || chNext == '{' || chNext == '}' || - chNext == ' ' || chNext == '\r' || chNext == '\n') { + if (!latexIsLetter(chNext)) { styler.ColourTo(i, state); state = SCE_L_DEFAULT; - i++; - chNext = styler.SafeGetCharAt(i + 1); + if (latexNextNotBlankIs(i+1, lengthDoc, styler, '[' )) { + state = SCE_L_CMDOPT; + } else if (latexLastWordIs(i, styler, "\\begin")) { + state = SCE_L_TAG; + } else if (latexLastWordIs(i, styler, "\\end")) { + state = SCE_L_TAG2; + } else if (latexLastWordIs(i, styler, "\\verb") && + chNext != '*' && chNext != ' ') { + chVerbatimDelim = chNext; + state = SCE_L_VERBATIM; + } } break; + case SCE_L_CMDOPT : + if (ch == ']') { + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + } + break; case SCE_L_TAG : - if (ch == '}') { + if (latexIsTagValid(i, lengthDoc, styler)) { + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + if (latexLastWordIs(i, styler, "{verbatim}")) { + state = SCE_L_VERBATIM; + } else if (latexLastWordIs(i, styler, "{comment}")) { + state = SCE_L_COMMENT2; + } else if (latexLastWordIs(i, styler, "{math}")) { + state = SCE_L_MATH; + } else if (latexLastWordIs(i, styler, "{displaymath}")) { + state = SCE_L_MATH2; + } else if (latexLastWordIs(i, styler, "{equation}")) { + state = SCE_L_MATH2; + } + } else { + state = SCE_L_ERROR; styler.ColourTo(i, state); state = SCE_L_DEFAULT; } + chNext = styler.SafeGetCharAt(i+1); + break; + case SCE_L_TAG2 : + if (latexIsTagValid(i, lengthDoc, styler)) { + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + } else { + state = SCE_L_ERROR; + } + chNext = styler.SafeGetCharAt(i+1); break; case SCE_L_MATH : if (ch == '$') { - if (chNext == '$') { - i++; - chNext = styler.SafeGetCharAt(i + 1); - } styler.ColourTo(i, state); state = SCE_L_DEFAULT; + } else if (ch == '\\' && chNext == ')') { + styler.ColourTo(i-1, state); + styler.ColourTo(i+1, SCE_L_SHORTCMD); + i++; + chNext = styler.SafeGetCharAt(i+1); + state = SCE_L_DEFAULT; + } else if (ch == '\\') { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{math}")) { + styler.ColourTo(i-1, state); + state = SCE_L_COMMAND; + } + } + } + } + + break; + case SCE_L_MATH2 : + if (ch == '$') { + if (chNext == '$') { + i++; + chNext = styler.SafeGetCharAt(i + 1); + styler.ColourTo(i, state); + state = SCE_L_DEFAULT; + } else { + styler.ColourTo(i, SCE_L_ERROR); + state = SCE_L_DEFAULT; + } + } else if (ch == '\\' && chNext == ']') { + styler.ColourTo(i-1, state); + styler.ColourTo(i+1, SCE_L_SHORTCMD); + i++; + chNext = styler.SafeGetCharAt(i+1); + state = SCE_L_DEFAULT; + } else if (ch == '\\') { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{displaymath}")) { + styler.ColourTo(i-1, state); + state = SCE_L_COMMAND; + } else if (latexLastWordIs(match, styler, "{equation}")) { + styler.ColourTo(i-1, state); + state = SCE_L_COMMAND; + } + } + } } break; case SCE_L_COMMENT : @@ -1247,18 +1432,55 @@ static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle, styler.ColourTo(i - 1, state); state = SCE_L_DEFAULT; } + break; + case SCE_L_COMMENT2 : + if (ch == '\\') { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{comment}")) { + styler.ColourTo(i-1, state); + state = SCE_L_COMMAND; + } + } + } + } + break; + case SCE_L_VERBATIM : + if (ch == '\\') { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{verbatim}")) { + styler.ColourTo(i-1, state); + state = SCE_L_COMMAND; + } + } + } + } else if (chNext == chVerbatimDelim) { + styler.ColourTo(i+1, state); + state = SCE_L_DEFAULT; + chVerbatimDelim = '\0'; + } else if (chVerbatimDelim != '\0' && (ch == '\n' || ch == '\r')) { + styler.ColourTo(i, SCE_L_ERROR); + state = SCE_L_DEFAULT; + chVerbatimDelim = '\0'; + } + break; } } styler.ColourTo(lengthDoc-1, state); } -static const char * const batchWordListDesc[] = { +static const char *const batchWordListDesc[] = { "Internal Commands", "External Commands", 0 }; -static const char * const emptyWordListDesc[] = { +static const char *const emptyWordListDesc[] = { 0 }; diff --git a/src/stc/scintilla/src/LexPB.cxx b/src/stc/scintilla/lexers/LexPB.cxx similarity index 98% rename from src/stc/scintilla/src/LexPB.cxx rename to src/stc/scintilla/lexers/LexPB.cxx index abc0ddc790..a7b5690ebb 100644 --- a/src/stc/scintilla/src/LexPB.cxx +++ b/src/stc/scintilla/lexers/LexPB.cxx @@ -35,18 +35,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexPLM.cxx b/src/stc/scintilla/lexers/LexPLM.cxx similarity index 97% rename from src/stc/scintilla/src/LexPLM.cxx rename to src/stc/scintilla/lexers/LexPLM.cxx index 604850fbe0..747d158944 100644 --- a/src/stc/scintilla/src/LexPLM.cxx +++ b/src/stc/scintilla/lexers/LexPLM.cxx @@ -4,18 +4,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" #include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexPOV.cxx b/src/stc/scintilla/lexers/LexPOV.cxx similarity index 98% rename from src/stc/scintilla/src/LexPOV.cxx rename to src/stc/scintilla/lexers/LexPOV.cxx index b845b2d472..353fbbe0fa 100644 --- a/src/stc/scintilla/src/LexPOV.cxx +++ b/src/stc/scintilla/lexers/LexPOV.cxx @@ -16,18 +16,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexPS.cxx b/src/stc/scintilla/lexers/LexPS.cxx similarity index 98% rename from src/stc/scintilla/src/LexPS.cxx rename to src/stc/scintilla/lexers/LexPS.cxx index 2edcff150a..3661c4b66e 100644 --- a/src/stc/scintilla/src/LexPS.cxx +++ b/src/stc/scintilla/lexers/LexPS.cxx @@ -8,18 +8,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> -#include <stdarg.h> #include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexPascal.cxx b/src/stc/scintilla/lexers/LexPascal.cxx similarity index 88% rename from src/stc/scintilla/src/LexPascal.cxx rename to src/stc/scintilla/lexers/LexPascal.cxx index 3dcf35ad53..1e2be23184 100644 --- a/src/stc/scintilla/src/LexPascal.cxx +++ b/src/stc/scintilla/lexers/LexPascal.cxx @@ -11,20 +11,20 @@ A few words about features of the new completely rewritten LexPascal... -Generally speaking LexPascal tries to support all available Delphi features (up +Generally speaking LexPascal tries to support all available Delphi features (up to Delphi 2009 at this time), including .NET specific features. ~ HIGHLIGHTING: -If you enable "lexer.pascal.smart.highlighting" property, some keywords will -only be highlighted in appropriate context. As implemented those are keywords -related to property and DLL exports declarations (similar to how Delphi IDE -works). +If you enable "lexer.pascal.smart.highlighting" property, some keywords will +only be highlighted in appropriate context. As implemented those are keywords +related to property and DLL exports declarations (similar to how Delphi IDE +works). -For example, keywords "read" and "write" will only be highlighted if they are in +For example, keywords "read" and "write" will only be highlighted if they are in property declaration: -property MyProperty: boolean read FMyProperty write FMyProperty; +property MyProperty: boolean read FMyProperty write FMyProperty; ~ FOLDING: @@ -32,34 +32,36 @@ Folding is supported in the following cases: - Folding of stream-like comments - Folding of groups of consecutive line comments -- Folding of preprocessor blocks (the following preprocessor blocks are -supported: IF / IFEND; IFDEF, IFNDEF, IFOPT / ENDIF and REGION / ENDREGION +- Folding of preprocessor blocks (the following preprocessor blocks are +supported: IF / IFEND; IFDEF, IFNDEF, IFOPT / ENDIF and REGION / ENDREGION blocks), including nesting of preprocessor blocks up to 255 levels -- Folding of code blocks on appropriate keywords (the following code blocks are -supported: "begin, asm, record, try, case / end" blocks, class & object +- Folding of code blocks on appropriate keywords (the following code blocks are +supported: "begin, asm, record, try, case / end" blocks, class & object declarations and interface declarations) Remarks: -- Folding of code blocks tries to handle all special cases in which folding +- Folding of code blocks tries to handle all special cases in which folding should not occur. As implemented those are: -1. Structure "record case / end" (there's only one "end" statement and "case" is +1. Structure "record case / end" (there's only one "end" statement and "case" is ignored as fold point) -2. Forward class declarations ("type TMyClass = class;") and object method -declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") are +2. Forward class declarations ("type TMyClass = class;") and object method +declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") are ignored as fold points -3. Simplified complete class declarations ("type TMyClass = class(TObject);") +3. Simplified complete class declarations ("type TMyClass = class(TObject);") are ignored as fold points -4. Every other situation when class keyword doesn't actually start class -declaration ("class procedure", "class function", "class of", "class var", +4. Every other situation when class keyword doesn't actually start class +declaration ("class procedure", "class function", "class of", "class var", "class property" and "class operator") +5. Forward (disp)interface declarations ("type IMyInterface = interface;") are +ignored as fold points -- Folding of code blocks inside preprocessor blocks is disabled (any comments -inside them will be folded fine) because there is no guarantee that complete -code block will be contained inside folded preprocessor block in which case -folded code block could end prematurely at the end of preprocessor block if -there is no closing statement inside. This was done in order to properly process +- Folding of code blocks inside preprocessor blocks is disabled (any comments +inside them will be folded fine) because there is no guarantee that complete +code block will be contained inside folded preprocessor block in which case +folded code block could end prematurely at the end of preprocessor block if +there is no closing statement inside. This was done in order to properly process document that may contain something like this: type @@ -76,52 +78,54 @@ type ... end; -If class declarations were folded, then the second class declaration would end -at "$ENDIF" statement, first class statement would end at "end;" statement and -preprocessor "$IFDEF" block would go all the way to the end of document. -However, having in mind all this, if you want to enable folding of code blocks -inside preprocessor blocks, you can disable folding of preprocessor blocks by -changing "fold.preprocessor" property, in which case everything inside them +If class declarations were folded, then the second class declaration would end +at "$ENDIF" statement, first class statement would end at "end;" statement and +preprocessor "$IFDEF" block would go all the way to the end of document. +However, having in mind all this, if you want to enable folding of code blocks +inside preprocessor blocks, you can disable folding of preprocessor blocks by +changing "fold.preprocessor" property, in which case everything inside them would be folded. ~ KEYWORDS: -The list of keywords that can be used in pascal.properties file (up to Delphi +The list of keywords that can be used in pascal.properties file (up to Delphi 2009): -- Keywords: absolute abstract and array as asm assembler automated begin case -cdecl class const constructor deprecated destructor dispid dispinterface div do -downto dynamic else end except export exports external far file final -finalization finally for forward function goto if implementation in inherited -initialization inline interface is label library message mod near nil not object -of on or out overload override packed pascal platform private procedure program -property protected public published raise record register reintroduce repeat -resourcestring safecall sealed set shl shr static stdcall strict string then +- Keywords: absolute abstract and array as asm assembler automated begin case +cdecl class const constructor deprecated destructor dispid dispinterface div do +downto dynamic else end except export exports external far file final +finalization finally for forward function goto if implementation in inherited +initialization inline interface is label library message mod near nil not object +of on or out overload override packed pascal platform private procedure program +property protected public published raise record register reintroduce repeat +resourcestring safecall sealed set shl shr static stdcall strict string then threadvar to try type unit unsafe until uses var varargs virtual while with xor -- Keywords related to the "smart highlithing" feature: add default implements +- Keywords related to the "smart highlithing" feature: add default implements index name nodefault read readonly remove stored write writeonly -- Keywords related to Delphi packages (in addition to all above): package +- Keywords related to Delphi packages (in addition to all above): package contains requires */ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" #include "StyleContext.h" #include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -155,12 +159,12 @@ static void GetForwardRangeLowered(unsigned int start, } enum { - stateInAsm = 0x1000, - stateInProperty = 0x2000, - stateInExport = 0x4000, - stateFoldInPreprocessor = 0x0100, - stateFoldInRecord = 0x0200, - stateFoldInPreprocessorLevelMask = 0x00FF, + stateInAsm = 0x1000, + stateInProperty = 0x2000, + stateInExport = 0x4000, + stateFoldInPreprocessor = 0x0100, + stateFoldInRecord = 0x0200, + stateFoldInPreprocessorLevelMask = 0x00FF, stateFoldMaskAll = 0x0FFF }; @@ -190,11 +194,11 @@ static void ClassifyPascalWord(WordList *keywordlists[], StyleContext &sc, int & ignoreKeyword = true; } else if (!(curLineState & stateInExport) && strcmp(s, "name") == 0) { ignoreKeyword = true; - } else if (!(curLineState & stateInProperty) && - (strcmp(s, "read") == 0 || strcmp(s, "write") == 0 || - strcmp(s, "default") == 0 || strcmp(s, "nodefault") == 0 || - strcmp(s, "stored") == 0 || strcmp(s, "implements") == 0 || - strcmp(s, "readonly") == 0 || strcmp(s, "writeonly") == 0 || + } else if (!(curLineState & stateInProperty) && + (strcmp(s, "read") == 0 || strcmp(s, "write") == 0 || + strcmp(s, "default") == 0 || strcmp(s, "nodefault") == 0 || + strcmp(s, "stored") == 0 || strcmp(s, "implements") == 0 || + strcmp(s, "readonly") == 0 || strcmp(s, "writeonly") == 0 || strcmp(s, "add") == 0 || strcmp(s, "remove") == 0)) { ignoreKeyword = true; } @@ -367,7 +371,7 @@ static void SetFoldInPreprocessorLevelFlag(int &lineFoldStateCurrent, unsigned i lineFoldStateCurrent |= nestLevel & stateFoldInPreprocessorLevelMask; } -static void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, +static void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, unsigned int startPos, Accessor &styler) { CharacterSet setWord(CharacterSet::setAlpha); @@ -376,17 +380,17 @@ static void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFold unsigned int nestLevel = GetFoldInPreprocessorLevelFlag(lineFoldStateCurrent); - if (strcmp(s, "if") == 0 || - strcmp(s, "ifdef") == 0 || - strcmp(s, "ifndef") == 0 || - strcmp(s, "ifopt") == 0 || + if (strcmp(s, "if") == 0 || + strcmp(s, "ifdef") == 0 || + strcmp(s, "ifndef") == 0 || + strcmp(s, "ifopt") == 0 || strcmp(s, "region") == 0) { nestLevel++; SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel); lineFoldStateCurrent |= stateFoldInPreprocessor; levelCurrent++; - } else if (strcmp(s, "endif") == 0 || - strcmp(s, "ifend") == 0 || + } else if (strcmp(s, "endif") == 0 || + strcmp(s, "ifend") == 0 || strcmp(s, "endregion") == 0) { nestLevel--; SetFoldInPreprocessorLevelFlag(lineFoldStateCurrent, nestLevel); @@ -400,12 +404,12 @@ static void ClassifyPascalPreprocessorFoldPoint(int &levelCurrent, int &lineFold } } -static unsigned int SkipWhiteSpace(unsigned int currentPos, unsigned int endPos, +static unsigned int SkipWhiteSpace(unsigned int currentPos, unsigned int endPos, Accessor &styler, bool includeChars = false) { CharacterSet setWord(CharacterSet::setAlphaNum, "_"); unsigned int j = currentPos + 1; char ch = styler.SafeGetCharAt(j); - while ((j < endPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' || + while ((j < endPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' || IsStreamCommentStyle(styler.StyleAt(j)) || (includeChars && setWord.Contains(ch)))) { j++; ch = styler.SafeGetCharAt(j); @@ -413,8 +417,8 @@ static unsigned int SkipWhiteSpace(unsigned int currentPos, unsigned int endPos, return j; } -static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, - int startPos, unsigned int endPos, +static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCurrent, + int startPos, unsigned int endPos, unsigned int lastStart, unsigned int currentPos, Accessor &styler) { char s[100]; GetRangeLowered(lastStart, currentPos, styler, s, sizeof(s)); @@ -422,9 +426,9 @@ static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCur if (strcmp(s, "record") == 0) { lineFoldStateCurrent |= stateFoldInRecord; levelCurrent++; - } else if (strcmp(s, "begin") == 0 || - strcmp(s, "asm") == 0 || - strcmp(s, "try") == 0 || + } else if (strcmp(s, "begin") == 0 || + strcmp(s, "asm") == 0 || + strcmp(s, "try") == 0 || (strcmp(s, "case") == 0 && !(lineFoldStateCurrent & stateFoldInRecord))) { levelCurrent++; } else if (strcmp(s, "class") == 0 || strcmp(s, "object") == 0) { @@ -436,13 +440,13 @@ static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCur CharacterSet setWord(CharacterSet::setAlphaNum, "_"); if (styler.SafeGetCharAt(j) == ';') { - // Handle forward class declarations ("type TMyClass = class;") + // Handle forward class declarations ("type TMyClass = class;") // and object method declarations ("TNotifyEvent = procedure(Sender: TObject) of object;") ignoreKeyword = true; } else if (strcmp(s, "class") == 0) { // "class" keyword has a few more special cases... if (styler.SafeGetCharAt(j) == '(') { - // Handle simplified complete class declarations ("type TMyClass = class(TObject);") + // Handle simplified complete class declarations ("type TMyClass = class(TObject);") j = SkipWhiteSpace(j, endPos, styler, true); if (j < endPos && styler.SafeGetCharAt(j) == ')') { j = SkipWhiteSpace(j, endPos, styler); @@ -454,11 +458,11 @@ static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCur char s2[11]; // Size of the longest possible keyword + one additional character + null GetForwardRangeLowered(j, setWord, styler, s2, sizeof(s2)); - if (strcmp(s2, "procedure") == 0 || - strcmp(s2, "function") == 0 || - strcmp(s2, "of") == 0 || - strcmp(s2, "var") == 0 || - strcmp(s2, "property") == 0 || + if (strcmp(s2, "procedure") == 0 || + strcmp(s2, "function") == 0 || + strcmp(s2, "of") == 0 || + strcmp(s2, "var") == 0 || + strcmp(s2, "property") == 0 || strcmp(s2, "operator") == 0) { ignoreKeyword = true; } @@ -473,7 +477,7 @@ static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCur bool ignoreKeyword = true; int j = lastStart - 1; char ch = styler.SafeGetCharAt(j); - while ((j >= startPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' || + while ((j >= startPos) && (IsASpaceOrTab(ch) || ch == '\r' || ch == '\n' || IsStreamCommentStyle(styler.StyleAt(j)))) { j--; ch = styler.SafeGetCharAt(j); @@ -481,6 +485,24 @@ static void ClassifyPascalWordFoldPoint(int &levelCurrent, int &lineFoldStateCur if (j >= startPos && styler.SafeGetCharAt(j) == '=') { ignoreKeyword = false; } + if (!ignoreKeyword) { + unsigned int k = SkipWhiteSpace(currentPos, endPos, styler); + if (k < endPos && styler.SafeGetCharAt(k) == ';') { + // Handle forward interface declarations ("type IMyInterface = interface;") + ignoreKeyword = true; + } + } + if (!ignoreKeyword) { + levelCurrent++; + } + } else if (strcmp(s, "dispinterface") == 0) { + // "dispinterface" keyword requires special handling... + bool ignoreKeyword = false; + unsigned int j = SkipWhiteSpace(currentPos, endPos, styler); + if (j < endPos && styler.SafeGetCharAt(j) == ';') { + // Handle forward dispinterface declarations ("type IMyInterface = dispinterface;") + ignoreKeyword = true; + } if (!ignoreKeyword) { levelCurrent++; } @@ -539,7 +561,7 @@ static void FoldPascalDoc(unsigned int startPos, int length, int initStyle, Word if (foldPreprocessor) { if (style == SCE_PAS_PREPROCESSOR && ch == '{' && chNext == '$') { ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 2, styler); - } else if (style == SCE_PAS_PREPROCESSOR2 && ch == '(' && chNext == '*' + } else if (style == SCE_PAS_PREPROCESSOR2 && ch == '(' && chNext == '*' && styler.SafeGetCharAt(i + 2) == '$') { ClassifyPascalPreprocessorFoldPoint(levelCurrent, lineFoldStateCurrent, i + 3, styler); } diff --git a/src/stc/scintilla/src/LexPerl.cxx b/src/stc/scintilla/lexers/LexPerl.cxx similarity index 53% rename from src/stc/scintilla/src/LexPerl.cxx rename to src/stc/scintilla/lexers/LexPerl.cxx index 0c66036200..da9038778b 100644 --- a/src/stc/scintilla/src/LexPerl.cxx +++ b/src/stc/scintilla/lexers/LexPerl.cxx @@ -1,6 +1,7 @@ // Scintilla source code edit control /** @file LexPerl.cxx ** Lexer for Perl. + ** Converted to lexer object by "Udo Lechner" <dlchnr(at)gmx(dot)net> **/ // Copyright 1998-2008 by Neil Hodgson <neilh@scintilla.org> // Lexical analysis fixes by Kein-Hong Man <mkh@pl.jaring.my> @@ -8,19 +9,24 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include <string> +#include <map> -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "StyleContext.h" #include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -59,8 +65,11 @@ using namespace Scintilla; #define BACK_OPERATOR 1 // whitespace/comments are insignificant #define BACK_KEYWORD 2 // operators/keywords are needed for disambiguation -static bool isPerlKeyword(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) -{ +// all interpolated styles are different from their parent styles by a constant difference +// we also assume SCE_PL_STRING_VAR is the interpolated style with the smallest value +#define INTERPOLATE_SHIFT (SCE_PL_STRING_VAR - SCE_PL_STRING) + +static bool isPerlKeyword(unsigned int start, unsigned int end, WordList &keywords, LexAccessor &styler) { // old-style keyword matcher; needed because GetCurrent() needs // current segment to be committed, but we may abandon early... char s[100]; @@ -71,9 +80,8 @@ static bool isPerlKeyword(unsigned int start, unsigned int end, WordList &keywor return keywords.InList(s); } -static int disambiguateBareword(Accessor &styler, unsigned int bk, unsigned int fw, - int backFlag, unsigned int backPos, unsigned int endPos) -{ +static int disambiguateBareword(LexAccessor &styler, unsigned int bk, unsigned int fw, + int backFlag, unsigned int backPos, unsigned int endPos) { // identifiers are recognized by Perl as barewords under some // conditions, the following attempts to do the disambiguation // by looking backward and forward; result in 2 LSB @@ -94,25 +102,25 @@ static int disambiguateBareword(Accessor &styler, unsigned int bk, unsigned int // {bareword: possible variable spec brace = true; } else if ((ch == '&' && styler.SafeGetCharAt(bk - 1) != '&') - // &bareword: subroutine call - || styler.Match(bk - 1, "->") - // ->bareword: part of variable spec - || styler.Match(bk - 2, "sub")) { - // sub bareword: subroutine declaration - // (implied BACK_KEYWORD, no keywords end in 'sub'!) + // &bareword: subroutine call + || styler.Match(bk - 1, "->") + // ->bareword: part of variable spec + || styler.Match(bk - 2, "sub")) { + // sub bareword: subroutine declaration + // (implied BACK_KEYWORD, no keywords end in 'sub'!) result |= 1; } // next, scan forward after word past tab/spaces only; // if ch isn't one of '[{(,' we can skip the test if ((ch == '{' || ch == '(' || ch == '['|| ch == ',') - && fw < endPos) { + && fw < endPos) { while (ch = static_cast<unsigned char>(styler.SafeGetCharAt(fw)), - IsASpaceOrTab(ch) && fw < endPos) { + IsASpaceOrTab(ch) && fw < endPos) { fw++; } if ((ch == '}' && brace) - // {bareword}: variable spec - || styler.Match(fw, "=>")) { + // {bareword}: variable spec + || styler.Match(fw, "=>")) { // [{(, bareword=>: hash literal result |= 2; } @@ -120,17 +128,15 @@ static int disambiguateBareword(Accessor &styler, unsigned int bk, unsigned int return result; } -static void skipWhitespaceComment(Accessor &styler, unsigned int &p) -{ +static void skipWhitespaceComment(LexAccessor &styler, unsigned int &p) { // when backtracking, we need to skip whitespace and comments int style; while ((p > 0) && (style = styler.StyleAt(p), - style == SCE_PL_DEFAULT || style == SCE_PL_COMMENTLINE)) + style == SCE_PL_DEFAULT || style == SCE_PL_COMMENTLINE)) p--; } -static int styleBeforeBracePair(Accessor &styler, unsigned int bk) -{ +static int styleBeforeBracePair(LexAccessor &styler, unsigned int bk) { // backtrack to find open '{' corresponding to a '}', balanced // return significant style to be tested for '/' disambiguation int braceCount = 1; @@ -157,8 +163,7 @@ static int styleBeforeBracePair(Accessor &styler, unsigned int bk) return SCE_PL_DEFAULT; } -static int styleCheckIdentifier(Accessor &styler, unsigned int bk) -{ +static int styleCheckIdentifier(LexAccessor &styler, unsigned int bk) { // backtrack to classify sub-styles of identifier under test // return sub-style to be tested for '/' disambiguation if (styler.SafeGetCharAt(bk) == '>') // inputsymbol, like <foo> @@ -170,7 +175,7 @@ static int styleCheckIdentifier(Accessor &styler, unsigned int bk) while (bk > 0) { int bkstyle = styler.StyleAt(bk); if (bkstyle == SCE_PL_DEFAULT - || bkstyle == SCE_PL_COMMENTLINE) { + || bkstyle == SCE_PL_COMMENTLINE) { // skip whitespace, comments } else if (bkstyle == SCE_PL_OPERATOR) { // test for "->" and "::" @@ -183,8 +188,7 @@ static int styleCheckIdentifier(Accessor &styler, unsigned int bk) return 0; } -static int inputsymbolScan(Accessor &styler, unsigned int pos, unsigned int endPos) -{ +static int inputsymbolScan(LexAccessor &styler, unsigned int pos, unsigned int endPos) { // looks forward for matching > on same line; a bit ugly unsigned int fw = pos; while (++fw < endPos) { @@ -200,8 +204,7 @@ static int inputsymbolScan(Accessor &styler, unsigned int pos, unsigned int endP return 0; } -static int podLineScan(Accessor &styler, unsigned int &pos, unsigned int endPos) -{ +static int podLineScan(LexAccessor &styler, unsigned int &pos, unsigned int endPos) { // forward scan the current line to classify line for POD style int state = -1; while (pos <= endPos) { @@ -225,8 +228,7 @@ static int podLineScan(Accessor &styler, unsigned int &pos, unsigned int endPos) return state; } -static bool styleCheckSubPrototype(Accessor &styler, unsigned int bk) -{ +static bool styleCheckSubPrototype(LexAccessor &styler, unsigned int bk) { // backtrack to identify if we're starting a subroutine prototype // we also need to ignore whitespace/comments: // 'sub' [whitespace|comment] <identifier> [whitespace|comment] @@ -239,20 +241,11 @@ static bool styleCheckSubPrototype(Accessor &styler, unsigned int bk) } skipWhitespaceComment(styler, bk); if (bk < 2 || styler.StyleAt(bk) != SCE_PL_WORD // check "sub" keyword - || !styler.Match(bk - 2, "sub")) // assume suffix is unique! + || !styler.Match(bk - 2, "sub")) // assume suffix is unique! return false; return true; } -static bool isMatch(const char *sref, char *s) -{ - // match per-line delimiter - must kill trailing CR if CRLF - int i = strlen(s); - if (i != 0 && s[i - 1] == '\r') - s[i - 1] = '\0'; - return (strcmp(sref, s) == 0); -} - static int actualNumStyle(int numberStyle) { if (numberStyle == PERLNUM_VECTOR || numberStyle == PERLNUM_V_VECTOR) { return SCE_PL_STRING; @@ -270,18 +263,262 @@ static int opposite(int ch) { return ch; } -static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { +static bool IsCommentLine(int line, LexAccessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eol_pos; i++) { + char ch = styler[i]; + int style = styler.StyleAt(i); + if (ch == '#' && style == SCE_PL_COMMENTLINE) + return true; + else if (!IsASpaceOrTab(ch)) + return false; + } + return false; +} + +static bool IsPackageLine(int line, LexAccessor &styler) { + int pos = styler.LineStart(line); + int style = styler.StyleAt(pos); + if (style == SCE_PL_WORD && styler.Match(pos, "package")) { + return true; + } + return false; +} + +static int PodHeadingLevel(int pos, LexAccessor &styler) { + int lvl = static_cast<unsigned char>(styler.SafeGetCharAt(pos + 5)); + if (lvl >= '1' && lvl <= '4') { + return lvl - '0'; + } + return 0; +} + +// An individual named option for use in an OptionSet + +// Options used for LexerPerl +struct OptionsPerl { + bool fold; + bool foldComment; + bool foldCompact; + // Custom folding of POD and packages + bool foldPOD; // fold.perl.pod + // Enable folding Pod blocks when using the Perl lexer. + bool foldPackage; // fold.perl.package + // Enable folding packages when using the Perl lexer. + + bool foldCommentExplicit; + + bool foldAtElse; + + OptionsPerl() { + fold = false; + foldComment = false; + foldCompact = true; + foldPOD = true; + foldPackage = true; + foldCommentExplicit = true; + foldAtElse = false; + } +}; + +static const char *const perlWordListDesc[] = { + "Keywords", + 0 +}; + +struct OptionSetPerl : public OptionSet<OptionsPerl> { + OptionSetPerl() { + DefineProperty("fold", &OptionsPerl::fold); + + DefineProperty("fold.comment", &OptionsPerl::foldComment); + + DefineProperty("fold.compact", &OptionsPerl::foldCompact); + + DefineProperty("fold.perl.pod", &OptionsPerl::foldPOD, + "Set to 0 to disable folding Pod blocks when using the Perl lexer."); + + DefineProperty("fold.perl.package", &OptionsPerl::foldPackage, + "Set to 0 to disable folding packages when using the Perl lexer."); + + DefineProperty("fold.perl.comment.explicit", &OptionsPerl::foldCommentExplicit, + "Set to 0 to disable explicit folding."); + + DefineProperty("fold.perl.at.else", &OptionsPerl::foldAtElse, + "This option enables Perl folding on a \"} else {\" line of an if statement."); + + DefineWordListSets(perlWordListDesc); + } +}; + +class LexerPerl : public ILexer { + CharacterSet setWordStart; + CharacterSet setWord; + CharacterSet setSpecialVar; + CharacterSet setControlVar; + WordList keywords; + OptionsPerl options; + OptionSetPerl osPerl; +public: + LexerPerl() : + setWordStart(CharacterSet::setAlpha, "_", 0x80, true), + setWord(CharacterSet::setAlphaNum, "_", 0x80, true), + setSpecialVar(CharacterSet::setNone, "\"$;<>&`'+,./\\%:=~!?@[]"), + setControlVar(CharacterSet::setNone, "ACDEFHILMNOPRSTVWX") { + } + virtual ~LexerPerl() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char *SCI_METHOD PropertyNames() { + return osPerl.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osPerl.PropertyType(name); + } + const char *SCI_METHOD DescribeProperty(const char *name) { + return osPerl.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char *SCI_METHOD DescribeWordListSets() { + return osPerl.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + + void *SCI_METHOD PrivateCall(int, void *) { + return 0; + } + + static ILexer *LexerFactoryPerl() { + return new LexerPerl(); + } + void InterpolateSegment(StyleContext &sc, int maxSeg, bool isPattern=false); +}; + +int SCI_METHOD LexerPerl::PropertySet(const char *key, const char *val) { + if (osPerl.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerPerl::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void LexerPerl::InterpolateSegment(StyleContext &sc, int maxSeg, bool isPattern) { + // interpolate a segment (with no active backslashes or delimiters within) + // switch in or out of an interpolation style or continue current style + // commit variable patterns if found, trim segment, repeat until done + while (maxSeg > 0) { + bool isVar = false; + int sLen = 0; + if ((maxSeg > 1) && (sc.ch == '$' || sc.ch == '@')) { + // $#[$]*word [$@][$]*word (where word or {word} is always present) + bool braces = false; + sLen = 1; + if (sc.ch == '$' && sc.chNext == '#') { // starts with $# + sLen++; + } + while ((maxSeg > sLen) && (sc.GetRelative(sLen) == '$')) // >0 $ dereference within + sLen++; + if ((maxSeg > sLen) && (sc.GetRelative(sLen) == '{')) { // { start for {word} + sLen++; + braces = true; + } + if (maxSeg > sLen) { + int c = sc.GetRelative(sLen); + if (setWordStart.Contains(c)) { // word (various) + sLen++; + isVar = true; + while ((maxSeg > sLen) && setWord.Contains(sc.GetRelative(sLen))) + sLen++; + } else if (braces && IsADigit(c) && (sLen == 2)) { // digit for ${digit} + sLen++; + isVar = true; + } + } + if (braces) { + if ((maxSeg > sLen) && (sc.GetRelative(sLen) == '}')) { // } end for {word} + sLen++; + } else + isVar = false; + } + } + if (!isVar && (maxSeg > 1)) { // $- or @-specific variable patterns + sLen = 1; + int c = sc.chNext; + if (sc.ch == '$') { + if (IsADigit(c)) { // $[0-9] and slurp trailing digits + sLen++; + isVar = true; + while ((maxSeg > sLen) && IsADigit(sc.GetRelative(sLen))) + sLen++; + } else if (setSpecialVar.Contains(c)) { // $ special variables + sLen++; + isVar = true; + } else if (!isPattern && ((c == '(') || (c == ')') || (c == '|'))) { // $ additional + sLen++; + isVar = true; + } else if (c == '^') { // $^A control-char style + sLen++; + if ((maxSeg > sLen) && setControlVar.Contains(sc.GetRelative(sLen))) { + sLen++; + isVar = true; + } + } + } else if (sc.ch == '@') { + if (!isPattern && ((c == '+') || (c == '-'))) { // @ specials non-pattern + sLen++; + isVar = true; + } + } + } + if (isVar) { // commit as interpolated variable or normal character + if (sc.state < SCE_PL_STRING_VAR) + sc.SetState(sc.state + INTERPOLATE_SHIFT); + sc.Forward(sLen); + maxSeg -= sLen; + } else { + if (sc.state >= SCE_PL_STRING_VAR) + sc.SetState(sc.state - INTERPOLATE_SHIFT); + sc.Forward(); + maxSeg--; + } + } + if (sc.state >= SCE_PL_STRING_VAR) + sc.SetState(sc.state - INTERPOLATE_SHIFT); +} - WordList &keywords = *keywordlists[0]; +void SCI_METHOD LexerPerl::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); // keywords that forces /PATTERN/ at all times; should track vim's behaviour WordList reWords; reWords.Set("elsif if split while"); // charset classes - CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true); - CharacterSet setWord(CharacterSet::setAlphaNum, "_", 0x80, true); CharacterSet setSingleCharOp(CharacterSet::setNone, "rwxoRWXOezsfdlpSbctugkTBMAC"); // lexing of "%*</" operators is non-trivial; these are missing in the set below CharacterSet setPerlOperator(CharacterSet::setNone, "^&\\()-+=|{}[]:;>,?!.~"); @@ -296,7 +533,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, CharacterSet &setPOD = setModifiers; CharacterSet setNonHereDoc(CharacterSet::setDigits, "=$@"); CharacterSet setHereDocDelim(CharacterSet::setAlphaNum, "_"); - CharacterSet setSubPrototype(CharacterSet::setNone, "\\[$@%&*];"); + CharacterSet setSubPrototype(CharacterSet::setNone, "\\[$@%&*+];"); // for format identifiers CharacterSet setFormatStart(CharacterSet::setAlpha, "_="); CharacterSet &setFormat = setHereDocDelim; @@ -307,9 +544,10 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, class HereDocCls { // Class to manage HERE doc sequence public: - int State; // 0: '<<' encountered - // 1: collect the delimiter - // 2: here doc text (lines after the delimiter) + int State; + // 0: '<<' encountered + // 1: collect the delimiter + // 2: here doc text (lines after the delimiter) int Quote; // the char after '<<' bool Quoted; // true if Quote in ('\'','"','`') int DelimiterLength; // strlen(Delimiter) @@ -333,7 +571,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, HereDocCls HereDoc; // TODO: FIFO for stacked here-docs class QuoteCls { // Class to manage quote pairs - public: + public: int Rep; int Count; int Up, Down; @@ -365,10 +603,13 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, // Includes strings (may be multi-line), numbers (additional state), format // bodies, as well as POD sections. if (initStyle == SCE_PL_HERE_Q - || initStyle == SCE_PL_HERE_QQ - || initStyle == SCE_PL_HERE_QX - || initStyle == SCE_PL_FORMAT - ) { + || initStyle == SCE_PL_HERE_QQ + || initStyle == SCE_PL_HERE_QX + || initStyle == SCE_PL_FORMAT + || initStyle == SCE_PL_HERE_QQ_VAR + || initStyle == SCE_PL_HERE_QX_VAR + ) { + // backtrack through multiple styles to reach the delimiter start int delim = (initStyle == SCE_PL_FORMAT) ? SCE_PL_FORMAT_IDENT:SCE_PL_HERE_DELIM; while ((startPos > 1) && (styler.StyleAt(startPos) != delim)) { startPos--; @@ -376,28 +617,47 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, startPos = styler.LineStart(styler.GetLine(startPos)); initStyle = styler.StyleAt(startPos - 1); } - if (initStyle == SCE_PL_STRING_Q - || initStyle == SCE_PL_STRING_QQ - || initStyle == SCE_PL_STRING_QX - || initStyle == SCE_PL_STRING_QR - || initStyle == SCE_PL_STRING_QW - || initStyle == SCE_PL_REGEX - || initStyle == SCE_PL_REGSUBST - || initStyle == SCE_PL_STRING - || initStyle == SCE_PL_BACKTICKS - || initStyle == SCE_PL_CHARACTER - || initStyle == SCE_PL_NUMBER - || initStyle == SCE_PL_IDENTIFIER - || initStyle == SCE_PL_ERROR - || initStyle == SCE_PL_SUB_PROTOTYPE - ) { + if (initStyle == SCE_PL_STRING + || initStyle == SCE_PL_STRING_QQ + || initStyle == SCE_PL_BACKTICKS + || initStyle == SCE_PL_STRING_QX + || initStyle == SCE_PL_REGEX + || initStyle == SCE_PL_STRING_QR + || initStyle == SCE_PL_REGSUBST + || initStyle == SCE_PL_STRING_VAR + || initStyle == SCE_PL_STRING_QQ_VAR + || initStyle == SCE_PL_BACKTICKS_VAR + || initStyle == SCE_PL_STRING_QX_VAR + || initStyle == SCE_PL_REGEX_VAR + || initStyle == SCE_PL_STRING_QR_VAR + || initStyle == SCE_PL_REGSUBST_VAR + ) { + // for interpolation, must backtrack through a mix of two different styles + int otherStyle = (initStyle >= SCE_PL_STRING_VAR) ? + initStyle - INTERPOLATE_SHIFT : initStyle + INTERPOLATE_SHIFT; + while (startPos > 1) { + int st = styler.StyleAt(startPos - 1); + if ((st != initStyle) && (st != otherStyle)) + break; + startPos--; + } + initStyle = SCE_PL_DEFAULT; + } else if (initStyle == SCE_PL_STRING_Q + || initStyle == SCE_PL_STRING_QW + || initStyle == SCE_PL_XLAT + || initStyle == SCE_PL_CHARACTER + || initStyle == SCE_PL_NUMBER + || initStyle == SCE_PL_IDENTIFIER + || initStyle == SCE_PL_ERROR + || initStyle == SCE_PL_SUB_PROTOTYPE + ) { while ((startPos > 1) && (styler.StyleAt(startPos - 1) == initStyle)) { startPos--; } initStyle = SCE_PL_DEFAULT; } else if (initStyle == SCE_PL_POD - || initStyle == SCE_PL_POD_VERB - ) { + || initStyle == SCE_PL_POD_VERB + ) { // POD backtracking finds preceeding blank lines and goes back past them int ln = styler.GetLine(startPos); if (ln > 0) { @@ -435,201 +695,233 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, // Determine if the current state should terminate. switch (sc.state) { - case SCE_PL_OPERATOR: + case SCE_PL_OPERATOR: + sc.SetState(SCE_PL_DEFAULT); + backFlag = BACK_OPERATOR; + backPos = sc.currentPos; + break; + case SCE_PL_IDENTIFIER: // identifier, bareword, inputsymbol + if ((!setWord.Contains(sc.ch) && sc.ch != '\'') + || sc.Match('.', '.') + || sc.chPrev == '>') { // end of inputsymbol sc.SetState(SCE_PL_DEFAULT); - backFlag = BACK_OPERATOR; - backPos = sc.currentPos; - break; - case SCE_PL_IDENTIFIER: // identifier, bareword, inputsymbol - if ((!setWord.Contains(sc.ch) && sc.ch != '\'') - || sc.Match('.', '.') - || sc.chPrev == '>') { // end of inputsymbol - sc.SetState(SCE_PL_DEFAULT); - } - break; - case SCE_PL_WORD: // keyword, plus special cases - if (!setWord.Contains(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if ((strcmp(s, "__DATA__") == 0) || (strcmp(s, "__END__") == 0)) { - sc.ChangeState(SCE_PL_DATASECTION); + } + break; + case SCE_PL_WORD: // keyword, plus special cases + if (!setWord.Contains(sc.ch)) { + char s[100]; + sc.GetCurrent(s, sizeof(s)); + if ((strcmp(s, "__DATA__") == 0) || (strcmp(s, "__END__") == 0)) { + sc.ChangeState(SCE_PL_DATASECTION); + } else { + if ((strcmp(s, "format") == 0)) { + sc.SetState(SCE_PL_FORMAT_IDENT); + HereDoc.State = 0; } else { - if ((strcmp(s, "format") == 0)) { - sc.SetState(SCE_PL_FORMAT_IDENT); - HereDoc.State = 0; - } else { - sc.SetState(SCE_PL_DEFAULT); - } - backFlag = BACK_KEYWORD; - backPos = sc.currentPos; + sc.SetState(SCE_PL_DEFAULT); } + backFlag = BACK_KEYWORD; + backPos = sc.currentPos; } - break; - case SCE_PL_SCALAR: - case SCE_PL_ARRAY: - case SCE_PL_HASH: - case SCE_PL_SYMBOLTABLE: - if (sc.Match(':', ':')) { // skip :: + } + break; + case SCE_PL_SCALAR: + case SCE_PL_ARRAY: + case SCE_PL_HASH: + case SCE_PL_SYMBOLTABLE: + if (sc.Match(':', ':')) { // skip :: + sc.Forward(); + } else if (!setVar.Contains(sc.ch)) { + if (sc.LengthCurrent() == 1) { + // Special variable: $(, $_ etc. sc.Forward(); - } else if (!setVar.Contains(sc.ch)) { - if (sc.LengthCurrent() == 1) { - // Special variable: $(, $_ etc. - sc.Forward(); - } - sc.SetState(SCE_PL_DEFAULT); } - break; - case SCE_PL_NUMBER: - // if no early break, number style is terminated at "(go through)" - if (sc.ch == '.') { - if (sc.chNext == '.') { - // double dot is always an operator (go through) - } else if (numState <= PERLNUM_FLOAT_EXP) { - // non-decimal number or float exponent, consume next dot - sc.SetState(SCE_PL_OPERATOR); - break; - } else { // decimal or vectors allows dots - dotCount++; - if (numState == PERLNUM_DECIMAL) { - if (dotCount <= 1) // number with one dot in it - break; - if (IsADigit(sc.chNext)) { // really a vector - numState = PERLNUM_VECTOR; - break; - } - // number then dot (go through) - } else if (IsADigit(sc.chNext)) // vectors - break; - // vector then dot (go through) - } - } else if (sc.ch == '_') { - // permissive underscoring for number and vector literals + sc.SetState(SCE_PL_DEFAULT); + } + break; + case SCE_PL_NUMBER: + // if no early break, number style is terminated at "(go through)" + if (sc.ch == '.') { + if (sc.chNext == '.') { + // double dot is always an operator (go through) + } else if (numState <= PERLNUM_FLOAT_EXP) { + // non-decimal number or float exponent, consume next dot + sc.SetState(SCE_PL_OPERATOR); break; - } else if (numState == PERLNUM_DECIMAL) { - if (sc.ch == 'E' || sc.ch == 'e') { // exponent, sign - numState = PERLNUM_FLOAT_EXP; - if (sc.chNext == '+' || sc.chNext == '-') { - sc.Forward(); + } else { // decimal or vectors allows dots + dotCount++; + if (numState == PERLNUM_DECIMAL) { + if (dotCount <= 1) // number with one dot in it + break; + if (IsADigit(sc.chNext)) { // really a vector + numState = PERLNUM_VECTOR; + break; } + // number then dot (go through) + } else if (IsADigit(sc.chNext)) // vectors break; - } else if (IsADigit(sc.ch)) - break; - // number then word (go through) - } else if (numState == PERLNUM_HEX) { - if (IsADigit(sc.ch, 16)) - break; - } else if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) { - if (IsADigit(sc.ch)) // vector - break; - if (setWord.Contains(sc.ch) && dotCount == 0) { // change to word - sc.ChangeState(SCE_PL_IDENTIFIER); - break; - } - // vector then word (go through) - } else if (IsADigit(sc.ch)) { - if (numState == PERLNUM_FLOAT_EXP) { - break; - } else if (numState == PERLNUM_OCTAL) { - if (sc.ch <= '7') break; - } else if (numState == PERLNUM_BINARY) { - if (sc.ch <= '1') break; + // vector then dot (go through) + } + } else if (sc.ch == '_') { + // permissive underscoring for number and vector literals + break; + } else if (numState == PERLNUM_DECIMAL) { + if (sc.ch == 'E' || sc.ch == 'e') { // exponent, sign + numState = PERLNUM_FLOAT_EXP; + if (sc.chNext == '+' || sc.chNext == '-') { + sc.Forward(); } - // mark invalid octal, binary numbers (go through) - numState = PERLNUM_BAD; + break; + } else if (IsADigit(sc.ch)) + break; + // number then word (go through) + } else if (numState == PERLNUM_HEX) { + if (IsADigit(sc.ch, 16)) + break; + } else if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) { + if (IsADigit(sc.ch)) // vector + break; + if (setWord.Contains(sc.ch) && dotCount == 0) { // change to word + sc.ChangeState(SCE_PL_IDENTIFIER); break; } - // complete current number or vector - sc.ChangeState(actualNumStyle(numState)); - sc.SetState(SCE_PL_DEFAULT); - break; - case SCE_PL_COMMENTLINE: - if (sc.atLineEnd) { - sc.SetState(SCE_PL_DEFAULT); + // vector then word (go through) + } else if (IsADigit(sc.ch)) { + if (numState == PERLNUM_FLOAT_EXP) { + break; + } else if (numState == PERLNUM_OCTAL) { + if (sc.ch <= '7') break; + } else if (numState == PERLNUM_BINARY) { + if (sc.ch <= '1') break; } + // mark invalid octal, binary numbers (go through) + numState = PERLNUM_BAD; break; - case SCE_PL_HERE_DELIM: - if (HereDoc.State == 0) { // '<<' encountered - int delim_ch = sc.chNext; - int ws_skip = 0; - HereDoc.State = 1; // pre-init HERE doc class - HereDoc.Quote = sc.chNext; - HereDoc.Quoted = false; - HereDoc.DelimiterLength = 0; - HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; - if (IsASpaceOrTab(delim_ch)) { - // skip whitespace; legal only for quoted delimiters - unsigned int i = sc.currentPos + 1; - while ((i < endPos) && IsASpaceOrTab(delim_ch)) { - i++; - delim_ch = static_cast<unsigned char>(styler.SafeGetCharAt(i)); - } - ws_skip = i - sc.currentPos - 1; + } + // complete current number or vector + sc.ChangeState(actualNumStyle(numState)); + sc.SetState(SCE_PL_DEFAULT); + break; + case SCE_PL_COMMENTLINE: + if (sc.atLineEnd) { + sc.SetState(SCE_PL_DEFAULT); + } + break; + case SCE_PL_HERE_DELIM: + if (HereDoc.State == 0) { // '<<' encountered + int delim_ch = sc.chNext; + int ws_skip = 0; + HereDoc.State = 1; // pre-init HERE doc class + HereDoc.Quote = sc.chNext; + HereDoc.Quoted = false; + HereDoc.DelimiterLength = 0; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + if (IsASpaceOrTab(delim_ch)) { + // skip whitespace; legal only for quoted delimiters + unsigned int i = sc.currentPos + 1; + while ((i < endPos) && IsASpaceOrTab(delim_ch)) { + i++; + delim_ch = static_cast<unsigned char>(styler.SafeGetCharAt(i)); } - if (delim_ch == '\'' || delim_ch == '"' || delim_ch == '`') { - // a quoted here-doc delimiter; skip any whitespace - sc.Forward(ws_skip + 1); - HereDoc.Quote = delim_ch; - HereDoc.Quoted = true; - } else if ((ws_skip == 0 && setNonHereDoc.Contains(sc.chNext)) - || ws_skip > 0) { - // left shift << or <<= operator cases - // restore position if operator - sc.ChangeState(SCE_PL_OPERATOR); + ws_skip = i - sc.currentPos - 1; + } + if (delim_ch == '\'' || delim_ch == '"' || delim_ch == '`') { + // a quoted here-doc delimiter; skip any whitespace + sc.Forward(ws_skip + 1); + HereDoc.Quote = delim_ch; + HereDoc.Quoted = true; + } else if ((ws_skip == 0 && setNonHereDoc.Contains(sc.chNext)) + || ws_skip > 0) { + // left shift << or <<= operator cases + // restore position if operator + sc.ChangeState(SCE_PL_OPERATOR); + sc.ForwardSetState(SCE_PL_DEFAULT); + backFlag = BACK_OPERATOR; + backPos = sc.currentPos; + HereDoc.State = 0; + } else { + // specially handle initial '\' for identifier + if (ws_skip == 0 && HereDoc.Quote == '\\') + sc.Forward(); + // an unquoted here-doc delimiter, no special handling + // (cannot be prefixed by spaces/tabs), or + // symbols terminates; deprecated zero-length delimiter + } + } else if (HereDoc.State == 1) { // collect the delimiter + backFlag = BACK_NONE; + if (HereDoc.Quoted) { // a quoted here-doc delimiter + if (sc.ch == HereDoc.Quote) { // closing quote => end of delimiter sc.ForwardSetState(SCE_PL_DEFAULT); - backFlag = BACK_OPERATOR; - backPos = sc.currentPos; - HereDoc.State = 0; - } else { - // specially handle initial '\' for identifier - if (ws_skip == 0 && HereDoc.Quote == '\\') + } else if (!sc.atLineEnd) { + if (sc.Match('\\', static_cast<char>(HereDoc.Quote))) { // escaped quote sc.Forward(); - // an unquoted here-doc delimiter, no special handling - // (cannot be prefixed by spaces/tabs), or - // symbols terminates; deprecated zero-length delimiter - } - } else if (HereDoc.State == 1) { // collect the delimiter - backFlag = BACK_NONE; - if (HereDoc.Quoted) { // a quoted here-doc delimiter - if (sc.ch == HereDoc.Quote) { // closing quote => end of delimiter - sc.ForwardSetState(SCE_PL_DEFAULT); - } else if (!sc.atLineEnd) { - if (sc.Match('\\', static_cast<char>(HereDoc.Quote))) { // escaped quote - sc.Forward(); - } - if (sc.ch != '\r') { // skip CR if CRLF - HereDoc.Append(sc.ch); - } } - } else { // an unquoted here-doc delimiter - if (setHereDocDelim.Contains(sc.ch)) { + if (sc.ch != '\r') { // skip CR if CRLF HereDoc.Append(sc.ch); - } else { - sc.SetState(SCE_PL_DEFAULT); } } - if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { - sc.SetState(SCE_PL_ERROR); - HereDoc.State = 0; + } else { // an unquoted here-doc delimiter + if (setHereDocDelim.Contains(sc.ch)) { + HereDoc.Append(sc.ch); + } else { + sc.SetState(SCE_PL_DEFAULT); } } - break; - case SCE_PL_HERE_Q: - case SCE_PL_HERE_QQ: - case SCE_PL_HERE_QX: { - // also implies HereDoc.State == 2 - sc.Complete(); - while (!sc.atLineEnd) - sc.Forward(); - char s[HERE_DELIM_MAX]; - sc.GetCurrent(s, sizeof(s)); - if (isMatch(HereDoc.Delimiter, s)) { + if (HereDoc.DelimiterLength >= HERE_DELIM_MAX - 1) { + sc.SetState(SCE_PL_ERROR); + HereDoc.State = 0; + } + } + break; + case SCE_PL_HERE_Q: + case SCE_PL_HERE_QQ: + case SCE_PL_HERE_QX: + // also implies HereDoc.State == 2 + sc.Complete(); + if (HereDoc.DelimiterLength == 0 || sc.Match(HereDoc.Delimiter)) { + int c = sc.GetRelative(HereDoc.DelimiterLength); + if (c == '\r' || c == '\n') { // peek first, do not consume match + sc.Forward(HereDoc.DelimiterLength); sc.SetState(SCE_PL_DEFAULT); backFlag = BACK_NONE; HereDoc.State = 0; + if (!sc.atLineEnd) + sc.Forward(); + break; + } + } + if (sc.state == SCE_PL_HERE_Q) { // \EOF and 'EOF' non-interpolated + while (!sc.atLineEnd) + sc.Forward(); + break; + } + while (!sc.atLineEnd) { // "EOF" and `EOF` interpolated + int s = 0, endType = 0; + int maxSeg = endPos - sc.currentPos; + while (s < maxSeg) { // scan to break string into segments + int c = sc.GetRelative(s); + if (c == '\\') { + endType = 1; break; + } else if (c == '\r' || c == '\n') { + endType = 2; break; + } + s++; } - } break; - case SCE_PL_POD: - case SCE_PL_POD_VERB: { + if (s > 0) // process non-empty segments + InterpolateSegment(sc, s); + if (endType == 1) { + sc.Forward(); + // \ at end-of-line does not appear to have any effect, skip + if (sc.ch != '\r' && sc.ch != '\n') + sc.Forward(); + } else if (endType == 2) { + if (!sc.atLineEnd) + sc.Forward(); + } + } + break; + case SCE_PL_POD: + case SCE_PL_POD_VERB: { unsigned int fw = sc.currentPos; int ln = styler.GetLine(fw); if (sc.atLineStart && sc.Match("=cut")) { // end of POD @@ -653,90 +945,165 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_PL_POD); } else fw = fw2; - } else - pod = SCE_PL_POD; + } } else { if (pod == SCE_PL_POD_VERB // still part of current paragraph - && (styler.GetLineState(ln - 1) == SCE_PL_POD)) { + && (styler.GetLineState(ln - 1) == SCE_PL_POD)) { pod = SCE_PL_POD; styler.SetLineState(ln, pod); } else if (pod == SCE_PL_POD - && (styler.GetLineState(ln - 1) == SCE_PL_POD_VERB)) { + && (styler.GetLineState(ln - 1) == SCE_PL_POD_VERB)) { pod = SCE_PL_POD_VERB; styler.SetLineState(ln, pod); } sc.SetState(pod); } sc.Forward(fw - sc.currentPos); // commit style - } break; - case SCE_PL_REGEX: - case SCE_PL_STRING_QR: - if (Quote.Rep <= 0) { - if (!setModifiers.Contains(sc.ch)) - sc.SetState(SCE_PL_DEFAULT); - } else if (!Quote.Up && !IsASpace(sc.ch)) { - Quote.Open(sc.ch); - } else if (sc.ch == '\\' && Quote.Up != '\\') { - sc.Forward(); - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) - Quote.Rep--; - } else if (sc.ch == Quote.Up) { - Quote.Count++; + } + break; + case SCE_PL_REGEX: + case SCE_PL_STRING_QR: + if (Quote.Rep <= 0) { + if (!setModifiers.Contains(sc.ch)) + sc.SetState(SCE_PL_DEFAULT); + } else if (!Quote.Up && !IsASpace(sc.ch)) { + Quote.Open(sc.ch); + } else { + int s = 0, endType = 0; + int maxSeg = endPos - sc.currentPos; + while (s < maxSeg) { // scan to break string into segments + int c = sc.GetRelative(s); + if (IsASpace(c)) { + break; + } else if (c == '\\' && Quote.Up != '\\') { + endType = 1; break; + } else if (c == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + Quote.Rep--; + break; + } + } else if (c == Quote.Up) + Quote.Count++; + s++; } - break; - case SCE_PL_REGSUBST: - if (Quote.Rep <= 0) { - if (!setModifiers.Contains(sc.ch)) - sc.SetState(SCE_PL_DEFAULT); - } else if (!Quote.Up && !IsASpace(sc.ch)) { - Quote.Open(sc.ch); - } else if (sc.ch == '\\' && Quote.Up != '\\') { + if (s > 0) { // process non-empty segments + if (Quote.Up != '\'') { + InterpolateSegment(sc, s, true); + } else // non-interpolated path + sc.Forward(s); + } + if (endType == 1) sc.Forward(); - } else if (Quote.Count == 0 && Quote.Rep == 1) { - // We matched something like s(...) or tr{...}, Perl 5.10 - // appears to allow almost any character for use as the - // next delimiters. Whitespace and comments are accepted in - // between, but we'll limit to whitespace here. - // For '#', if no whitespace in between, it's a delimiter. - if (IsASpace(sc.ch)) { - // Keep going - } else if (sc.ch == '#' && IsASpaceOrTab(sc.chPrev)) { - sc.SetState(SCE_PL_DEFAULT); - } else { - Quote.Open(sc.ch); - } - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) - Quote.Rep--; - if (Quote.Up == Quote.Down) + } + break; + case SCE_PL_REGSUBST: + case SCE_PL_XLAT: + if (Quote.Rep <= 0) { + if (!setModifiers.Contains(sc.ch)) + sc.SetState(SCE_PL_DEFAULT); + } else if (!Quote.Up && !IsASpace(sc.ch)) { + Quote.Open(sc.ch); + } else { + int s = 0, endType = 0; + int maxSeg = endPos - sc.currentPos; + bool isPattern = (Quote.Rep == 2); + while (s < maxSeg) { // scan to break string into segments + int c = sc.GetRelative(s); + if (c == '\\' && Quote.Up != '\\') { + endType = 2; break; + } else if (Quote.Count == 0 && Quote.Rep == 1) { + // We matched something like s(...) or tr{...}, Perl 5.10 + // appears to allow almost any character for use as the + // next delimiters. Whitespace and comments are accepted in + // between, but we'll limit to whitespace here. + // For '#', if no whitespace in between, it's a delimiter. + if (IsASpace(c)) { + // Keep going + } else if (c == '#' && IsASpaceOrTab(sc.GetRelative(s - 1))) { + endType = 3; + } else + Quote.Open(c); + break; + } else if (c == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + Quote.Rep--; + endType = 1; + } + if (Quote.Up == Quote.Down) + Quote.Count++; + if (endType == 1) + break; + } else if (c == Quote.Up) { Quote.Count++; - } else if (sc.ch == Quote.Up) { - Quote.Count++; + } else if (IsASpace(c)) + break; + s++; } - break; - case SCE_PL_STRING_Q: - case SCE_PL_STRING_QQ: - case SCE_PL_STRING_QX: - case SCE_PL_STRING_QW: - case SCE_PL_STRING: - case SCE_PL_CHARACTER: - case SCE_PL_BACKTICKS: - if (!Quote.Down && !IsASpace(sc.ch)) { - Quote.Open(sc.ch); - } else if (sc.ch == '\\' && Quote.Up != '\\') { + if (s > 0) { // process non-empty segments + if (sc.state == SCE_PL_REGSUBST && Quote.Up != '\'') { + InterpolateSegment(sc, s, isPattern); + } else // non-interpolated path + sc.Forward(s); + } + if (endType == 2) { sc.Forward(); - } else if (sc.ch == Quote.Down) { - Quote.Count--; - if (Quote.Count == 0) - sc.ForwardSetState(SCE_PL_DEFAULT); - } else if (sc.ch == Quote.Up) { - Quote.Count++; + } else if (endType == 3) + sc.SetState(SCE_PL_DEFAULT); + } + break; + case SCE_PL_STRING_Q: + case SCE_PL_STRING_QQ: + case SCE_PL_STRING_QX: + case SCE_PL_STRING_QW: + case SCE_PL_STRING: + case SCE_PL_CHARACTER: + case SCE_PL_BACKTICKS: + if (!Quote.Down && !IsASpace(sc.ch)) { + Quote.Open(sc.ch); + } else { + int s = 0, endType = 0; + int maxSeg = endPos - sc.currentPos; + while (s < maxSeg) { // scan to break string into segments + int c = sc.GetRelative(s); + if (IsASpace(c)) { + break; + } else if (c == '\\' && Quote.Up != '\\') { + endType = 2; break; + } else if (c == Quote.Down) { + Quote.Count--; + if (Quote.Count == 0) { + endType = 3; break; + } + } else if (c == Quote.Up) + Quote.Count++; + s++; } - break; - case SCE_PL_SUB_PROTOTYPE: { + if (s > 0) { // process non-empty segments + switch (sc.state) { + case SCE_PL_STRING: + case SCE_PL_STRING_QQ: + case SCE_PL_BACKTICKS: + InterpolateSegment(sc, s); + break; + case SCE_PL_STRING_QX: + if (Quote.Up != '\'') { + InterpolateSegment(sc, s); + break; + } + // (continued for ' delim) + default: // non-interpolated path + sc.Forward(s); + } + } + if (endType == 2) { + sc.Forward(); + } else if (endType == 3) + sc.ForwardSetState(SCE_PL_DEFAULT); + } + break; + case SCE_PL_SUB_PROTOTYPE: { int i = 0; // forward scan; must all be valid proto characters while (setSubPrototype.Contains(sc.GetRelative(i))) @@ -749,51 +1116,54 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, sc.ChangeState(SCE_PL_OPERATOR); sc.SetState(SCE_PL_DEFAULT); } - } break; - case SCE_PL_FORMAT: { + } + break; + case SCE_PL_FORMAT: { sc.Complete(); + if (sc.Match('.')) { + sc.Forward(); + if (sc.atLineEnd || ((sc.ch == '\r' && sc.chNext == '\n'))) + sc.SetState(SCE_PL_DEFAULT); + } while (!sc.atLineEnd) sc.Forward(); - char s[10]; - sc.GetCurrent(s, sizeof(s)); - if (isMatch(".", s)) - sc.SetState(SCE_PL_DEFAULT); - } break; - case SCE_PL_ERROR: - break; + } + break; + case SCE_PL_ERROR: + break; } // Needed for specific continuation styles (one follows the other) switch (sc.state) { // continued from SCE_PL_WORD - case SCE_PL_FORMAT_IDENT: - // occupies HereDoc state 3 to avoid clashing with HERE docs - if (IsASpaceOrTab(sc.ch)) { // skip whitespace - sc.ChangeState(SCE_PL_DEFAULT); - while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) + case SCE_PL_FORMAT_IDENT: + // occupies HereDoc state 3 to avoid clashing with HERE docs + if (IsASpaceOrTab(sc.ch)) { // skip whitespace + sc.ChangeState(SCE_PL_DEFAULT); + while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) + sc.Forward(); + sc.SetState(SCE_PL_FORMAT_IDENT); + } + if (setFormatStart.Contains(sc.ch)) { // identifier or '=' + if (sc.ch != '=') { + do { sc.Forward(); - sc.SetState(SCE_PL_FORMAT_IDENT); + } while (setFormat.Contains(sc.ch)); } - if (setFormatStart.Contains(sc.ch)) { // identifier or '=' - if (sc.ch != '=') { - do { - sc.Forward(); - } while (setFormat.Contains(sc.ch)); - } - while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) - sc.Forward(); - if (sc.ch == '=') { - sc.ForwardSetState(SCE_PL_DEFAULT); - HereDoc.State = 3; - } else { - // invalid indentifier; inexact fallback, but hey - sc.ChangeState(SCE_PL_IDENTIFIER); - sc.SetState(SCE_PL_DEFAULT); - } + while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) + sc.Forward(); + if (sc.ch == '=') { + sc.ForwardSetState(SCE_PL_DEFAULT); + HereDoc.State = 3; } else { - sc.ChangeState(SCE_PL_DEFAULT); // invalid indentifier + // invalid indentifier; inexact fallback, but hey + sc.ChangeState(SCE_PL_IDENTIFIER); + sc.SetState(SCE_PL_DEFAULT); } - backFlag = BACK_NONE; - break; + } else { + sc.ChangeState(SCE_PL_DEFAULT); // invalid indentifier + } + backFlag = BACK_NONE; + break; } // Must check end of HereDoc states here before default state is handled @@ -810,9 +1180,15 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, sc.ChangeState(SCE_PL_ERROR); } switch (HereDoc.Quote) { - case '\'': st_new = SCE_PL_HERE_Q ; break; - case '"' : st_new = SCE_PL_HERE_QQ; break; - case '`' : st_new = SCE_PL_HERE_QX; break; + case '\'': + st_new = SCE_PL_HERE_Q ; + break; + case '"' : + st_new = SCE_PL_HERE_QQ; + break; + case '`' : + st_new = SCE_PL_HERE_QX; + break; } } else { if (HereDoc.Quote == '\\') @@ -829,15 +1205,15 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, // Determine if a new state should be entered. if (sc.state == SCE_PL_DEFAULT) { if (IsADigit(sc.ch) || - (IsADigit(sc.chNext) && (sc.ch == '.' || sc.ch == 'v'))) { + (IsADigit(sc.chNext) && (sc.ch == '.' || sc.ch == 'v'))) { sc.SetState(SCE_PL_NUMBER); backFlag = BACK_NONE; numState = PERLNUM_DECIMAL; dotCount = 0; if (sc.ch == '0') { // hex,bin,octal - if (sc.chNext == 'x') { + if (sc.chNext == 'x' || sc.chNext == 'X') { numState = PERLNUM_HEX; - } else if (sc.chNext == 'b') { + } else if (sc.chNext == 'b' || sc.chNext == 'B') { numState = PERLNUM_BINARY; } else if (IsADigit(sc.chNext)) { numState = PERLNUM_OCTAL; @@ -867,16 +1243,16 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, sc.ChangeState(SCE_PL_STRING_Q); Quote.New(); } else if (sc.ch == 'y' && !setWord.Contains(sc.chNext)) { - sc.ChangeState(SCE_PL_REGSUBST); + sc.ChangeState(SCE_PL_XLAT); Quote.New(2); } else if (sc.Match('t', 'r') && !setWord.Contains(sc.GetRelative(2))) { - sc.ChangeState(SCE_PL_REGSUBST); + sc.ChangeState(SCE_PL_XLAT); Quote.New(2); sc.Forward(); fw++; } else if (sc.ch == 'q' && setQDelim.Contains(sc.chNext) - && !setWord.Contains(sc.GetRelative(2))) { - if (sc.chNext == 'q') sc.ChangeState(SCE_PL_STRING_QQ); + && !setWord.Contains(sc.GetRelative(2))) { + if (sc.chNext == 'q') sc.ChangeState(SCE_PL_STRING_QQ); else if (sc.chNext == 'x') sc.ChangeState(SCE_PL_STRING_QX); else if (sc.chNext == 'r') sc.ChangeState(SCE_PL_STRING_QR); else sc.ChangeState(SCE_PL_STRING_QW); // sc.chNext == 'w' @@ -884,8 +1260,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, sc.Forward(); fw++; } else if (sc.ch == 'x' && (sc.chNext == '=' || // repetition - !setWord.Contains(sc.chNext) || - (IsADigit(sc.chPrev) && IsADigit(sc.chNext)))) { + !setWord.Contains(sc.chNext) || + (IsADigit(sc.chPrev) && IsADigit(sc.chNext)))) { sc.ChangeState(SCE_PL_OPERATOR); } // if potentially a keyword, scan forward and grab word, then check @@ -962,7 +1338,6 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, bool isHereDoc = sc.Match('<', '<'); bool hereDocSpace = false; // for: SCALAR [whitespace] '<<' unsigned int bk = (sc.currentPos > 0) ? sc.currentPos - 1: 0; - unsigned int bkend; sc.Complete(); styler.Flush(); if (styler.StyleAt(bk) == SCE_PL_DEFAULT) @@ -974,7 +1349,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, } else { int bkstyle = styler.StyleAt(bk); int bkch = static_cast<unsigned char>(styler.SafeGetCharAt(bk)); - switch(bkstyle) { + switch (bkstyle) { case SCE_PL_OPERATOR: preferRE = true; if (bkch == ')' || bkch == ']') { @@ -984,17 +1359,17 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, // needed to test for variables like ${}, @{} etc. bkstyle = styleBeforeBracePair(styler, bk); if (bkstyle == SCE_PL_SCALAR - || bkstyle == SCE_PL_ARRAY - || bkstyle == SCE_PL_HASH - || bkstyle == SCE_PL_SYMBOLTABLE - || bkstyle == SCE_PL_OPERATOR) { + || bkstyle == SCE_PL_ARRAY + || bkstyle == SCE_PL_HASH + || bkstyle == SCE_PL_SYMBOLTABLE + || bkstyle == SCE_PL_OPERATOR) { preferRE = false; } } else if (bkch == '+' || bkch == '-') { if (bkch == static_cast<unsigned char>(styler.SafeGetCharAt(bk - 1)) - && bkch != static_cast<unsigned char>(styler.SafeGetCharAt(bk - 2))) - // exceptions for operators: unary suffixes ++, -- - preferRE = false; + && bkch != static_cast<unsigned char>(styler.SafeGetCharAt(bk - 2))) + // exceptions for operators: unary suffixes ++, -- + preferRE = false; } break; case SCE_PL_IDENTIFIER: @@ -1031,7 +1406,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, // keywords always forced as /PATTERN/: split, if, elsif, while // everything else /PATTERN/ unless digit/space immediately after '/' // for '//', defined-or favoured unless special keywords - bkend = bk + 1; + unsigned int bkend = bk + 1; while (bk > 0 && styler.StyleAt(bk - 1) == SCE_PL_WORD) { bk--; } @@ -1047,7 +1422,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, preferRE = false; } break; - // other styles uses the default, preferRE=false + + // other styles uses the default, preferRE=false case SCE_PL_POD: case SCE_PL_HERE_Q: case SCE_PL_HERE_QQ: @@ -1121,15 +1497,15 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, } } } else if (sc.ch == '=' // POD - && setPOD.Contains(sc.chNext) - && sc.atLineStart) { + && setPOD.Contains(sc.chNext) + && sc.atLineStart) { sc.SetState(SCE_PL_POD); backFlag = BACK_NONE; } else if (sc.ch == '-' && setWordStart.Contains(sc.chNext)) { // extended '-' cases unsigned int bk = sc.currentPos; unsigned int fw = 2; if (setSingleCharOp.Contains(sc.chNext) && // file test operators - !setWord.Contains(sc.GetRelative(2))) { + !setWord.Contains(sc.GetRelative(2))) { sc.SetState(SCE_PL_WORD); } else { // nominally a minus and bareword; find extent of bareword @@ -1165,39 +1541,37 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle, } } sc.Complete(); -} - -static bool IsCommentLine(int line, Accessor &styler) { - int pos = styler.LineStart(line); - int eol_pos = styler.LineStart(line + 1) - 1; - for (int i = pos; i < eol_pos; i++) { - char ch = styler[i]; - int style = styler.StyleAt(i); - if (ch == '#' && style == SCE_PL_COMMENTLINE) - return true; - else if (!IsASpaceOrTab(ch)) - return false; + if (sc.state == SCE_PL_HERE_Q + || sc.state == SCE_PL_HERE_QQ + || sc.state == SCE_PL_HERE_QX + || sc.state == SCE_PL_FORMAT) { + styler.ChangeLexerState(sc.currentPos, styler.Length()); } - return false; + sc.Complete(); } -static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[], - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - // Custom folding of POD and packages +#define PERL_HEADFOLD_SHIFT 4 +#define PERL_HEADFOLD_MASK 0xF0 + +void SCI_METHOD LexerPerl::Fold(unsigned int startPos, int length, int /* initStyle */, IDocument *pAccess) { - // property fold.perl.pod - // Enable folding Pod blocks when using the Perl lexer. - bool foldPOD = styler.GetPropertyInt("fold.perl.pod", 1) != 0; + if (!options.fold) + return; - // property fold.perl.package - // Enable folding packages when using the Perl lexer. - bool foldPackage = styler.GetPropertyInt("fold.perl.package", 1) != 0; + LexAccessor styler(pAccess); unsigned int endPos = startPos + length; int visibleChars = 0; int lineCurrent = styler.GetLine(startPos); + + // Backtrack to previous line in case need to fix its fold status + if (startPos > 0) { + if (lineCurrent > 0) { + lineCurrent--; + startPos = styler.LineStart(lineCurrent); + } + } + int levelPrev = SC_FOLDLEVELBASE; if (lineCurrent > 0) levelPrev = styler.LevelAt(lineCurrent - 1) >> 16; @@ -1207,67 +1581,118 @@ static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[], int styleNext = styler.StyleAt(startPos); // Used at end of line to determine if the line was a package definition bool isPackageLine = false; - bool isPodHeading = false; + int podHeading = 0; for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); int style = styleNext; styleNext = styler.StyleAt(i + 1); + int stylePrevCh = (i) ? styler.StyleAt(i - 1):SCE_PL_DEFAULT; bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); bool atLineStart = ((chPrev == '\r') || (chPrev == '\n')) || i == 0; // Comment folding - if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) - { + if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { if (!IsCommentLine(lineCurrent - 1, styler) - && IsCommentLine(lineCurrent + 1, styler)) + && IsCommentLine(lineCurrent + 1, styler)) levelCurrent++; else if (IsCommentLine(lineCurrent - 1, styler) - && !IsCommentLine(lineCurrent+1, styler)) + && !IsCommentLine(lineCurrent + 1, styler)) levelCurrent--; } + // {} [] block folding if (style == SCE_PL_OPERATOR) { if (ch == '{') { + if (options.foldAtElse && levelCurrent < levelPrev) + --levelPrev; levelCurrent++; } else if (ch == '}') { levelCurrent--; } + if (ch == '[') { + if (options.foldAtElse && levelCurrent < levelPrev) + --levelPrev; + levelCurrent++; + } else if (ch == ']') { + levelCurrent--; + } } - // Custom POD folding - if (foldPOD && atLineStart) { - int stylePrevCh = (i) ? styler.StyleAt(i - 1):SCE_PL_DEFAULT; + // POD folding + if (options.foldPOD && atLineStart) { if (style == SCE_PL_POD) { if (stylePrevCh != SCE_PL_POD && stylePrevCh != SCE_PL_POD_VERB) levelCurrent++; else if (styler.Match(i, "=cut")) - levelCurrent--; + levelCurrent = (levelCurrent & ~PERL_HEADFOLD_MASK) - 1; else if (styler.Match(i, "=head")) - isPodHeading = true; + podHeading = PodHeadingLevel(i, styler); } else if (style == SCE_PL_DATASECTION) { - if (ch == '=' && isalpha(chNext) && levelCurrent == SC_FOLDLEVELBASE) + if (ch == '=' && isascii(chNext) && isalpha(chNext) && levelCurrent == SC_FOLDLEVELBASE) levelCurrent++; else if (styler.Match(i, "=cut") && levelCurrent > SC_FOLDLEVELBASE) - levelCurrent--; + levelCurrent = (levelCurrent & ~PERL_HEADFOLD_MASK) - 1; else if (styler.Match(i, "=head")) - isPodHeading = true; + podHeading = PodHeadingLevel(i, styler); // if package used or unclosed brace, level > SC_FOLDLEVELBASE! // reset needed as level test is vs. SC_FOLDLEVELBASE - else if (styler.Match(i, "__END__")) + else if (stylePrevCh != SCE_PL_DATASECTION) levelCurrent = SC_FOLDLEVELBASE; } } - // Custom package folding - if (foldPackage && atLineStart) { - if (style == SCE_PL_WORD && styler.Match(i, "package")) { + // package folding + if (options.foldPackage && atLineStart) { + if (IsPackageLine(lineCurrent, styler) + && !IsPackageLine(lineCurrent + 1, styler)) isPackageLine = true; + } + + //heredoc folding + switch (style) { + case SCE_PL_HERE_QQ : + case SCE_PL_HERE_Q : + case SCE_PL_HERE_QX : + switch (stylePrevCh) { + case SCE_PL_HERE_QQ : + case SCE_PL_HERE_Q : + case SCE_PL_HERE_QX : + //do nothing; + break; + default : + levelCurrent++; + break; + } + break; + default: + switch (stylePrevCh) { + case SCE_PL_HERE_QQ : + case SCE_PL_HERE_Q : + case SCE_PL_HERE_QX : + levelCurrent--; + break; + default : + //do nothing; + break; + } + break; + } + + //explicit folding + if (options.foldCommentExplicit && style == SCE_PL_COMMENTLINE && ch == '#') { + if (chNext == '{') { + levelCurrent++; + } else if (levelCurrent > SC_FOLDLEVELBASE && chNext == '}') { + levelCurrent--; } } if (atEOL) { int lev = levelPrev; - if (isPodHeading) { - lev = levelPrev - 1; + // POD headings occupy bits 7-4, leaving some breathing room for + // non-standard practice -- POD sections stuck in blocks, etc. + if (podHeading > 0) { + levelCurrent = (lev & ~PERL_HEADFOLD_MASK) | (podHeading << PERL_HEADFOLD_SHIFT); + lev = levelCurrent - 1; lev |= SC_FOLDLEVELHEADERFLAG; - isPodHeading = false; + podHeading = 0; } // Check if line was a package declaration // because packages need "special" treatment @@ -1277,7 +1702,7 @@ static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[], isPackageLine = false; } lev |= levelCurrent << 16; - if (visibleChars == 0 && foldCompact) + if (visibleChars == 0 && options.foldCompact) lev |= SC_FOLDLEVELWHITEFLAG; if ((levelCurrent > levelPrev) && (visibleChars > 0)) lev |= SC_FOLDLEVELHEADERFLAG; @@ -1297,9 +1722,4 @@ static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[], styler.SetLevel(lineCurrent, levelPrev | flagsNext); } -static const char * const perlWordListDesc[] = { - "Keywords", - 0 -}; - -LexerModule lmPerl(SCLEX_PERL, ColourisePerlDoc, "perl", FoldPerlDoc, perlWordListDesc, 8); +LexerModule lmPerl(SCLEX_PERL, LexerPerl::LexerFactoryPerl, "perl", perlWordListDesc, 8); diff --git a/src/stc/scintilla/src/LexPowerPro.cxx b/src/stc/scintilla/lexers/LexPowerPro.cxx similarity index 64% rename from src/stc/scintilla/src/LexPowerPro.cxx rename to src/stc/scintilla/lexers/LexPowerPro.cxx index 9320baf943..e8a7a6689b 100644 --- a/src/stc/scintilla/src/LexPowerPro.cxx +++ b/src/stc/scintilla/lexers/LexPowerPro.cxx @@ -3,42 +3,45 @@ // PowerPro utility, written by Bruce Switzer, is available from http://powerpro.webeddie.com // PowerPro lexer is written by Christopher Bean (cbean@cb-software.net) // -// Lexer code heavily borrowed from: +// Lexer code heavily borrowed from: // LexAU3.cxx by Jos van der Zande // LexCPP.cxx by Neil Hodgson // LexVB.cxx by Neil Hodgson // // Changes: // 2008-10-25 - Initial release -// 2008-10-26 - Changed how <name> is hilighted in 'function <name>' so that +// 2008-10-26 - Changed how <name> is hilighted in 'function <name>' so that // local isFunction = "" and local functions = "" don't get falsely highlighted -// 2008-12-14 - Added bounds checking for szKeyword and szDo +// 2008-12-14 - Added bounds checking for szFirstWord and szDo // - Replaced SetOfCharacters with CharacterSet // - Made sure that CharacterSet::Contains is passed only positive values -// - Made sure that the return value of Accessor::SafeGetCharAt is positive before -// passsing to functions that require positive values like isspacechar() +// - Made sure that the return value of Accessor::SafeGetCharAt is positive before +// passing to functions that require positive values like isspacechar() // - Removed unused visibleChars processing from ColourisePowerProDoc() -// - Fixed bug with folding logic where line continuations didn't end where +// - Fixed bug with folding logic where line continuations didn't end where // they were supposed to // - Moved all helper functions to the top of the file -// +// 2010-06-03 - Added onlySpaces variable to allow the @function and ;comment styles to be indented +// - Modified HasFunction function to be a bit more robust +// - Renamed HasFunction function to IsFunction +// - Cleanup // Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. -#include <ctype.h> -#include <stdarg.h> -#include <stdio.h> -#include <stdlib.h> #include <string.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" #include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -48,65 +51,81 @@ static inline bool IsStreamCommentStyle(int style) { return style == SCE_POWERPRO_COMMENTBLOCK; } +static inline bool IsLineEndChar(unsigned char ch) { + return ch == 0x0a //LF + || ch == 0x0c //FF + || ch == 0x0d; //CR +} + static bool IsContinuationLine(unsigned int szLine, Accessor &styler) { - int nsPos = styler.LineStart(szLine); - int nePos = styler.LineStart(szLine + 1) - 2; - while (nsPos < nePos) + int startPos = styler.LineStart(szLine); + int endPos = styler.LineStart(szLine + 1) - 2; + while (startPos < endPos) { - int stylech = styler.StyleAt(nsPos); + char stylech = styler.StyleAt(startPos); if (!(stylech == SCE_POWERPRO_COMMENTBLOCK)) { - char ch = styler.SafeGetCharAt(nePos); - char chPrev = styler.SafeGetCharAt(nePos-1); - char chPrevPrev = styler.SafeGetCharAt(nePos-2); - if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) ) { - if (chPrevPrev == ';' && chPrev == ';' && ch == '+') - return true; - else - return false; + char ch = styler.SafeGetCharAt(endPos); + char chPrev = styler.SafeGetCharAt(endPos - 1); + char chPrevPrev = styler.SafeGetCharAt(endPos - 2); + if (ch > 0 && chPrev > 0 && chPrevPrev > 0 && !isspacechar(ch) && !isspacechar(chPrev) && !isspacechar(chPrevPrev) ) + return (chPrevPrev == ';' && chPrev == ';' && ch == '+'); } - } - nePos--; // skip to next char + endPos--; // skip to next char } return false; } // Routine to find first none space on the current line and return its Style -// needed for comment lines not starting on pos 1 -static int GetStyleFirstWord(unsigned int szLine, Accessor &styler) +// needed for comment lines not starting on pos 1 +static int GetStyleFirstWord(int szLine, Accessor &styler) { - int nsPos = styler.LineStart(szLine); - int nePos = styler.LineStart(szLine+1) - 1; - char ch = styler.SafeGetCharAt(nsPos); - - while (ch > 0 && isspacechar(ch) && nsPos < nePos) - { - nsPos++; // skip to next char - ch = styler.SafeGetCharAt(nsPos); + int startPos = styler.LineStart(szLine); + int endPos = styler.LineStart(szLine + 1) - 1; + char ch = styler.SafeGetCharAt(startPos); + while (ch > 0 && isspacechar(ch) && startPos < endPos) + { + startPos++; // skip to next char + ch = styler.SafeGetCharAt(startPos); } - return styler.StyleAt(nsPos); + return styler.StyleAt(startPos); } //returns true if there is a function to highlight //used to highlight <name> in 'function <name>' -static bool HasFunction(Accessor &styler, unsigned int currentPos) { - - //check for presence of 'function ' - return (styler.SafeGetCharAt(currentPos) == ' ' - && tolower(styler.SafeGetCharAt(currentPos-1)) == 'n' - && tolower(styler.SafeGetCharAt(currentPos-2)) == 'o' - && tolower(styler.SafeGetCharAt(currentPos-3)) == 'i' - && tolower(styler.SafeGetCharAt(currentPos-4)) == 't' - && tolower(styler.SafeGetCharAt(currentPos-5)) == 'c' - && tolower(styler.SafeGetCharAt(currentPos-6)) == 'n' - && tolower(styler.SafeGetCharAt(currentPos-7)) == 'u' - && tolower(styler.SafeGetCharAt(currentPos-8)) == 'f' - //only allow 'function ' to appear at the beginning of a line - && (styler.SafeGetCharAt(currentPos-9) == '\n' - || styler.SafeGetCharAt(currentPos-9) == '\r' - || (styler.SafeGetCharAt(currentPos -9, '\0')) == '\0') //is the first line - ); +//note: +// sample line (without quotes): "\tfunction asdf() +// currentPos will be the position of 'a' +static bool IsFunction(Accessor &styler, unsigned int currentPos) { + + const char function[10] = "function "; //10 includes \0 + unsigned int numberOfCharacters = sizeof(function) - 1; + unsigned int position = currentPos - numberOfCharacters; + + //compare each character with the letters in the function array + //return false if ALL don't match + for (unsigned int i = 0; i < numberOfCharacters; i++) { + char c = styler.SafeGetCharAt(position++); + if (c != function[i]) + return false; + } + + //make sure that there are only spaces (or tabs) between the beginning + //of the line and the function declaration + position = currentPos - numberOfCharacters - 1; //-1 to move to char before 'function' + for (unsigned int j = 0; j < 16; j++) { //check up to 16 preceeding characters + char c = styler.SafeGetCharAt(position--, '\0'); //if can't read char, return NUL (past beginning of document) + if (c <= 0) //reached beginning of document + return true; + if (c > 0 && IsLineEndChar(c)) + return true; + else if (c > 0 && !IsASpaceOrTab(c)) + return false; + } + + //fall-through + return false; } static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], @@ -116,32 +135,32 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl WordList &keywords2 = *keywordlists[1]; WordList &keywords3 = *keywordlists[2]; WordList &keywords4 = *keywordlists[3]; - - //define the character sets + + //define the character sets CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true); CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); StyleContext sc(startPos, length, initStyle, styler); char s_save[100]; //for last line highlighting - + + //are there only spaces between the first letter of the line and the beginning of the line + bool onlySpaces = true; + for (; sc.More(); sc.Forward()) { - - // ********************************************** + // save the total current word for eof processing char s[100]; sc.GetCurrentLowered(s, sizeof(s)); - - if ((sc.ch > 0) && setWord.Contains(sc.ch)) + + if ((sc.ch > 0) && setWord.Contains(sc.ch)) { strcpy(s_save,s); - int tp = strlen(s_save); + int tp = static_cast<int>(strlen(s_save)); if (tp < 99) { s_save[tp] = static_cast<char>(tolower(sc.ch)); s_save[tp+1] = '\0'; } } - // ********************************************** - // if (sc.atLineStart) { if (sc.state == SCE_POWERPRO_DOUBLEQUOTEDSTRING) { @@ -156,12 +175,12 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl case SCE_POWERPRO_OPERATOR: sc.SetState(SCE_POWERPRO_DEFAULT); break; - + case SCE_POWERPRO_NUMBER: if (!IsADigit(sc.ch)) sc.SetState(SCE_POWERPRO_DEFAULT); - + break; case SCE_POWERPRO_IDENTIFIER: @@ -173,6 +192,7 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl } else { sc.GetCurrentLowered(s, sizeof(s)); } + if (keywords.InList(s)) { sc.ChangeState(SCE_POWERPRO_WORD); } else if (keywords2.InList(s)) { @@ -256,9 +276,9 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl } } break; - + case SCE_POWERPRO_FUNCTION: - if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ' ' || sc.ch == '(') { + if (isspacechar(sc.ch) || sc.ch == '(') { sc.SetState(SCE_POWERPRO_DEFAULT); } break; @@ -276,20 +296,20 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl sc.SetState(SCE_POWERPRO_ALTQUOTE); sc.Forward(); } - } else if (HasFunction(styler, sc.currentPos)) { //highlight <name> in 'function <name>' - sc.SetState(SCE_POWERPRO_FUNCTION); - } else if (sc.ch == '@' && sc.atLineStart) { //alternate function definition [label] + } else if (IsFunction(styler, sc.currentPos)) { //highlight <name> in 'function <name>' + sc.SetState(SCE_POWERPRO_FUNCTION); + } else if (onlySpaces && sc.ch == '@') { //alternate function definition [label] sc.SetState(SCE_POWERPRO_FUNCTION); } else if ((sc.ch > 0) && (setWordStart.Contains(sc.ch) || (sc.ch == '?'))) { sc.SetState(SCE_POWERPRO_IDENTIFIER); - } else if (sc.Match(";;+")) { + } else if (sc.Match(";;+")) { sc.SetState(SCE_POWERPRO_LINECONTINUE); } else if (sc.Match('/', '*')) { sc.SetState(SCE_POWERPRO_COMMENTBLOCK); sc.Forward(); // Eat the * so it isn't used for the end of the comment } else if (sc.Match('/', '/')) { sc.SetState(SCE_POWERPRO_COMMENTLINE); - } else if (sc.atLineStart && sc.ch == ';') { //legacy comment that can only appear at the beginning of a line + } else if (onlySpaces && sc.ch == ';') { //legacy comment that can only have blank space in front of it sc.SetState(SCE_POWERPRO_COMMENTLINE); } else if (sc.Match(";;")) { sc.SetState(SCE_POWERPRO_COMMENTLINE); @@ -301,10 +321,19 @@ static void ColourisePowerProDoc(unsigned int startPos, int length, int initStyl sc.SetState(SCE_POWERPRO_OPERATOR); } } + + //maintain a record of whether or not all the preceding characters on + //a line are space characters + if (onlySpaces && !IsASpaceOrTab(sc.ch)) + onlySpaces = false; + + //reset when starting a new line + if (sc.atLineEnd) + onlySpaces = true; } //************************************* - // Colourize the last word correctly + // Colourize the last word correctly //************************************* if (sc.state == SCE_POWERPRO_IDENTIFIER) { @@ -337,7 +366,9 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[] CharacterSet setWordStart(CharacterSet::setAlpha, "_@", 0x80, true); CharacterSet setWord(CharacterSet::setAlphaNum, "._", 0x80, true); - bool isFoldingAll = true; //used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function) + //used to tell if we're recursively folding the whole document, or just a small piece (ie: if statement or 1 function) + bool isFoldingAll = true; + int endPos = startPos + length; int lastLine = styler.GetLine(styler.Length()); //used to help fold the last line correctly @@ -345,7 +376,7 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[] bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldInComment = styler.GetPropertyInt("fold.comment") == 2; bool foldCompact = true; - + // Backtrack to previous line in case need to fix its fold status int lineCurrent = styler.GetLine(startPos); if (startPos > 0) { @@ -355,153 +386,156 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[] startPos = styler.LineStart(lineCurrent); } } - // vars for style of previous/current/next lines + // vars for style of previous/current/next lines int style = GetStyleFirstWord(lineCurrent,styler); int stylePrev = 0; - + // find the first previous line without continuation character at the end - while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) || - (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) { + while ((lineCurrent > 0 && IsContinuationLine(lineCurrent, styler)) + || (lineCurrent > 1 && IsContinuationLine(lineCurrent - 1, styler))) { lineCurrent--; startPos = styler.LineStart(lineCurrent); } + if (lineCurrent > 0) { stylePrev = GetStyleFirstWord(lineCurrent-1,styler); } + // vars for getting first word to check for keywords - bool FirstWordStart = false; - bool FirstWordEnd = false; - - const unsigned int KEYWORD_MAX = 10; - char szKeyword[KEYWORD_MAX]=""; - unsigned int szKeywordlen = 0; - + bool isFirstWordStarted = false; + bool isFirstWordEnded = false; + + const unsigned int FIRST_WORD_MAX_LEN = 10; + char szFirstWord[FIRST_WORD_MAX_LEN] = ""; + unsigned int firstWordLen = 0; + char szDo[3]=""; int szDolen = 0; - bool DoFoundLast = false; - + bool isDoLastWord = false; + // var for indentlevel int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) { + if (lineCurrent > 0) levelCurrent = styler.LevelAt(lineCurrent-1) >> 16; - } int levelNext = levelCurrent; - + int visibleChars = 0; int functionCount = 0; - + char chNext = styler.SafeGetCharAt(startPos); char chPrev = '\0'; char chPrevPrev = '\0'; char chPrevPrevPrev = '\0'; - + for (int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); - - if ((ch > 0) && setWord.Contains(ch)) { + + if ((ch > 0) && setWord.Contains(ch)) visibleChars++; - } - + // get the syle for the current character neede to check in comment int stylech = styler.StyleAt(i); - - // get first word for the line for indent check max 9 characters - if (FirstWordStart && (!(FirstWordEnd))) { - if ((ch > 0) && !setWord.Contains(ch)) { - FirstWordEnd = true; + + // start the capture of the first word + if (!isFirstWordStarted && (ch > 0)) { + if (setWord.Contains(ch) || setWordStart.Contains(ch) || ch == ';' || ch == '/') { + isFirstWordStarted = true; + if (firstWordLen < FIRST_WORD_MAX_LEN - 1) { + szFirstWord[firstWordLen++] = static_cast<char>(tolower(ch)); + szFirstWord[firstWordLen] = '\0'; + } } - else if (szKeywordlen < KEYWORD_MAX - 1) { - szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch)); - szKeyword[szKeywordlen] = '\0'; + } // continue capture of the first word on the line + else if (isFirstWordStarted && !isFirstWordEnded && (ch > 0)) { + if (!setWord.Contains(ch)) { + isFirstWordEnded = true; } - } - - // start the capture of the first word - if (!(FirstWordStart)) { - if ((ch > 0) && (setWord.Contains(ch) || setWordStart.Contains(ch) || ch == ';' || ch == '/')) { - FirstWordStart = true; - if (szKeywordlen < KEYWORD_MAX - 1) { - szKeyword[szKeywordlen++] = static_cast<char>(tolower(ch)); - szKeyword[szKeywordlen] = '\0'; - } + else if (firstWordLen < (FIRST_WORD_MAX_LEN - 1)) { + szFirstWord[firstWordLen++] = static_cast<char>(tolower(ch)); + szFirstWord[firstWordLen] = '\0'; } } - // only process this logic when not in comment section + if (stylech != SCE_POWERPRO_COMMENTLINE) { - if (DoFoundLast) { - if (DoFoundLast && (ch > 0) && setWord.Contains(ch)) { - DoFoundLast = false; - } - } - // find out if the word "do" is the last on a "if" line - if (FirstWordEnd && strcmp(szKeyword,"if") == 0) { + + //reset isDoLastWord if we find a character(ignoring spaces) after 'do' + if (isDoLastWord && (ch > 0) && setWord.Contains(ch)) + isDoLastWord = false; + + // --find out if the word "do" is the last on a "if" line-- + // collect each letter and put it into a buffer 2 chars long + // if we end up with "do" in the buffer when we reach the end of + // the line, "do" was the last word on the line + if ((ch > 0) && isFirstWordEnded && strcmp(szFirstWord, "if") == 0) { if (szDolen == 2) { szDo[0] = szDo[1]; szDo[1] = static_cast<char>(tolower(ch)); szDo[2] = '\0'; - if (strcmp(szDo,"do") == 0 ) { - DoFoundLast = true; - } - } - else if (szDolen < 2) { + + if (strcmp(szDo, "do") == 0) + isDoLastWord = true; + + } else if (szDolen < 2) { szDo[szDolen++] = static_cast<char>(tolower(ch)); szDo[szDolen] = '\0'; } } } - // End of Line found so process the information - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { - + // End of Line found so process the information + if ((ch == '\r' && chNext != '\n') // \r\n + || ch == '\n' // \n + || i == endPos) { // end of selection + // ************************** // Folding logic for Keywords // ************************** - + // if a keyword is found on the current line and the line doesn't end with ;;+ (continuation) // and we are not inside a commentblock. - if (szKeywordlen > 0 && - (!(chPrev == '+' && chPrevPrev == ';' && chPrevPrevPrev ==';')) && - ((!(IsStreamCommentStyle(style)) || foldInComment)) ) { - + if (firstWordLen > 0 + && chPrev != '+' && chPrevPrev != ';' && chPrevPrevPrev !=';' + && (!IsStreamCommentStyle(style) || foldInComment) ) { + // only fold "if" last keyword is "then" (else its a one line if) - if (strcmp(szKeyword,"if") == 0 && DoFoundLast) { + if (strcmp(szFirstWord, "if") == 0 && isDoLastWord) levelNext++; - } - // create new fold for these words - if (strcmp(szKeyword,"for") == 0) { + + // create new fold for these words + if (strcmp(szFirstWord, "for") == 0) levelNext++; - } - + //handle folding for functions/labels //Note: Functions and labels don't have an explicit end like [end function] // 1. functions/labels end at the start of another function // 2. functions/labels end at the end of the file - if ((strcmp(szKeyword,"function") == 0) || (szKeywordlen > 0 && szKeyword[0] == '@')) { + if ((strcmp(szFirstWord, "function") == 0) || (firstWordLen > 0 && szFirstWord[0] == '@')) { if (isFoldingAll) { //if we're folding the whole document (recursivly by lua script) - + if (functionCount > 0) { levelCurrent--; } else { levelNext++; } - functionCount++; - + functionCount++; + } else { //if just folding a small piece (by clicking on the minus sign next to the word) levelCurrent--; } } - + // end the fold for these words before the current line - if (strcmp(szKeyword,"endif") == 0 || strcmp(szKeyword,"endfor") == 0) { + if (strcmp(szFirstWord, "endif") == 0 || strcmp(szFirstWord, "endfor") == 0) { levelNext--; levelCurrent--; } - // end the fold for these words before the current line and Start new fold - if (strcmp(szKeyword,"else") == 0 || strcmp(szKeyword,"elseif") == 0 ) { + + // end the fold for these words before the current line and Start new fold + if (strcmp(szFirstWord, "else") == 0 || strcmp(szFirstWord, "elseif") == 0 ) levelCurrent--; - } + } // Preprocessor and Comment folding int styleNext = GetStyleFirstWord(lineCurrent + 1,styler); @@ -510,20 +544,19 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[] // Folding logic for Comment blocks // ********************************* if (foldComment && IsStreamCommentStyle(style)) { + // Start of a comment block - if (!(stylePrev==style) && IsStreamCommentStyle(styleNext) && styleNext==style) { + if (stylePrev != style && IsStreamCommentStyle(styleNext) && styleNext == style) { levelNext++; - } - // fold till the last line for normal comment lines - else if (IsStreamCommentStyle(stylePrev) - && !(styleNext == SCE_POWERPRO_COMMENTLINE) - && stylePrev == SCE_POWERPRO_COMMENTLINE + } // fold till the last line for normal comment lines + else if (IsStreamCommentStyle(stylePrev) + && styleNext != SCE_POWERPRO_COMMENTLINE + && stylePrev == SCE_POWERPRO_COMMENTLINE && style == SCE_POWERPRO_COMMENTLINE) { levelNext--; - } - // fold till the one but last line for Blockcomment lines - else if (IsStreamCommentStyle(stylePrev) - && !(styleNext == SCE_POWERPRO_COMMENTBLOCK) + } // fold till the one but last line for Blockcomment lines + else if (IsStreamCommentStyle(stylePrev) + && styleNext != SCE_POWERPRO_COMMENTBLOCK && style == SCE_POWERPRO_COMMENTBLOCK) { levelNext--; levelCurrent--; @@ -534,12 +567,10 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[] int lev = levelUse | levelNext << 16; if (visibleChars == 0 && foldCompact) lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) { + if (levelUse < levelNext) lev |= SC_FOLDLEVELHEADERFLAG; - } - if (lev != styler.LevelAt(lineCurrent)) { + if (lev != styler.LevelAt(lineCurrent)) styler.SetLevel(lineCurrent, lev); - } // reset values for the next line lineCurrent++; @@ -547,20 +578,18 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[] style = styleNext; levelCurrent = levelNext; visibleChars = 0; - + // if the last characters are ;;+ then don't reset since the line continues on the next line. - if (chPrev == '+' && chPrevPrev == ';' && chPrevPrevPrev == ';') { - //do nothing - } else { - szKeywordlen = 0; + if (chPrev != '+' && chPrevPrev != ';' && chPrevPrevPrev != ';') { + firstWordLen = 0; szDolen = 0; - FirstWordStart = false; - FirstWordEnd = false; - DoFoundLast = false; - //blank out keyword - for (unsigned int i = 0; i < KEYWORD_MAX; i++) { - szKeyword[i] = '\0'; - } + isFirstWordStarted = false; + isFirstWordEnded = false; + isDoLastWord = false; + + //blank out first word + for (unsigned int i = 0; i < FIRST_WORD_MAX_LEN; i++) + szFirstWord[i] = '\0'; } } @@ -569,11 +598,10 @@ static void FoldPowerProDoc(unsigned int startPos, int length, int, WordList *[] chPrevPrevPrev = chPrevPrev; chPrevPrev = chPrev; chPrev = ch; - visibleChars++; } } - //close folds on the last line - without this a 'phantom' + //close folds on the last line - without this a 'phantom' //fold can appear when an open fold is on the last line //this can occur because functions and labels don't have an explicit end if (lineCurrent >= lastLine) { @@ -598,3 +626,5 @@ static void ColourisePowerProDocWrapper(unsigned int startPos, int length, int i } LexerModule lmPowerPro(SCLEX_POWERPRO, ColourisePowerProDocWrapper, "powerpro", FoldPowerProDoc, powerProWordLists); + + diff --git a/src/stc/scintilla/src/LexPowerShell.cxx b/src/stc/scintilla/lexers/LexPowerShell.cxx similarity index 82% rename from src/stc/scintilla/src/LexPowerShell.cxx rename to src/stc/scintilla/lexers/LexPowerShell.cxx index d16ba98426..7f741fc74e 100644 --- a/src/stc/scintilla/src/LexPowerShell.cxx +++ b/src/stc/scintilla/lexers/LexPowerShell.cxx @@ -7,18 +7,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -26,7 +29,7 @@ using namespace Scintilla; // Extended to accept accented characters static inline bool IsAWordChar(int ch) { - return ch >= 0x80 || isalnum(ch) || ch == '-'; + return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_'; } static void ColourisePowerShellDoc(unsigned int startPos, int length, int initStyle, @@ -35,6 +38,8 @@ static void ColourisePowerShellDoc(unsigned int startPos, int length, int initSt WordList &keywords = *keywordlists[0]; WordList &keywords2 = *keywordlists[1]; WordList &keywords3 = *keywordlists[2]; + WordList &keywords4 = *keywordlists[3]; + WordList &keywords5 = *keywordlists[4]; styler.StartAt(startPos); @@ -46,6 +51,10 @@ static void ColourisePowerShellDoc(unsigned int startPos, int length, int initSt if (sc.atLineEnd) { sc.SetState(SCE_POWERSHELL_DEFAULT); } + } else if (sc.state == SCE_POWERSHELL_COMMENTSTREAM) { + if (sc.ch == '>' && sc.chPrev == '#') { + sc.ForwardSetState(SCE_POWERSHELL_DEFAULT); + } } else if (sc.state == SCE_POWERSHELL_STRING) { // This is a doubles quotes string if (sc.ch == '\"') { @@ -79,6 +88,10 @@ static void ColourisePowerShellDoc(unsigned int startPos, int length, int initSt sc.ChangeState(SCE_POWERSHELL_CMDLET); } else if (keywords3.InList(s)) { sc.ChangeState(SCE_POWERSHELL_ALIAS); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_POWERSHELL_FUNCTION); + } else if (keywords5.InList(s)) { + sc.ChangeState(SCE_POWERSHELL_USER1); } sc.SetState(SCE_POWERSHELL_DEFAULT); } @@ -88,6 +101,8 @@ static void ColourisePowerShellDoc(unsigned int startPos, int length, int initSt if (sc.state == SCE_POWERSHELL_DEFAULT) { if (sc.ch == '#') { sc.SetState(SCE_POWERSHELL_COMMENT); + } else if (sc.ch == '<' && sc.chNext == '#') { + sc.SetState(SCE_POWERSHELL_COMMENTSTREAM); } else if (sc.ch == '\"') { sc.SetState(SCE_POWERSHELL_STRING); } else if (sc.ch == '\'') { @@ -109,8 +124,9 @@ static void ColourisePowerShellDoc(unsigned int startPos, int length, int initSt // Store both the current line's fold level and the next lines in the // level store to make it easy to pick up with each increment // and to make it possible to fiddle the current level for "} else {". -static void FoldPowerShellDoc(unsigned int startPos, int length, int, +static void FoldPowerShellDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; unsigned int endPos = startPos + length; @@ -123,10 +139,12 @@ static void FoldPowerShellDoc(unsigned int startPos, int length, int, int levelNext = levelCurrent; char chNext = styler[startPos]; int styleNext = styler.StyleAt(startPos); + int style = initStyle; for (unsigned int i = startPos; i < endPos; i++) { char ch = chNext; chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; + int stylePrev = style; + style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); if (style == SCE_POWERSHELL_OPERATOR) { @@ -140,6 +158,12 @@ static void FoldPowerShellDoc(unsigned int startPos, int length, int, } else if (ch == '}') { levelNext--; } + } else if (foldComment && style == SCE_POWERSHELL_COMMENTSTREAM) { + if (stylePrev != SCE_POWERSHELL_COMMENTSTREAM) { + levelNext++; + } else if (styleNext != SCE_POWERSHELL_COMMENTSTREAM) { + levelNext--; + } } if (!IsASpace(ch)) visibleChars++; @@ -168,6 +192,8 @@ static const char * const powershellWordLists[] = { "Commands", "Cmdlets", "Aliases", + "Functions", + "User1", 0 }; diff --git a/src/stc/scintilla/src/LexProgress.cxx b/src/stc/scintilla/lexers/LexProgress.cxx similarity index 98% rename from src/stc/scintilla/src/LexProgress.cxx rename to src/stc/scintilla/lexers/LexProgress.cxx index 9e1940e298..2031720a2f 100644 --- a/src/stc/scintilla/src/LexProgress.cxx +++ b/src/stc/scintilla/lexers/LexProgress.cxx @@ -13,18 +13,21 @@ Support more than 6 comments levels **/ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -47,7 +50,7 @@ static void Colourise4glDoc(unsigned int startPos, int length, int initStyle, Wo WordList &keywords2 = *keywordlists[1]; // block opening keywords, only when SentenceStart WordList &keywords3 = *keywordlists[2]; // block opening keywords //WordList &keywords4 = *keywordlists[3]; // preprocessor keywords. Not implemented - + int visibleChars = 0; int mask; @@ -180,7 +183,7 @@ static void Colourise4glDoc(unsigned int startPos, int length, int initStyle, Wo } else if (isoperator(static_cast<char>(sc.ch))) { /* This code allows highlight of handles. Alas, it would cause the phrase "last-event:function" to be recognized as a BlockBegin */ - + if (sc.ch == ':') sc.SetState(SCE_4GL_OPERATOR & SetSentenceStart); /* else */ diff --git a/src/stc/scintilla/src/LexPython.cxx b/src/stc/scintilla/lexers/LexPython.cxx similarity index 87% rename from src/stc/scintilla/src/LexPython.cxx rename to src/stc/scintilla/lexers/LexPython.cxx index 897a136e94..fedc312599 100644 --- a/src/stc/scintilla/src/LexPython.cxx +++ b/src/stc/scintilla/lexers/LexPython.cxx @@ -7,25 +7,28 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif /* kwCDef, kwCTypeName only used for Cython */ -enum kwType { kwOther, kwClass, kwDef, kwImport, kwCDef, kwCTypeName }; +enum kwType { kwOther, kwClass, kwDef, kwImport, kwCDef, kwCTypeName, kwCPDef }; static const int indicatorWhitespace = 1; @@ -36,7 +39,7 @@ static bool IsPyComment(Accessor &styler, int pos, int len) { enum literalsAllowed { litNone=0, litU=1, litB=2}; static bool IsPyStringTypeChar(int ch, literalsAllowed allowed) { - return + return ((allowed & litB) && (ch == 'b' || ch == 'B')) || ((allowed & litU) && (ch == 'u' || ch == 'U')); } @@ -136,13 +139,13 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, WordList &keywords2 = *keywordlists[1]; // property tab.timmy.whinge.level - // For Python code, checks whether indenting is consistent. - // The default, 0 turns off indentation checking, - // 1 checks whether each line is potentially inconsistent with the previous line, - // 2 checks whether any space characters occur before a tab character in the indentation, - // 3 checks whether any spaces are in the indentation, and + // For Python code, checks whether indenting is consistent. + // The default, 0 turns off indentation checking, + // 1 checks whether each line is potentially inconsistent with the previous line, + // 2 checks whether any space characters occur before a tab character in the indentation, + // 3 checks whether any spaces are in the indentation, and // 4 checks for any tab characters in the indentation. - // 1 is a good level to use. + // 1 is a good level to use. const int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level"); // property lexer.python.literals.binary @@ -162,6 +165,11 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, // Set to 1 to allow strings to span newline characters. bool stringsOverNewline = styler.GetPropertyInt("lexer.python.strings.over.newline") != 0; + // property lexer.python.keywords2.no.sub.identifiers + // When enabled, it will not style keywords2 items that are used as a sub-identifier. + // Example: when set, will not highlight "foo.open" when "open" is a keywords2 item. + const bool keywords2NoSubIdentifiers = styler.GetPropertyInt("lexer.python.keywords2.no.sub.identifiers") != 0; + initStyle = initStyle & 31; if (initStyle == SCE_P_STRINGEOL) { initStyle = SCE_P_DEFAULT; @@ -243,7 +251,7 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, style = SCE_P_CLASSNAME; } else if (kwLast == kwDef) { style = SCE_P_DEFNAME; - } else if (kwLast == kwCDef) { + } else if (kwLast == kwCDef || kwLast == kwCPDef) { int pos = sc.currentPos; unsigned char ch = styler.SafeGetCharAt(pos, '\0'); while (ch != '\0') { @@ -261,7 +269,16 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, } } } else if (keywords2.InList(s)) { - style = SCE_P_WORD2; + if (keywords2NoSubIdentifiers) { + // We don't want to highlight keywords2 + // that are used as a sub-identifier, + // i.e. not open in "foo.open". + int pos = styler.GetStartSegment() - 1; + if (pos < 0 || (styler.SafeGetCharAt(pos, '\0') != '.')) + style = SCE_P_WORD2; + } else { + style = SCE_P_WORD2; + } } sc.ChangeState(style); sc.SetState(SCE_P_DEFAULT); @@ -274,11 +291,13 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, kwLast = kwImport; else if (0 == strcmp(s, "cdef")) kwLast = kwCDef; + else if (0 == strcmp(s, "cpdef")) + kwLast = kwCPDef; else if (0 == strcmp(s, "cimport")) kwLast = kwImport; - else if (kwLast != kwCDef) + else if (kwLast != kwCDef && kwLast != kwCPDef) kwLast = kwOther; - } else if (kwLast != kwCDef) { + } else if (kwLast != kwCDef && kwLast != kwCPDef) { kwLast = kwOther; } } @@ -334,8 +353,8 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, indentGood = true; } - // One cdef line, clear kwLast only at end of line - if (kwLast == kwCDef && sc.atLineEnd) { + // One cdef or cpdef line, clear kwLast only at end of line + if ((kwLast == kwCDef || kwLast == kwCPDef) && sc.atLineEnd) { kwLast = kwOther; } @@ -353,7 +372,7 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle, if (sc.ch == '0' && (sc.chNext == 'x' || sc.chNext == 'X')) { base_n_number = true; sc.SetState(SCE_P_NUMBER); - } else if (sc.ch == '0' && + } else if (sc.ch == '0' && (sc.chNext == 'o' || sc.chNext == 'O' || sc.chNext == 'b' || sc.chNext == 'B')) { if (base2or8Literals) { base_n_number = true; @@ -409,12 +428,8 @@ static bool IsQuoteLine(int line, Accessor &styler) { static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unused*/, WordList *[], Accessor &styler) { const int maxPos = startPos + length; - const int maxLines = styler.GetLine(maxPos - 1); // Requested last line - const int docLines = styler.GetLine(styler.Length() - 1); // Available last line - - // property fold.comment.python - // This option enables folding multi-line comments when using the Python lexer. - const bool foldComment = styler.GetPropertyInt("fold.comment.python") != 0; + const int maxLines = (maxPos == styler.Length()) ? styler.GetLine(maxPos) : styler.GetLine(maxPos - 1); // Requested last line + const int docLines = styler.GetLine(styler.Length()); // Available last line // property fold.quotes.python // This option enables folding multi-line quoted strings when using the Python lexer. @@ -445,14 +460,11 @@ static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unuse if (lineCurrent >= 1) prev_state = styler.StyleAt(startPos - 1) & 31; int prevQuote = foldQuotes && ((prev_state == SCE_P_TRIPLE) || (prev_state == SCE_P_TRIPLEDOUBLE)); - int prevComment = 0; - if (lineCurrent >= 1) - prevComment = foldComment && IsCommentLine(lineCurrent - 1, styler); // Process all characters to end of requested range or end of any triple quote - // or comment that hangs over the end of the range. Cap processing in all cases - // to end of document (in case of unclosed quote or comment at end). - while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevQuote || prevComment)) { + //that hangs over the end of the range. Cap processing in all cases + // to end of document (in case of unclosed quote at end). + while ((lineCurrent <= docLines) && ((lineCurrent <= maxLines) || prevQuote)) { // Gather info int lev = indentCurrent; @@ -462,16 +474,13 @@ static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unuse if (lineNext <= docLines) { // Information about next line is only available if not at end of document indentNext = styler.IndentAmount(lineNext, &spaceFlags, NULL); - int style = styler.StyleAt(styler.LineStart(lineNext)) & 31; + int lookAtPos = (styler.LineStart(lineNext) == styler.Length()) ? styler.Length() - 1 : styler.LineStart(lineNext); + int style = styler.StyleAt(lookAtPos) & 31; quote = foldQuotes && ((style == SCE_P_TRIPLE) || (style == SCE_P_TRIPLEDOUBLE)); } const int quote_start = (quote && !prevQuote); const int quote_continue = (quote && prevQuote); - const int comment = foldComment && IsCommentLine(lineCurrent, styler); - const int comment_start = (comment && !prevComment && (lineNext <= docLines) && - IsCommentLine(lineNext, styler) && (lev > SC_FOLDLEVELBASE)); - const int comment_continue = (comment && prevComment); - if ((!quote || !prevQuote) && !comment) + if (!quote || !prevQuote) indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK; if (quote) indentNext = indentCurrentLevel; @@ -484,12 +493,6 @@ static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unuse } else if (quote_continue || prevQuote) { // Add level to rest of lines in the string lev = lev + 1; - } else if (comment_start) { - // Place fold point at start of a block of comments - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (comment_continue) { - // Add level to rest of lines in the block - lev = lev + 1; } // Skip past any blank lines for next indent level info; we skip also @@ -507,7 +510,7 @@ static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unuse } const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; - const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments); + const int levelBeforeComments = Maximum(indentCurrentLevel,levelAfterComments); // Now set all the indent levels on the lines we skipped // Do this from end to start. Once we encounter one line @@ -537,18 +540,17 @@ static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unuse } } - // Set fold header on non-quote/non-comment line - if (!quote && !comment && !(indentCurrent & SC_FOLDLEVELWHITEFLAG) ) { + // Set fold header on non-quote line + if (!quote && !(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) lev |= SC_FOLDLEVELHEADERFLAG; } - // Keep track of triple quote and block comment state of previous line + // Keep track of triple quote state of previous line prevQuote = quote; - prevComment = comment_start || comment_continue; // Set fold level for this line and move to next line - styler.SetLevel(lineCurrent, lev); + styler.SetLevel(lineCurrent, foldCompact ? lev : lev & ~SC_FOLDLEVELWHITEFLAG); indentCurrent = indentNext; lineCurrent = lineNext; } @@ -558,7 +560,7 @@ static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unuse //styler.SetLevel(lineCurrent, indentCurrent); } -static const char * const pythonWordListDesc[] = { +static const char *const pythonWordListDesc[] = { "Keywords", "Highlighted identifiers", 0 diff --git a/src/stc/scintilla/src/LexR.cxx b/src/stc/scintilla/lexers/LexR.cxx similarity index 96% rename from src/stc/scintilla/src/LexR.cxx rename to src/stc/scintilla/lexers/LexR.cxx index 67e779f55f..d18fffb9f4 100644 --- a/src/stc/scintilla/src/LexR.cxx +++ b/src/stc/scintilla/lexers/LexR.cxx @@ -8,18 +8,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -77,9 +80,9 @@ static void ColouriseRDoc(unsigned int startPos, int length, int initStyle, Word sc.SetState(SCE_R_DEFAULT); } } else if (sc.state == SCE_R_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + if (!IsAWordChar(sc.ch)) { char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); + sc.GetCurrent(s, sizeof(s)); if (keywords.InList(s)) { sc.ChangeState(SCE_R_KWORD); } else if (keywords2.InList(s)) { diff --git a/src/stc/scintilla/src/LexRebol.cxx b/src/stc/scintilla/lexers/LexRebol.cxx similarity index 98% rename from src/stc/scintilla/src/LexRebol.cxx rename to src/stc/scintilla/lexers/LexRebol.cxx index 7139b8dbd5..7d000df042 100644 --- a/src/stc/scintilla/src/LexRebol.cxx +++ b/src/stc/scintilla/lexers/LexRebol.cxx @@ -13,18 +13,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" #include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexRuby.cxx b/src/stc/scintilla/lexers/LexRuby.cxx similarity index 95% rename from src/stc/scintilla/src/LexRuby.cxx rename to src/stc/scintilla/lexers/LexRuby.cxx index 8d6dc90b8f..23115e6e09 100644 --- a/src/stc/scintilla/src/LexRuby.cxx +++ b/src/stc/scintilla/lexers/LexRuby.cxx @@ -7,18 +7,22 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -78,7 +82,7 @@ static bool followsDot(unsigned int pos, Accessor &styler) { return false; } break; - + case SCE_RB_OPERATOR: return styler[pos] == '.'; @@ -118,7 +122,7 @@ static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywor else if (keywords.InList(s) && !followsDot(start - 1, styler)) { if (keywordIsAmbiguous(s) && keywordIsModifier(s, start, styler)) { - + // Demoted keywords are colored as keywords, // but do not affect changes in indentation. // @@ -127,7 +131,7 @@ static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywor // 2. <<stmt if test>> : demoted // 3. <<lhs = if ...>> : normal: start a new indent level // 4. <<obj.if = 10>> : color as identifer, since it follows '.' - + chAttr = SCE_RB_WORD_DEMOTED; } else { chAttr = SCE_RB_WORD; @@ -224,7 +228,7 @@ static bool currLineContainsHereDelims(int& startPos, // Leave the pointers where they are -- there are no // here doc delims on the current line, even if // the EOL isn't default style - + return false; } else { styler.Flush(); @@ -276,7 +280,7 @@ class QuoteCls { } return *this; } - + }; @@ -352,7 +356,7 @@ static int skipWhitespace(int startPos, } return endPos; } - + // This routine looks for false positives like // undef foo, << // There aren't too many. @@ -362,7 +366,7 @@ static int skipWhitespace(int startPos, static bool sureThisIsHeredoc(int iPrev, Accessor &styler, char *prevWord) { - + // Not so fast, since Ruby's so dynamic. Check the context // to make sure we're OK. int prevStyle; @@ -453,7 +457,7 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, styler.Flush(); const bool definitely_not_a_here_doc = true; const bool looks_like_a_here_doc = false; - + // Find the first word after some whitespace int firstWordPosn = skipWhitespace(lineStartPosn, lt2StartPos, styler); if (firstWordPosn >= lt2StartPos) { @@ -531,7 +535,7 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, target_quote = styler[j]; j += 1; } - + if (isSafeAlnum(styler[j])) { // Init target_end because some compilers think it won't // be initialized by the time it's used @@ -549,7 +553,7 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, // And for now make sure that it's a newline // don't handle arbitrary expressions yet - + target_end = j; if (target_quote) { // Now we can move to the character after the string delimiter. @@ -592,7 +596,7 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, } //todo: if we aren't looking at a stdio character, -// move to the start of the first line that is not in a +// move to the start of the first line that is not in a // multi-line construct static void synchronizeDocStart(unsigned int& startPos, @@ -610,7 +614,7 @@ static void synchronizeDocStart(unsigned int& startPos, // Don't do anything else with these. return; } - + int pos = startPos; // Quick way to characterize each line int lineStart; @@ -651,7 +655,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // Lexer for Ruby often has to backtrack to start of current style to determine // which characters are being used as quotes, how deeply nested is the // start position and what the termination string is for here documents - + WordList &keywords = *keywordlists[0]; class HereDocCls { @@ -674,7 +678,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, CanBeIndented = false; } }; - HereDocCls HereDoc; + HereDocCls HereDoc; QuoteCls Quote; @@ -750,7 +754,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, i += 1; continue; } - + // skip on DOS/Windows //No, don't, because some things will get tagged on, // so we won't recognize keywords, for example @@ -759,7 +763,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, continue; } #endif - + if (HereDoc.State == 1 && isEOLChar(ch)) { // Begin of here-doc (the line after the here-doc delimiter): HereDoc.State = 2; @@ -784,13 +788,13 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, state = SCE_RB_COMMENTLINE; } else if (ch == '=') { // =begin indicates the start of a comment (doc) block - if (i == 0 || (isEOLChar(chPrev) + if ((i == 0 || isEOLChar(chPrev)) && chNext == 'b' && styler.SafeGetCharAt(i + 2) == 'e' && styler.SafeGetCharAt(i + 3) == 'g' && styler.SafeGetCharAt(i + 4) == 'i' && styler.SafeGetCharAt(i + 5) == 'n' - && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6)))) { + && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6))) { styler.ColourTo(i - 1, state); state = SCE_RB_POD; } else { @@ -973,6 +977,15 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } else if (preferRE && !isSafeWordcharOrHigh(chNext)) { // Ruby doesn't allow high bit chars here, // but the editor host might + Quote.New(); + state = SCE_RB_STRING_QQ; + Quote.Open(chNext); + advance_char(i, ch, chNext, chNext2); // pass by ref + have_string = true; + } else if (!isSafeWordcharOrHigh(chNext) && !iswhitespace(chNext) && !isEOLChar(chNext)) { + // Ruby doesn't allow high bit chars here, + // but the editor host might + Quote.New(); state = SCE_RB_STRING_QQ; Quote.Open(chNext); advance_char(i, ch, chNext, chNext2); // pass by ref @@ -1003,7 +1016,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // So if we don't have one of these chars, // we aren't ending an object exp'n, and ops // like : << / are unary operators. - + if (ch == '{') { ++brace_counts; preferRE = true; @@ -1035,7 +1048,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // Default accessor treats '.' as word-chars, // but we don't for now. - + if (ch == '=' && isSafeWordcharOrHigh(chPrev) && (chNext == '(' @@ -1066,11 +1079,11 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, case SCE_RB_WORD: preferRE = RE_CanFollowKeyword(prevWord); break; - + case SCE_RB_WORD_DEMOTED: preferRE = true; break; - + case SCE_RB_IDENTIFIER: if (isMatch(styler, lengthDoc, wordStartPos, "print")) { preferRE = true; @@ -1087,7 +1100,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // We might be redefining an operator-method preferRE = false; } - // And if it's the first + // And if it's the first redo_char(i, ch, chNext, chNext2, state); // pass by ref } } @@ -1124,6 +1137,10 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } } else if (isSafeAlnumOrHigh(ch) || ch == '_') { // Keep going + } else if (ch == '.' && chNext == '.') { + ++numDots; + styler.ColourTo(i - 1, state); + redo_char(i, ch, chNext, chNext2, state); // pass by ref } else if (ch == '.' && ++numDots == 1) { // Keep going } else { @@ -1141,7 +1158,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // See the comment for SCE_RB_HERE_DELIM in LexPerl.cxx // Slightly different: if we find an immediate '-', // the target can appear indented. - + if (HereDoc.State == 0) { // '<<' encountered HereDoc.State = 1; HereDoc.DelimiterLength = 0; @@ -1157,7 +1174,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, preferRE = false; } else { HereDoc.Quote = ch; - + if (ch == '\'' || ch == '"' || ch == '`') { HereDoc.Quoted = true; HereDoc.Delimiter[0] = '\0'; @@ -1175,7 +1192,6 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, state = SCE_RB_DEFAULT; i--; chNext = ch; - chNext2 = chNext; preferRE = false; } else if (HereDoc.Quoted) { if (ch == HereDoc.Quote) { // closing quote => end of delimiter @@ -1291,7 +1307,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } else if (ch == Quote.Up) { // Only if close quoter != open quoter Quote.Count++; - + } else if (ch == '#' ) { if (chNext == '{' && inner_string_count < INNER_STRINGS_MAX_COUNT) { @@ -1332,11 +1348,10 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } } chNext = styler.SafeGetCharAt(i + 1); - chNext2 = styler.SafeGetCharAt(i + 2); } } // Quotes of all kinds... - } else if (state == SCE_RB_STRING_Q || state == SCE_RB_STRING_QQ || + } else if (state == SCE_RB_STRING_Q || state == SCE_RB_STRING_QQ || state == SCE_RB_STRING_QX || state == SCE_RB_STRING_QW || state == SCE_RB_STRING || state == SCE_RB_CHARACTER || state == SCE_RB_BACKTICKS) { @@ -1373,7 +1388,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, advance_char(i, ch, chNext, chNext2); } } - + if (state == SCE_RB_ERROR) { break; } @@ -1389,7 +1404,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } // Helper functions for folding, disambiguation keywords -// Assert that there are no high-bit chars +// Assert that there are no high-bit chars static void getPrevWord(int pos, char *prevWord, @@ -1430,7 +1445,7 @@ static bool keywordIsAmbiguous(const char *prevWord) // Demote keywords in the following conditions: // if, while, unless, until modify a statement -// do after a while or until, as a noise word (like then after if) +// do after a while or until, as a noise word (like then after if) static bool keywordIsModifier(const char *word, int pos, @@ -1439,10 +1454,32 @@ static bool keywordIsModifier(const char *word, if (word[0] == 'd' && word[1] == 'o' && !word[2]) { return keywordDoStartsLoop(pos, styler); } - char ch; + char ch, chPrev, chPrev2; int style = SCE_RB_DEFAULT; int lineStart = styler.GetLine(pos); int lineStartPosn = styler.LineStart(lineStart); + // We want to step backwards until we don't care about the current + // position. But first move lineStartPosn back behind any + // continuations immediately above word. + while (lineStartPosn > 0) { + ch = styler[lineStartPosn-1]; + if (ch == '\n' || ch == '\r') { + chPrev = styler.SafeGetCharAt(lineStartPosn-2); + chPrev2 = styler.SafeGetCharAt(lineStartPosn-3); + lineStart = styler.GetLine(lineStartPosn-1); + // If we find a continuation line, include it in our analysis. + if (chPrev == '\\') { + lineStartPosn = styler.LineStart(lineStart); + } else if (ch == '\n' && chPrev == '\r' && chPrev2 == '\\') { + lineStartPosn = styler.LineStart(lineStart); + } else { + break; + } + } else { + break; + } + } + styler.Flush(); while (--pos >= lineStartPosn) { style = actual_style(styler.StyleAt(pos)); @@ -1453,14 +1490,27 @@ static bool keywordIsModifier(const char *word, // Scintilla's LineStart() and GetLine() routines aren't // platform-independent, so if we have text prepared with // a different system we can't rely on it. - return false; + + // Also, lineStartPosn may have been moved to more than one + // line above word's line while pushing past continuations. + chPrev = styler.SafeGetCharAt(pos - 1); + chPrev2 = styler.SafeGetCharAt(pos - 2); + if (chPrev == '\\') { + pos-=1; // gloss over the "\\" + //continue + } else if (ch == '\n' && chPrev == '\r' && chPrev2 == '\\') { + pos-=2; // gloss over the "\\\r" + //continue + } else { + return false; + } } } else { break; } } if (pos < lineStartPosn) { - return false; //XXX not quite right if the prev line is a continuation + return false; } // First things where the action is unambiguous switch (style) { @@ -1490,7 +1540,7 @@ static bool keywordIsModifier(const char *word, // Assume that if the keyword follows an operator, // usually it's a block assignment, like // a << if x then y else z - + ch = styler[pos]; switch (ch) { case ')': @@ -1561,25 +1611,25 @@ static bool keywordDoStartsLoop(int pos, /* * Folding Ruby - * + * * The language is quite complex to analyze without a full parse. * For example, this line shouldn't affect fold level: - * + * * print "hello" if feeling_friendly? - * + * * Neither should this: - * + * * print "hello" \ * if feeling_friendly? - * - * + * + * * But this should: - * + * * if feeling_friendly? #++ * print "hello" \ * print "goodbye" * end #-- - * + * * So we cheat, by actually looking at the existing indentation * levels for each line, and just echoing it back. Like Python. * Then if we get better at it, we'll take braces into consideration, @@ -1587,29 +1637,29 @@ static bool keywordDoStartsLoop(int pos, * How the keywords should work: * No effect: - * __FILE__ __LINE__ BEGIN END alias and + * __FILE__ __LINE__ BEGIN END alias and * defined? false in nil not or self super then * true undef * Always increment: * begin class def do for module when { - * + * * Always decrement: * end } - * + * * Increment if these start a statement * if unless until while -- do nothing if they're modifiers * These end a block if there's no modifier, but don't bother * break next redo retry return yield - * + * * These temporarily de-indent, but re-indent * case else elsif ensure rescue - * + * * This means that the folder reflects indentation rather * than setting it. The language-service updates indentation * when users type return and finishes entering de-denters. - * + * * Later offer to fold POD, here-docs, strings, and blocks of comments */ @@ -1617,7 +1667,7 @@ static void FoldRbDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) { const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - + synchronizeDocStart(startPos, length, initStyle, styler, // ref args false); unsigned int endPos = startPos + length; @@ -1676,7 +1726,13 @@ static void FoldRbDoc(unsigned int startPos, int length, int initStyle, ) { levelCurrent++; } - } + } else if (style == SCE_RB_HERE_DELIM) { + if (styler.SafeGetCharAt(i-2) == '<' && styler.SafeGetCharAt(i-1) == '<') { + levelCurrent++; + } else if (styleNext == SCE_RB_DEFAULT) { + levelCurrent--; + } + } if (atEOL) { int lev = levelPrev; if (visibleChars == 0 && foldCompact) @@ -1712,4 +1768,4 @@ static const char * const rubyWordListDesc[] = { 0 }; -LexerModule lmRuby(SCLEX_RUBY, ColouriseRbDoc, "ruby", FoldRbDoc, rubyWordListDesc); +LexerModule lmRuby(SCLEX_RUBY, ColouriseRbDoc, "ruby", FoldRbDoc, rubyWordListDesc, 6); diff --git a/src/stc/scintilla/src/LexSML.cxx b/src/stc/scintilla/lexers/LexSML.cxx similarity index 95% rename from src/stc/scintilla/src/LexSML.cxx rename to src/stc/scintilla/lexers/LexSML.cxx index a61753077f..6ab902dc5d 100644 --- a/src/stc/scintilla/src/LexSML.cxx +++ b/src/stc/scintilla/lexers/LexSML.cxx @@ -6,21 +6,23 @@ // Modified from LexCaml.cxx by Robert Roessler <robertr@rftp.com> Copyright 2005 // The License.txt file describes the conditions under which this software may be distributed. - #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" inline int issml(int c) {return isalnum(c) || c == '_';} inline int issmlf(int c) {return isalpha(c) || c == '_';} @@ -67,7 +69,7 @@ void ColouriseSMLDoc( else if (sc.Match('#','\"')){ state2 = SCE_SML_CHAR,chLit = 0; sc.Forward(); - + } else if (isdigit(sc.ch)) { state2 = SCE_SML_NUMBER, chBase = 10; @@ -203,13 +205,11 @@ void ColouriseSMLDoc( } void FoldSMLDoc( - unsigned int startPos, int length, - int initStyle, - WordList *keywordlists[], - Accessor &styler) + unsigned int, int, + int, + WordList *[], + Accessor &) { - //supress "not used" warnings - startPos || length || initStyle || keywordlists[0] || styler.Length(); } static const char * const SMLWordListDesc[] = { @@ -220,4 +220,4 @@ static const char * const SMLWordListDesc[] = { }; LexerModule lmSML(SCLEX_SML, ColouriseSMLDoc, "SML", FoldSMLDoc, SMLWordListDesc); - + diff --git a/src/stc/scintilla/lexers/LexSQL.cxx b/src/stc/scintilla/lexers/LexSQL.cxx new file mode 100644 index 0000000000..d9013db9b9 --- /dev/null +++ b/src/stc/scintilla/lexers/LexSQL.cxx @@ -0,0 +1,834 @@ +//-*- coding: utf-8 -*- +// Scintilla source code edit control +/** @file LexSQL.cxx + ** Lexer for SQL, including PL/SQL and SQL*Plus. + ** Improved by Jérôme LAFORGE <jerome.laforge_AT_gmail_DOT_com> from 2010 to 2012. + **/ +// Copyright 1998-2012 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include <string> +#include <vector> +#include <map> +#include <algorithm> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" +#include "SparseState.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static inline bool IsAWordChar(int ch, bool sqlAllowDottedWord) { + if (!sqlAllowDottedWord) + return (ch < 0x80) && (isalnum(ch) || ch == '_'); + else + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.'); +} + +static inline bool IsAWordStart(int ch) { + return (ch < 0x80) && (isalpha(ch) || ch == '_'); +} + +static inline bool IsADoxygenChar(int ch) { + return (islower(ch) || ch == '$' || ch == '@' || + ch == '\\' || ch == '&' || ch == '<' || + ch == '>' || ch == '#' || ch == '{' || + ch == '}' || ch == '[' || ch == ']'); +} + +static inline bool IsANumberChar(int ch) { + // Not exactly following number definition (several dots are seen as OK, etc.) + // but probably enough in most cases. + return (ch < 0x80) && + (isdigit(ch) || toupper(ch) == 'E' || + ch == '.' || ch == '-' || ch == '+'); +} + + +class SQLStates { +public : + void Set(int lineNumber, unsigned short int sqlStatesLine) { + sqlStatement.Set(lineNumber, sqlStatesLine); + } + + unsigned short int IgnoreWhen (unsigned short int sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_IGNORE_WHEN; + else + sqlStatesLine &= ~MASK_IGNORE_WHEN; + + return sqlStatesLine; + } + + unsigned short int IntoCondition (unsigned short int sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_INTO_CONDITION; + else + sqlStatesLine &= ~MASK_INTO_CONDITION; + + return sqlStatesLine; + } + + unsigned short int IntoExceptionBlock (unsigned short int sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_INTO_EXCEPTION; + else + sqlStatesLine &= ~MASK_INTO_EXCEPTION; + + return sqlStatesLine; + } + + unsigned short int IntoDeclareBlock (unsigned short int sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_INTO_DECLARE; + else + sqlStatesLine &= ~MASK_INTO_DECLARE; + + return sqlStatesLine; + } + + unsigned short int IntoMergeStatement (unsigned short int sqlStatesLine, bool enable) { + if (enable) + sqlStatesLine |= MASK_MERGE_STATEMENT; + else + sqlStatesLine &= ~MASK_MERGE_STATEMENT; + + return sqlStatesLine; + } + + unsigned short int CaseMergeWithoutWhenFound (unsigned short int sqlStatesLine, bool found) { + if (found) + sqlStatesLine |= MASK_CASE_MERGE_WITHOUT_WHEN_FOUND; + else + sqlStatesLine &= ~MASK_CASE_MERGE_WITHOUT_WHEN_FOUND; + + return sqlStatesLine; + } + + unsigned short int IntoSelectStatement (unsigned short int sqlStatesLine, bool found) { + if (found) + sqlStatesLine |= MASK_INTO_SELECT_STATEMENT; + else + sqlStatesLine &= ~MASK_INTO_SELECT_STATEMENT; + + return sqlStatesLine; + } + + unsigned short int BeginCaseBlock (unsigned short int sqlStatesLine) { + if ((sqlStatesLine & MASK_NESTED_CASES) < MASK_NESTED_CASES) { + sqlStatesLine++; + } + return sqlStatesLine; + } + + unsigned short int EndCaseBlock (unsigned short int sqlStatesLine) { + if ((sqlStatesLine & MASK_NESTED_CASES) > 0) { + sqlStatesLine--; + } + return sqlStatesLine; + } + + bool IsIgnoreWhen (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_IGNORE_WHEN) != 0; + } + + bool IsIntoCondition (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_CONDITION) != 0; + } + + bool IsIntoCaseBlock (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_NESTED_CASES) != 0; + } + + bool IsIntoExceptionBlock (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_EXCEPTION) != 0; + } + + bool IsIntoSelectStatement (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_SELECT_STATEMENT) != 0; + } + + bool IsCaseMergeWithoutWhenFound (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_CASE_MERGE_WITHOUT_WHEN_FOUND) != 0; + } + + bool IsIntoDeclareBlock (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_INTO_DECLARE) != 0; + } + + bool IsIntoMergeStatement (unsigned short int sqlStatesLine) { + return (sqlStatesLine & MASK_MERGE_STATEMENT) != 0; + } + + unsigned short int ForLine(int lineNumber) { + return sqlStatement.ValueAt(lineNumber); + } + + SQLStates() {} + +private : + SparseState <unsigned short int> sqlStatement; + enum { + MASK_NESTED_CASES = 0x01FF, + MASK_INTO_SELECT_STATEMENT = 0x0200, + MASK_CASE_MERGE_WITHOUT_WHEN_FOUND = 0x0400, + MASK_MERGE_STATEMENT = 0x0800, + MASK_INTO_DECLARE = 0x1000, + MASK_INTO_EXCEPTION = 0x2000, + MASK_INTO_CONDITION = 0x4000, + MASK_IGNORE_WHEN = 0x8000 + }; +}; + +// Options used for LexerSQL +struct OptionsSQL { + bool fold; + bool foldAtElse; + bool foldComment; + bool foldCompact; + bool foldOnlyBegin; + bool sqlBackticksIdentifier; + bool sqlNumbersignComment; + bool sqlBackslashEscapes; + bool sqlAllowDottedWord; + OptionsSQL() { + fold = false; + foldAtElse = false; + foldComment = false; + foldCompact = false; + foldOnlyBegin = false; + sqlBackticksIdentifier = false; + sqlNumbersignComment = false; + sqlBackslashEscapes = false; + sqlAllowDottedWord = false; + } +}; + +static const char * const sqlWordListDesc[] = { + "Keywords", + "Database Objects", + "PLDoc", + "SQL*Plus", + "User Keywords 1", + "User Keywords 2", + "User Keywords 3", + "User Keywords 4", + 0 +}; + +struct OptionSetSQL : public OptionSet<OptionsSQL> { + OptionSetSQL() { + DefineProperty("fold", &OptionsSQL::fold); + + DefineProperty("fold.sql.at.else", &OptionsSQL::foldAtElse, + "This option enables SQL folding on a \"ELSE\" and \"ELSIF\" line of an IF statement."); + + DefineProperty("fold.comment", &OptionsSQL::foldComment); + + DefineProperty("fold.compact", &OptionsSQL::foldCompact); + + DefineProperty("fold.sql.only.begin", &OptionsSQL::foldOnlyBegin); + + DefineProperty("lexer.sql.backticks.identifier", &OptionsSQL::sqlBackticksIdentifier); + + DefineProperty("lexer.sql.numbersign.comment", &OptionsSQL::sqlNumbersignComment, + "If \"lexer.sql.numbersign.comment\" property is set to 0 a line beginning with '#' will not be a comment."); + + DefineProperty("sql.backslash.escapes", &OptionsSQL::sqlBackslashEscapes, + "Enables backslash as an escape character in SQL."); + + DefineProperty("lexer.sql.allow.dotted.word", &OptionsSQL::sqlAllowDottedWord, + "Set to 1 to colourise recognized words with dots " + "(recommended for Oracle PL/SQL objects)."); + + DefineWordListSets(sqlWordListDesc); + } +}; + +class LexerSQL : public ILexer { +public : + LexerSQL() {} + + virtual ~LexerSQL() {} + + int SCI_METHOD Version () const { + return lvOriginal; + } + + void SCI_METHOD Release() { + delete this; + } + + const char * SCI_METHOD PropertyNames() { + return osSQL.PropertyNames(); + } + + int SCI_METHOD PropertyType(const char *name) { + return osSQL.PropertyType(name); + } + + const char * SCI_METHOD DescribeProperty(const char *name) { + return osSQL.DescribeProperty(name); + } + + int SCI_METHOD PropertySet(const char *key, const char *val) { + if (osSQL.PropertySet(&options, key, val)) { + return 0; + } + return -1; + } + + const char * SCI_METHOD DescribeWordListSets() { + return osSQL.DescribeWordListSets(); + } + + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex (unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + + static ILexer *LexerFactorySQL() { + return new LexerSQL(); + } +private: + bool IsStreamCommentStyle(int style) { + return style == SCE_SQL_COMMENT || + style == SCE_SQL_COMMENTDOC || + style == SCE_SQL_COMMENTDOCKEYWORD || + style == SCE_SQL_COMMENTDOCKEYWORDERROR; + } + + bool IsCommentStyle (int style) { + switch (style) { + case SCE_SQL_COMMENT : + case SCE_SQL_COMMENTDOC : + case SCE_SQL_COMMENTLINE : + case SCE_SQL_COMMENTLINEDOC : + case SCE_SQL_COMMENTDOCKEYWORD : + case SCE_SQL_COMMENTDOCKEYWORDERROR : + return true; + default : + return false; + } + } + + bool IsCommentLine (int line, LexAccessor &styler) { + int pos = styler.LineStart(line); + int eol_pos = styler.LineStart(line + 1) - 1; + for (int i = pos; i + 1 < eol_pos; i++) { + int style = styler.StyleAt(i); + // MySQL needs -- comments to be followed by space or control char + if (style == SCE_SQL_COMMENTLINE && styler.Match(i, "--")) + return true; + else if (!IsASpaceOrTab(styler[i])) + return false; + } + return false; + } + + OptionsSQL options; + OptionSetSQL osSQL; + SQLStates sqlStates; + + WordList keywords1; + WordList keywords2; + WordList kw_pldoc; + WordList kw_sqlplus; + WordList kw_user1; + WordList kw_user2; + WordList kw_user3; + WordList kw_user4; +}; + +int SCI_METHOD LexerSQL::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &keywords1; + break; + case 1: + wordListN = &keywords2; + break; + case 2: + wordListN = &kw_pldoc; + break; + case 3: + wordListN = &kw_sqlplus; + break; + case 4: + wordListN = &kw_user1; + break; + case 5: + wordListN = &kw_user2; + break; + case 6: + wordListN = &kw_user3; + break; + case 7: + wordListN = &kw_user4; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + StyleContext sc(startPos, length, initStyle, styler); + int styleBeforeDCKeyword = SCE_SQL_DEFAULT; + int offset = 0; + for (; sc.More(); sc.Forward(), offset++) { + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_SQL_OPERATOR: + sc.SetState(SCE_SQL_DEFAULT); + break; + case SCE_SQL_NUMBER: + // We stop the number definition on non-numerical non-dot non-eE non-sign char + if (!IsANumberChar(sc.ch)) { + sc.SetState(SCE_SQL_DEFAULT); + } + break; + case SCE_SQL_IDENTIFIER: + if (!IsAWordChar(sc.ch, options.sqlAllowDottedWord)) { + int nextState = SCE_SQL_DEFAULT; + char s[1000]; + sc.GetCurrentLowered(s, sizeof(s)); + if (keywords1.InList(s)) { + sc.ChangeState(SCE_SQL_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_SQL_WORD2); + } else if (kw_sqlplus.InListAbbreviated(s, '~')) { + sc.ChangeState(SCE_SQL_SQLPLUS); + if (strncmp(s, "rem", 3) == 0) { + nextState = SCE_SQL_SQLPLUS_COMMENT; + } else if (strncmp(s, "pro", 3) == 0) { + nextState = SCE_SQL_SQLPLUS_PROMPT; + } + } else if (kw_user1.InList(s)) { + sc.ChangeState(SCE_SQL_USER1); + } else if (kw_user2.InList(s)) { + sc.ChangeState(SCE_SQL_USER2); + } else if (kw_user3.InList(s)) { + sc.ChangeState(SCE_SQL_USER3); + } else if (kw_user4.InList(s)) { + sc.ChangeState(SCE_SQL_USER4); + } + sc.SetState(nextState); + } + break; + case SCE_SQL_QUOTEDIDENTIFIER: + if (sc.ch == 0x60) { + if (sc.chNext == 0x60) { + sc.Forward(); // Ignore it + } else { + sc.ForwardSetState(SCE_SQL_DEFAULT); + } + } + break; + case SCE_SQL_COMMENT: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_SQL_DEFAULT); + } + break; + case SCE_SQL_COMMENTDOC: + if (sc.Match('*', '/')) { + sc.Forward(); + sc.ForwardSetState(SCE_SQL_DEFAULT); + } else if (sc.ch == '@' || sc.ch == '\\') { // Doxygen support + // Verify that we have the conditions to mark a comment-doc-keyword + if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { + styleBeforeDCKeyword = SCE_SQL_COMMENTDOC; + sc.SetState(SCE_SQL_COMMENTDOCKEYWORD); + } + } + break; + case SCE_SQL_COMMENTLINE: + case SCE_SQL_COMMENTLINEDOC: + case SCE_SQL_SQLPLUS_COMMENT: + case SCE_SQL_SQLPLUS_PROMPT: + if (sc.atLineStart) { + sc.SetState(SCE_SQL_DEFAULT); + } + break; + case SCE_SQL_COMMENTDOCKEYWORD: + if ((styleBeforeDCKeyword == SCE_SQL_COMMENTDOC) && sc.Match('*', '/')) { + sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR); + sc.Forward(); + sc.ForwardSetState(SCE_SQL_DEFAULT); + } else if (!IsADoxygenChar(sc.ch)) { + char s[100]; + sc.GetCurrentLowered(s, sizeof(s)); + if (!isspace(sc.ch) || !kw_pldoc.InList(s + 1)) { + sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR); + } + sc.SetState(styleBeforeDCKeyword); + } + break; + case SCE_SQL_CHARACTER: + if (options.sqlBackslashEscapes && sc.ch == '\\') { + sc.Forward(); + } else if (sc.ch == '\'') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_SQL_DEFAULT); + } + } + break; + case SCE_SQL_STRING: + if (sc.ch == '\\') { + // Escape sequence + sc.Forward(); + } else if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.Forward(); + } else { + sc.ForwardSetState(SCE_SQL_DEFAULT); + } + } + break; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_SQL_DEFAULT) { + if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_SQL_NUMBER); + } else if (IsAWordStart(sc.ch)) { + sc.SetState(SCE_SQL_IDENTIFIER); + } else if (sc.ch == 0x60 && options.sqlBackticksIdentifier) { + sc.SetState(SCE_SQL_QUOTEDIDENTIFIER); + } else if (sc.Match('/', '*')) { + if (sc.Match("/**") || sc.Match("/*!")) { // Support of Doxygen doc. style + sc.SetState(SCE_SQL_COMMENTDOC); + } else { + sc.SetState(SCE_SQL_COMMENT); + } + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.Match('-', '-')) { + // MySQL requires a space or control char after -- + // http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html + // Perhaps we should enforce that with proper property: + //~ } else if (sc.Match("-- ")) { + sc.SetState(SCE_SQL_COMMENTLINE); + } else if (sc.ch == '#' && options.sqlNumbersignComment) { + sc.SetState(SCE_SQL_COMMENTLINEDOC); + } else if (sc.ch == '\'') { + sc.SetState(SCE_SQL_CHARACTER); + } else if (sc.ch == '\"') { + sc.SetState(SCE_SQL_STRING); + } else if (isoperator(static_cast<char>(sc.ch))) { + sc.SetState(SCE_SQL_OPERATOR); + } + } + } + sc.Complete(); +} + +void SCI_METHOD LexerSQL::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + if (!options.fold) + return; + LexAccessor styler(pAccess); + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + + if (lineCurrent > 0) { + // Backtrack to previous line in case need to fix its fold status for folding block of single-line comments (i.e. '--'). + lineCurrent -= 1; + startPos = styler.LineStart(lineCurrent); + + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; + } + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + bool endFound = false; + bool isUnfoldingIgnored = false; + // this statementFound flag avoids to fold when the statement is on only one line by ignoring ELSE or ELSIF + // eg. "IF condition1 THEN ... ELSIF condition2 THEN ... ELSE ... END IF;" + bool statementFound = false; + unsigned short int sqlStatesCurrentLine = 0; + if (!options.foldOnlyBegin) { + sqlStatesCurrentLine = sqlStates.ForLine(lineCurrent); + } + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int stylePrev = style; + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (atEOL || (!IsCommentStyle(style) && ch == ';')) { + if (endFound) { + //Maybe this is the end of "EXCEPTION" BLOCK (eg. "BEGIN ... EXCEPTION ... END;") + sqlStatesCurrentLine = sqlStates.IntoExceptionBlock(sqlStatesCurrentLine, false); + } + // set endFound and isUnfoldingIgnored to false if EOL is reached or ';' is found + endFound = false; + isUnfoldingIgnored = false; + } + if ((!IsCommentStyle(style) && ch == ';')) { + if (sqlStates.IsIntoMergeStatement(sqlStatesCurrentLine)) { + // This is the end of "MERGE" statement. + if (!sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) + levelNext--; + sqlStatesCurrentLine = sqlStates.IntoMergeStatement(sqlStatesCurrentLine, false); + levelNext--; + } + if (sqlStates.IsIntoSelectStatement(sqlStatesCurrentLine)) + sqlStatesCurrentLine = sqlStates.IntoSelectStatement(sqlStatesCurrentLine, false); + } + if (options.foldComment && IsStreamCommentStyle(style)) { + if (!IsStreamCommentStyle(stylePrev)) { + levelNext++; + } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { + // Comments don't end at end of line and the next character may be unstyled. + levelNext--; + } + } + if (options.foldComment && (style == SCE_SQL_COMMENTLINE)) { + // MySQL needs -- comments to be followed by space or control char + if ((ch == '-') && (chNext == '-')) { + char chNext2 = styler.SafeGetCharAt(i + 2); + char chNext3 = styler.SafeGetCharAt(i + 3); + if (chNext2 == '{' || chNext3 == '{') { + levelNext++; + } else if (chNext2 == '}' || chNext3 == '}') { + levelNext--; + } + } + } + // Fold block of single-line comments (i.e. '--'). + if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { + if (!IsCommentLine(lineCurrent - 1, styler) && IsCommentLine(lineCurrent + 1, styler)) + levelNext++; + else if (IsCommentLine(lineCurrent - 1, styler) && !IsCommentLine(lineCurrent + 1, styler)) + levelNext--; + } + if (style == SCE_SQL_OPERATOR) { + if (ch == '(') { + if (levelCurrent > levelNext) + levelCurrent--; + levelNext++; + } else if (ch == ')') { + levelNext--; + } else if ((!options.foldOnlyBegin) && ch == ';') { + sqlStatesCurrentLine = sqlStates.IgnoreWhen(sqlStatesCurrentLine, false); + } + } + // If new keyword (cannot trigger on elseif or nullif, does less tests) + if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) { + const int MAX_KW_LEN = 9; // Maximum length of folding keywords + char s[MAX_KW_LEN + 2]; + unsigned int j = 0; + for (; j < MAX_KW_LEN + 1; j++) { + if (!iswordchar(styler[i + j])) { + break; + } + s[j] = static_cast<char>(tolower(styler[i + j])); + } + if (j == MAX_KW_LEN + 1) { + // Keyword too long, don't test it + s[0] = '\0'; + } else { + s[j] = '\0'; + } + + if (!options.foldOnlyBegin && + strcmp(s, "select") == 0) { + sqlStatesCurrentLine = sqlStates.IntoSelectStatement(sqlStatesCurrentLine, true); + } else if (strcmp(s, "if") == 0) { + if (endFound) { + endFound = false; + if (options.foldOnlyBegin && !isUnfoldingIgnored) { + // this end isn't for begin block, but for if block ("end if;") + // so ignore previous "end" by increment levelNext. + levelNext++; + } + } else { + if (!options.foldOnlyBegin) + sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true); + if (levelCurrent > levelNext) { + // doesn't include this line into the folding block + // because doesn't hide IF (eg "END; IF") + levelCurrent = levelNext; + } + } + } else if (!options.foldOnlyBegin && + strcmp(s, "then") == 0 && + sqlStates.IsIntoCondition(sqlStatesCurrentLine)) { + sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, false); + if (!options.foldOnlyBegin) { + if (levelCurrent > levelNext) { + levelCurrent = levelNext; + } + if (!statementFound) + levelNext++; + + statementFound = true; + } else if (levelCurrent > levelNext) { + // doesn't include this line into the folding block + // because doesn't hide LOOP or CASE (eg "END; LOOP" or "END; CASE") + levelCurrent = levelNext; + } + } else if (strcmp(s, "loop") == 0 || + strcmp(s, "case") == 0) { + if (endFound) { + endFound = false; + if (options.foldOnlyBegin && !isUnfoldingIgnored) { + // this end isn't for begin block, but for loop block ("end loop;") or case block ("end case;") + // so ignore previous "end" by increment levelNext. + levelNext++; + } + if ((!options.foldOnlyBegin) && strcmp(s, "case") == 0) { + sqlStatesCurrentLine = sqlStates.EndCaseBlock(sqlStatesCurrentLine); + if (!sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) + levelNext--; //again for the "end case;" and block when + } + } else if (!options.foldOnlyBegin) { + if (strcmp(s, "case") == 0) + sqlStatesCurrentLine = sqlStates.BeginCaseBlock(sqlStatesCurrentLine); + + if (levelCurrent > levelNext) + levelCurrent = levelNext; + + if (!statementFound) + levelNext++; + + sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, true); + statementFound = true; + } else if (levelCurrent > levelNext) { + // doesn't include this line into the folding block + // because doesn't hide LOOP or CASE (eg "END; LOOP" or "END; CASE") + levelCurrent = levelNext; + } + } else if ((!options.foldOnlyBegin) && ( + // folding for ELSE and ELSIF block only if foldAtElse is set + // and IF or CASE aren't on only one line with ELSE or ELSIF (with flag statementFound) + options.foldAtElse && !statementFound) && strcmp(s, "elsif") == 0) { + sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true); + levelCurrent--; + levelNext--; + } else if ((!options.foldOnlyBegin) && ( + // folding for ELSE and ELSIF block only if foldAtElse is set + // and IF or CASE aren't on only one line with ELSE or ELSIF (with flag statementFound) + options.foldAtElse && !statementFound) && strcmp(s, "else") == 0) { + // prevent also ELSE is on the same line (eg. "ELSE ... END IF;") + statementFound = true; + if (sqlStates.IsIntoCaseBlock(sqlStatesCurrentLine) && sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) { + sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, false); + levelNext++; + } else { + // we are in same case "} ELSE {" in C language + levelCurrent--; + } + } else if (strcmp(s, "begin") == 0) { + levelNext++; + sqlStatesCurrentLine = sqlStates.IntoDeclareBlock(sqlStatesCurrentLine, false); + } else if ((strcmp(s, "end") == 0) || + // SQL Anywhere permits IF ... ELSE ... ENDIF + // will only be active if "endif" appears in the + // keyword list. + (strcmp(s, "endif") == 0)) { + endFound = true; + levelNext--; + if (sqlStates.IsIntoSelectStatement(sqlStatesCurrentLine) && !sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) + levelNext--; + if (levelNext < SC_FOLDLEVELBASE) { + levelNext = SC_FOLDLEVELBASE; + isUnfoldingIgnored = true; + } + } else if ((!options.foldOnlyBegin) && + strcmp(s, "when") == 0 && + !sqlStates.IsIgnoreWhen(sqlStatesCurrentLine) && + !sqlStates.IsIntoExceptionBlock(sqlStatesCurrentLine) && ( + sqlStates.IsIntoCaseBlock(sqlStatesCurrentLine) || + sqlStates.IsIntoMergeStatement(sqlStatesCurrentLine) + ) + ) { + sqlStatesCurrentLine = sqlStates.IntoCondition(sqlStatesCurrentLine, true); + + // Don't foldind when CASE and WHEN are on the same line (with flag statementFound) (eg. "CASE selector WHEN expression1 THEN sequence_of_statements1;\n") + // and same way for MERGE statement. + if (!statementFound) { + if (!sqlStates.IsCaseMergeWithoutWhenFound(sqlStatesCurrentLine)) { + levelCurrent--; + levelNext--; + } + sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, false); + } + } else if ((!options.foldOnlyBegin) && strcmp(s, "exit") == 0) { + sqlStatesCurrentLine = sqlStates.IgnoreWhen(sqlStatesCurrentLine, true); + } else if ((!options.foldOnlyBegin) && !sqlStates.IsIntoDeclareBlock(sqlStatesCurrentLine) && strcmp(s, "exception") == 0) { + sqlStatesCurrentLine = sqlStates.IntoExceptionBlock(sqlStatesCurrentLine, true); + } else if ((!options.foldOnlyBegin) && + (strcmp(s, "declare") == 0 || + strcmp(s, "function") == 0 || + strcmp(s, "procedure") == 0 || + strcmp(s, "package") == 0)) { + sqlStatesCurrentLine = sqlStates.IntoDeclareBlock(sqlStatesCurrentLine, true); + } else if ((!options.foldOnlyBegin) && + strcmp(s, "merge") == 0) { + sqlStatesCurrentLine = sqlStates.IntoMergeStatement(sqlStatesCurrentLine, true); + sqlStatesCurrentLine = sqlStates.CaseMergeWithoutWhenFound(sqlStatesCurrentLine, true); + levelNext++; + statementFound = true; + } + } + if (atEOL) { + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (visibleChars == 0 && options.foldCompact) + lev |= SC_FOLDLEVELWHITEFLAG; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(lineCurrent)) { + styler.SetLevel(lineCurrent, lev); + } + lineCurrent++; + levelCurrent = levelNext; + visibleChars = 0; + statementFound = false; + if (!options.foldOnlyBegin) + sqlStates.Set(lineCurrent, sqlStatesCurrentLine); + } + if (!isspacechar(ch)) { + visibleChars++; + } + } +} + +LexerModule lmSQL(SCLEX_SQL, LexerSQL::LexerFactorySQL, "sql", sqlWordListDesc); diff --git a/src/stc/scintilla/src/LexScriptol.cxx b/src/stc/scintilla/lexers/LexScriptol.cxx similarity index 98% rename from src/stc/scintilla/src/LexScriptol.cxx rename to src/stc/scintilla/lexers/LexScriptol.cxx index 76c38e6b68..4b91923147 100644 --- a/src/stc/scintilla/src/LexScriptol.cxx +++ b/src/stc/scintilla/lexers/LexScriptol.cxx @@ -5,18 +5,22 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif @@ -48,10 +52,9 @@ static void ClassifyWordSol(unsigned int start, unsigned int end, WordList &keyw static bool IsSolComment(Accessor &styler, int pos, int len) { - char c; if(len > 0) { - c = styler[pos]; + char c = styler[pos]; if(c == '`') return true; if(len > 1) { @@ -328,7 +331,7 @@ static void ColouriseSolDoc(unsigned int startPos, int length, int initStyle, state = SCE_SCRIPTOL_DEFAULT; } } - + } chPrev2 = chPrev; chPrev = ch; @@ -365,7 +368,7 @@ static void FoldSolDoc(unsigned int startPos, int length, int initStyle, int state = initStyle & 31; int spaceFlags = 0; int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsSolComment); - if ((state == SCE_SCRIPTOL_TRIPLE)) + if (state == SCE_SCRIPTOL_TRIPLE) indentCurrent |= SC_FOLDLEVELWHITEFLAG; char chNext = styler[startPos]; for (int i = startPos; i < lengthDoc; i++) diff --git a/src/stc/scintilla/src/LexSmalltalk.cxx b/src/stc/scintilla/lexers/LexSmalltalk.cxx similarity index 97% rename from src/stc/scintilla/src/LexSmalltalk.cxx rename to src/stc/scintilla/lexers/LexSmalltalk.cxx index 265de38038..7c7c06769d 100644 --- a/src/stc/scintilla/src/LexSmalltalk.cxx +++ b/src/stc/scintilla/lexers/LexSmalltalk.cxx @@ -8,16 +8,21 @@ #include <stdlib.h> #include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> #include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -39,7 +44,7 @@ classificationBlock value: #BinSel value: '~@%&*-+=|\/,<>?!'; value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. -((String new: 500) streamContents: [ :stream | +((String new: 500) streamContents: [ :stream | stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'. lexTable keysAndValuesDo: [ :index :value | ((index - 1) rem: 16) == 0 ifTrue: [ @@ -50,7 +55,7 @@ classificationBlock index ~= 256 ifTrue: [ stream nextPut: $,]]. stream crLf; nextPutAll: '};'; crLf. - + charClasses keysAndValuesDo: [ :index :name | stream crLf; @@ -95,7 +100,7 @@ static inline bool isDigitOfRadix(int ch, int radix) } static inline void skipComment(StyleContext& sc) -{ +{ while (sc.More() && sc.ch != '\"') sc.Forward(); } @@ -118,7 +123,7 @@ static void handleHash(StyleContext& sc) sc.SetState(SCE_ST_SPECIAL); return; } - + sc.SetState(SCE_ST_SYMBOL); sc.Forward(); if (sc.ch == '\'') { @@ -162,7 +167,7 @@ static void handleNumeric(StyleContext& sc) char num[256]; int nl; int radix; - + sc.SetState(SCE_ST_NUMBER); num[0] = static_cast<char>(sc.ch); nl = 1; @@ -217,7 +222,7 @@ static void handleLetter(StyleContext& sc, WordList* specialSelectorList) int il; int state; bool doubleColonPresent; - + sc.SetState(SCE_ST_DEFAULT); ident[0] = static_cast<char>(sc.ch); @@ -237,7 +242,7 @@ static void handleLetter(StyleContext& sc, WordList* specialSelectorList) else doubleColonPresent = false; ident[il] = 0; - + if (specialSelectorList->InList(ident)) state = SCE_ST_SPEC_SEL; else if (doubleColonPresent) @@ -256,7 +261,7 @@ static void handleLetter(StyleContext& sc, WordList* specialSelectorList) else state = SCE_ST_DEFAULT; } - + sc.ChangeState(state); } @@ -277,7 +282,7 @@ static void colorizeSmalltalkDoc(unsigned int startPos, int length, int initStyl for (; sc.More(); sc.Forward()) { int ch; - + ch = sc.ch; if (ch == '\"') { sc.SetState(SCE_ST_COMMENT); diff --git a/src/stc/scintilla/src/LexSorcus.cxx b/src/stc/scintilla/lexers/LexSorcus.cxx similarity index 83% rename from src/stc/scintilla/src/LexSorcus.cxx rename to src/stc/scintilla/lexers/LexSorcus.cxx index 1d8ba277a2..ba5588b311 100644 --- a/src/stc/scintilla/src/LexSorcus.cxx +++ b/src/stc/scintilla/lexers/LexSorcus.cxx @@ -9,18 +9,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -29,7 +32,7 @@ using namespace Scintilla; //each character a..z and A..Z + '_' can be part of a keyword //additionally numbers that follow 'M' can be contained in a keyword -static inline bool IsSWordStart(const int ch, const int prev_ch) +static inline bool IsSWordStart(const int ch, const int prev_ch) { if (isalpha(ch) || (ch == '_') || ((isdigit(ch)) && (prev_ch == 'M'))) return true; @@ -39,7 +42,7 @@ static inline bool IsSWordStart(const int ch, const int prev_ch) //only digits that are not preceded by 'M' count as a number -static inline bool IsSorcusNumber(const int ch, const int prev_ch) +static inline bool IsSorcusNumber(const int ch, const int prev_ch) { if ((isdigit(ch)) && (prev_ch != 'M')) return true; @@ -49,46 +52,46 @@ static inline bool IsSorcusNumber(const int ch, const int prev_ch) //only = is a valid operator -static inline bool IsSorcusOperator(const int ch) +static inline bool IsSorcusOperator(const int ch) { if (ch == '=') return true; - + return false; } static void ColouriseSorcusDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) + Accessor &styler) { - + WordList &Command = *keywordlists[0]; WordList &Parameter = *keywordlists[1]; WordList &Constant = *keywordlists[2]; - + // Do not leak onto next line - if (initStyle == SCE_SORCUS_STRINGEOL) + if (initStyle == SCE_SORCUS_STRINGEOL) initStyle = SCE_SORCUS_DEFAULT; - + StyleContext sc(startPos, length, initStyle, styler); - + for (; sc.More(); sc.Forward()) { - + // Prevent SCE_SORCUS_STRINGEOL from leaking back to previous line if (sc.atLineStart && (sc.state == SCE_SORCUS_STRING)) { - sc.SetState(SCE_SORCUS_STRING); - } - + sc.SetState(SCE_SORCUS_STRING); + } + // Determine if the current state should terminate. if (sc.state == SCE_SORCUS_OPERATOR) { - if (!IsSorcusOperator(sc.ch)) + if (!IsSorcusOperator(sc.ch)) { sc.SetState(SCE_SORCUS_DEFAULT); } - } + } else if(sc.state == SCE_SORCUS_NUMBER) { if(!IsSorcusNumber(sc.ch, sc.chPrev)) @@ -101,25 +104,25 @@ static void ColouriseSorcusDoc(unsigned int startPos, int length, int initStyle, if (!IsSWordStart(sc.ch, sc.chPrev)) { char s[100]; - + sc.GetCurrent(s, sizeof(s)); - + if (Command.InList(s)) - { - sc.ChangeState(SCE_SORCUS_COMMAND); + { + sc.ChangeState(SCE_SORCUS_COMMAND); } else if (Parameter.InList(s)) - { + { sc.ChangeState(SCE_SORCUS_PARAMETER); } else if (Constant.InList(s)) - { + { sc.ChangeState(SCE_SORCUS_CONSTANT); } - + sc.SetState(SCE_SORCUS_DEFAULT); } - } + } else if (sc.state == SCE_SORCUS_COMMENTLINE ) { if (sc.atLineEnd) @@ -133,24 +136,24 @@ static void ColouriseSorcusDoc(unsigned int startPos, int length, int initStyle, { sc.ForwardSetState(SCE_SORCUS_DEFAULT); } - else if (sc.atLineEnd) + else if (sc.atLineEnd) { sc.ChangeState(SCE_SORCUS_STRINGEOL); sc.ForwardSetState(SCE_SORCUS_DEFAULT); } } - + // Determine if a new state should be entered. if (sc.state == SCE_SORCUS_DEFAULT) { if ((sc.ch == ';') || (sc.ch == '\'')) { sc.SetState(SCE_SORCUS_COMMENTLINE); - } + } else if (IsSWordStart(sc.ch, sc.chPrev)) { sc.SetState(SCE_SORCUS_IDENTIFIER); - } + } else if (sc.ch == '\"') { sc.SetState(SCE_SORCUS_STRING); @@ -164,42 +167,42 @@ static void ColouriseSorcusDoc(unsigned int startPos, int length, int initStyle, sc.SetState(SCE_SORCUS_NUMBER); } } - + } sc.Complete(); } static const char* const SorcusWordListDesc[] = {"Command","Parameter", "Constant", 0}; - + LexerModule lmSorc(SCLEX_SORCUS, ColouriseSorcusDoc, "sorcins", 0, SorcusWordListDesc); - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/stc/scintilla/src/LexSpecman.cxx b/src/stc/scintilla/lexers/LexSpecman.cxx similarity index 98% rename from src/stc/scintilla/src/LexSpecman.cxx rename to src/stc/scintilla/lexers/LexSpecman.cxx index 093efae755..1b96482ea0 100644 --- a/src/stc/scintilla/src/LexSpecman.cxx +++ b/src/stc/scintilla/lexers/LexSpecman.cxx @@ -11,15 +11,18 @@ #include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexSpice.cxx b/src/stc/scintilla/lexers/LexSpice.cxx similarity index 97% rename from src/stc/scintilla/src/LexSpice.cxx rename to src/stc/scintilla/lexers/LexSpice.cxx index 6aa2e8fdca..5fb5dd7766 100644 --- a/src/stc/scintilla/src/LexSpice.cxx +++ b/src/stc/scintilla/lexers/LexSpice.cxx @@ -6,19 +6,24 @@ // The License.txt file describes the conditions under which this software may be distributed. #include <stdlib.h> -#include <ctype.h> #include <string.h> #include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> #include <string> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "PropSet.h" -#include "KeyWords.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexTACL.cxx b/src/stc/scintilla/lexers/LexTACL.cxx similarity index 98% rename from src/stc/scintilla/src/LexTACL.cxx rename to src/stc/scintilla/lexers/LexTACL.cxx index b0c12440dc..fb7d695fdf 100644 --- a/src/stc/scintilla/src/LexTACL.cxx +++ b/src/stc/scintilla/lexers/LexTACL.cxx @@ -10,18 +10,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" #include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexTADS3.cxx b/src/stc/scintilla/lexers/LexTADS3.cxx similarity index 99% rename from src/stc/scintilla/src/LexTADS3.cxx rename to src/stc/scintilla/lexers/LexTADS3.cxx index ee16a0ac07..54cb88ad68 100644 --- a/src/stc/scintilla/src/LexTADS3.cxx +++ b/src/stc/scintilla/lexers/LexTADS3.cxx @@ -33,18 +33,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -70,7 +73,7 @@ static inline bool IsEOL(const int ch, const int chNext) { * - it doesn't want to admit that there's a newline until reaching the END * of the sequence. We meet both needs by saying that there's a newline * when we see the CR in a CR-LF, but skipping the CR before returning so - * that the caller's caller will see that we've stopped at the LF. + * that the caller's caller will see that we've stopped at the LF. */ static inline bool IsEOLSkip(StyleContext &sc) { @@ -82,17 +85,13 @@ static inline bool IsEOLSkip(StyleContext &sc) return true; } - /* + /* * in other cases, we have at most a 1-character newline, so do the - * normal IsEOL test + * normal IsEOL test */ return IsEOL(sc.ch, sc.chNext); } -static inline bool IsASpaceOrTab(const int ch) { - return ch == ' ' || ch == '\t'; -} - static inline bool IsATADS3Operator(const int ch) { return ch == '=' || ch == '{' || ch == '}' || ch == '(' || ch == ')' || ch == '[' || ch == ']' || ch == ',' || ch == ':' || ch == ';' @@ -156,7 +155,7 @@ static void ColouriseTADSHTMLString(StyleContext &sc, int &lineState) { sc.Forward(); } if (chQuote == '"') - lineState &= ~T3_HTML_SQUOTE; + lineState &= ~T3_HTML_SQUOTE; else lineState |= T3_HTML_SQUOTE; @@ -698,7 +697,7 @@ static inline bool IsAnIdentifier(const int style) { } static inline bool IsAnOperator(const int style) { - return style == SCE_T3_OPERATOR || SCE_T3_BRACE; + return style == SCE_T3_OPERATOR || style == SCE_T3_BRACE; } static inline bool IsSpaceEquivalent(const int ch, const int style) { diff --git a/src/stc/scintilla/src/LexTAL.cxx b/src/stc/scintilla/lexers/LexTAL.cxx similarity index 98% rename from src/stc/scintilla/src/LexTAL.cxx rename to src/stc/scintilla/lexers/LexTAL.cxx index a76a296d68..15dc7410ce 100644 --- a/src/stc/scintilla/src/LexTAL.cxx +++ b/src/stc/scintilla/lexers/LexTAL.cxx @@ -10,18 +10,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" #include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -94,7 +97,7 @@ static int classifyWordTAL(unsigned int start, unsigned int end, /*WordList &key else if (strcmp(s, "end") == 0) { ret = -1; } - } + } else if (s[0] == '$' || builtins.InList(s)) { chAttr = SCE_C_WORD2; } diff --git a/src/stc/scintilla/src/LexTCL.cxx b/src/stc/scintilla/lexers/LexTCL.cxx similarity index 97% rename from src/stc/scintilla/src/LexTCL.cxx rename to src/stc/scintilla/lexers/LexTCL.cxx index 3c175de2a0..f6924e05e0 100644 --- a/src/stc/scintilla/src/LexTCL.cxx +++ b/src/stc/scintilla/lexers/LexTCL.cxx @@ -7,18 +7,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> -#include <stdarg.h> #include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -47,7 +50,7 @@ static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *k bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool commentLevel = false; bool subBrace = false; // substitution begin with a brace ${.....} - enum tLineState {LS_DEFAULT, LS_OPEN_COMMENT, LS_OPEN_DOUBLE_QUOTE, LS_COMMENT_BOX, LS_MASK_STATE = 0xf, + enum tLineState {LS_DEFAULT, LS_OPEN_COMMENT, LS_OPEN_DOUBLE_QUOTE, LS_COMMENT_BOX, LS_MASK_STATE = 0xf, LS_COMMAND_EXPECTED = 16, LS_BRACE_ONLY = 32 } lineState = LS_DEFAULT; bool prevSlash = false; int currentLevel = 0; @@ -86,7 +89,7 @@ static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *k StyleContext sc(startPos, length, SCE_TCL_DEFAULT, styler); for (; ; sc.Forward()) { next: - if (sc.ch=='\r' && sc.chNext == '\n') // only ignore \r on PC process on the mac + if (sc.ch=='\r' && sc.chNext == '\n') // only ignore \r on PC process on the mac continue; bool atEnd = !sc.More(); // make sure we coloured the last word if (lineState != LS_DEFAULT) { @@ -170,7 +173,7 @@ next: sc.ChangeState(SCE_TCL_WORD7); } else if (keywords9.InList(s)) { sc.ChangeState(SCE_TCL_WORD8); - } + } } expected = false; sc.SetState(quote ? SCE_TCL_IN_QUOTE : SCE_TCL_DEFAULT); @@ -212,7 +215,7 @@ next: } else if (sc.state == SCE_TCL_COMMENT_BOX) lineState = LS_COMMENT_BOX; } - styler.SetLineState(currentLine, + styler.SetLineState(currentLine, (subBrace ? LS_BRACE_ONLY : 0) | (expected ? LS_COMMAND_EXPECTED : 0) | lineState); if (lineState == LS_COMMENT_BOX) @@ -285,7 +288,7 @@ next: if (sc.ch == '\\') { prevSlash = true; - continue; + continue; } // Determine if a new state should be entered. @@ -306,6 +309,7 @@ next: break; case '}': sc.SetState(SCE_TCL_OPERATOR); + expected = true; --currentLevel; break; case '[': @@ -322,7 +326,7 @@ next: subParen = 0; if (sc.chNext != '{') { sc.SetState(SCE_TCL_SUBSTITUTION); - } + } else { sc.SetState(SCE_TCL_OPERATOR); // $ sc.Forward(); // { diff --git a/src/stc/scintilla/lexers/LexTCMD.cxx b/src/stc/scintilla/lexers/LexTCMD.cxx new file mode 100644 index 0000000000..ed747da876 --- /dev/null +++ b/src/stc/scintilla/lexers/LexTCMD.cxx @@ -0,0 +1,511 @@ +// Scintilla\ source code edit control +/** @file LexTCMD.cxx + ** Lexer for Take Command / TCC batch scripts (.bat, .btm, .cmd). + **/ +// Written by Rex Conn (rconn [at] jpsoft [dot] com) +// based on the CMD lexer +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + +static bool IsAlphabetic(int ch) { + return isascii(ch) && isalpha(ch); +} + +static inline bool AtEOL(Accessor &styler, unsigned int i) { + return (styler[i] == '\n') || ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n')); +} + +// Tests for BATCH Operators +static bool IsBOperator(char ch) { + return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') || (ch == '|') || (ch == '&') || (ch == '!') || (ch == '?') || (ch == '*') || (ch == '(') || (ch == ')'); +} + +// Tests for BATCH Separators +static bool IsBSeparator(char ch) { + return (ch == '\\') || (ch == '.') || (ch == ';') || (ch == ' ') || (ch == '\t') || (ch == '[') || (ch == ']') || (ch == '\"') || (ch == '\'') || (ch == '/'); +} + +// Tests for Environment Variable symbol +static inline bool IsEnvironmentVar(char ch) { + return isalpha(ch) || isdigit(ch) || (ch == '_') || (ch == '$'); +} + +// Find length of CMD FOR variable with modifier (%~...) or return 0 +static unsigned int GetBatchVarLen( char *wordBuffer ) +{ + int nLength = 0; + if ( wordBuffer[0] == '%' ) { + + if ( wordBuffer[1] == '~' ) + nLength = 2; + else if (( wordBuffer[1] == '%' ) && ( wordBuffer[2] == '~' )) + nLength++; + else + return 0; + + for ( ; ( wordBuffer[nLength] ); nLength++ ) { + + switch ( toupper(wordBuffer[nLength]) ) { + case 'A': + // file attributes + case 'D': + // drive letter only + case 'F': + // fully qualified path name + case 'N': + // filename only + case 'P': + // path only + case 'S': + // short name + case 'T': + // date / time of file + case 'X': + // file extension only + case 'Z': + // file size + break; + default: + return nLength; + } + } + } + + return nLength; +} + + +static void ColouriseTCMDLine( char *lineBuffer, unsigned int lengthLine, unsigned int startLine, unsigned int endPos, WordList *keywordlists[], Accessor &styler) +{ + unsigned int offset = 0; // Line Buffer Offset + char wordBuffer[260]; // Word Buffer - large to catch long paths + unsigned int wbl; // Word Buffer Length + unsigned int wbo; // Word Buffer Offset - also Special Keyword Buffer Length + WordList &keywords = *keywordlists[0]; // Internal Commands +// WordList &keywords2 = *keywordlists[1]; // Aliases (optional) + bool isDelayedExpansion = 1; // !var! + + bool continueProcessing = true; // Used to toggle Regular Keyword Checking + // Special Keywords are those that allow certain characters without whitespace after the command + // Examples are: cd. cd\ echo: echo. path= + bool inString = false; // Used for processing while "" + // Special Keyword Buffer used to determine if the first n characters is a Keyword + char sKeywordBuffer[260]; // Special Keyword Buffer + bool sKeywordFound; // Exit Special Keyword for-loop if found + + // Skip leading whitespace + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_TCMD_DEFAULT); + + if ( offset >= lengthLine ) + return; + + // Check for Fake Label (Comment) or Real Label - return if found + if (lineBuffer[offset] == ':') { + if (lineBuffer[offset + 1] == ':') { + // Colorize Fake Label (Comment) - :: is the same as REM + styler.ColourTo(endPos, SCE_TCMD_COMMENT); + } else { + // Colorize Real Label + styler.ColourTo(endPos, SCE_TCMD_LABEL); + } + return; + + // Check for Comment - return if found + } else if (( CompareNCaseInsensitive(lineBuffer+offset, "rem", 3) == 0 ) && (( lineBuffer[offset+3] == 0 ) || ( isspace(lineBuffer[offset+3] )))) { + styler.ColourTo(endPos, SCE_TCMD_COMMENT); + return; + + // Check for Drive Change (Drive Change is internal command) - return if found + } else if ((IsAlphabetic(lineBuffer[offset])) && + (lineBuffer[offset + 1] == ':') && + ((isspacechar(lineBuffer[offset + 2])) || + (((lineBuffer[offset + 2] == '\\')) && + (isspacechar(lineBuffer[offset + 3]))))) { + // Colorize Regular Keyword + styler.ColourTo(endPos, SCE_TCMD_WORD); + return; + } + + // Check for Hide Command (@ECHO OFF/ON) + if (lineBuffer[offset] == '@') { + styler.ColourTo(startLine + offset, SCE_TCMD_HIDE); + offset++; + } + // Skip whitespace + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + + // Read remainder of line word-at-a-time or remainder-of-word-at-a-time + while (offset < lengthLine) { + if (offset > startLine) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_TCMD_DEFAULT); + } + // Copy word from Line Buffer into Word Buffer + wbl = 0; + for (; offset < lengthLine && ( wbl < 260 ) && !isspacechar(lineBuffer[offset]); wbl++, offset++) { + wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset])); + } + wordBuffer[wbl] = '\0'; + wbo = 0; + + // Check for Separator + if (IsBSeparator(wordBuffer[0])) { + + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + // Colorize Default Text + styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT); + + if (wordBuffer[0] == '"') + inString = !inString; + + // Check for Regular expression + } else if (( wordBuffer[0] == ':' ) && ( wordBuffer[1] == ':' ) && (continueProcessing)) { + + // Colorize Regular exoressuin + styler.ColourTo(startLine + offset - 1, SCE_TCMD_DEFAULT); + // No need to Reset Offset + + // Check for Labels in text (... :label) + } else if (wordBuffer[0] == ':' && isspacechar(lineBuffer[offset - wbl - 1])) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_TCMD_DEFAULT); + // Colorize Label + styler.ColourTo(startLine + offset - 1, SCE_TCMD_CLABEL); + // No need to Reset Offset + // Check for delayed expansion Variable (!x...!) + } else if (isDelayedExpansion && wordBuffer[0] == '!') { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_TCMD_DEFAULT); + wbo++; + // Search to end of word for second ! + while ((wbo < wbl) && (wordBuffer[wbo] != '!') && (!IsBOperator(wordBuffer[wbo])) && (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + if (wordBuffer[wbo] == '!') { + wbo++; + // Colorize Environment Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_TCMD_EXPANSION); + } else { + wbo = 1; + // Colorize Symbol + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_TCMD_DEFAULT); + } + + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + + // Check for Regular Keyword in list + } else if ((keywords.InList(wordBuffer)) && (!inString) && (continueProcessing)) { + + // ECHO, PATH, and PROMPT require no further Regular Keyword Checking + if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) || + (CompareCaseInsensitive(sKeywordBuffer, "echos") == 0) || + (CompareCaseInsensitive(sKeywordBuffer, "echoerr") == 0) || + (CompareCaseInsensitive(sKeywordBuffer, "echoserr") == 0) || + (CompareCaseInsensitive(wordBuffer, "path") == 0) || + (CompareCaseInsensitive(wordBuffer, "prompt") == 0)) { + continueProcessing = false; + } + + // Colorize Regular keyword + styler.ColourTo(startLine + offset - 1, SCE_TCMD_WORD); + // No need to Reset Offset + + } else if ((wordBuffer[0] != '%') && (wordBuffer[0] != '!') && (!IsBOperator(wordBuffer[0])) && (!inString) && (continueProcessing)) { + + // a few commands accept "illegal" syntax -- cd\, echo., etc. + sscanf( wordBuffer, "%[^.<>|&=\\/]", sKeywordBuffer ); + sKeywordFound = false; + + if ((CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) || + (CompareCaseInsensitive(sKeywordBuffer, "echos") == 0) || + (CompareCaseInsensitive(sKeywordBuffer, "echoerr") == 0) || + (CompareCaseInsensitive(sKeywordBuffer, "echoserr") == 0) || + (CompareCaseInsensitive(sKeywordBuffer, "cd") == 0) || + (CompareCaseInsensitive(sKeywordBuffer, "path") == 0) || + (CompareCaseInsensitive(sKeywordBuffer, "prompt") == 0)) { + + // no further Regular Keyword Checking + continueProcessing = false; + sKeywordFound = true; + wbo = (unsigned int)strlen( sKeywordBuffer ); + + // Colorize Special Keyword as Regular Keyword + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_TCMD_WORD); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + + // Check for Default Text + if (!sKeywordFound) { + wbo = 0; + // Read up to %, Operator or Separator + while ((wbo < wbl) && (wordBuffer[wbo] != '%') && (!isDelayedExpansion || wordBuffer[wbo] != '!') && (!IsBOperator(wordBuffer[wbo])) && (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_TCMD_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + + // Check for Argument (%n), Environment Variable (%x...%) or Local Variable (%%a) + } else if (wordBuffer[0] == '%') { + unsigned int varlen; + unsigned int n = 1; + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_TCMD_DEFAULT); + wbo++; + + // check for %[nn] syntax + if ( wordBuffer[1] == '[' ) { + n++; + while ((n < wbl) && (wordBuffer[n] != ']')) { + n++; + } + if ( wordBuffer[n] == ']' ) + n++; + goto ColorizeArg; + } + + // Search to end of word for second % or to the first terminator (can be a long path) + while ((wbo < wbl) && (wordBuffer[wbo] != '%') && (!IsBOperator(wordBuffer[wbo])) && (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + + // Check for Argument (%n) or (%*) + if (((isdigit(wordBuffer[1])) || (wordBuffer[1] == '*')) && (wordBuffer[wbo] != '%')) { + while (( wordBuffer[n] ) && ( strchr( "%0123456789*#$", wordBuffer[n] ) != NULL )) + n++; +ColorizeArg: + // Colorize Argument + styler.ColourTo(startLine + offset - 1 - (wbl - n), SCE_TCMD_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - n); + + // Check for Variable with modifiers (%~...) + } else if ((varlen = GetBatchVarLen(wordBuffer)) != 0) { + + // Colorize Variable + styler.ColourTo(startLine + offset - 1 - (wbl - varlen), SCE_TCMD_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - varlen); + + // Check for Environment Variable (%x...%) + } else if (( wordBuffer[1] ) && ( wordBuffer[1] != '%')) { + if ( wordBuffer[wbo] == '%' ) + wbo++; + + // Colorize Environment Variable + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_TCMD_ENVIRONMENT); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + + // Check for Local Variable (%%a) + } else if ( (wbl > 2) && (wordBuffer[1] == '%') && (wordBuffer[2] != '%') && (!IsBOperator(wordBuffer[2])) && (!IsBSeparator(wordBuffer[2]))) { + + n = 2; + while (( wordBuffer[n] ) && (!IsBOperator(wordBuffer[n])) && (!IsBSeparator(wordBuffer[n]))) + n++; + + // Colorize Local Variable + styler.ColourTo(startLine + offset - 1 - (wbl - n), SCE_TCMD_IDENTIFIER); + // Reset Offset to re-process remainder of word + offset -= (wbl - n); + + // Check for %% + } else if ((wbl > 1) && (wordBuffer[1] == '%')) { + + // Colorize Symbols + styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_TCMD_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - 2); + } else { + + // Colorize Symbol + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_TCMD_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + } + + // Check for Operator + } else if (IsBOperator(wordBuffer[0])) { + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - wbl, SCE_TCMD_DEFAULT); + + // Check for Pipe, compound, or conditional Operator + if ((wordBuffer[0] == '|') || (wordBuffer[0] == '&')) { + + // Colorize Pipe Operator + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_TCMD_OPERATOR); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + continueProcessing = true; + + // Check for Other Operator + } else { + // Check for > Operator + if ((wordBuffer[0] == '>') || (wordBuffer[0] == '<')) { + // Turn Keyword and External Command / Program checking back on + continueProcessing = true; + } + // Colorize Other Operator + if (!inString || !(wordBuffer[0] == '(' || wordBuffer[0] == ')')) + styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_TCMD_OPERATOR); + // Reset Offset to re-process remainder of word + offset -= (wbl - 1); + } + + // Check for Default Text + } else { + // Read up to %, Operator or Separator + while ((wbo < wbl) && (wordBuffer[wbo] != '%') && (!isDelayedExpansion || wordBuffer[wbo] != '!') && (!IsBOperator(wordBuffer[wbo])) && (!IsBSeparator(wordBuffer[wbo]))) { + wbo++; + } + // Colorize Default Text + styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_TCMD_DEFAULT); + // Reset Offset to re-process remainder of word + offset -= (wbl - wbo); + } + + // Skip whitespace - nothing happens if Offset was Reset + while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) { + offset++; + } + } + // Colorize Default Text for remainder of line - currently not lexed + styler.ColourTo(endPos, SCE_TCMD_DEFAULT); +} + +static void ColouriseTCMDDoc( unsigned int startPos, int length, int /*initStyle*/, WordList *keywordlists[], Accessor &styler ) +{ + char lineBuffer[16384]; + + styler.StartAt(startPos); + styler.StartSegment(startPos); + unsigned int linePos = 0; + unsigned int startLine = startPos; + for (unsigned int i = startPos; i < startPos + length; i++) { + lineBuffer[linePos++] = styler[i]; + if (AtEOL(styler, i) || (linePos >= sizeof(lineBuffer) - 1)) { + // End of line (or of line buffer) met, colourise it + lineBuffer[linePos] = '\0'; + ColouriseTCMDLine(lineBuffer, linePos, startLine, i, keywordlists, styler); + linePos = 0; + startLine = i + 1; + } + } + if (linePos > 0) { // Last line does not have ending characters + lineBuffer[linePos] = '\0'; + ColouriseTCMDLine(lineBuffer, linePos, startLine, startPos + length - 1, keywordlists, styler); + } +} + +// Convert string to upper case +static void StrUpr(char *s) { + while (*s) { + *s = MakeUpperCase(*s); + s++; + } +} + +// Folding support (for DO, IFF, SWITCH, TEXT, and command groups) +static void FoldTCMDDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + int line = styler.GetLine(startPos); + int level = styler.LevelAt(line); + int levelIndent = 0; + unsigned int endPos = startPos + length; + char s[16]; + + char chPrev = styler.SafeGetCharAt(startPos - 1); + + // Scan for ( and ) + for (unsigned int i = startPos; i < endPos; i++) { + + int c = styler.SafeGetCharAt(i, '\n'); + int style = styler.StyleAt(i); + bool bLineStart = ((chPrev == '\r') || (chPrev == '\n')) || i == 0; + + if (style == SCE_TCMD_OPERATOR) { + // CheckFoldPoint + if (c == '(') { + levelIndent += 1; + } else if (c == ')') { + levelIndent -= 1; + } + } + + if (( bLineStart ) && ( style == SCE_TCMD_WORD )) { + for (unsigned int j = 0; j < 10; j++) { + if (!iswordchar(styler[i + j])) { + break; + } + s[j] = styler[i + j]; + s[j + 1] = '\0'; + } + + StrUpr( s ); + if ((strcmp(s, "DO") == 0) || (strcmp(s, "IFF") == 0) || (strcmp(s, "SWITCH") == 0) || (strcmp(s, "TEXT") == 0)) { + levelIndent++; + } else if ((strcmp(s, "ENDDO") == 0) || (strcmp(s, "ENDIFF") == 0) || (strcmp(s, "ENDSWITCH") == 0) || (strcmp(s, "ENDTEXT") == 0)) { + levelIndent--; + } + } + + if (c == '\n') { // line end + if (levelIndent > 0) { + level |= SC_FOLDLEVELHEADERFLAG; + } + if (level != styler.LevelAt(line)) + styler.SetLevel(line, level); + level += levelIndent; + if ((level & SC_FOLDLEVELNUMBERMASK) < SC_FOLDLEVELBASE) + level = SC_FOLDLEVELBASE; + line++; + // reset state + levelIndent = 0; + level &= ~SC_FOLDLEVELHEADERFLAG; + level &= ~SC_FOLDLEVELWHITEFLAG; + } + + chPrev = c; + } +} + +static const char *const tcmdWordListDesc[] = { + "Internal Commands", + "Aliases", + 0 +}; + +LexerModule lmTCMD(SCLEX_TCMD, ColouriseTCMDDoc, "tcmd", FoldTCMDDoc, tcmdWordListDesc); diff --git a/src/stc/scintilla/src/LexTeX.cxx b/src/stc/scintilla/lexers/LexTeX.cxx similarity index 96% rename from src/stc/scintilla/src/LexTeX.cxx rename to src/stc/scintilla/lexers/LexTeX.cxx index 62ade1d758..062c7abb9b 100644 --- a/src/stc/scintilla/src/LexTeX.cxx +++ b/src/stc/scintilla/lexers/LexTeX.cxx @@ -18,18 +18,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" +#include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" #include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -219,7 +222,7 @@ static void ColouriseTeXDoc( sc.ForwardSetState(SCE_TEX_TEXT) ; } else { sc.GetCurrent(key, sizeof(key)-1) ; - k = strlen(key) ; + k = static_cast<int>(strlen(key)) ; memmove(key,key+1,k) ; // shift left over escape token key[k] = '\0' ; k-- ; @@ -285,8 +288,8 @@ static void ColouriseTeXDoc( static inline bool isNumber(int ch) { return - (ch == '0') || (ch == '1') || (ch == '2') || - (ch == '3') || (ch == '4') || (ch == '5') || + (ch == '0') || (ch == '1') || (ch == '2') || + (ch == '3') || (ch == '4') || (ch == '5') || (ch == '6') || (ch == '7') || (ch == '8') || (ch == '9'); } @@ -298,7 +301,7 @@ static int ParseTeXCommand(unsigned int pos, Accessor &styler, char *command) { int length=0; char ch=styler.SafeGetCharAt(pos+1); - + if(ch==',' || ch==':' || ch==';' || ch=='%'){ command[0]=ch; command[1]=0; @@ -311,14 +314,14 @@ static int ParseTeXCommand(unsigned int pos, Accessor &styler, char *command) length++; ch=styler.SafeGetCharAt(pos+length+1); } - - command[length]='\0'; + + command[length]='\0'; if(!length) return 0; return length+1; } static int classifyFoldPointTeXPaired(const char* s) { - int lev=0; + int lev=0; if (!(isdigit(s[0]) || (s[0] == '.'))){ if (strcmp(s, "begin")==0||strcmp(s,"FoldStart")==0|| strcmp(s,"abstract")==0||strcmp(s,"unprotect")==0|| @@ -330,14 +333,14 @@ static int classifyFoldPointTeXPaired(const char* s) { strcmp(s,"maketitle")==0||strcmp(s,"protect")==0|| strncmp(s,"stop",4)==0||strncmp(s,"Stop",4)==0|| strcmp(s,"fi")==0 - ) + ) lev=-1; } return lev; } static int classifyFoldPointTeXUnpaired(const char* s) { - int lev=0; + int lev=0; if (!(isdigit(s[0]) || (s[0] == '.'))){ if (strcmp(s,"part")==0|| strcmp(s,"chapter")==0|| @@ -362,7 +365,7 @@ static int classifyFoldPointTeXUnpaired(const char* s) { static bool IsTeXCommentLine(int line, Accessor &styler) { int pos = styler.LineStart(line); int eol_pos = styler.LineStart(line + 1) - 1; - + int startpos = pos; while (startpos<eol_pos){ @@ -370,14 +373,14 @@ static bool IsTeXCommentLine(int line, Accessor &styler) { if (ch!='%' && ch!=' ') return false; else if (ch=='%') return true; startpos++; - } + } return false; } // FoldTeXDoc: borrowed from VisualTeX with modifications -static void FoldTexDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +static void FoldTexDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; unsigned int endPos = startPos+length; @@ -387,7 +390,7 @@ static void FoldTexDoc(unsigned int startPos, int length, int, WordList *[], Acc int levelCurrent=levelPrev; char chNext=styler[startPos]; char buffer[100]=""; - + for (unsigned int i=startPos; i < endPos; i++) { char ch=chNext; chNext=styler.SafeGetCharAt(i+1); @@ -412,12 +415,12 @@ static void FoldTexDoc(unsigned int startPos, int length, int, WordList *[], Acc chNext4=styler.SafeGetCharAt(i+4); chNext5=styler.SafeGetCharAt(i+5); - bool atEOfold = (ch == '%') && - (chNext == '%') && (chNext2=='}') && + bool atEOfold = (ch == '%') && + (chNext == '%') && (chNext2=='}') && (chNext3=='}')&& (chNext4=='-')&& (chNext5=='-'); - bool atBOfold = (ch == '%') && - (chNext == '%') && (chNext2=='-') && + bool atBOfold = (ch == '%') && + (chNext == '%') && (chNext2=='-') && (chNext3=='-')&& (chNext4=='{')&& (chNext5=='{'); if(atBOfold){ @@ -427,11 +430,11 @@ static void FoldTexDoc(unsigned int startPos, int length, int, WordList *[], Acc if(atEOfold){ levelCurrent-=1; } - + if(ch=='\\' && chNext=='['){ levelCurrent+=1; } - + if(ch=='\\' && chNext==']'){ levelCurrent-=1; } @@ -452,8 +455,8 @@ static void FoldTexDoc(unsigned int startPos, int length, int, WordList *[], Acc levelCurrent--; } -//--------------------------------------------------------------------------------------------- - +//--------------------------------------------------------------------------------------------- + if (atEOL) { int lev = levelPrev; if (visibleChars == 0 && foldCompact) diff --git a/src/stc/scintilla/lexers/LexTxt2tags.cxx b/src/stc/scintilla/lexers/LexTxt2tags.cxx new file mode 100644 index 0000000000..8f8e181bab --- /dev/null +++ b/src/stc/scintilla/lexers/LexTxt2tags.cxx @@ -0,0 +1,480 @@ +/****************************************************************** + * LexTxt2tags.cxx + * + * A simple Txt2tags lexer for scintilla. + * + * + * Adapted by Eric Forgeot + * Based on the LexMarkdown.cxx by Jon Strait - jstrait@moonloop.net + * + * What could be improved: + * - Verbatim lines could be like for raw lines : when there is no space between the ``` and the following text, the first letter should be colored so the user would understand there must be a space for a valid tag. + * - marks such as bold, italic, strikeout, underline should begin to be highlighted only when they are closed and valid. + * - verbatim and raw area should be highlighted too. + * + * The License.txt file describes the conditions under which this + * software may be distributed. + * + *****************************************************************/ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + + + +static inline bool IsNewline(const int ch) { + return (ch == '\n' || ch == '\r'); +} + +// True if can follow ch down to the end with possibly trailing whitespace +static bool FollowToLineEnd(const int ch, const int state, const unsigned int endPos, StyleContext &sc) { + unsigned int i = 0; + while (sc.GetRelative(++i) == ch) + ; + // Skip over whitespace + while (IsASpaceOrTab(sc.GetRelative(i)) && sc.currentPos + i < endPos) + ++i; + if (IsNewline(sc.GetRelative(i)) || sc.currentPos + i == endPos) { + sc.Forward(i); + sc.ChangeState(state); + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + return true; + } + else return false; +} + +// Does the previous line have more than spaces and tabs? +static bool HasPrevLineContent(StyleContext &sc) { + int i = 0; + // Go back to the previous newline + while ((--i + sc.currentPos) && !IsNewline(sc.GetRelative(i))) + ; + while (--i + sc.currentPos) { + if (IsNewline(sc.GetRelative(i))) + break; + if (!IsASpaceOrTab(sc.GetRelative(i))) + return true; + } + return false; +} + +// Separator line +static bool IsValidHrule(const unsigned int endPos, StyleContext &sc) { + int c, count = 1; + unsigned int i = 0; + while (++i) { + c = sc.GetRelative(i); + if (c == sc.ch) + ++count; + // hit a terminating character + else if (!IsASpaceOrTab(c) || sc.currentPos + i == endPos) { + // Are we a valid HRULE + if ((IsNewline(c) || sc.currentPos + i == endPos) && + count >= 20 && !HasPrevLineContent(sc)) { + sc.SetState(SCE_TXT2TAGS_HRULE); + sc.Forward(i); + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + return true; + } + else { + sc.SetState(SCE_TXT2TAGS_DEFAULT); + return false; + } + } + } + return false; +} + +static void ColorizeTxt2tagsDoc(unsigned int startPos, int length, int initStyle, + WordList **, Accessor &styler) { + unsigned int endPos = startPos + length; + int precharCount = 0; + // Don't advance on a new loop iteration and retry at the same position. + // Useful in the corner case of having to start at the beginning file position + // in the default state. + bool freezeCursor = false; + + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + // Skip past escaped characters + if (sc.ch == '\\') { + sc.Forward(); + continue; + } + + // A blockquotes resets the line semantics + if (sc.state == SCE_TXT2TAGS_BLOCKQUOTE){ + sc.Forward(2); + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + } + // An option colors the whole line + if (sc.state == SCE_TXT2TAGS_OPTION){ + FollowToLineEnd('%', SCE_TXT2TAGS_OPTION, endPos, sc); + } + if (sc.state == SCE_TXT2TAGS_POSTPROC){ + FollowToLineEnd('%', SCE_TXT2TAGS_POSTPROC, endPos, sc); + } + if (sc.state == SCE_TXT2TAGS_PREPROC){ + FollowToLineEnd('%', SCE_TXT2TAGS_PREPROC, endPos, sc); + } + // A comment colors the whole line + if (sc.state == SCE_TXT2TAGS_COMMENT){ + FollowToLineEnd('%', SCE_TXT2TAGS_COMMENT, endPos, sc); + } + // Conditional state-based actions + if (sc.state == SCE_TXT2TAGS_CODE2) { + if (IsNewline(sc.ch)) + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + if (sc.Match("``") && sc.GetRelative(-2) != ' ') { + sc.Forward(2); + sc.SetState(SCE_TXT2TAGS_DEFAULT); + } + } + // Table + else if (sc.state == SCE_TXT2TAGS_CODE) { + if (IsNewline(sc.ch)) + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + if (sc.ch == '|' && sc.chPrev != ' ') + sc.ForwardSetState(SCE_TXT2TAGS_DEFAULT); + } + // Strong + else if (sc.state == SCE_TXT2TAGS_STRONG1) { + if (IsNewline(sc.ch)) + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + if (sc.Match("**") && sc.chPrev != ' ') { + sc.Forward(2); + sc.SetState(SCE_TXT2TAGS_DEFAULT); + } + } + // Emphasis + else if (sc.state == SCE_TXT2TAGS_EM1) { + if (IsNewline(sc.ch)) + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + if (sc.Match("//") && sc.chPrev != ' ') { + sc.Forward(2); + sc.ForwardSetState(SCE_TXT2TAGS_DEFAULT); + } + } + // Underline + else if (sc.state == SCE_TXT2TAGS_EM2) { + if (IsNewline(sc.ch)) + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + if (sc.Match("__") && sc.chPrev != ' ') { + sc.Forward(2); + sc.ForwardSetState(SCE_TXT2TAGS_DEFAULT); + } + } + // codeblock + else if (sc.state == SCE_TXT2TAGS_CODEBK) { + if (IsNewline(sc.ch)) + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + if (sc.atLineStart && sc.Match("```")) { + int i = 1; + while (!IsNewline(sc.GetRelative(i)) && sc.currentPos + i < endPos) + i++; + sc.Forward(i); + sc.SetState(SCE_TXT2TAGS_DEFAULT); + } + } + // strikeout + else if (sc.state == SCE_TXT2TAGS_STRIKEOUT) { + if (IsNewline(sc.ch)) + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + if (sc.Match("--") && sc.chPrev != ' ') { + sc.Forward(2); + sc.SetState(SCE_TXT2TAGS_DEFAULT); + } + } + // Headers + else if (sc.state == SCE_TXT2TAGS_LINE_BEGIN) { + if (sc.Match("======")) + { + sc.SetState(SCE_TXT2TAGS_HEADER6); + sc.Forward(); + } + else if (sc.Match("=====")) + { + sc.SetState(SCE_TXT2TAGS_HEADER5); + sc.Forward(); + } + else if (sc.Match("====")) + { + sc.SetState(SCE_TXT2TAGS_HEADER4); + sc.Forward(); + } + else if (sc.Match("===")) + { + sc.SetState(SCE_TXT2TAGS_HEADER3); + sc.Forward(); + } + //SetStateAndZoom(SCE_TXT2TAGS_HEADER3, 3, '=', sc); + else if (sc.Match("==")) { + sc.SetState(SCE_TXT2TAGS_HEADER2); + sc.Forward(); + } + //SetStateAndZoom(SCE_TXT2TAGS_HEADER2, 2, '=', sc); + else if (sc.Match("=")) { + // Catch the special case of an unordered list + if (sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) { + precharCount = 0; + sc.SetState(SCE_TXT2TAGS_PRECHAR); + } + else + { + sc.SetState(SCE_TXT2TAGS_HEADER1); + sc.Forward(); + } + //SetStateAndZoom(SCE_TXT2TAGS_HEADER1, 1, '=', sc); + } + + // Numbered title + else if (sc.Match("++++++")) + { + sc.SetState(SCE_TXT2TAGS_HEADER6); + sc.Forward(); + } + else if (sc.Match("+++++")) + { + sc.SetState(SCE_TXT2TAGS_HEADER5); + sc.Forward(); + } + else if (sc.Match("++++")) + { + sc.SetState(SCE_TXT2TAGS_HEADER4); + sc.Forward(); + } + else if (sc.Match("+++")) + { + sc.SetState(SCE_TXT2TAGS_HEADER3); + sc.Forward(); + } + //SetStateAndZoom(SCE_TXT2TAGS_HEADER3, 3, '+', sc); + else if (sc.Match("++")) { + sc.SetState(SCE_TXT2TAGS_HEADER2); + sc.Forward(); + } + //SetStateAndZoom(SCE_TXT2TAGS_HEADER2, 2, '+', sc); + else if (sc.Match("+")) { + // Catch the special case of an unordered list + if (sc.chNext == ' ' && IsASpaceOrTab(sc.GetRelative(1))) { + // if (IsNewline(sc.ch)) { + //precharCount = 0; + // sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + //sc.SetState(SCE_TXT2TAGS_PRECHAR); + // } + // else { + // precharCount = 0; + sc.SetState(SCE_TXT2TAGS_OLIST_ITEM); + sc.Forward(2); + sc.SetState(SCE_TXT2TAGS_DEFAULT); + // sc.SetState(SCE_TXT2TAGS_PRECHAR); + // } + } + else + { + sc.SetState(SCE_TXT2TAGS_HEADER1); + sc.Forward(); + } + } + + + // Codeblock + else if (sc.Match("```")) { + if (!HasPrevLineContent(sc)) + // if (!FollowToLineEnd(sc)) + sc.SetState(SCE_TXT2TAGS_CODEBK); + else + sc.SetState(SCE_TXT2TAGS_DEFAULT); + } + + // Preproc + else if (sc.Match("%!preproc")) { + sc.SetState(SCE_TXT2TAGS_PREPROC); + } + // Postproc + else if (sc.Match("%!postproc")) { + sc.SetState(SCE_TXT2TAGS_POSTPROC); + } + // Option + else if (sc.Match("%!")) { + sc.SetState(SCE_TXT2TAGS_OPTION); + } + + // Comment + else if (sc.ch == '%') { + sc.SetState(SCE_TXT2TAGS_COMMENT); + } + // list + else if (sc.ch == '-') { + precharCount = 0; + sc.SetState(SCE_TXT2TAGS_PRECHAR); + } + // def list + else if (sc.ch == ':') { + precharCount = 0; + sc.SetState(SCE_TXT2TAGS_OLIST_ITEM); + sc.Forward(1); + sc.SetState(SCE_TXT2TAGS_PRECHAR); + } + else if (IsNewline(sc.ch)) + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + else { + precharCount = 0; + sc.SetState(SCE_TXT2TAGS_PRECHAR); + } + } + + // The header lasts until the newline + else if (sc.state == SCE_TXT2TAGS_HEADER1 || sc.state == SCE_TXT2TAGS_HEADER2 || + sc.state == SCE_TXT2TAGS_HEADER3 || sc.state == SCE_TXT2TAGS_HEADER4 || + sc.state == SCE_TXT2TAGS_HEADER5 || sc.state == SCE_TXT2TAGS_HEADER6) { + if (IsNewline(sc.ch)) + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + } + + // New state only within the initial whitespace + if (sc.state == SCE_TXT2TAGS_PRECHAR) { + // Blockquote + if (sc.Match("\"\"\"") && precharCount < 5){ + + sc.SetState(SCE_TXT2TAGS_BLOCKQUOTE); + sc.Forward(1); + } + /* + // Begin of code block + else if (!HasPrevLineContent(sc) && (sc.chPrev == '\t' || precharCount >= 4)) + sc.SetState(SCE_TXT2TAGS_CODEBK); + */ + // HRule - Total of 20 or more hyphens, asterisks, or underscores + // on a line by themselves + else if ((sc.ch == '-' ) && IsValidHrule(endPos, sc)) + ; + // Unordered list + else if ((sc.ch == '-') && IsASpaceOrTab(sc.chNext)) { + sc.SetState(SCE_TXT2TAGS_ULIST_ITEM); + sc.ForwardSetState(SCE_TXT2TAGS_DEFAULT); + } + // Ordered list + else if (IsADigit(sc.ch)) { + int digitCount = 0; + while (IsADigit(sc.GetRelative(++digitCount))) + ; + if (sc.GetRelative(digitCount) == '.' && + IsASpaceOrTab(sc.GetRelative(digitCount + 1))) { + sc.SetState(SCE_TXT2TAGS_OLIST_ITEM); + sc.Forward(digitCount + 1); + sc.SetState(SCE_TXT2TAGS_DEFAULT); + } + } + // Alternate Ordered list + else if (sc.ch == '+' && sc.chNext == ' ' && IsASpaceOrTab(sc.GetRelative(2))) { + // sc.SetState(SCE_TXT2TAGS_OLIST_ITEM); + // sc.Forward(2); + // sc.SetState(SCE_TXT2TAGS_DEFAULT); + } + else if (sc.ch != ' ' || precharCount > 2) + sc.SetState(SCE_TXT2TAGS_DEFAULT); + else + ++precharCount; + } + + // New state anywhere in doc + if (sc.state == SCE_TXT2TAGS_DEFAULT) { + // if (sc.atLineStart && sc.ch == '#') { + // sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + // freezeCursor = true; + // } + // Links and Images + if (sc.Match("![") || sc.ch == '[') { + int i = 0, j = 0, k = 0; + int len = endPos - sc.currentPos; + while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\')) + ; + if (sc.GetRelative(i) == ']') { + j = i; + if (sc.GetRelative(++i) == '(') { + while (i < len && (sc.GetRelative(++i) != '(' || sc.GetRelative(i - 1) == '\\')) + ; + if (sc.GetRelative(i) == '(') + k = i; + } + + else if (sc.GetRelative(i) == '[' || sc.GetRelative(++i) == '[') { + while (i < len && (sc.GetRelative(++i) != ']' || sc.GetRelative(i - 1) == '\\')) + ; + if (sc.GetRelative(i) == ']') + k = i; + } + } + // At least a link text + if (j) { + sc.SetState(SCE_TXT2TAGS_LINK); + sc.Forward(j); + // Also has a URL or reference portion + if (k) + sc.Forward(k - j); + sc.ForwardSetState(SCE_TXT2TAGS_DEFAULT); + } + } + // Code - also a special case for alternate inside spacing + if (sc.Match("``") && sc.GetRelative(3) != ' ') { + sc.SetState(SCE_TXT2TAGS_CODE2); + sc.Forward(); + } + else if (sc.ch == '|' && sc.GetRelative(3) != ' ') { + sc.SetState(SCE_TXT2TAGS_CODE); + } + // Strong + else if (sc.Match("**") && sc.GetRelative(2) != ' ') { + sc.SetState(SCE_TXT2TAGS_STRONG1); + sc.Forward(); + } + // Emphasis + else if (sc.Match("//") && sc.GetRelative(2) != ' ') { + sc.SetState(SCE_TXT2TAGS_EM1); + sc.Forward(); + } + else if (sc.Match("__") && sc.GetRelative(2) != ' ') { + sc.SetState(SCE_TXT2TAGS_EM2); + sc.Forward(); + } + // Strikeout + else if (sc.Match("--") && sc.GetRelative(2) != ' ') { + sc.SetState(SCE_TXT2TAGS_STRIKEOUT); + sc.Forward(); + } + + // Beginning of line + else if (IsNewline(sc.ch)) + sc.SetState(SCE_TXT2TAGS_LINE_BEGIN); + } + // Advance if not holding back the cursor for this iteration. + if (!freezeCursor) + sc.Forward(); + freezeCursor = false; + } + sc.Complete(); +} + +LexerModule lmTxt2tags(SCLEX_TXT2TAGS, ColorizeTxt2tagsDoc, "txt2tags"); + + diff --git a/src/stc/scintilla/src/LexVB.cxx b/src/stc/scintilla/lexers/LexVB.cxx similarity index 98% rename from src/stc/scintilla/src/LexVB.cxx rename to src/stc/scintilla/lexers/LexVB.cxx index c57a9ac49d..54050c7bce 100644 --- a/src/stc/scintilla/src/LexVB.cxx +++ b/src/stc/scintilla/lexers/LexVB.cxx @@ -7,18 +7,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; diff --git a/src/stc/scintilla/src/LexVHDL.cxx b/src/stc/scintilla/lexers/LexVHDL.cxx similarity index 93% rename from src/stc/scintilla/src/LexVHDL.cxx rename to src/stc/scintilla/lexers/LexVHDL.cxx index c082cdb923..ee9d6628fa 100644 --- a/src/stc/scintilla/src/LexVHDL.cxx +++ b/src/stc/scintilla/lexers/LexVHDL.cxx @@ -1,9 +1,9 @@ // Scintilla source code edit control /** @file LexVHDL.cxx ** Lexer for VHDL - ** Written by Phil Reid, + ** Written by Phil Reid, ** Based on: - ** - The Verilog Lexer by Avi Yegudin + ** - The Verilog Lexer by Avi Yegudin ** - The Fortran Lexer by Chuan-jian Shen ** - The C++ lexer by Neil Hodgson **/ @@ -15,15 +15,18 @@ #include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -101,7 +104,7 @@ static void ColouriseVHDLDoc( } sc.SetState(SCE_VHDL_DEFAULT); } - } else if (sc.state == SCE_VHDL_COMMENT || sc.state == SCE_V_COMMENTLINEBANG) { + } else if (sc.state == SCE_VHDL_COMMENT || sc.state == SCE_VHDL_COMMENTLINEBANG) { if (sc.atLineEnd) { sc.SetState(SCE_VHDL_DEFAULT); } @@ -113,7 +116,7 @@ static void ColouriseVHDLDoc( } else if (sc.ch == '\"') { sc.ForwardSetState(SCE_VHDL_DEFAULT); } else if (sc.atLineEnd) { - sc.ChangeState(SCE_V_STRINGEOL); + sc.ChangeState(SCE_VHDL_STRINGEOL); sc.ForwardSetState(SCE_VHDL_DEFAULT); } } @@ -124,9 +127,6 @@ static void ColouriseVHDLDoc( sc.SetState(SCE_VHDL_NUMBER); } else if (IsAWordStart(sc.ch)) { sc.SetState(SCE_VHDL_IDENTIFIER); - } else if (sc.Match('-', '-')) { - sc.SetState(SCE_VHDL_COMMENT); - sc.Forward(); } else if (sc.Match('-', '-')) { if (sc.Match("--!")) // Nice to have a different comment style sc.SetState(SCE_VHDL_COMMENTLINEBANG); @@ -161,7 +161,7 @@ static bool IsCommentLine(int line, Accessor &styler) { static void FoldNoBoxVHDLDoc( unsigned int startPos, int length, - int initStyle, + int, Accessor &styler) { // Decided it would be smarter to have the lexer have all keywords included. Therefore I @@ -232,7 +232,7 @@ static void FoldNoBoxVHDLDoc( } } } - for(j=j+strlen(prevWord); j<endPos; j++) + for(j=j+static_cast<unsigned int>(strlen(prevWord)); j<endPos; j++) { char ch = styler.SafeGetCharAt(j); int style = styler.StyleAt(j); @@ -249,7 +249,6 @@ static void FoldNoBoxVHDLDoc( char chPrev = '\0'; char chNextNonBlank; int styleNext = styler.StyleAt(startPos); - int style = initStyle; //Platform::DebugPrintf("Line[%04d] Prev[%20s] ************************* Level[%x]\n", lineCurrent+1, prevWord, levelCurrent); /***************************************/ @@ -265,16 +264,16 @@ static void FoldNoBoxVHDLDoc( j ++ ; chNextNonBlank = styler.SafeGetCharAt(j); } - style = styleNext; + int style = styleNext; styleNext = styler.StyleAt(i + 1); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { if(!IsCommentLine(lineCurrent-1, styler) && IsCommentLine(lineCurrent+1, styler)) { levelNext++; - } + } else if(IsCommentLine(lineCurrent-1, styler) && !IsCommentLine(lineCurrent+1, styler)) { levelNext--; @@ -380,7 +379,7 @@ static void FoldNoBoxVHDLDoc( ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "function") == 0)) || ((strcmp(s, "begin") == 0) && (strcmp(prevWord, "procedure") == 0))) { - levelMinCurrentBegin = levelNext - 1; + levelMinCurrentBegin = levelNext - 1; } //Platform::DebugPrintf("Line[%04d] Prev[%20s] Cur[%20s] Level[%x]\n", lineCurrent+1, prevWord, s, levelCurrent); strcpy(prevWord, s); @@ -444,34 +443,34 @@ LexerModule lmVHDL(SCLEX_VHDL, ColouriseVHDLDoc, "vhdl", FoldVHDLDoc, VHDLWordLi // Keyword: -// access after alias all architecture array assert attribute begin block body buffer bus case component -// configuration constant disconnect downto else elsif end entity exit file for function generate generic -// group guarded if impure in inertial inout is label library linkage literal loop map new next null of -// on open others out package port postponed procedure process pure range record register reject report -// return select severity shared signal subtype then to transport type unaffected units until use variable +// access after alias all architecture array assert attribute begin block body buffer bus case component +// configuration constant disconnect downto else elsif end entity exit file for function generate generic +// group guarded if impure in inertial inout is label library linkage literal loop map new next null of +// on open others out package port postponed procedure process pure range record register reject report +// return select severity shared signal subtype then to transport type unaffected units until use variable // wait when while with // // Operators: // abs and mod nand nor not or rem rol ror sla sll sra srl xnor xor // // Attributes: -// left right low high ascending image value pos val succ pred leftof rightof base range reverse_range -// length delayed stable quiet transaction event active last_event last_active last_value driving +// left right low high ascending image value pos val succ pred leftof rightof base range reverse_range +// length delayed stable quiet transaction event active last_event last_active last_value driving // driving_value simple_name path_name instance_name // // Std Functions: -// now readline read writeline write endfile resolved to_bit to_bitvector to_stdulogic to_stdlogicvector -// to_stdulogicvector to_x01 to_x01z to_UX01 rising_edge falling_edge is_x shift_left shift_right rotate_left +// now readline read writeline write endfile resolved to_bit to_bitvector to_stdulogic to_stdlogicvector +// to_stdulogicvector to_x01 to_x01z to_UX01 rising_edge falling_edge is_x shift_left shift_right rotate_left // rotate_right resize to_integer to_unsigned to_signed std_match to_01 // // Std Packages: -// std ieee work standard textio std_logic_1164 std_logic_arith std_logic_misc std_logic_signed -// std_logic_textio std_logic_unsigned numeric_bit numeric_std math_complex math_real vital_primitives +// std ieee work standard textio std_logic_1164 std_logic_arith std_logic_misc std_logic_signed +// std_logic_textio std_logic_unsigned numeric_bit numeric_std math_complex math_real vital_primitives // vital_timing // // Std Types: -// boolean bit character severity_level integer real time delay_length natural positive string bit_vector -// file_open_kind file_open_status line text side width std_ulogic std_ulogic_vector std_logic +// boolean bit character severity_level integer real time delay_length natural positive string bit_vector +// file_open_kind file_open_status line text side width std_ulogic std_ulogic_vector std_logic // std_logic_vector X01 X01Z UX01 UX01Z unsigned signed // diff --git a/src/stc/scintilla/src/LexVerilog.cxx b/src/stc/scintilla/lexers/LexVerilog.cxx similarity index 85% rename from src/stc/scintilla/src/LexVerilog.cxx rename to src/stc/scintilla/lexers/LexVerilog.cxx index 3fd0fc35c6..ed39c2b177 100644 --- a/src/stc/scintilla/src/LexVerilog.cxx +++ b/src/stc/scintilla/lexers/LexVerilog.cxx @@ -8,25 +8,28 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''|| ch == '$'); } static inline bool IsAWordStart(const int ch) { @@ -150,6 +153,22 @@ static bool IsStreamCommentStyle(int style) { return style == SCE_V_COMMENT; } +static bool IsCommentLine(int line, Accessor &styler) { + int pos = styler.LineStart(line); + int eolPos = styler.LineStart(line + 1) - 1; + for (int i = pos; i < eolPos; i++) { + char ch = styler[i]; + char chNext = styler.SafeGetCharAt(i + 1); + int style = styler.StyleAt(i); + if (ch == '/' && chNext == '/' && + (style == SCE_V_COMMENTLINE || style == SCE_V_COMMENTLINEBANG)) { + return true; + } else if (!IsASpaceOrTab(ch)) { + return false; + } + } + return false; +} // Store both the current line's fold level and the next lines in the // level store to make it easy to pick up with each increment // and to make it possible to fiddle the current level for "} else {". @@ -195,6 +214,15 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle levelNext--; } } + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelNext++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent+1, styler)) + levelNext--; + } if (foldComment && (style == SCE_V_COMMENTLINE)) { if ((ch == '/') && (chNext == '/')) { char chNext2 = styler.SafeGetCharAt(i + 2); @@ -241,24 +269,36 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle if (styler.Match(j, "case") || styler.Match(j, "casex") || styler.Match(j, "casez") || + styler.Match(j, "class") || styler.Match(j, "function") || - styler.Match(j, "fork") || - styler.Match(j, "table") || - styler.Match(j, "task") || styler.Match(j, "generate") || - styler.Match(j, "specify") || + styler.Match(j, "covergroup") || + styler.Match(j, "package") || styler.Match(j, "primitive") || + styler.Match(j, "program") || + styler.Match(j, "sequence") || + styler.Match(j, "specify") || + styler.Match(j, "table") || + styler.Match(j, "task") || + styler.Match(j, "fork") || (styler.Match(j, "module") && foldAtModule) || styler.Match(j, "begin")) { levelNext++; } else if (styler.Match(j, "endcase") || + styler.Match(j, "endclass") || styler.Match(j, "endfunction") || - styler.Match(j, "join") || - styler.Match(j, "endtask") || styler.Match(j, "endgenerate") || - styler.Match(j, "endtable") || - styler.Match(j, "endspecify") || + styler.Match(j, "endgroup") || + styler.Match(j, "endpackage") || styler.Match(j, "endprimitive") || + styler.Match(j, "endprogram") || + styler.Match(j, "endsequence") || + styler.Match(j, "endspecify") || + styler.Match(j, "endtable") || + styler.Match(j, "endtask") || + styler.Match(j, "join") || + styler.Match(j, "join_any") || + styler.Match(j, "join_none") || (styler.Match(j, "endmodule") && foldAtModule) || (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3)))) { levelNext--; diff --git a/src/stc/scintilla/lexers/LexVisualProlog.cxx b/src/stc/scintilla/lexers/LexVisualProlog.cxx new file mode 100644 index 0000000000..8a7495b9ad --- /dev/null +++ b/src/stc/scintilla/lexers/LexVisualProlog.cxx @@ -0,0 +1,470 @@ +// Scintilla source code edit control +/** @file LexVisualProlog.cxx +** Lexer for Visual Prolog. +**/ +// Author Thomas Linder Puls, Prolog Development Denter A/S, http://www.visual-prolog.com +// Based on Lexer for C++, C, Java, and JavaScript. +// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> + +#ifdef _MSC_VER +#pragma warning(disable: 4786) +#endif + +#include <string> +#include <vector> +#include <map> +#include <algorithm> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "OptionSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +// Options used for LexerVisualProlog +struct OptionsVisualProlog { + OptionsVisualProlog() { + } +}; + +static const char *const visualPrologWordLists[] = { + "Major keywords (class, predicates, ...)", + "Minor keywords (if, then, try, ...)", + "Directive keywords without the '#' (include, requires, ...)", + "Documentation keywords without the '@' (short, detail, ...)", + 0, +}; + +struct OptionSetVisualProlog : public OptionSet<OptionsVisualProlog> { + OptionSetVisualProlog() { + DefineWordListSets(visualPrologWordLists); + } +}; + +class LexerVisualProlog : public ILexer { + WordList majorKeywords; + WordList minorKeywords; + WordList directiveKeywords; + WordList docKeywords; + OptionsVisualProlog options; + OptionSetVisualProlog osVisualProlog; +public: + LexerVisualProlog() { + } + virtual ~LexerVisualProlog() { + } + void SCI_METHOD Release() { + delete this; + } + int SCI_METHOD Version() const { + return lvOriginal; + } + const char * SCI_METHOD PropertyNames() { + return osVisualProlog.PropertyNames(); + } + int SCI_METHOD PropertyType(const char *name) { + return osVisualProlog.PropertyType(name); + } + const char * SCI_METHOD DescribeProperty(const char *name) { + return osVisualProlog.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets() { + return osVisualProlog.DescribeWordListSets(); + } + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess); + + void * SCI_METHOD PrivateCall(int, void *) { + return 0; + } + + static ILexer *LexerFactoryVisualProlog() { + return new LexerVisualProlog(); + } +}; + +int SCI_METHOD LexerVisualProlog::PropertySet(const char *key, const char *val) { + if (osVisualProlog.PropertySet(&options, key, val)) { + return 0; + } + return -1; +} + +int SCI_METHOD LexerVisualProlog::WordListSet(int n, const char *wl) { + WordList *wordListN = 0; + switch (n) { + case 0: + wordListN = &majorKeywords; + break; + case 1: + wordListN = &minorKeywords; + break; + case 2: + wordListN = &directiveKeywords; + break; + case 3: + wordListN = &docKeywords; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + } + } + return firstModification; +} + +// Functor used to truncate history +struct After { + int line; + After(int line_) : line(line_) {} +}; + +// Look ahead to see which colour "end" should have (takes colour after the following keyword) +static void endLookAhead(char s[], LexAccessor &styler, int start, CharacterSet &setIdentifier) { + char ch = styler.SafeGetCharAt(start, '\n'); + while (' ' == ch) { + start++; + ch = styler.SafeGetCharAt(start, '\n'); + } + int i = 0; + while (i < 100 && setIdentifier.Contains(ch)){ + s[i] = ch; + i++; + ch = styler.SafeGetCharAt(start + i, '\n'); + } + s[i] = '\0'; +} + +static void forwardEscapeLiteral(StyleContext &sc, int OwnChar, int EscapeState) { + sc.Forward(); + if (sc.ch == OwnChar || sc.ch == '\\' || sc.ch == 'n' || sc.ch == 'l' || sc.ch == 'r' || sc.ch == 't') { + sc.ChangeState(EscapeState); + } else if (sc.ch == 'u') { + if (IsADigit(sc.chNext, 16)) { + sc.Forward(); + if (IsADigit(sc.chNext, 16)) { + sc.Forward(); + if (IsADigit(sc.chNext, 16)) { + sc.Forward(); + if (IsADigit(sc.chNext, 16)) { + sc.Forward(); + sc.ChangeState(EscapeState); + } + } + } + } + } +} + +void SCI_METHOD LexerVisualProlog::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + LexAccessor styler(pAccess); + + CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); + + CharacterSet setLowerStart(CharacterSet::setLower); + CharacterSet setVariableStart(CharacterSet::setUpper); + CharacterSet setIdentifier(CharacterSet::setAlphaNum, "_", 0x80, true); + + int styleBeforeDocKeyword = SCE_VISUALPROLOG_DEFAULT; + + int currentLine = styler.GetLine(startPos); + + int nestLevel = 0; + if (currentLine >= 1) + { + nestLevel = styler.GetLineState(currentLine - 1); + } + + StyleContext sc(startPos, length, initStyle, styler, 0x7f); + + // Truncate ppDefineHistory before current line + + for (; sc.More(); sc.Forward()) { + + if (sc.atLineEnd) { + // Update the line state, so it can be seen by next line + styler.SetLineState(currentLine, nestLevel); + currentLine++; + } + + if (sc.atLineStart) { + if ((sc.state == SCE_VISUALPROLOG_STRING) || (sc.state == SCE_VISUALPROLOG_CHARACTER)) { + // Prevent SCE_VISUALPROLOG_STRING_EOL from leaking back to previous line which + // ends with a line continuation by locking in the state upto this position. + sc.SetState(sc.state); + } + } + + const bool atLineEndBeforeSwitch = sc.atLineEnd; + + // Determine if the current state should terminate. + switch (sc.state) { + case SCE_VISUALPROLOG_OPERATOR: + sc.SetState(SCE_VISUALPROLOG_DEFAULT); + break; + case SCE_VISUALPROLOG_NUMBER: + // We accept almost anything because of hex. and number suffixes + if (!(setIdentifier.Contains(sc.ch) || (sc.ch == '.') || ((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')))) { + sc.SetState(SCE_VISUALPROLOG_DEFAULT); + } + break; + case SCE_VISUALPROLOG_IDENTIFIER: + if (!setIdentifier.Contains(sc.ch)) { + char s[1000]; + sc.GetCurrent(s, sizeof(s)); + if (0 == strcmp(s, "end")) { + endLookAhead(s, styler, sc.currentPos, setIdentifier); + } + if (majorKeywords.InList(s)) { + sc.ChangeState(SCE_VISUALPROLOG_KEY_MAJOR); + } else if (minorKeywords.InList(s)) { + sc.ChangeState(SCE_VISUALPROLOG_KEY_MINOR); + } + sc.SetState(SCE_VISUALPROLOG_DEFAULT); + } + break; + case SCE_VISUALPROLOG_VARIABLE: + case SCE_VISUALPROLOG_ANONYMOUS: + if (!setIdentifier.Contains(sc.ch)) { + sc.SetState(SCE_VISUALPROLOG_DEFAULT); + } + break; + case SCE_VISUALPROLOG_KEY_DIRECTIVE: + if (!setLowerStart.Contains(sc.ch)) { + char s[1000]; + sc.GetCurrent(s, sizeof(s)); + if (!directiveKeywords.InList(s+1)) { + sc.ChangeState(SCE_VISUALPROLOG_IDENTIFIER); + } + sc.SetState(SCE_VISUALPROLOG_DEFAULT); + } + break; + case SCE_VISUALPROLOG_COMMENT_BLOCK: + if (sc.Match('*', '/')) { + sc.Forward(); + nestLevel--; + int nextState = (nestLevel == 0) ? SCE_VISUALPROLOG_DEFAULT : SCE_VISUALPROLOG_COMMENT_BLOCK; + sc.ForwardSetState(nextState); + } else if (sc.Match('/', '*')) { + sc.Forward(); + nestLevel++; + } else if (sc.ch == '%') { + sc.SetState(SCE_VISUALPROLOG_COMMENT_LINE); + } else if (sc.ch == '@') { + styleBeforeDocKeyword = sc.state; + sc.SetState(SCE_VISUALPROLOG_COMMENT_KEY_ERROR); + } + break; + case SCE_VISUALPROLOG_COMMENT_LINE: + if (sc.atLineEnd) { + int nextState = (nestLevel == 0) ? SCE_VISUALPROLOG_DEFAULT : SCE_VISUALPROLOG_COMMENT_BLOCK; + sc.SetState(nextState); + } else if (sc.ch == '@') { + styleBeforeDocKeyword = sc.state; + sc.SetState(SCE_VISUALPROLOG_COMMENT_KEY_ERROR); + } + break; + case SCE_VISUALPROLOG_COMMENT_KEY_ERROR: + if (!setDoxygen.Contains(sc.ch)) { + char s[1000]; + sc.GetCurrent(s, sizeof(s)); + if (docKeywords.InList(s+1)) { + sc.ChangeState(SCE_VISUALPROLOG_COMMENT_KEY); + } + sc.SetState(styleBeforeDocKeyword); + } + if (SCE_VISUALPROLOG_COMMENT_LINE == styleBeforeDocKeyword && sc.atLineStart) { + sc.SetState(SCE_VISUALPROLOG_DEFAULT); + } else if (SCE_VISUALPROLOG_COMMENT_BLOCK == styleBeforeDocKeyword && sc.atLineStart) { + sc.SetState(SCE_VISUALPROLOG_COMMENT_BLOCK); + } + break; + case SCE_VISUALPROLOG_STRING_ESCAPE: + case SCE_VISUALPROLOG_STRING_ESCAPE_ERROR: + // return to SCE_VISUALPROLOG_STRING and treat as such (fall-through) + sc.SetState(SCE_VISUALPROLOG_STRING); + case SCE_VISUALPROLOG_STRING: + if (sc.atLineEnd) { + sc.SetState(SCE_VISUALPROLOG_STRING_EOL_OPEN); + } else if (sc.ch == '"') { + sc.ForwardSetState(SCE_VISUALPROLOG_DEFAULT); + } else if (sc.ch == '\\') { + sc.SetState(SCE_VISUALPROLOG_STRING_ESCAPE_ERROR); + forwardEscapeLiteral(sc, '"', SCE_VISUALPROLOG_STRING_ESCAPE); + } + break; + case SCE_VISUALPROLOG_CHARACTER_TOO_MANY: + if (sc.atLineStart) { + sc.SetState(SCE_VISUALPROLOG_DEFAULT); + } else if (sc.ch == '\'') { + sc.SetState(SCE_VISUALPROLOG_CHARACTER); + sc.ForwardSetState(SCE_VISUALPROLOG_DEFAULT); + } + break; + case SCE_VISUALPROLOG_CHARACTER: + if (sc.atLineEnd) { + sc.SetState(SCE_VISUALPROLOG_STRING_EOL_OPEN); // reuse STRING_EOL_OPEN for this + } else if (sc.ch == '\'') { + sc.SetState(SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR); + sc.ForwardSetState(SCE_VISUALPROLOG_DEFAULT); + } else { + if (sc.ch == '\\') { + sc.SetState(SCE_VISUALPROLOG_CHARACTER_ESCAPE_ERROR); + forwardEscapeLiteral(sc, '\'', SCE_VISUALPROLOG_CHARACTER); + } + sc.ForwardSetState(SCE_VISUALPROLOG_CHARACTER); + if (sc.ch == '\'') { + sc.ForwardSetState(SCE_VISUALPROLOG_DEFAULT); + } else { + sc.SetState(SCE_VISUALPROLOG_CHARACTER_TOO_MANY); + } + } + break; + case SCE_VISUALPROLOG_STRING_EOL_OPEN: + if (sc.atLineStart) { + sc.SetState(SCE_VISUALPROLOG_DEFAULT); + } + break; + case SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL: + case SCE_VISUALPROLOG_STRING_VERBATIM_EOL: + // return to SCE_VISUALPROLOG_STRING_VERBATIM and treat as such (fall-through) + sc.SetState(SCE_VISUALPROLOG_STRING_VERBATIM); + case SCE_VISUALPROLOG_STRING_VERBATIM: + if (sc.atLineEnd) { + sc.SetState(SCE_VISUALPROLOG_STRING_VERBATIM_EOL); + } else if (sc.ch == '\"') { + if (sc.chNext == '\"') { + sc.SetState(SCE_VISUALPROLOG_STRING_VERBATIM_SPECIAL); + sc.Forward(); + } else { + sc.ForwardSetState(SCE_VISUALPROLOG_DEFAULT); + } + } + break; + } + + if (sc.atLineEnd && !atLineEndBeforeSwitch) { + // State exit processing consumed characters up to end of line. + currentLine++; + } + + // Determine if a new state should be entered. + if (sc.state == SCE_VISUALPROLOG_DEFAULT) { + if (sc.Match('@', '\"')) { + sc.SetState(SCE_VISUALPROLOG_STRING_VERBATIM); + sc.Forward(); + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + sc.SetState(SCE_VISUALPROLOG_NUMBER); + } else if (setLowerStart.Contains(sc.ch)) { + sc.SetState(SCE_VISUALPROLOG_IDENTIFIER); + } else if (setVariableStart.Contains(sc.ch)) { + sc.SetState(SCE_VISUALPROLOG_VARIABLE); + } else if (sc.ch == '_') { + sc.SetState(SCE_VISUALPROLOG_ANONYMOUS); + } else if (sc.Match('/', '*')) { + sc.SetState(SCE_VISUALPROLOG_COMMENT_BLOCK); + nestLevel = 1; + sc.Forward(); // Eat the * so it isn't used for the end of the comment + } else if (sc.ch == '%') { + sc.SetState(SCE_VISUALPROLOG_COMMENT_LINE); + } else if (sc.ch == '\"') { + sc.SetState(SCE_VISUALPROLOG_STRING); + } else if (sc.ch == '\'') { + sc.SetState(SCE_VISUALPROLOG_CHARACTER); + } else if (sc.ch == '#') { + sc.SetState(SCE_VISUALPROLOG_KEY_DIRECTIVE); + } else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '\\') { + sc.SetState(SCE_VISUALPROLOG_OPERATOR); + } + } + + } + sc.Complete(); + styler.Flush(); +} + +// Store both the current line's fold level and the next lines in the +// level store to make it easy to pick up with each increment +// and to make it possible to fiddle the current level for "} else {". + +void SCI_METHOD LexerVisualProlog::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + + LexAccessor styler(pAccess); + + unsigned int endPos = startPos + length; + int visibleChars = 0; + int currentLine = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (currentLine > 0) + levelCurrent = styler.LevelAt(currentLine-1) >> 16; + int levelMinCurrent = levelCurrent; + int levelNext = levelCurrent; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int style = initStyle; + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + if (style == SCE_VISUALPROLOG_OPERATOR) { + if (ch == '{') { + // Measure the minimum before a '{' to allow + // folding on "} else {" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (ch == '}') { + levelNext--; + } + } + if (!IsASpace(ch)) + visibleChars++; + if (atEOL || (i == endPos-1)) { + int levelUse = levelCurrent; + int lev = levelUse | levelNext << 16; + if (levelUse < levelNext) + lev |= SC_FOLDLEVELHEADERFLAG; + if (lev != styler.LevelAt(currentLine)) { + styler.SetLevel(currentLine, lev); + } + currentLine++; + levelCurrent = levelNext; + levelMinCurrent = levelCurrent; + if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) { + // There is an empty line at end of file so give it same level and empty + styler.SetLevel(currentLine, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG); + } + visibleChars = 0; + } + } +} + +LexerModule lmVisualProlog(SCLEX_VISUALPROLOG, LexerVisualProlog::LexerFactoryVisualProlog, "visualprolog", visualPrologWordLists); diff --git a/src/stc/scintilla/src/LexYAML.cxx b/src/stc/scintilla/lexers/LexYAML.cxx similarity index 97% rename from src/stc/scintilla/src/LexYAML.cxx rename to src/stc/scintilla/lexers/LexYAML.cxx index 99f34da889..727e8af8ff 100644 --- a/src/stc/scintilla/src/LexYAML.cxx +++ b/src/stc/scintilla/lexers/LexYAML.cxx @@ -7,18 +7,21 @@ #include <stdlib.h> #include <string.h> -#include <ctype.h> #include <stdio.h> #include <stdarg.h> +#include <assert.h> +#include <ctype.h> -#include "Platform.h" +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" -#include "PropSet.h" +#include "WordList.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" +#include "CharacterSet.h" +#include "LexerModule.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -270,7 +273,7 @@ static void FoldYAMLDoc(unsigned int startPos, int length, int /*initStyle - unu } const int levelAfterComments = indentNext & SC_FOLDLEVELNUMBERMASK; - const int levelBeforeComments = Platform::Maximum(indentCurrentLevel,levelAfterComments); + const int levelBeforeComments = Maximum(indentCurrentLevel,levelAfterComments); // Now set all the indent levels on the lines we skipped // Do this from end to start. Once we encounter one line diff --git a/src/stc/scintilla/lexlib/Accessor.cxx b/src/stc/scintilla/lexlib/Accessor.cxx new file mode 100644 index 0000000000..65609598f4 --- /dev/null +++ b/src/stc/scintilla/lexlib/Accessor.cxx @@ -0,0 +1,79 @@ +// Scintilla source code edit control +/** @file KeyWords.cxx + ** Colourise for particular languages. + **/ +// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +Accessor::Accessor(IDocument *pAccess_, PropSetSimple *pprops_) : LexAccessor(pAccess_), pprops(pprops_) { +} + +int Accessor::GetPropertyInt(const char *key, int defaultValue) { + return pprops->GetInt(key, defaultValue); +} + +int Accessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) { + int end = Length(); + int spaceFlags = 0; + + // Determines the indentation level of the current line and also checks for consistent + // indentation compared to the previous line. + // Indentation is judged consistent when the indentation whitespace of each line lines + // the same or the indentation of one line is a prefix of the other. + + int pos = LineStart(line); + char ch = (*this)[pos]; + int indent = 0; + bool inPrevPrefix = line > 0; + int posPrev = inPrevPrefix ? LineStart(line-1) : 0; + while ((ch == ' ' || ch == '\t') && (pos < end)) { + if (inPrevPrefix) { + char chPrev = (*this)[posPrev++]; + if (chPrev == ' ' || chPrev == '\t') { + if (chPrev != ch) + spaceFlags |= wsInconsistent; + } else { + inPrevPrefix = false; + } + } + if (ch == ' ') { + spaceFlags |= wsSpace; + indent++; + } else { // Tab + spaceFlags |= wsTab; + if (spaceFlags & wsSpace) + spaceFlags |= wsSpaceTab; + indent = (indent / 8 + 1) * 8; + } + ch = (*this)[++pos]; + } + + *flags = spaceFlags; + indent += SC_FOLDLEVELBASE; + // if completely empty line or the start of a comment... + if ((LineStart(line) == Length()) || (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') || + (pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos))) + return indent | SC_FOLDLEVELWHITEFLAG; + else + return indent; +} diff --git a/src/stc/scintilla/lexlib/Accessor.h b/src/stc/scintilla/lexlib/Accessor.h new file mode 100644 index 0000000000..2f28c1acda --- /dev/null +++ b/src/stc/scintilla/lexlib/Accessor.h @@ -0,0 +1,35 @@ +// Scintilla source code edit control +/** @file Accessor.h + ** Interfaces between Scintilla and lexers. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef ACCESSOR_H +#define ACCESSOR_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +enum { wsSpace = 1, wsTab = 2, wsSpaceTab = 4, wsInconsistent=8}; + +class Accessor; +class WordList; +class PropSetSimple; + +typedef bool (*PFNIsCommentLeader)(Accessor &styler, int pos, int len); + +class Accessor : public LexAccessor { +public: + PropSetSimple *pprops; + Accessor(IDocument *pAccess_, PropSetSimple *pprops_); + int GetPropertyInt(const char *, int defaultValue=0); + int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0); +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/lexlib/CharacterSet.cxx b/src/stc/scintilla/lexlib/CharacterSet.cxx new file mode 100644 index 0000000000..35669dff8a --- /dev/null +++ b/src/stc/scintilla/lexlib/CharacterSet.cxx @@ -0,0 +1,61 @@ +// Scintilla source code edit control +/** @file CharacterSet.cxx + ** Simple case functions for ASCII. + ** Lexer infrastructure. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <assert.h> + +#include "CharacterSet.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +int CompareCaseInsensitive(const char *a, const char *b) { + while (*a && *b) { + if (*a != *b) { + char upperA = MakeUpperCase(*a); + char upperB = MakeUpperCase(*b); + if (upperA != upperB) + return upperA - upperB; + } + a++; + b++; + } + // Either *a or *b is nul + return *a - *b; +} + +int CompareNCaseInsensitive(const char *a, const char *b, size_t len) { + while (*a && *b && len) { + if (*a != *b) { + char upperA = MakeUpperCase(*a); + char upperB = MakeUpperCase(*b); + if (upperA != upperB) + return upperA - upperB; + } + a++; + b++; + len--; + } + if (len == 0) + return 0; + else + // Either *a or *b is nul + return *a - *b; +} + +#ifdef SCI_NAMESPACE +} +#endif diff --git a/src/stc/scintilla/lexlib/CharacterSet.h b/src/stc/scintilla/lexlib/CharacterSet.h new file mode 100644 index 0000000000..a0c45b2fbc --- /dev/null +++ b/src/stc/scintilla/lexlib/CharacterSet.h @@ -0,0 +1,177 @@ +// Scintilla source code edit control +/** @file CharacterSet.h + ** Encapsulates a set of characters. Used to test if a character is within a set. + **/ +// Copyright 2007 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef CHARACTERSET_H +#define CHARACTERSET_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +class CharacterSet { + int size; + bool valueAfter; + bool *bset; +public: + enum setBase { + setNone=0, + setLower=1, + setUpper=2, + setDigits=4, + setAlpha=setLower|setUpper, + setAlphaNum=setAlpha|setDigits + }; + CharacterSet(setBase base=setNone, const char *initialSet="", int size_=0x80, bool valueAfter_=false) { + size = size_; + valueAfter = valueAfter_; + bset = new bool[size]; + for (int i=0; i < size; i++) { + bset[i] = false; + } + AddString(initialSet); + if (base & setLower) + AddString("abcdefghijklmnopqrstuvwxyz"); + if (base & setUpper) + AddString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); + if (base & setDigits) + AddString("0123456789"); + } + CharacterSet(const CharacterSet &other) { + size = other.size; + valueAfter = other.valueAfter; + bset = new bool[size]; + for (int i=0; i < size; i++) { + bset[i] = other.bset[i]; + } + } + ~CharacterSet() { + delete []bset; + bset = 0; + size = 0; + } + CharacterSet &operator=(const CharacterSet &other) { + if (this != &other) { + bool *bsetNew = new bool[other.size]; + for (int i=0; i < other.size; i++) { + bsetNew[i] = other.bset[i]; + } + delete []bset; + size = other.size; + valueAfter = other.valueAfter; + bset = bsetNew; + } + return *this; + } + void Add(int val) { + assert(val >= 0); + assert(val < size); + bset[val] = true; + } + void AddString(const char *setToAdd) { + for (const char *cp=setToAdd; *cp; cp++) { + int val = static_cast<unsigned char>(*cp); + assert(val >= 0); + assert(val < size); + bset[val] = true; + } + } + bool Contains(int val) const { + assert(val >= 0); + if (val < 0) return false; + return (val < size) ? bset[val] : valueAfter; + } +}; + +// Functions for classifying characters + +inline bool IsASpace(int ch) { + return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d)); +} + +inline bool IsASpaceOrTab(int ch) { + return (ch == ' ') || (ch == '\t'); +} + +inline bool IsADigit(int ch) { + return (ch >= '0') && (ch <= '9'); +} + +inline bool IsADigit(int ch, int base) { + if (base <= 10) { + return (ch >= '0') && (ch < '0' + base); + } else { + return ((ch >= '0') && (ch <= '9')) || + ((ch >= 'A') && (ch < 'A' + base - 10)) || + ((ch >= 'a') && (ch < 'a' + base - 10)); + } +} + +inline bool IsASCII(int ch) { + return (ch >= 0) && (ch < 0x80); +} + +inline bool IsLowerCase(int ch) { + return (ch >= 'a') && (ch <= 'z'); +} + +inline bool IsUpperCase(int ch) { + return (ch >= 'A') && (ch <= 'Z'); +} + +inline bool IsAlphaNumeric(int ch) { + return + ((ch >= '0') && (ch <= '9')) || + ((ch >= 'a') && (ch <= 'z')) || + ((ch >= 'A') && (ch <= 'Z')); +} + +/** + * Check if a character is a space. + * This is ASCII specific but is safe with chars >= 0x80. + */ +inline bool isspacechar(int ch) { + return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d)); +} + +inline bool iswordchar(int ch) { + return IsAlphaNumeric(ch) || ch == '.' || ch == '_'; +} + +inline bool iswordstart(int ch) { + return IsAlphaNumeric(ch) || ch == '_'; +} + +inline bool isoperator(int ch) { + if (IsAlphaNumeric(ch)) + return false; + if (ch == '%' || ch == '^' || ch == '&' || ch == '*' || + ch == '(' || ch == ')' || ch == '-' || ch == '+' || + ch == '=' || ch == '|' || ch == '{' || ch == '}' || + ch == '[' || ch == ']' || ch == ':' || ch == ';' || + ch == '<' || ch == '>' || ch == ',' || ch == '/' || + ch == '?' || ch == '!' || ch == '.' || ch == '~') + return true; + return false; +} + +// Simple case functions for ASCII. + +inline char MakeUpperCase(char ch) { + if (ch < 'a' || ch > 'z') + return ch; + else + return static_cast<char>(ch - 'a' + 'A'); +} + +int CompareCaseInsensitive(const char *a, const char *b); +int CompareNCaseInsensitive(const char *a, const char *b, size_t len); + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/lexlib/LexAccessor.h b/src/stc/scintilla/lexlib/LexAccessor.h new file mode 100644 index 0000000000..c38392e88c --- /dev/null +++ b/src/stc/scintilla/lexlib/LexAccessor.h @@ -0,0 +1,175 @@ +// Scintilla source code edit control +/** @file LexAccessor.h + ** Interfaces between Scintilla and lexers. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef LEXACCESSOR_H +#define LEXACCESSOR_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +class LexAccessor { +private: + IDocument *pAccess; + enum {extremePosition=0x7FFFFFFF}; + /** @a bufferSize is a trade off between time taken to copy the characters + * and retrieval overhead. + * @a slopSize positions the buffer before the desired position + * in case there is some backtracking. */ + enum {bufferSize=4000, slopSize=bufferSize/8}; + char buf[bufferSize+1]; + int startPos; + int endPos; + int codePage; + int lenDoc; + int mask; + char styleBuf[bufferSize]; + int validLen; + char chFlags; + char chWhile; + unsigned int startSeg; + int startPosStyling; + + void Fill(int position) { + startPos = position - slopSize; + if (startPos + bufferSize > lenDoc) + startPos = lenDoc - bufferSize; + if (startPos < 0) + startPos = 0; + endPos = startPos + bufferSize; + if (endPos > lenDoc) + endPos = lenDoc; + + pAccess->GetCharRange(buf, startPos, endPos-startPos); + buf[endPos-startPos] = '\0'; + } + +public: + LexAccessor(IDocument *pAccess_) : + pAccess(pAccess_), startPos(extremePosition), endPos(0), + codePage(pAccess->CodePage()), lenDoc(pAccess->Length()), + mask(127), validLen(0), chFlags(0), chWhile(0), + startSeg(0), startPosStyling(0) { + } + char operator[](int position) { + if (position < startPos || position >= endPos) { + Fill(position); + } + return buf[position - startPos]; + } + /** Safe version of operator[], returning a defined value for invalid position. */ + char SafeGetCharAt(int position, char chDefault=' ') { + if (position < startPos || position >= endPos) { + Fill(position); + if (position < startPos || position >= endPos) { + // Position is outside range of document + return chDefault; + } + } + return buf[position - startPos]; + } + bool IsLeadByte(char ch) { + return pAccess->IsDBCSLeadByte(ch); + } + + bool Match(int pos, const char *s) { + for (int i=0; *s; i++) { + if (*s != SafeGetCharAt(pos+i)) + return false; + s++; + } + return true; + } + char StyleAt(int position) { + return static_cast<char>(pAccess->StyleAt(position) & mask); + } + int GetLine(int position) { + return pAccess->LineFromPosition(position); + } + int LineStart(int line) { + return pAccess->LineStart(line); + } + int LevelAt(int line) { + return pAccess->GetLevel(line); + } + int Length() const { + return lenDoc; + } + void Flush() { + startPos = extremePosition; + if (validLen > 0) { + pAccess->SetStyles(validLen, styleBuf); + startPosStyling += validLen; + validLen = 0; + } + } + int GetLineState(int line) { + return pAccess->GetLineState(line); + } + int SetLineState(int line, int state) { + return pAccess->SetLineState(line, state); + } + // Style setting + void StartAt(unsigned int start, char chMask=31) { + // Store the mask specified for use with StyleAt. + mask = chMask; + pAccess->StartStyling(start, chMask); + startPosStyling = start; + } + void SetFlags(char chFlags_, char chWhile_) { + chFlags = chFlags_; + chWhile = chWhile_; + } + unsigned int GetStartSegment() const { + return startSeg; + } + void StartSegment(unsigned int pos) { + startSeg = pos; + } + void ColourTo(unsigned int pos, int chAttr) { + // Only perform styling if non empty range + if (pos != startSeg - 1) { + assert(pos >= startSeg); + if (pos < startSeg) { + return; + } + + if (validLen + (pos - startSeg + 1) >= bufferSize) + Flush(); + if (validLen + (pos - startSeg + 1) >= bufferSize) { + // Too big for buffer so send directly + pAccess->SetStyleFor(pos - startSeg + 1, static_cast<char>(chAttr)); + } else { + if (chAttr != chWhile) + chFlags = 0; + chAttr = static_cast<char>(chAttr | chFlags); + for (unsigned int i = startSeg; i <= pos; i++) { + assert((startPosStyling + validLen) < Length()); + styleBuf[validLen++] = static_cast<char>(chAttr); + } + } + } + startSeg = pos+1; + } + void SetLevel(int line, int level) { + pAccess->SetLevel(line, level); + } + void IndicatorFill(int start, int end, int indicator, int value) { + pAccess->DecorationSetCurrentIndicator(indicator); + pAccess->DecorationFillRange(start, value, end - start); + } + + void ChangeLexerState(int start, int end) { + pAccess->ChangeLexerState(start, end); + } +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/lexlib/LexerBase.cxx b/src/stc/scintilla/lexlib/LexerBase.cxx new file mode 100644 index 0000000000..ea5734d247 --- /dev/null +++ b/src/stc/scintilla/lexlib/LexerBase.cxx @@ -0,0 +1,92 @@ +// Scintilla source code edit control +/** @file LexerSimple.cxx + ** A simple lexer with no state. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "LexerModule.h" +#include "LexerBase.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +LexerBase::LexerBase() { + for (int wl = 0; wl < numWordLists; wl++) + keyWordLists[wl] = new WordList; + keyWordLists[numWordLists] = 0; +} + +LexerBase::~LexerBase() { + for (int wl = 0; wl < numWordLists; wl++) { + delete keyWordLists[wl]; + keyWordLists[wl] = 0; + } + keyWordLists[numWordLists] = 0; +} + +void SCI_METHOD LexerBase::Release() { + delete this; +} + +int SCI_METHOD LexerBase::Version() const { + return lvOriginal; +} + +const char * SCI_METHOD LexerBase::PropertyNames() { + return ""; +} + +int SCI_METHOD LexerBase::PropertyType(const char *) { + return SC_TYPE_BOOLEAN; +} + +const char * SCI_METHOD LexerBase::DescribeProperty(const char *) { + return ""; +} + +int SCI_METHOD LexerBase::PropertySet(const char *key, const char *val) { + const char *valOld = props.Get(key); + if (strcmp(val, valOld) != 0) { + props.Set(key, val); + return 0; + } else { + return -1; + } +} + +const char * SCI_METHOD LexerBase::DescribeWordListSets() { + return ""; +} + +int SCI_METHOD LexerBase::WordListSet(int n, const char *wl) { + if (n < numWordLists) { + WordList wlNew; + wlNew.Set(wl); + if (*keyWordLists[n] != wlNew) { + keyWordLists[n]->Set(wl); + return 0; + } + } + return -1; +} + +void * SCI_METHOD LexerBase::PrivateCall(int, void *) { + return 0; +} diff --git a/src/stc/scintilla/lexlib/LexerBase.h b/src/stc/scintilla/lexlib/LexerBase.h new file mode 100644 index 0000000000..2998d2449f --- /dev/null +++ b/src/stc/scintilla/lexlib/LexerBase.h @@ -0,0 +1,41 @@ +// Scintilla source code edit control +/** @file LexerBase.h + ** A simple lexer with no state. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef LEXERBASE_H +#define LEXERBASE_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +// A simple lexer with no state +class LexerBase : public ILexer { +protected: + PropSetSimple props; + enum {numWordLists=KEYWORDSET_MAX+1}; + WordList *keyWordLists[numWordLists+1]; +public: + LexerBase(); + virtual ~LexerBase(); + void SCI_METHOD Release(); + int SCI_METHOD Version() const; + const char * SCI_METHOD PropertyNames(); + int SCI_METHOD PropertyType(const char *name); + const char * SCI_METHOD DescribeProperty(const char *name); + int SCI_METHOD PropertySet(const char *key, const char *val); + const char * SCI_METHOD DescribeWordListSets(); + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; + void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) = 0; + void * SCI_METHOD PrivateCall(int operation, void *pointer); +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/lexlib/LexerModule.cxx b/src/stc/scintilla/lexlib/LexerModule.cxx new file mode 100644 index 0000000000..defc86356a --- /dev/null +++ b/src/stc/scintilla/lexlib/LexerModule.cxx @@ -0,0 +1,121 @@ +// Scintilla source code edit control +/** @file LexerModule.cxx + ** Colourise for particular languages. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include <string> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "LexerModule.h" +#include "LexerBase.h" +#include "LexerSimple.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +LexerModule::LexerModule(int language_, + LexerFunction fnLexer_, + const char *languageName_, + LexerFunction fnFolder_, + const char *const wordListDescriptions_[], + int styleBits_) : + language(language_), + fnLexer(fnLexer_), + fnFolder(fnFolder_), + fnFactory(0), + wordListDescriptions(wordListDescriptions_), + styleBits(styleBits_), + languageName(languageName_) { +} + +LexerModule::LexerModule(int language_, + LexerFactoryFunction fnFactory_, + const char *languageName_, + const char * const wordListDescriptions_[], + int styleBits_) : + language(language_), + fnLexer(0), + fnFolder(0), + fnFactory(fnFactory_), + wordListDescriptions(wordListDescriptions_), + styleBits(styleBits_), + languageName(languageName_) { +} + +int LexerModule::GetNumWordLists() const { + if (wordListDescriptions == NULL) { + return -1; + } else { + int numWordLists = 0; + + while (wordListDescriptions[numWordLists]) { + ++numWordLists; + } + + return numWordLists; + } +} + +const char *LexerModule::GetWordListDescription(int index) const { + static const char *emptyStr = ""; + + assert(index < GetNumWordLists()); + if (index >= GetNumWordLists()) { + return emptyStr; + } else { + return wordListDescriptions[index]; + } +} + +int LexerModule::GetStyleBitsNeeded() const { + return styleBits; +} + +ILexer *LexerModule::Create() const { + if (fnFactory) + return fnFactory(); + else + return new LexerSimple(this); +} + +void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle, + WordList *keywordlists[], Accessor &styler) const { + if (fnLexer) + fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler); +} + +void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle, + WordList *keywordlists[], Accessor &styler) const { + if (fnFolder) { + int lineCurrent = styler.GetLine(startPos); + // Move back one line in case deletion wrecked current line fold state + if (lineCurrent > 0) { + lineCurrent--; + int newStartPos = styler.LineStart(lineCurrent); + lengthDoc += startPos - newStartPos; + startPos = newStartPos; + initStyle = 0; + if (startPos > 0) { + initStyle = styler.StyleAt(startPos - 1); + } + } + fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler); + } +} diff --git a/src/stc/scintilla/lexlib/LexerModule.h b/src/stc/scintilla/lexlib/LexerModule.h new file mode 100644 index 0000000000..e502541b2d --- /dev/null +++ b/src/stc/scintilla/lexlib/LexerModule.h @@ -0,0 +1,82 @@ +// Scintilla source code edit control +/** @file LexerModule.h + ** Colourise for particular languages. + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef LEXERMODULE_H +#define LEXERMODULE_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +class Accessor; +class WordList; + +typedef void (*LexerFunction)(unsigned int startPos, int lengthDoc, int initStyle, + WordList *keywordlists[], Accessor &styler); +typedef ILexer *(*LexerFactoryFunction)(); + +/** + * A LexerModule is responsible for lexing and folding a particular language. + * The class maintains a list of LexerModules which can be searched to find a + * module appropriate to a particular language. + */ +class LexerModule { +protected: + int language; + LexerFunction fnLexer; + LexerFunction fnFolder; + LexerFactoryFunction fnFactory; + const char * const * wordListDescriptions; + int styleBits; + +public: + const char *languageName; + LexerModule(int language_, + LexerFunction fnLexer_, + const char *languageName_=0, + LexerFunction fnFolder_=0, + const char * const wordListDescriptions_[] = NULL, + int styleBits_=5); + LexerModule(int language_, + LexerFactoryFunction fnFactory_, + const char *languageName_, + const char * const wordListDescriptions_[] = NULL, + int styleBits_=8); + virtual ~LexerModule() { + } + int GetLanguage() const { return language; } + + // -1 is returned if no WordList information is available + int GetNumWordLists() const; + const char *GetWordListDescription(int index) const; + + int GetStyleBitsNeeded() const; + + ILexer *Create() const; + + virtual void Lex(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) const; + virtual void Fold(unsigned int startPos, int length, int initStyle, + WordList *keywordlists[], Accessor &styler) const; + + friend class Catalogue; +}; + +inline int Maximum(int a, int b) { + return (a > b) ? a : b; +} + +// Shut up annoying Visual C++ warnings: +#ifdef _MSC_VER +#pragma warning(disable: 4244 4309 4514 4710) +#endif + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/lexlib/LexerNoExceptions.cxx b/src/stc/scintilla/lexlib/LexerNoExceptions.cxx new file mode 100644 index 0000000000..9ebae2af09 --- /dev/null +++ b/src/stc/scintilla/lexlib/LexerNoExceptions.cxx @@ -0,0 +1,68 @@ +// Scintilla source code edit control +/** @file LexerNoExceptions.cxx + ** A simple lexer with no state which does not throw exceptions so can be used in an external lexer. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "LexerModule.h" +#include "LexerBase.h" +#include "LexerNoExceptions.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +int SCI_METHOD LexerNoExceptions::PropertySet(const char *key, const char *val) { + try { + return LexerBase::PropertySet(key, val); + } catch (...) { + // Should not throw into caller as may be compiled with different compiler or options + } + return -1; +} + +int SCI_METHOD LexerNoExceptions::WordListSet(int n, const char *wl) { + try { + return LexerBase::WordListSet(n, wl); + } catch (...) { + // Should not throw into caller as may be compiled with different compiler or options + } + return -1; +} + +void SCI_METHOD LexerNoExceptions::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + try { + Accessor astyler(pAccess, &props); + Lexer(startPos, length, initStyle, pAccess, astyler); + astyler.Flush(); + } catch (...) { + // Should not throw into caller as may be compiled with different compiler or options + pAccess->SetErrorStatus(SC_STATUS_FAILURE); + } +} +void SCI_METHOD LexerNoExceptions::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + try { + Accessor astyler(pAccess, &props); + Folder(startPos, length, initStyle, pAccess, astyler); + astyler.Flush(); + } catch (...) { + // Should not throw into caller as may be compiled with different compiler or options + pAccess->SetErrorStatus(SC_STATUS_FAILURE); + } +} diff --git a/src/stc/scintilla/lexlib/LexerNoExceptions.h b/src/stc/scintilla/lexlib/LexerNoExceptions.h new file mode 100644 index 0000000000..caac61a834 --- /dev/null +++ b/src/stc/scintilla/lexlib/LexerNoExceptions.h @@ -0,0 +1,32 @@ +// Scintilla source code edit control +/** @file LexerNoExceptions.h + ** A simple lexer with no state. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef LexerNoExceptions_H +#define LexerNoExceptions_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +// A simple lexer with no state +class LexerNoExceptions : public LexerBase { +public: + // TODO Also need to prevent exceptions in constructor and destructor + int SCI_METHOD PropertySet(const char *key, const char *val); + int SCI_METHOD WordListSet(int n, const char *wl); + void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *); + + virtual void Lexer(unsigned int startPos, int length, int initStyle, IDocument *pAccess, Accessor &styler) = 0; + virtual void Folder(unsigned int startPos, int length, int initStyle, IDocument *pAccess, Accessor &styler) = 0; +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/lexlib/LexerSimple.cxx b/src/stc/scintilla/lexlib/LexerSimple.cxx new file mode 100644 index 0000000000..4d0e178ca9 --- /dev/null +++ b/src/stc/scintilla/lexlib/LexerSimple.cxx @@ -0,0 +1,57 @@ +// Scintilla source code edit control +/** @file LexerSimple.cxx + ** A simple lexer with no state. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> + +#include <string> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "LexerModule.h" +#include "LexerBase.h" +#include "LexerSimple.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +LexerSimple::LexerSimple(const LexerModule *module_) : module(module_) { + for (int wl = 0; wl < module->GetNumWordLists(); wl++) { + if (!wordLists.empty()) + wordLists += "\n"; + wordLists += module->GetWordListDescription(wl); + } +} + +const char * SCI_METHOD LexerSimple::DescribeWordListSets() { + return wordLists.c_str(); +} + +void SCI_METHOD LexerSimple::Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) { + Accessor astyler(pAccess, &props); + module->Lex(startPos, lengthDoc, initStyle, keyWordLists, astyler); + astyler.Flush(); +} + +void SCI_METHOD LexerSimple::Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess) { + if (props.GetInt("fold")) { + Accessor astyler(pAccess, &props); + module->Fold(startPos, lengthDoc, initStyle, keyWordLists, astyler); + astyler.Flush(); + } +} diff --git a/src/stc/scintilla/lexlib/LexerSimple.h b/src/stc/scintilla/lexlib/LexerSimple.h new file mode 100644 index 0000000000..89631936f8 --- /dev/null +++ b/src/stc/scintilla/lexlib/LexerSimple.h @@ -0,0 +1,30 @@ +// Scintilla source code edit control +/** @file LexerSimple.h + ** A simple lexer with no state. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef LEXERSIMPLE_H +#define LEXERSIMPLE_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +// A simple lexer with no state +class LexerSimple : public LexerBase { + const LexerModule *module; + std::string wordLists; +public: + LexerSimple(const LexerModule *module_); + const char * SCI_METHOD DescribeWordListSets(); + void SCI_METHOD Lex(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); + void SCI_METHOD Fold(unsigned int startPos, int lengthDoc, int initStyle, IDocument *pAccess); +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/lexlib/OptionSet.h b/src/stc/scintilla/lexlib/OptionSet.h new file mode 100644 index 0000000000..873ac8b6c7 --- /dev/null +++ b/src/stc/scintilla/lexlib/OptionSet.h @@ -0,0 +1,142 @@ +// Scintilla source code edit control +/** @file OptionSet.h + ** Manage descriptive information about an options struct for a lexer. + ** Hold the names, positions, and descriptions of boolean, integer and string options and + ** allow setting options and retrieving metadata about the options. + **/ +// Copyright 2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef OPTIONSET_H +#define OPTIONSET_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +template <typename T> +class OptionSet { + typedef T Target; + typedef bool T::*plcob; + typedef int T::*plcoi; + typedef std::string T::*plcos; + struct Option { + int opType; + union { + plcob pb; + plcoi pi; + plcos ps; + }; + std::string description; + Option() : + opType(SC_TYPE_BOOLEAN), pb(0), description("") { + } + Option(plcob pb_, std::string description_="") : + opType(SC_TYPE_BOOLEAN), pb(pb_), description(description_) { + } + Option(plcoi pi_, std::string description_) : + opType(SC_TYPE_INTEGER), pi(pi_), description(description_) { + } + Option(plcos ps_, std::string description_) : + opType(SC_TYPE_STRING), ps(ps_), description(description_) { + } + bool Set(T *base, const char *val) { + switch (opType) { + case SC_TYPE_BOOLEAN: { + bool option = atoi(val) != 0; + if ((*base).*pb != option) { + (*base).*pb = option; + return true; + } + break; + } + case SC_TYPE_INTEGER: { + int option = atoi(val); + if ((*base).*pi != option) { + (*base).*pi = option; + return true; + } + break; + } + case SC_TYPE_STRING: { + if ((*base).*ps != val) { + (*base).*ps = val; + return true; + } + break; + } + } + return false; + } + }; + typedef std::map<std::string, Option> OptionMap; + OptionMap nameToDef; + std::string names; + std::string wordLists; + + void AppendName(const char *name) { + if (!names.empty()) + names += "\n"; + names += name; + } +public: + virtual ~OptionSet() { + } + void DefineProperty(const char *name, plcob pb, std::string description="") { + nameToDef[name] = Option(pb, description); + AppendName(name); + } + void DefineProperty(const char *name, plcoi pi, std::string description="") { + nameToDef[name] = Option(pi, description); + AppendName(name); + } + void DefineProperty(const char *name, plcos ps, std::string description="") { + nameToDef[name] = Option(ps, description); + AppendName(name); + } + const char *PropertyNames() { + return names.c_str(); + } + int PropertyType(const char *name) { + typename OptionMap::iterator it = nameToDef.find(name); + if (it != nameToDef.end()) { + return it->second.opType; + } + return SC_TYPE_BOOLEAN; + } + const char *DescribeProperty(const char *name) { + typename OptionMap::iterator it = nameToDef.find(name); + if (it != nameToDef.end()) { + return it->second.description.c_str(); + } + return ""; + } + + bool PropertySet(T *base, const char *name, const char *val) { + typename OptionMap::iterator it = nameToDef.find(name); + if (it != nameToDef.end()) { + return it->second.Set(base, val); + } + return false; + } + + void DefineWordListSets(const char * const wordListDescriptions[]) { + if (wordListDescriptions) { + for (size_t wl = 0; wordListDescriptions[wl]; wl++) { + if (!wordLists.empty()) + wordLists += "\n"; + wordLists += wordListDescriptions[wl]; + } + } + } + + const char *DescribeWordListSets() { + return wordLists.c_str(); + } +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/src/PropSet.cxx b/src/stc/scintilla/lexlib/PropSetSimple.cxx similarity index 83% rename from src/stc/scintilla/src/PropSet.cxx rename to src/stc/scintilla/lexlib/PropSetSimple.cxx index 9936c39d12..c0ec59459e 100644 --- a/src/stc/scintilla/src/PropSet.cxx +++ b/src/stc/scintilla/lexlib/PropSetSimple.cxx @@ -1,8 +1,8 @@ // SciTE - Scintilla based Text Editor -/** @file PropSet.cxx +/** @file PropSetSimple.cxx ** A Java style properties file module. **/ -// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. // Maintain a dictionary of properties @@ -12,16 +12,13 @@ #include <stdio.h> #ifdef _MSC_VER -// Visual C++ doesn't like unreachable code or long decorated names in its own headers. -#pragma warning(disable: 4018 4100 4245 4511 4512 4663 4702 4786) +// Visual C++ doesn't like unreachable code in its own headers. +#pragma warning(disable: 4018 4100 4245 4511 4512 4663 4702) #endif #include <string> #include <map> -#include "Platform.h" - -#include "PropSet.h" #include "PropSetSimple.h" #ifdef SCI_NAMESPACE @@ -64,9 +61,10 @@ void PropSetSimple::Set(const char *keyVal) { endVal++; const char *eqAt = strchr(keyVal, '='); if (eqAt) { - Set(keyVal, eqAt + 1, eqAt-keyVal, endVal - eqAt - 1); + Set(keyVal, eqAt + 1, static_cast<int>(eqAt-keyVal), + static_cast<int>(endVal - eqAt - 1)); } else if (*keyVal) { // No '=' so assume '=1' - Set(keyVal, "1", endVal-keyVal, 1); + Set(keyVal, "1", static_cast<int>(endVal-keyVal), 1); } } @@ -96,7 +94,7 @@ const char *PropSetSimple::Get(const char *key) const { // for that, through a recursive function and a simple chain of pointers. struct VarChain { - VarChain(const char*var_=NULL, const VarChain *link_=NULL): var(var_), link(link_) {} + VarChain(const char *var_=NULL, const VarChain *link_=NULL): var(var_), link(link_) {} bool contains(const char *testVar) const { return (var && (0 == strcmp(var, testVar))) @@ -151,18 +149,14 @@ char *PropSetSimple::Expanded(const char *key) const { return ret; } -char *PropSetSimple::ToString() const { - mapss *props = static_cast<mapss *>(impl); - std::string sval; - for (mapss::const_iterator it=props->begin(); it != props->end(); it++) { - sval += it->first; - sval += "="; - sval += it->second; - sval += "\n"; +int PropSetSimple::GetExpanded(const char *key, char *result) const { + char *val = Expanded(key); + const int n = static_cast<int>(strlen(val)); + if (result) { + strcpy(result, val); } - char *ret = new char [sval.size() + 1]; - strcpy(ret, sval.c_str()); - return ret; + delete []val; + return n; // Not including NUL } int PropSetSimple::GetInt(const char *key, int defaultValue) const { diff --git a/src/stc/scintilla/src/PropSetSimple.h b/src/stc/scintilla/lexlib/PropSetSimple.h similarity index 90% rename from src/stc/scintilla/src/PropSetSimple.h rename to src/stc/scintilla/lexlib/PropSetSimple.h index 1674cfb9e6..b798737207 100644 --- a/src/stc/scintilla/src/PropSetSimple.h +++ b/src/stc/scintilla/lexlib/PropSetSimple.h @@ -12,7 +12,7 @@ namespace Scintilla { #endif -class PropSetSimple : public PropertyGet { +class PropSetSimple { void *impl; void Set(const char *keyVal); public: @@ -22,7 +22,7 @@ public: void SetMultiple(const char *); const char *Get(const char *key) const; char *Expanded(const char *key) const; - char *ToString() const; + int GetExpanded(const char *key, char *result) const; int GetInt(const char *key, int defaultValue=0) const; }; diff --git a/src/stc/scintilla/lexlib/SparseState.h b/src/stc/scintilla/lexlib/SparseState.h new file mode 100644 index 0000000000..08ff104d32 --- /dev/null +++ b/src/stc/scintilla/lexlib/SparseState.h @@ -0,0 +1,110 @@ +// Scintilla source code edit control +/** @file SparseState.h + ** Hold lexer state that may change rarely. + ** This is often per-line state such as whether a particular type of section has been entered. + ** A state continues until it is changed. + **/ +// Copyright 2011 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef SPARSESTATE_H +#define SPARSESTATE_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +template <typename T> +class SparseState { + struct State { + int position; + T value; + State(int position_, T value_) : position(position_), value(value_) { + } + inline bool operator<(const State &other) const { + return position < other.position; + } + inline bool operator==(const State &other) const { + return (position == other.position) && (value == other.value); + } + }; + int positionFirst; + typedef std::vector<State> stateVector; + stateVector states; + + typename stateVector::iterator Find(int position) { + State searchValue(position, T()); + return std::lower_bound(states.begin(), states.end(), searchValue); + } + +public: + SparseState(int positionFirst_=-1) { + positionFirst = positionFirst_; + } + void Set(int position, T value) { + Delete(position); + if (states.empty() || (value != states[states.size()-1].value)) { + states.push_back(State(position, value)); + } + } + T ValueAt(int position) { + if (states.empty()) + return T(); + if (position < states[0].position) + return T(); + typename stateVector::iterator low = Find(position); + if (low == states.end()) { + return states[states.size()-1].value; + } else { + if (low->position > position) { + --low; + } + return low->value; + } + } + bool Delete(int position) { + typename stateVector::iterator low = Find(position); + if (low != states.end()) { + states.erase(low, states.end()); + return true; + } + return false; + } + size_t size() const { + return states.size(); + } + + // Returns true if Merge caused a significant change + bool Merge(const SparseState<T> &other, int ignoreAfter) { + // Changes caused beyond ignoreAfter are not significant + Delete(ignoreAfter+1); + + bool different = true; + bool changed = false; + typename stateVector::iterator low = Find(other.positionFirst); + if (static_cast<size_t>(states.end() - low) == other.states.size()) { + // Same number in other as after positionFirst in this + different = !std::equal(low, states.end(), other.states.begin()); + } + if (different) { + if (low != states.end()) { + states.erase(low, states.end()); + changed = true; + } + typename stateVector::const_iterator startOther = other.states.begin(); + if (!states.empty() && !other.states.empty() && states.back().value == startOther->value) + ++startOther; + if (startOther != other.states.end()) { + states.insert(states.end(), startOther, other.states.end()); + changed = true; + } + } + return changed; + } +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/src/StyleContext.cxx b/src/stc/scintilla/lexlib/StyleContext.cxx similarity index 91% rename from src/stc/scintilla/src/StyleContext.cxx rename to src/stc/scintilla/lexlib/StyleContext.cxx index 4a1f71622f..cf59fdd24e 100644 --- a/src/stc/scintilla/src/StyleContext.cxx +++ b/src/stc/scintilla/lexlib/StyleContext.cxx @@ -9,10 +9,11 @@ #include <string.h> #include <ctype.h> #include <stdio.h> +#include <assert.h> -#include "Platform.h" +#include "ILexer.h" -#include "PropSet.h" +#include "LexAccessor.h" #include "Accessor.h" #include "StyleContext.h" @@ -22,7 +23,7 @@ using namespace Scintilla; static void getRange(unsigned int start, unsigned int end, - Accessor &styler, + LexAccessor &styler, char *s, unsigned int len) { unsigned int i = 0; @@ -39,7 +40,7 @@ void StyleContext::GetCurrent(char *s, unsigned int len) { static void getRangeLowered(unsigned int start, unsigned int end, - Accessor &styler, + LexAccessor &styler, char *s, unsigned int len) { unsigned int i = 0; diff --git a/src/stc/scintilla/src/StyleContext.h b/src/stc/scintilla/lexlib/StyleContext.h similarity index 78% rename from src/stc/scintilla/src/StyleContext.h rename to src/stc/scintilla/lexlib/StyleContext.h index 9342ebd68e..c2d223e3fb 100644 --- a/src/stc/scintilla/src/StyleContext.h +++ b/src/stc/scintilla/lexlib/StyleContext.h @@ -5,18 +5,28 @@ // Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org> // This file is in the public domain. +#ifndef STYLECONTEXT_H +#define STYLECONTEXT_H + #ifdef SCI_NAMESPACE namespace Scintilla { #endif +static inline int MakeLowerCase(int ch) { + if (ch < 'A' || ch > 'Z') + return ch; + else + return ch - 'A' + 'a'; +} + // All languages handled so far can treat all characters >= 0x80 as one class // which just continues the current token or starts an identifier if in default. // DBCS treated specially as the second character can be < 0x80 and hence // syntactically significant. UTF-8 avoids this as all trail bytes are >= 0x80 class StyleContext { - Accessor &styler; + LexAccessor &styler; unsigned int endPos; - StyleContext& operator=(const StyleContext&); + StyleContext &operator=(const StyleContext &); void GetNextChar(unsigned int pos) { chNext = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1)); if (styler.IsLeadByte(static_cast<char>(chNext))) { @@ -41,11 +51,10 @@ public: int chNext; StyleContext(unsigned int startPos, unsigned int length, - int initStyle, Accessor &styler_, char chMask=31) : + int initStyle, LexAccessor &styler_, char chMask=31) : styler(styler_), endPos(startPos + length), currentPos(startPos), - atLineStart(true), atLineEnd(false), state(initStyle & chMask), // Mask off all bits which aren't in the chMask. chPrev(0), @@ -53,6 +62,7 @@ public: chNext(0) { styler.StartAt(startPos, chMask); styler.StartSegment(startPos); + atLineStart = static_cast<unsigned int>(styler.LineStart(styler.GetLine(startPos))) == startPos; unsigned int pos = currentPos; ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos)); if (styler.IsLeadByte(static_cast<char>(ch))) { @@ -64,8 +74,9 @@ public: } void Complete() { styler.ColourTo(currentPos - 1, state); + styler.Flush(); } - bool More() { + bool More() const { return currentPos < endPos; } void Forward() { @@ -108,10 +119,10 @@ public: int GetRelative(int n) { return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n)); } - bool Match(char ch0) { + bool Match(char ch0) const { return ch == static_cast<unsigned char>(ch0); } - bool Match(char ch0, char ch1) { + bool Match(char ch0, char ch1) const { return (ch == static_cast<unsigned char>(ch0)) && (chNext == static_cast<unsigned char>(ch1)); } bool Match(const char *s) { @@ -131,15 +142,15 @@ public: return true; } bool MatchIgnoreCase(const char *s) { - if (tolower(ch) != static_cast<unsigned char>(*s)) + if (MakeLowerCase(ch) != static_cast<unsigned char>(*s)) return false; s++; - if (tolower(chNext) != static_cast<unsigned char>(*s)) + if (MakeLowerCase(chNext) != static_cast<unsigned char>(*s)) return false; s++; for (int n=2; *s; n++) { if (static_cast<unsigned char>(*s) != - tolower(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n)))) + MakeLowerCase(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n)))) return false; s++; } @@ -154,24 +165,4 @@ public: } #endif -inline bool IsASpace(unsigned int ch) { - return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d)); -} - -inline bool IsASpaceOrTab(unsigned int ch) { - return (ch == ' ') || (ch == '\t'); -} - -inline bool IsADigit(unsigned int ch) { - return (ch >= '0') && (ch <= '9'); -} - -inline bool IsADigit(unsigned int ch, unsigned int base) { - if (base <= 10) { - return (ch >= '0') && (ch < '0' + base); - } else { - return ((ch >= '0') && (ch <= '9')) || - ((ch >= 'A') && (ch < 'A' + base - 10)) || - ((ch >= 'a') && (ch < 'a' + base - 10)); - } -} +#endif diff --git a/src/stc/scintilla/lexlib/WordList.cxx b/src/stc/scintilla/lexlib/WordList.cxx new file mode 100644 index 0000000000..9c2c9653ba --- /dev/null +++ b/src/stc/scintilla/lexlib/WordList.cxx @@ -0,0 +1,219 @@ +// Scintilla source code edit control +/** @file KeyWords.cxx + ** Colourise for particular languages. + **/ +// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> + +#include <algorithm> + +#include "WordList.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +/** + * Creates an array that points into each word in the string and puts \0 terminators + * after each word. + */ +static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = false) { + int prev = '\n'; + int words = 0; + // For rapid determination of whether a character is a separator, build + // a look up table. + bool wordSeparator[256]; + for (int i=0; i<256; i++) { + wordSeparator[i] = false; + } + wordSeparator['\r'] = true; + wordSeparator['\n'] = true; + if (!onlyLineEnds) { + wordSeparator[' '] = true; + wordSeparator['\t'] = true; + } + for (int j = 0; wordlist[j]; j++) { + int curr = static_cast<unsigned char>(wordlist[j]); + if (!wordSeparator[curr] && wordSeparator[prev]) + words++; + prev = curr; + } + char **keywords = new char *[words + 1]; + if (keywords) { + words = 0; + prev = '\0'; + size_t slen = strlen(wordlist); + for (size_t k = 0; k < slen; k++) { + if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) { + if (!prev) { + keywords[words] = &wordlist[k]; + words++; + } + } else { + wordlist[k] = '\0'; + } + prev = wordlist[k]; + } + keywords[words] = &wordlist[slen]; + *len = words; + } else { + *len = 0; + } + return keywords; +} + +bool WordList::operator!=(const WordList &other) const { + if (len != other.len) + return true; + for (int i=0; i<len; i++) { + if (strcmp(words[i], other.words[i]) != 0) + return true; + } + return false; +} + +void WordList::Clear() { + if (words) { + delete []list; + delete []words; + } + words = 0; + list = 0; + len = 0; +} + +#ifdef _MSC_VER + +static bool cmpWords(const char *a, const char *b) { + return strcmp(a, b) == -1; +} + +#else + +static int cmpWords(const void *a, const void *b) { + return strcmp(*static_cast<const char * const *>(a), *static_cast<const char * const *>(b)); +} + +static void SortWordList(char **words, unsigned int len) { + qsort(reinterpret_cast<void *>(words), len, sizeof(*words), cmpWords); +} + +#endif + +void WordList::Set(const char *s) { + Clear(); + list = new char[strlen(s) + 1]; + strcpy(list, s); + words = ArrayFromWordList(list, &len, onlyLineEnds); +#ifdef _MSC_VER + std::sort(words, words + len, cmpWords); +#else + SortWordList(words, len); +#endif + for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++) + starts[k] = -1; + for (int l = len - 1; l >= 0; l--) { + unsigned char indexChar = words[l][0]; + starts[indexChar] = l; + } +} + +/** Check whether a string is in the list. + * List elements are either exact matches or prefixes. + * Prefix elements start with '^' and match all strings that start with the rest of the element + * so '^GTK_' matches 'GTK_X', 'GTK_MAJOR_VERSION', and 'GTK_'. + */ +bool WordList::InList(const char *s) const { + if (0 == words) + return false; + unsigned char firstChar = s[0]; + int j = starts[firstChar]; + if (j >= 0) { + while (static_cast<unsigned char>(words[j][0]) == firstChar) { + if (s[1] == words[j][1]) { + const char *a = words[j] + 1; + const char *b = s + 1; + while (*a && *a == *b) { + a++; + b++; + } + if (!*a && !*b) + return true; + } + j++; + } + } + j = starts['^']; + if (j >= 0) { + while (words[j][0] == '^') { + const char *a = words[j] + 1; + const char *b = s; + while (*a && *a == *b) { + a++; + b++; + } + if (!*a) + return true; + j++; + } + } + return false; +} + +/** similar to InList, but word s can be a substring of keyword. + * eg. the keyword define is defined as def~ine. This means the word must start + * with def to be a keyword, but also defi, defin and define are valid. + * The marker is ~ in this case. + */ +bool WordList::InListAbbreviated(const char *s, const char marker) const { + if (0 == words) + return false; + unsigned char firstChar = s[0]; + int j = starts[firstChar]; + if (j >= 0) { + while (static_cast<unsigned char>(words[j][0]) == firstChar) { + bool isSubword = false; + int start = 1; + if (words[j][1] == marker) { + isSubword = true; + start++; + } + if (s[1] == words[j][start]) { + const char *a = words[j] + start; + const char *b = s + 1; + while (*a && *a == *b) { + a++; + if (*a == marker) { + isSubword = true; + a++; + } + b++; + } + if ((!*a || isSubword) && !*b) + return true; + } + j++; + } + } + j = starts['^']; + if (j >= 0) { + while (words[j][0] == '^') { + const char *a = words[j] + 1; + const char *b = s; + while (*a && *a == *b) { + a++; + b++; + } + if (!*a) + return true; + j++; + } + } + return false; +} diff --git a/src/stc/scintilla/lexlib/WordList.h b/src/stc/scintilla/lexlib/WordList.h new file mode 100644 index 0000000000..ea5be1d550 --- /dev/null +++ b/src/stc/scintilla/lexlib/WordList.h @@ -0,0 +1,41 @@ +// Scintilla source code edit control +/** @file WordList.h + ** Hold a list of words. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef WORDLIST_H +#define WORDLIST_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +/** + */ +class WordList { +public: + // Each word contains at least one character - a empty word acts as sentinel at the end. + char **words; + char *list; + int len; + bool onlyLineEnds; ///< Delimited by any white space or only line ends + int starts[256]; + WordList(bool onlyLineEnds_ = false) : + words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) + {} + ~WordList() { Clear(); } + operator bool() const { return len ? true : false; } + bool operator!=(const WordList &other) const; + void Clear(); + void Set(const char *s); + bool InList(const char *s) const; + bool InListAbbreviated(const char *s, const char marker) const; +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/src/AutoComplete.cxx b/src/stc/scintilla/src/AutoComplete.cxx index 86c64df563..82773f4dbe 100644 --- a/src/stc/scintilla/src/AutoComplete.cxx +++ b/src/stc/scintilla/src/AutoComplete.cxx @@ -8,11 +8,15 @@ #include <stdlib.h> #include <string.h> #include <stdio.h> +#include <assert.h> + +#include <string> #include "Platform.h" -#include "CharClassify.h" +#include "CharacterSet.h" #include "AutoComplete.h" +#include "Scintilla.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -29,7 +33,8 @@ AutoComplete::AutoComplete() : startLen(0), cancelAtStartPos(true), autoHide(true), - dropRestOfWord(false) { + dropRestOfWord(false), + ignoreCaseBehaviour(SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE) { lb = ListBox::Allocate(); stopChars[0] = '\0'; fillUpChars[0] = '\0'; @@ -43,17 +48,17 @@ AutoComplete::~AutoComplete() { } } -bool AutoComplete::Active() { +bool AutoComplete::Active() const { return active; } -void AutoComplete::Start(Window &parent, int ctrlID, - int position, Point location, int startLen_, - int lineHeight, bool unicodeMode) { +void AutoComplete::Start(Window &parent, int ctrlID, + int position, Point location, int startLen_, + int lineHeight, bool unicodeMode, int technology) { if (active) { Cancel(); } - lb->Create(parent, ctrlID, location, lineHeight, unicodeMode); + lb->Create(parent, ctrlID, location, lineHeight, unicodeMode, technology); lb->Clear(); active = true; startLen = startLen_; @@ -82,7 +87,7 @@ void AutoComplete::SetSeparator(char separator_) { separator = separator_; } -char AutoComplete::GetSeparator() { +char AutoComplete::GetSeparator() const { return separator; } @@ -90,7 +95,7 @@ void AutoComplete::SetTypesep(char separator_) { typesep = separator_; } -char AutoComplete::GetTypesep() { +char AutoComplete::GetTypesep() const { return typesep; } @@ -98,6 +103,16 @@ void AutoComplete::SetList(const char *list) { lb->SetList(list, separator, typesep); } +int AutoComplete::GetSelection() const { + return lb->GetSelection(); +} + +std::string AutoComplete::GetValue(int item) const { + char value[maxItemLen]; + lb->GetValue(item, value, sizeof(value)); + return std::string(value); +} + void AutoComplete::Show(bool show) { lb->Show(show); if (show) @@ -127,12 +142,11 @@ void AutoComplete::Move(int delta) { void AutoComplete::Select(const char *word) { size_t lenWord = strlen(word); int location = -1; - const int maxItemLen=1000; - char item[maxItemLen]; int start = 0; // lower bound of the api array block to search int end = lb->Length() - 1; // upper bound of the api array block to search while ((start <= end) && (location == -1)) { // Binary searching loop int pivot = (start + end) / 2; + char item[maxItemLen]; lb->GetValue(pivot, item, maxItemLen); int cond; if (ignoreCase) @@ -152,7 +166,8 @@ void AutoComplete::Select(const char *word) { --pivot; } location = pivot; - if (ignoreCase) { + if (ignoreCase + && ignoreCaseBehaviour == SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE) { // Check for exact-case match for (; pivot <= end; pivot++) { lb->GetValue(pivot, item, maxItemLen); diff --git a/src/stc/scintilla/src/AutoComplete.h b/src/stc/scintilla/src/AutoComplete.h index b10cdce82f..91e084857b 100644 --- a/src/stc/scintilla/src/AutoComplete.h +++ b/src/stc/scintilla/src/AutoComplete.h @@ -20,8 +20,10 @@ class AutoComplete { char fillUpChars[256]; char separator; char typesep; // Type seperator + enum { maxItemLen=1000 }; public: + bool ignoreCase; bool chooseSingle; ListBox *lb; @@ -31,16 +33,17 @@ public: bool cancelAtStartPos; bool autoHide; bool dropRestOfWord; + unsigned int ignoreCaseBehaviour; AutoComplete(); ~AutoComplete(); /// Is the auto completion list displayed? - bool Active(); + bool Active() const; /// Display the auto completion list positioned to be near a character position void Start(Window &parent, int ctrlID, int position, Point location, - int startLen_, int lineHeight, bool unicodeMode); + int startLen_, int lineHeight, bool unicodeMode, int technology); /// The stop chars are characters which, when typed, cause the auto completion list to disappear void SetStopChars(const char *stopChars_); @@ -52,14 +55,20 @@ public: /// The separator character is used when interpreting the list in SetList void SetSeparator(char separator_); - char GetSeparator(); + char GetSeparator() const; /// The typesep character is used for seperating the word from the type void SetTypesep(char separator_); - char GetTypesep(); + char GetTypesep() const; /// The list string contains a sequence of words separated by the separator character void SetList(const char *list); + + /// Return the position of the currently selected list item + int GetSelection() const; + + /// Return the value of an item in the list + std::string GetValue(int item) const; void Show(bool show); void Cancel(); diff --git a/src/stc/scintilla/src/CallTip.cxx b/src/stc/scintilla/src/CallTip.cxx index 3ea2d48fd3..d93d804119 100644 --- a/src/stc/scintilla/src/CallTip.cxx +++ b/src/stc/scintilla/src/CallTip.cxx @@ -29,22 +29,26 @@ CallTip::CallTip() { rectUp = PRectangle(0,0,0,0); rectDown = PRectangle(0,0,0,0); lineHeight = 1; + offsetMain = 0; startHighlight = 0; endHighlight = 0; tabSize = 0; + above = false; useStyleCallTip = false; // for backwards compatibility #ifdef __APPLE__ // proper apple colours for the default - colourBG.desired = ColourDesired(0xff, 0xff, 0xc6); - colourUnSel.desired = ColourDesired(0, 0, 0); + colourBG = ColourDesired(0xff, 0xff, 0xc6); + colourUnSel = ColourDesired(0, 0, 0); #else - colourBG.desired = ColourDesired(0xff, 0xff, 0xff); - colourUnSel.desired = ColourDesired(0x80, 0x80, 0x80); + colourBG = ColourDesired(0xff, 0xff, 0xff); + colourUnSel = ColourDesired(0x80, 0x80, 0x80); #endif - colourSel.desired = ColourDesired(0, 0, 0x80); - colourShade.desired = ColourDesired(0, 0, 0); - colourLight.desired = ColourDesired(0xc0, 0xc0, 0xc0); + colourSel = ColourDesired(0, 0, 0x80); + colourShade = ColourDesired(0, 0, 0); + colourLight = ColourDesired(0xc0, 0xc0, 0xc0); + codePage = 0; + clickPlace = 0; } CallTip::~CallTip() { @@ -54,21 +58,13 @@ CallTip::~CallTip() { val = 0; } -void CallTip::RefreshColourPalette(Palette &pal, bool want) { - pal.WantFind(colourBG, want); - pal.WantFind(colourUnSel, want); - pal.WantFind(colourSel, want); - pal.WantFind(colourShade, want); - pal.WantFind(colourLight, want); -} - // Although this test includes 0, we should never see a \0 character. static bool IsArrowCharacter(char ch) { return (ch == 0) || (ch == '\001') || (ch == '\002'); } // We ignore tabs unless a tab width has been set. -bool CallTip::IsTabCharacter(char ch) { +bool CallTip::IsTabCharacter(char ch) const { return (tabSize > 0) && (ch == '\t'); } @@ -95,9 +91,9 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s, int maxEnd = 0; const int numEnds = 10; int ends[numEnds + 2]; - for (int i=0;i<len;i++) { + for (int i=0; i<len; i++) { if ((maxEnd < numEnds) && - (IsArrowCharacter(s[i]) || IsTabCharacter(s[i])) ) { + (IsArrowCharacter(s[i]) || IsTabCharacter(s[i]))) { if (i > 0) ends[maxEnd++] = i; ends[maxEnd++] = i+1; @@ -117,10 +113,10 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s, const int halfWidth = widthArrow / 2 - 3; const int centreX = rcClient.left + widthArrow / 2 - 1; const int centreY = (rcClient.top + rcClient.bottom) / 2; - surface->FillRectangle(rcClient, colourBG.allocated); + surface->FillRectangle(rcClient, colourBG); PRectangle rcClientInner(rcClient.left + 1, rcClient.top + 1, rcClient.right - 2, rcClient.bottom - 1); - surface->FillRectangle(rcClientInner, colourUnSel.allocated); + surface->FillRectangle(rcClientInner, colourUnSel); if (upArrow) { // Up arrow Point pts[] = { @@ -129,7 +125,7 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s, Point(centreX, centreY - halfWidth + halfWidth / 2), }; surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), - colourBG.allocated, colourBG.allocated); + colourBG, colourBG); } else { // Down arrow Point pts[] = { Point(centreX - halfWidth, centreY - halfWidth / 2), @@ -137,7 +133,7 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s, Point(centreX, centreY + halfWidth - halfWidth / 2), }; surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), - colourBG.allocated, colourBG.allocated); + colourBG, colourBG); } } xEnd = rcClient.right; @@ -156,7 +152,7 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s, rcClient.right = xEnd; surface->DrawTextTransparent(rcClient, font, ytext, s+startSeg, endSeg - startSeg, - highlight ? colourSel.allocated : colourUnSel.allocated); + highlight ? colourSel : colourUnSel); } } x = xEnd; @@ -224,7 +220,7 @@ void CallTip::PaintCT(Surface *surfaceWindow) { rcClientPos.bottom - rcClientPos.top); PRectangle rcClient(1, 1, rcClientSize.right - 1, rcClientSize.bottom - 1); - surfaceWindow->FillRectangle(rcClient, colourBG.allocated); + surfaceWindow->FillRectangle(rcClient, colourBG); offsetMain = insetX; // initial alignment assuming no arrows PaintContents(surfaceWindow, true); @@ -233,10 +229,10 @@ void CallTip::PaintCT(Surface *surfaceWindow) { // OSX doesn't put borders on "help tags" // Draw a raised border around the edges of the window surfaceWindow->MoveTo(0, rcClientSize.bottom - 1); - surfaceWindow->PenColour(colourShade.allocated); + surfaceWindow->PenColour(colourShade); surfaceWindow->LineTo(rcClientSize.right - 1, rcClientSize.bottom - 1); surfaceWindow->LineTo(rcClientSize.right - 1, 0); - surfaceWindow->PenColour(colourLight.allocated); + surfaceWindow->PenColour(colourLight); surfaceWindow->LineTo(0, 0); surfaceWindow->LineTo(0, rcClientSize.bottom - 1); #endif @@ -250,16 +246,17 @@ void CallTip::MouseClick(Point pt) { clickPlace = 2; } -PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn, +PRectangle CallTip::CallTipStart(int pos, Point pt, int textHeight, const char *defn, const char *faceName, int size, - int codePage_, int characterSet, Window &wParent) { + int codePage_, int characterSet, + int technology, Window &wParent) { clickPlace = 0; delete []val; val = 0; val = new char[strlen(defn) + 1]; strcpy(val, defn); codePage = codePage_; - Surface *surfaceMeasure = Surface::Allocate(); + Surface *surfaceMeasure = Surface::Allocate(technology); if (!surfaceMeasure) return PRectangle(); surfaceMeasure->Init(wParent.GetID()); @@ -270,7 +267,8 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn, inCallTipMode = true; posStartCallTip = pos; int deviceHeight = surfaceMeasure->DeviceHeightFont(size); - font.Create(faceName, characterSet, deviceHeight, false, false); + FontParameters fp(faceName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, SC_WEIGHT_NORMAL, false, 0, technology, characterSet); + font.Create(fp); // Look for multiple lines in the text // Only support \n here - simply means container must avoid \r! int numLines = 1; @@ -291,7 +289,11 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn, // the tip text, else to the tip text left edge. int height = lineHeight * numLines - surfaceMeasure->InternalLeading(font) + 2 + 2; delete surfaceMeasure; - return PRectangle(pt.x - offsetMain, pt.y + 1, pt.x + width - offsetMain, pt.y + 1 + height); + if (above) { + return PRectangle(pt.x - offsetMain, pt.y - 1 - height, pt.x + width - offsetMain, pt.y - 1); + } else { + return PRectangle(pt.x - offsetMain, pt.y + 1 + textHeight, pt.x + width - offsetMain, pt.y + 1 + textHeight + height); + } } void CallTip::CallTipCancel() { @@ -319,9 +321,15 @@ void CallTip::SetTabSize(int tabSz) { useStyleCallTip = true; } +// Set the calltip position, below the text by default or if above is false +// else above the text. +void CallTip::SetPosition(bool aboveText) { + above = aboveText; +} + // It might be better to have two access functions for this and to use // them for all settings of colours. -void CallTip::SetForeBack(const ColourPair &fore, const ColourPair &back) { +void CallTip::SetForeBack(const ColourDesired &fore, const ColourDesired &back) { colourBG = back; colourUnSel = fore; } diff --git a/src/stc/scintilla/src/CallTip.h b/src/stc/scintilla/src/CallTip.h index a64755fd18..657e0caa1c 100644 --- a/src/stc/scintilla/src/CallTip.h +++ b/src/stc/scintilla/src/CallTip.h @@ -25,6 +25,7 @@ class CallTip { int offsetMain; // The alignment point of the call tip int tabSize; // Tab size in pixels, <=0 no TAB expand bool useStyleCallTip; // if true, STYLE_CALLTIP should be used + bool above; // if true, display calltip above text // Private so CallTip objects can not be copied CallTip(const CallTip &); @@ -33,7 +34,7 @@ class CallTip { int posStart, int posEnd, int ytext, PRectangle rcClient, bool highlight, bool draw); int PaintContents(Surface *surfaceWindow, bool draw); - bool IsTabCharacter(char c); + bool IsTabCharacter(char c) const; int NextTabPos(int x); public: @@ -41,28 +42,25 @@ public: Window wDraw; bool inCallTipMode; int posStartCallTip; - ColourPair colourBG; - ColourPair colourUnSel; - ColourPair colourSel; - ColourPair colourShade; - ColourPair colourLight; + ColourDesired colourBG; + ColourDesired colourUnSel; + ColourDesired colourSel; + ColourDesired colourShade; + ColourDesired colourLight; int codePage; int clickPlace; CallTip(); ~CallTip(); - /// Claim or accept palette entries for the colours required to paint a calltip. - void RefreshColourPalette(Palette &pal, bool want); - void PaintCT(Surface *surfaceWindow); void MouseClick(Point pt); /// Setup the calltip and return a rectangle of the area required. - PRectangle CallTipStart(int pos, Point pt, const char *defn, - const char *faceName, int size, int codePage_, - int characterSet, Window &wParent); + PRectangle CallTipStart(int pos, Point pt, int textHeight, const char *defn, + const char *faceName, int size, int codePage_, + int characterSet, int technology, Window &wParent); void CallTipCancel(); @@ -73,11 +71,14 @@ public: /// Set the tab size in pixels for the call tip. 0 or -ve means no tab expand. void SetTabSize(int tabSz); + /// Set calltip position. + void SetPosition(bool aboveText); + /// Used to determine which STYLE_xxxx to use for call tip information bool UseStyleCallTip() const { return useStyleCallTip;} // Modify foreground and background colours - void SetForeBack(const ColourPair &fore, const ColourPair &back); + void SetForeBack(const ColourDesired &fore, const ColourDesired &back); }; #ifdef SCI_NAMESPACE diff --git a/src/stc/scintilla/src/Catalogue.cxx b/src/stc/scintilla/src/Catalogue.cxx new file mode 100644 index 0000000000..2f752472b3 --- /dev/null +++ b/src/stc/scintilla/src/Catalogue.cxx @@ -0,0 +1,192 @@ +// Scintilla source code edit control +/** @file KeyWords.cxx + ** Colourise for particular languages. + **/ +// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> + +#include <vector> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "LexerModule.h" +#include "Catalogue.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +static std::vector<LexerModule *> lexerCatalogue; +static int nextLanguage = SCLEX_AUTOMATIC+1; + +const LexerModule *Catalogue::Find(int language) { + Scintilla_LinkLexers(); + for (std::vector<LexerModule *>::iterator it=lexerCatalogue.begin(); + it != lexerCatalogue.end(); ++it) { + if ((*it)->GetLanguage() == language) { + return *it; + } + } + return 0; +} + +const LexerModule *Catalogue::Find(const char *languageName) { + Scintilla_LinkLexers(); + if (languageName) { + for (std::vector<LexerModule *>::iterator it=lexerCatalogue.begin(); + it != lexerCatalogue.end(); ++it) { + if ((*it)->languageName && (0 == strcmp((*it)->languageName, languageName))) { + return *it; + } + } + } + return 0; +} + +void Catalogue::AddLexerModule(LexerModule *plm) { + if (plm->GetLanguage() == SCLEX_AUTOMATIC) { + plm->language = nextLanguage; + nextLanguage++; + } + lexerCatalogue.push_back(plm); +} + +// Alternative historical name for Scintilla_LinkLexers +int wxForceScintillaLexers(void) { + return Scintilla_LinkLexers(); +} + +// To add or remove a lexer, add or remove its file and run LexGen.py. + +// Force a reference to all of the Scintilla lexers so that the linker will +// not remove the code of the lexers. +int Scintilla_LinkLexers() { + + static int initialised = 0; + if (initialised) + return 0; + initialised = 1; + +// Shorten the code that declares a lexer and ensures it is linked in by calling a method. +#define LINK_LEXER(lexer) extern LexerModule lexer; Catalogue::AddLexerModule(&lexer); + +//++Autogenerated -- run src/LexGen.py to regenerate +//**\(\tLINK_LEXER(\*);\n\) + LINK_LEXER(lmA68k); + LINK_LEXER(lmAbaqus); + LINK_LEXER(lmAda); + LINK_LEXER(lmAns1); + LINK_LEXER(lmAPDL); + LINK_LEXER(lmAsm); + LINK_LEXER(lmASY); + LINK_LEXER(lmAU3); + LINK_LEXER(lmAVE); + LINK_LEXER(lmAVS); + LINK_LEXER(lmBaan); + LINK_LEXER(lmBash); + LINK_LEXER(lmBatch); + LINK_LEXER(lmBlitzBasic); + LINK_LEXER(lmBullant); + LINK_LEXER(lmCaml); + LINK_LEXER(lmClw); + LINK_LEXER(lmClwNoCase); + LINK_LEXER(lmCmake); + LINK_LEXER(lmCOBOL); + LINK_LEXER(lmCoffeeScript); + LINK_LEXER(lmConf); + LINK_LEXER(lmCPP); + LINK_LEXER(lmCPPNoCase); + LINK_LEXER(lmCsound); + LINK_LEXER(lmCss); + LINK_LEXER(lmD); + LINK_LEXER(lmDiff); + LINK_LEXER(lmECL); + LINK_LEXER(lmEiffel); + LINK_LEXER(lmEiffelkw); + LINK_LEXER(lmErlang); + LINK_LEXER(lmErrorList); + LINK_LEXER(lmESCRIPT); + LINK_LEXER(lmF77); + LINK_LEXER(lmFlagShip); + LINK_LEXER(lmForth); + LINK_LEXER(lmFortran); + LINK_LEXER(lmFreeBasic); + LINK_LEXER(lmGAP); + LINK_LEXER(lmGui4Cli); + LINK_LEXER(lmHaskell); + LINK_LEXER(lmHTML); + LINK_LEXER(lmInno); + LINK_LEXER(lmKix); + LINK_LEXER(lmLatex); + LINK_LEXER(lmLISP); + LINK_LEXER(lmLot); + LINK_LEXER(lmLout); + LINK_LEXER(lmLua); + LINK_LEXER(lmMagikSF); + LINK_LEXER(lmMake); + LINK_LEXER(lmMarkdown); + LINK_LEXER(lmMatlab); + LINK_LEXER(lmMETAPOST); + LINK_LEXER(lmMMIXAL); + LINK_LEXER(lmModula); + LINK_LEXER(lmMSSQL); + LINK_LEXER(lmMySQL); + LINK_LEXER(lmNimrod); + LINK_LEXER(lmNncrontab); + LINK_LEXER(lmNsis); + LINK_LEXER(lmNull); + LINK_LEXER(lmOctave); + LINK_LEXER(lmOpal); + LINK_LEXER(lmOScript); + LINK_LEXER(lmPascal); + LINK_LEXER(lmPB); + LINK_LEXER(lmPerl); + LINK_LEXER(lmPHPSCRIPT); + LINK_LEXER(lmPLM); + LINK_LEXER(lmPo); + LINK_LEXER(lmPOV); + LINK_LEXER(lmPowerPro); + LINK_LEXER(lmPowerShell); + LINK_LEXER(lmProgress); + LINK_LEXER(lmProps); + LINK_LEXER(lmPS); + LINK_LEXER(lmPureBasic); + LINK_LEXER(lmPython); + LINK_LEXER(lmR); + LINK_LEXER(lmREBOL); + LINK_LEXER(lmRuby); + LINK_LEXER(lmScriptol); + LINK_LEXER(lmSmalltalk); + LINK_LEXER(lmSML); + LINK_LEXER(lmSorc); + LINK_LEXER(lmSpecman); + LINK_LEXER(lmSpice); + LINK_LEXER(lmSQL); + LINK_LEXER(lmTACL); + LINK_LEXER(lmTADS3); + LINK_LEXER(lmTAL); + LINK_LEXER(lmTCL); + LINK_LEXER(lmTCMD); + LINK_LEXER(lmTeX); + LINK_LEXER(lmTxt2tags); + LINK_LEXER(lmVB); + LINK_LEXER(lmVBScript); + LINK_LEXER(lmVerilog); + LINK_LEXER(lmVHDL); + LINK_LEXER(lmVisualProlog); + LINK_LEXER(lmXML); + LINK_LEXER(lmYAML); + +//--Autogenerated -- end of automatically generated section + + return 1; +} diff --git a/src/stc/scintilla/src/Catalogue.h b/src/stc/scintilla/src/Catalogue.h new file mode 100644 index 0000000000..7fea37da80 --- /dev/null +++ b/src/stc/scintilla/src/Catalogue.h @@ -0,0 +1,26 @@ +// Scintilla source code edit control +/** @file Catalogue.h + ** Lexer infrastructure. + **/ +// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef CATALOGUE_H +#define CATALOGUE_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +class Catalogue { +public: + static const LexerModule *Find(int language); + static const LexerModule *Find(const char *languageName); + static void AddLexerModule(LexerModule *plm); +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/src/stc/scintilla/src/CellBuffer.cxx b/src/stc/scintilla/src/CellBuffer.cxx index be0440304d..11b8b4acda 100644 --- a/src/stc/scintilla/src/CellBuffer.cxx +++ b/src/stc/scintilla/src/CellBuffer.cxx @@ -44,9 +44,11 @@ void LineVector::InsertText(int line, int delta) { starts.InsertText(line, delta); } -void LineVector::InsertLine(int line, int position) { +void LineVector::InsertLine(int line, int position, bool lineStart) { starts.InsertPartition(line, position); if (perLine) { + if ((line > 0) && lineStart) + line--; perLine->InsertLine(line); } } @@ -197,7 +199,7 @@ void UndoHistory::AppendAction(actionType at, int position, char *data, int leng // Insertions must be immediately after to coalesce currentAction++; } else if (at == removeAction) { - if ((lengthData == 1) || (lengthData == 2)){ + if ((lengthData == 1) || (lengthData == 2)) { if ((position + lengthData) == actPrevious->position) { ; // Backspace -> OK } else if (position == actPrevious->position) { @@ -339,7 +341,7 @@ char CellBuffer::CharAt(int position) const { return substance.ValueAt(position); } -void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) { +void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) const { if (lengthRetrieve < 0) return; if (position < 0) @@ -349,20 +351,38 @@ void CellBuffer::GetCharRange(char *buffer, int position, int lengthRetrieve) { lengthRetrieve, substance.Length()); return; } - - for (int i=0; i<lengthRetrieve; i++) { - *buffer++ = substance.ValueAt(position + i); - } + substance.GetRange(buffer, position, lengthRetrieve); } -char CellBuffer::StyleAt(int position) { +char CellBuffer::StyleAt(int position) const { return style.ValueAt(position); } -const char *CellBuffer::BufferPointer() { +void CellBuffer::GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const { + if (lengthRetrieve < 0) + return; + if (position < 0) + return; + if ((position + lengthRetrieve) > style.Length()) { + Platform::DebugPrintf("Bad GetStyleRange %d for %d of %d\n", position, + lengthRetrieve, style.Length()); + return; + } + style.GetRange(reinterpret_cast<char *>(buffer), position, lengthRetrieve); +} + +const char *CellBuffer::BufferPointer() { return substance.BufferPointer(); } +const char *CellBuffer::RangePointer(int position, int rangeLength) { + return substance.RangePointer(position, rangeLength); +} + +int CellBuffer::GapPosition() const { + return substance.GapPosition(); +} + // The char* returned is to an allocation owned by the undo history const char *CellBuffer::InsertString(int position, const char *s, int insertLength, bool &startSequence) { char *data = 0; @@ -455,7 +475,7 @@ int CellBuffer::LineStart(int line) const { return lv.LineStart(line); } -bool CellBuffer::IsReadOnly() { +bool CellBuffer::IsReadOnly() const { return readOnly; } @@ -473,8 +493,8 @@ bool CellBuffer::IsSavePoint() { // Without undo -void CellBuffer::InsertLine(int line, int position) { - lv.InsertLine(line, position); +void CellBuffer::InsertLine(int line, int position, bool lineStart) { + lv.InsertLine(line, position, lineStart); } void CellBuffer::RemoveLine(int line) { @@ -490,27 +510,28 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength style.InsertValue(position, insertLength, 0); int lineInsert = lv.LineFromPosition(position) + 1; + bool atLineStart = lv.LineStart(lineInsert-1) == position; // Point all the lines after the insertion point further along in the buffer lv.InsertText(lineInsert-1, insertLength); char chPrev = substance.ValueAt(position - 1); char chAfter = substance.ValueAt(position + insertLength); if (chPrev == '\r' && chAfter == '\n') { // Splitting up a crlf pair at position - InsertLine(lineInsert, position); + InsertLine(lineInsert, position, false); lineInsert++; } char ch = ' '; for (int i = 0; i < insertLength; i++) { ch = s[i]; if (ch == '\r') { - InsertLine(lineInsert, (position + i) + 1); + InsertLine(lineInsert, (position + i) + 1, atLineStart); lineInsert++; } else if (ch == '\n') { if (chPrev == '\r') { // Patch up what was end of line lv.SetLineStart(lineInsert - 1, (position + i) + 1); } else { - InsertLine(lineInsert, (position + i) + 1); + InsertLine(lineInsert, (position + i) + 1, atLineStart); lineInsert++; } } @@ -586,7 +607,7 @@ bool CellBuffer::SetUndoCollection(bool collectUndo) { return collectingUndo; } -bool CellBuffer::IsCollectingUndo() { +bool CellBuffer::IsCollectingUndo() const { return collectingUndo; } diff --git a/src/stc/scintilla/src/CellBuffer.h b/src/stc/scintilla/src/CellBuffer.h index 3381c19c2c..388b9027bf 100644 --- a/src/stc/scintilla/src/CellBuffer.h +++ b/src/stc/scintilla/src/CellBuffer.h @@ -37,7 +37,7 @@ public: void SetPerLine(PerLine *pl); void InsertText(int line, int delta); - void InsertLine(int line, int position); + void InsertLine(int line, int position, bool lineStart); void SetLineStart(int line, int position); void RemoveLine(int line); int Lines() const { @@ -142,6 +142,10 @@ private: LineVector lv; + /// Actions without undo + void BasicInsertString(int position, const char *s, int insertLength); + void BasicDeleteChars(int position, int deleteLength); + public: CellBuffer(); @@ -149,9 +153,12 @@ public: /// Retrieving positions outside the range of the buffer works and returns 0 char CharAt(int position) const; - void GetCharRange(char *buffer, int position, int lengthRetrieve); - char StyleAt(int position); + void GetCharRange(char *buffer, int position, int lengthRetrieve) const; + char StyleAt(int position) const; + void GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const; const char *BufferPointer(); + const char *RangePointer(int position, int rangeLength); + int GapPosition() const; int Length() const; void Allocate(int newSize); @@ -159,7 +166,7 @@ public: int Lines() const; int LineStart(int line) const; int LineFromPosition(int pos) const { return lv.LineFromPosition(pos); } - void InsertLine(int line, int position); + void InsertLine(int line, int position, bool lineStart); void RemoveLine(int line); const char *InsertString(int position, const char *s, int insertLength, bool &startSequence); @@ -170,7 +177,7 @@ public: const char *DeleteChars(int position, int deleteLength, bool &startSequence); - bool IsReadOnly(); + bool IsReadOnly() const; void SetReadOnly(bool set); /// The save point is a marker in the undo stack where the container has stated that @@ -178,12 +185,8 @@ public: void SetSavePoint(); bool IsSavePoint(); - /// Actions without undo - void BasicInsertString(int position, const char *s, int insertLength); - void BasicDeleteChars(int position, int deleteLength); - bool SetUndoCollection(bool collectUndo); - bool IsCollectingUndo(); + bool IsCollectingUndo() const; void BeginUndoAction(); void EndUndoAction(); void AddUndoAction(int token, bool mayCoalesce); diff --git a/src/stc/scintilla/src/CharClassify.cxx b/src/stc/scintilla/src/CharClassify.cxx index bbd25a0f8d..7e3db737e3 100644 --- a/src/stc/scintilla/src/CharClassify.cxx +++ b/src/stc/scintilla/src/CharClassify.cxx @@ -10,6 +10,10 @@ #include "CharClassify.h" +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + // Shut up annoying Visual C++ warnings: #ifdef _MSC_VER #pragma warning(disable: 4514) @@ -43,36 +47,18 @@ void CharClassify::SetCharClasses(const unsigned char *chars, cc newCharClass) { } } -int CompareCaseInsensitive(const char *a, const char *b) { - while (*a && *b) { - if (*a != *b) { - char upperA = MakeUpperCase(*a); - char upperB = MakeUpperCase(*b); - if (upperA != upperB) - return upperA - upperB; - } - a++; - b++; - } - // Either *a or *b is nul - return *a - *b; -} - -int CompareNCaseInsensitive(const char *a, const char *b, size_t len) { - while (*a && *b && len) { - if (*a != *b) { - char upperA = MakeUpperCase(*a); - char upperB = MakeUpperCase(*b); - if (upperA != upperB) - return upperA - upperB; +int CharClassify::GetCharsOfClass(cc characterClass, unsigned char *buffer) { + // Get characters belonging to the given char class; return the number + // of characters (if the buffer is NULL, don't write to it). + int count = 0; + for (int ch = maxChar - 1; ch >= 0; --ch) { + if (charClass[ch] == characterClass) { + ++count; + if (buffer) { + *buffer = static_cast<unsigned char>(ch); + buffer++; + } } - a++; - b++; - len--; } - if (len == 0) - return 0; - else - // Either *a or *b is nul - return *a - *b; + return count; } diff --git a/src/stc/scintilla/src/CharClassify.h b/src/stc/scintilla/src/CharClassify.h index d746fe02dd..5d2734c006 100644 --- a/src/stc/scintilla/src/CharClassify.h +++ b/src/stc/scintilla/src/CharClassify.h @@ -8,6 +8,10 @@ #ifndef CHARCLASSIFY_H #define CHARCLASSIFY_H +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + class CharClassify { public: CharClassify(); @@ -15,6 +19,7 @@ public: enum cc { ccSpace, ccNewLine, ccWord, ccPunctuation }; void SetDefaultCharClasses(bool includeWordClass); void SetCharClasses(const unsigned char *chars, cc newCharClass); + int GetCharsOfClass(cc charClass, unsigned char *buffer); cc GetClass(unsigned char ch) const { return static_cast<cc>(charClass[ch]);} bool IsWord(unsigned char ch) const { return static_cast<cc>(charClass[ch]) == ccWord;} @@ -23,15 +28,8 @@ private: unsigned char charClass[maxChar]; // not type cc to save space }; -// These functions are implemented because each platform calls them something different. -int CompareCaseInsensitive(const char *a, const char *b); -int CompareNCaseInsensitive(const char *a, const char *b, size_t len); - -inline char MakeUpperCase(char ch) { - if (ch < 'a' || ch > 'z') - return ch; - else - return static_cast<char>(ch - 'a' + 'A'); +#ifdef SCI_NAMESPACE } +#endif #endif diff --git a/src/stc/scintilla/src/CharacterSet.h b/src/stc/scintilla/src/CharacterSet.h deleted file mode 100644 index 4e8ffbdf6f..0000000000 --- a/src/stc/scintilla/src/CharacterSet.h +++ /dev/null @@ -1,58 +0,0 @@ -// Scintilla source code edit control -/** @file CharacterSet.h - ** Encapsulates a set of characters. Used to test if a character is within a set. - **/ -// Copyright 2007 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -class CharacterSet { - int size; - bool valueAfter; - bool *bset; -public: - enum setBase { - setNone=0, - setLower=1, - setUpper=2, - setDigits=4, - setAlpha=setLower|setUpper, - setAlphaNum=setAlpha|setDigits - }; - CharacterSet(setBase base=setNone, const char *initialSet="", int size_=0x80, bool valueAfter_=false) { - size = size_; - valueAfter = valueAfter_; - bset = new bool[size]; - for (int i=0; i < size; i++) { - bset[i] = false; - } - AddString(initialSet); - if (base & setLower) - AddString("abcdefghijklmnopqrstuvwxyz"); - if (base & setUpper) - AddString("ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - if (base & setDigits) - AddString("0123456789"); - } - ~CharacterSet() { - delete []bset; - bset = 0; - size = 0; - } - void Add(int val) { - PLATFORM_ASSERT(val >= 0); - PLATFORM_ASSERT(val < size); - bset[val] = true; - } - void AddString(const char *CharacterSet) { - for (const char *cp=CharacterSet; *cp; cp++) { - int val = static_cast<unsigned char>(*cp); - PLATFORM_ASSERT(val >= 0); - PLATFORM_ASSERT(val < size); - bset[val] = true; - } - } - bool Contains(int val) const { - PLATFORM_ASSERT(val >= 0); - return (val < size) ? bset[val] : valueAfter; - } -}; diff --git a/src/stc/scintilla/src/ContractionState.cxx b/src/stc/scintilla/src/ContractionState.cxx index 08de5cf1f7..af0f4f3dbf 100644 --- a/src/stc/scintilla/src/ContractionState.cxx +++ b/src/stc/scintilla/src/ContractionState.cxx @@ -168,6 +168,14 @@ bool ContractionState::SetVisible(int lineDocStart, int lineDocEnd, bool visible } } +bool ContractionState::HiddenLines() const { + if (OneToOne()) { + return false; + } else { + return !visible->AllSameAs(1); + } +} + bool ContractionState::GetExpanded(int lineDoc) const { if (OneToOne()) { return true; @@ -193,6 +201,23 @@ bool ContractionState::SetExpanded(int lineDoc, bool expanded_) { } } +int ContractionState::ContractedNext(int lineDocStart) const { + if (OneToOne()) { + return -1; + } else { + Check(); + if (!expanded->ValueAt(lineDocStart)) { + return lineDocStart; + } else { + int lineDocNextChange = expanded->EndRun(lineDocStart); + if (lineDocNextChange < LinesInDoc()) + return lineDocNextChange; + else + return -1; + } + } +} + int ContractionState::GetHeight(int lineDoc) const { if (OneToOne()) { return 1; @@ -206,7 +231,7 @@ int ContractionState::GetHeight(int lineDoc) const { bool ContractionState::SetHeight(int lineDoc, int height) { if (OneToOne() && (height == 1)) { return false; - } else { + } else if (lineDoc < LinesInDoc()) { EnsureData(); if (GetHeight(lineDoc) != height) { if (GetVisible(lineDoc)) { @@ -219,6 +244,8 @@ bool ContractionState::SetHeight(int lineDoc, int height) { Check(); return false; } + } else { + return false; } } @@ -232,11 +259,11 @@ void ContractionState::ShowAll() { void ContractionState::Check() const { #ifdef CHECK_CORRECTNESS - for (int vline = 0;vline < LinesDisplayed(); vline++) { + for (int vline = 0; vline < LinesDisplayed(); vline++) { const int lineDoc = DocFromDisplay(vline); PLATFORM_ASSERT(GetVisible(lineDoc)); } - for (int lineDoc = 0;lineDoc < LinesInDoc(); lineDoc++) { + for (int lineDoc = 0; lineDoc < LinesInDoc(); lineDoc++) { const int displayThis = DisplayFromDoc(lineDoc); const int displayNext = DisplayFromDoc(lineDoc + 1); const int height = displayNext - displayThis; diff --git a/src/stc/scintilla/src/ContractionState.h b/src/stc/scintilla/src/ContractionState.h index ba62975128..0309fc2691 100644 --- a/src/stc/scintilla/src/ContractionState.h +++ b/src/stc/scintilla/src/ContractionState.h @@ -48,9 +48,11 @@ public: bool GetVisible(int lineDoc) const; bool SetVisible(int lineDocStart, int lineDocEnd, bool visible); + bool HiddenLines() const; bool GetExpanded(int lineDoc) const; bool SetExpanded(int lineDoc, bool expanded); + int ContractedNext(int lineDocStart) const; int GetHeight(int lineDoc) const; bool SetHeight(int lineDoc, int height); diff --git a/src/stc/scintilla/src/Decoration.cxx b/src/stc/scintilla/src/Decoration.cxx index e4ac0e07c6..b489c3c02f 100644 --- a/src/stc/scintilla/src/Decoration.cxx +++ b/src/stc/scintilla/src/Decoration.cxx @@ -28,7 +28,7 @@ Decoration::~Decoration() { } bool Decoration::Empty() { - return rs.starts->Partitions() == 1; + return (rs.Runs() == 1) && (rs.AllSameAs(0)); } DecorationList::DecorationList() : currentIndicator(0), currentValue(1), current(0), @@ -126,9 +126,13 @@ bool DecorationList::FillRange(int &position, int value, int &fillLength) { } void DecorationList::InsertSpace(int position, int insertLength) { + const bool atEnd = position == lengthDocument; lengthDocument += insertLength; for (Decoration *deco=root; deco; deco = deco->next) { deco->rs.InsertSpace(position, insertLength); + if (atEnd) { + deco->rs.FillRange(position, 0, insertLength); + } } } @@ -144,7 +148,7 @@ void DecorationList::DeleteRange(int position, int deleteLength) { void DecorationList::DeleteAnyEmpty() { Decoration *deco = root; while (deco) { - if (deco->Empty()) { + if ((lengthDocument == 0) || deco->Empty()) { Delete(deco->indicator); deco = root; } else { diff --git a/src/stc/scintilla/src/Decoration.h b/src/stc/scintilla/src/Decoration.h index 2809641afd..fedff97736 100644 --- a/src/stc/scintilla/src/Decoration.h +++ b/src/stc/scintilla/src/Decoration.h @@ -40,10 +40,10 @@ public: ~DecorationList(); void SetCurrentIndicator(int indicator); - int GetCurrentIndicator() { return currentIndicator; } + int GetCurrentIndicator() const { return currentIndicator; } void SetCurrentValue(int value); - int GetCurrentValue() { return currentValue; } + int GetCurrentValue() const { return currentValue; } // Returns true if some values may have changed bool FillRange(int &position, int value, int &fillLength); diff --git a/src/stc/scintilla/src/Document.cxx b/src/stc/scintilla/src/Document.cxx index a5d1adbbb1..4ce62c45b3 100644 --- a/src/stc/scintilla/src/Document.cxx +++ b/src/stc/scintilla/src/Document.cxx @@ -2,58 +2,77 @@ /** @file Document.cxx ** Text document that handles notifications, DBCS, styling, words and end of line. **/ -// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> +// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. #include <stdlib.h> #include <string.h> #include <stdio.h> #include <ctype.h> +#include <assert.h> + +#include <string> +#include <vector> #include "Platform.h" +#include "ILexer.h" #include "Scintilla.h" + #include "SplitVector.h" #include "Partitioning.h" #include "RunStyles.h" #include "CellBuffer.h" #include "PerLine.h" #include "CharClassify.h" +#include "CharacterSet.h" #include "Decoration.h" #include "Document.h" #include "RESearch.h" +#include "UniConversion.h" #ifdef SCI_NAMESPACE using namespace Scintilla; #endif -// This is ASCII specific but is safe with chars >= 0x80 -static inline bool isspacechar(unsigned char ch) { - return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d)); -} - static inline bool IsPunctuation(char ch) { return isascii(ch) && ispunct(ch); } -static inline bool IsADigit(char ch) { - return isascii(ch) && isdigit(ch); -} +void LexInterface::Colourise(int start, int end) { + if (pdoc && instance && !performingStyle) { + // Protect against reentrance, which may occur, for example, when + // fold points are discovered while performing styling and the folding + // code looks for child lines which may trigger styling. + performingStyle = true; -static inline bool IsLowerCase(char ch) { - return isascii(ch) && islower(ch); -} + int lengthDoc = pdoc->Length(); + if (end == -1) + end = lengthDoc; + int len = end - start; + + PLATFORM_ASSERT(len >= 0); + PLATFORM_ASSERT(start + len <= lengthDoc); -static inline bool IsUpperCase(char ch) { - return isascii(ch) && isupper(ch); + int styleStart = 0; + if (start > 0) + styleStart = pdoc->StyleAt(start - 1) & pdoc->stylingBitsMask; + + if (len > 0) { + instance->Lex(start, len, styleStart, pdoc); + instance->Fold(start, len, styleStart, pdoc); + } + + performingStyle = false; + } } Document::Document() { refCount = 0; -#ifdef unix - eolMode = SC_EOL_LF; -#else +#ifdef _WIN32 eolMode = SC_EOL_CRLF; +#else + eolMode = SC_EOL_LF; #endif dbcsCodePage = 0; stylingBits = 5; @@ -76,6 +95,8 @@ Document::Document() { matchesValid = false; regex = 0; + UTF8BytesOfLeadInitialise(); + perLineData[ldMarkers] = new LineMarkers(); perLineData[ldLevels] = new LineLevels(); perLineData[ldState] = new LineState(); @@ -83,6 +104,8 @@ Document::Document() { perLineData[ldAnnotation] = new LineAnnotation(); cb.SetPerLine(this); + + pli = 0; } Document::~Document() { @@ -98,6 +121,8 @@ Document::~Document() { lenWatchers = 0; delete regex; regex = 0; + delete pli; + pli = 0; } void Document::Init() { @@ -128,7 +153,7 @@ int Document::AddRef() { // Decrease reference count and return its previous value. // Delete the document if reference count reaches zero. -int Document::Release() { +int SCI_METHOD Document::Release() { int curRefCount = --refCount; if (curRefCount == 0) delete this; @@ -140,13 +165,17 @@ void Document::SetSavePoint() { NotifySavePoint(true); } -int Document::GetMark(int line) { - return static_cast<LineMarkers*>(perLineData[ldMarkers])->MarkValue(line); +int Document::GetMark(int line) { + return static_cast<LineMarkers *>(perLineData[ldMarkers])->MarkValue(line); +} + +int Document::MarkerNext(int lineStart, int mask) const { + return static_cast<LineMarkers *>(perLineData[ldMarkers])->MarkerNext(lineStart, mask); } int Document::AddMark(int line, int markerNum) { - if (line <= LinesTotal()) { - int prev = static_cast<LineMarkers*>(perLineData[ldMarkers])-> + if (line >= 0 && line <= LinesTotal()) { + int prev = static_cast<LineMarkers *>(perLineData[ldMarkers])-> AddMark(line, markerNum, LinesTotal()); DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); NotifyModified(mh); @@ -157,42 +186,49 @@ int Document::AddMark(int line, int markerNum) { } void Document::AddMarkSet(int line, int valueSet) { + if (line < 0 || line > LinesTotal()) { + return; + } unsigned int m = valueSet; for (int i = 0; m; i++, m >>= 1) if (m & 1) - static_cast<LineMarkers*>(perLineData[ldMarkers])-> + static_cast<LineMarkers *>(perLineData[ldMarkers])-> AddMark(line, i, LinesTotal()); DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); NotifyModified(mh); } void Document::DeleteMark(int line, int markerNum) { - static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMark(line, markerNum, false); + static_cast<LineMarkers *>(perLineData[ldMarkers])->DeleteMark(line, markerNum, false); DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); NotifyModified(mh); } void Document::DeleteMarkFromHandle(int markerHandle) { - static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMarkFromHandle(markerHandle); + static_cast<LineMarkers *>(perLineData[ldMarkers])->DeleteMarkFromHandle(markerHandle); DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0); mh.line = -1; NotifyModified(mh); } void Document::DeleteAllMarks(int markerNum) { + bool someChanges = false; for (int line = 0; line < LinesTotal(); line++) { - static_cast<LineMarkers*>(perLineData[ldMarkers])->DeleteMark(line, markerNum, true); + if (static_cast<LineMarkers *>(perLineData[ldMarkers])->DeleteMark(line, markerNum, true)) + someChanges = true; + } + if (someChanges) { + DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0); + mh.line = -1; + NotifyModified(mh); } - DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0); - mh.line = -1; - NotifyModified(mh); } -int Document::LineFromHandle(int markerHandle) { - return static_cast<LineMarkers*>(perLineData[ldMarkers])->LineFromHandle(markerHandle); +int Document::LineFromHandle(int markerHandle) { + return static_cast<LineMarkers *>(perLineData[ldMarkers])->LineFromHandle(markerHandle); } -int Document::LineStart(int line) const { +int SCI_METHOD Document::LineStart(int line) const { return cb.LineStart(line); } @@ -209,7 +245,14 @@ int Document::LineEnd(int line) const { } } -int Document::LineFromPosition(int pos) const { +void SCI_METHOD Document::SetErrorStatus(int status) { + // Tell the watchers the lexer has changed. + for (int i = 0; i < lenWatchers; i++) { + watchers[i].watcher->NotifyErrorOccurred(this, watchers[i].userData, status); + } +} + +int SCI_METHOD Document::LineFromPosition(int pos) const { return cb.LineFromPosition(pos); } @@ -226,7 +269,7 @@ int Document::VCHomePosition(int position) const { int startPosition = LineStart(line); int endLine = LineEnd(line); int startText = startPosition; - while (startText < endLine && (cb.CharAt(startText) == ' ' || cb.CharAt(startText) == '\t' ) ) + while (startText < endLine && (cb.CharAt(startText) == ' ' || cb.CharAt(startText) == '\t')) startText++; if (position == startText) return startPosition; @@ -234,8 +277,8 @@ int Document::VCHomePosition(int position) const { return startText; } -int Document::SetLevel(int line, int level) { - int prev = static_cast<LineLevels*>(perLineData[ldLevels])->SetLevel(line, level, LinesTotal()); +int SCI_METHOD Document::SetLevel(int line, int level) { + int prev = static_cast<LineLevels *>(perLineData[ldLevels])->SetLevel(line, level, LinesTotal()); if (prev != level) { DocModification mh(SC_MOD_CHANGEFOLD | SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line); @@ -246,12 +289,12 @@ int Document::SetLevel(int line, int level) { return prev; } -int Document::GetLevel(int line) { - return static_cast<LineLevels*>(perLineData[ldLevels])->GetLevel(line); +int SCI_METHOD Document::GetLevel(int line) const { + return static_cast<LineLevels *>(perLineData[ldLevels])->GetLevel(line); } -void Document::ClearLevels() { - static_cast<LineLevels*>(perLineData[ldLevels])->ClearLevels(); +void Document::ClearLevels() { + static_cast<LineLevels *>(perLineData[ldLevels])->ClearLevels(); } static bool IsSubordinate(int levelStart, int levelTry) { @@ -261,15 +304,18 @@ static bool IsSubordinate(int levelStart, int levelTry) { return (levelStart & SC_FOLDLEVELNUMBERMASK) < (levelTry & SC_FOLDLEVELNUMBERMASK); } -int Document::GetLastChild(int lineParent, int level) { +int Document::GetLastChild(int lineParent, int level, int lastLine) { if (level == -1) level = GetLevel(lineParent) & SC_FOLDLEVELNUMBERMASK; int maxLine = LinesTotal(); + int lookLastLine = (lastLine != -1) ? Platform::Minimum(LinesTotal() - 1, lastLine) : -1; int lineMaxSubord = lineParent; while (lineMaxSubord < maxLine - 1) { EnsureStyledTo(LineStart(lineMaxSubord + 2)); if (!IsSubordinate(level, GetLevel(lineMaxSubord + 1))) break; + if ((lookLastLine != -1) && (lineMaxSubord >= lookLastLine) && !(GetLevel(lineMaxSubord) & SC_FOLDLEVELWHITEFLAG)) + break; lineMaxSubord++; } if (lineMaxSubord > lineParent) { @@ -300,6 +346,76 @@ int Document::GetFoldParent(int line) { } } +void Document::GetHighlightDelimiters(HighlightDelimiter &highlightDelimiter, int line, int lastLine) { + int level = GetLevel(line); + int lookLastLine = Platform::Maximum(line, lastLine) + 1; + + int lookLine = line; + int lookLineLevel = level; + int lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + while ((lookLine > 0) && ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || + ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum >= (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))))) { + lookLineLevel = GetLevel(--lookLine); + lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + } + + int beginFoldBlock = (lookLineLevel & SC_FOLDLEVELHEADERFLAG) ? lookLine : GetFoldParent(lookLine); + if (beginFoldBlock == -1) { + highlightDelimiter.Clear(); + return; + } + + int endFoldBlock = GetLastChild(beginFoldBlock, -1, lookLastLine); + int firstChangeableLineBefore = -1; + if (endFoldBlock < line) { + lookLine = beginFoldBlock - 1; + lookLineLevel = GetLevel(lookLine); + lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + while ((lookLine >= 0) && (lookLineLevelNum >= SC_FOLDLEVELBASE)) { + if (lookLineLevel & SC_FOLDLEVELHEADERFLAG) { + if (GetLastChild(lookLine, -1, lookLastLine) == line) { + beginFoldBlock = lookLine; + endFoldBlock = line; + firstChangeableLineBefore = line - 1; + } + } + if ((lookLine > 0) && (lookLineLevelNum == SC_FOLDLEVELBASE) && ((GetLevel(lookLine - 1) & SC_FOLDLEVELNUMBERMASK) > lookLineLevelNum)) + break; + lookLineLevel = GetLevel(--lookLine); + lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + } + } + if (firstChangeableLineBefore == -1) { + for (lookLine = line - 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + lookLine >= beginFoldBlock; + lookLineLevel = GetLevel(--lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) { + if ((lookLineLevel & SC_FOLDLEVELWHITEFLAG) || (lookLineLevelNum > (level & SC_FOLDLEVELNUMBERMASK))) { + firstChangeableLineBefore = lookLine; + break; + } + } + } + if (firstChangeableLineBefore == -1) + firstChangeableLineBefore = beginFoldBlock - 1; + + int firstChangeableLineAfter = -1; + for (lookLine = line + 1, lookLineLevel = GetLevel(lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK; + lookLine <= endFoldBlock; + lookLineLevel = GetLevel(++lookLine), lookLineLevelNum = lookLineLevel & SC_FOLDLEVELNUMBERMASK) { + if ((lookLineLevel & SC_FOLDLEVELHEADERFLAG) && (lookLineLevelNum < (GetLevel(lookLine + 1) & SC_FOLDLEVELNUMBERMASK))) { + firstChangeableLineAfter = lookLine; + break; + } + } + if (firstChangeableLineAfter == -1) + firstChangeableLineAfter = endFoldBlock + 1; + + highlightDelimiter.beginFoldBlock = beginFoldBlock; + highlightDelimiter.endFoldBlock = endFoldBlock; + highlightDelimiter.firstChangeableLineBefore = firstChangeableLineBefore; + highlightDelimiter.firstChangeableLineAfter = firstChangeableLineAfter; +} + int Document::ClampPositionIntoDocument(int pos) { return Platform::Clamp(pos, 0, Length()); } @@ -312,85 +428,49 @@ bool Document::IsCrLf(int pos) { return (cb.CharAt(pos) == '\r') && (cb.CharAt(pos + 1) == '\n'); } -static const int maxBytesInDBCSCharacter=5; - int Document::LenChar(int pos) { if (pos < 0) { return 1; } else if (IsCrLf(pos)) { return 2; } else if (SC_CP_UTF8 == dbcsCodePage) { - unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos)); - if (ch < 0x80) - return 1; - int len = 2; - if (ch >= (0x80 + 0x40 + 0x20 + 0x10)) - len = 4; - else if (ch >= (0x80 + 0x40 + 0x20)) - len = 3; + const unsigned char leadByte = static_cast<unsigned char>(cb.CharAt(pos)); + const int widthCharBytes = UTF8BytesOfLead[leadByte]; int lengthDoc = Length(); - if ((pos + len) > lengthDoc) - return lengthDoc -pos; + if ((pos + widthCharBytes) > lengthDoc) + return lengthDoc - pos; else - return len; + return widthCharBytes; } else if (dbcsCodePage) { - char mbstr[maxBytesInDBCSCharacter+1]; - int i; - for (i=0; i<Platform::DBCSCharMaxLength(); i++) { - mbstr[i] = cb.CharAt(pos+i); - } - mbstr[i] = '\0'; - return Platform::DBCSCharLength(dbcsCodePage, mbstr); + return IsDBCSLeadByte(cb.CharAt(pos)) ? 2 : 1; } else { return 1; } } -static bool IsTrailByte(int ch) { - return (ch >= 0x80) && (ch < (0x80 + 0x40)); -} +bool Document::InGoodUTF8(int pos, int &start, int &end) const { + int trail = pos; + while ((trail>0) && (pos-trail < UTF8MaxBytes) && UTF8IsTrailByte(static_cast<unsigned char>(cb.CharAt(trail-1)))) + trail--; + start = (trail > 0) ? trail-1 : trail; -static int BytesFromLead(int leadByte) { - if (leadByte > 0xF4) { - // Characters longer than 4 bytes not possible in current UTF-8 - return 0; - } else if (leadByte >= 0xF0) { - return 4; - } else if (leadByte >= 0xE0) { - return 3; - } else if (leadByte >= 0xC2) { - return 2; - } - return 0; -} - -bool Document::InGoodUTF8(int pos, int &start, int &end) { - int lead = pos; - while ((lead>0) && (pos-lead < 4) && IsTrailByte(static_cast<unsigned char>(cb.CharAt(lead-1)))) - lead--; - start = 0; - if (lead > 0) { - start = lead-1; - } - int leadByte = static_cast<unsigned char>(cb.CharAt(start)); - int bytes = BytesFromLead(leadByte); - if (bytes == 0) { + const unsigned char leadByte = static_cast<unsigned char>(cb.CharAt(start)); + const int widthCharBytes = UTF8BytesOfLead[leadByte]; + if (widthCharBytes == 1) { return false; } else { - int trailBytes = bytes - 1; - int len = pos - lead + 1; + int trailBytes = widthCharBytes - 1; + int len = pos - start; if (len > trailBytes) // pos too far from lead return false; - // Check that there are enough trails for this lead - int trail = pos + 1; - while ((trail-lead<trailBytes) && (trail < Length())) { - if (!IsTrailByte(static_cast<unsigned char>(cb.CharAt(trail)))) { - return false; - } - trail++; - } - end = start + bytes; + char charBytes[UTF8MaxBytes] = {static_cast<char>(leadByte),0,0,0}; + for (int b=1; b<widthCharBytes && ((start+b) < Length()); b++) + charBytes[b] = cb.CharAt(static_cast<int>(start+b)); + int utf8status = UTF8Classify(reinterpret_cast<const unsigned char *>(charBytes), widthCharBytes); + if (utf8status & UTF8MaskInvalid) + return false; + end = start + widthCharBytes; return true; } } @@ -416,33 +496,37 @@ int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) { return pos - 1; } - // Not between CR and LF - if (dbcsCodePage) { if (SC_CP_UTF8 == dbcsCodePage) { unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos)); - int startUTF = pos; - int endUTF = pos; - if (IsTrailByte(ch) && InGoodUTF8(pos, startUTF, endUTF)) { - // ch is a trail byte within a UTF-8 character - if (moveDir > 0) - pos = endUTF; - else - pos = startUTF; + // If ch is not a trail byte then pos is valid intercharacter position + if (UTF8IsTrailByte(ch)) { + int startUTF = pos; + int endUTF = pos; + if (InGoodUTF8(pos, startUTF, endUTF)) { + // ch is a trail byte within a UTF-8 character + if (moveDir > 0) + pos = endUTF; + else + pos = startUTF; + } + // Else invalid UTF-8 so return position of isolated trail byte } } else { // Anchor DBCS calculations at start of line because start of line can // not be a DBCS trail byte. - int posCheck = LineStart(LineFromPosition(pos)); - while (posCheck < pos) { - char mbstr[maxBytesInDBCSCharacter+1]; - int i; - for(i=0;i<Platform::DBCSCharMaxLength();i++) { - mbstr[i] = cb.CharAt(posCheck+i); - } - mbstr[i] = '\0'; + int posStartLine = LineStart(LineFromPosition(pos)); + if (pos == posStartLine) + return pos; + + // Step back until a non-lead-byte is found. + int posCheck = pos; + while ((posCheck > posStartLine) && IsDBCSLeadByte(cb.CharAt(posCheck-1))) + posCheck--; - int mbsize = Platform::DBCSCharLength(dbcsCodePage, mbstr); + // Check from known start of character. + while (posCheck < pos) { + int mbsize = IsDBCSLeadByte(cb.CharAt(posCheck)) ? 2 : 1; if (posCheck + mbsize == pos) { return pos; } else if (posCheck + mbsize > pos) { @@ -460,6 +544,179 @@ int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) { return pos; } +// NextPosition moves between valid positions - it can not handle a position in the middle of a +// multi-byte character. It is used to iterate through text more efficiently than MovePositionOutsideChar. +// A \r\n pair is treated as two characters. +int Document::NextPosition(int pos, int moveDir) const { + // If out of range, just return minimum/maximum value. + int increment = (moveDir > 0) ? 1 : -1; + if (pos + increment <= 0) + return 0; + if (pos + increment >= Length()) + return Length(); + + if (dbcsCodePage) { + if (SC_CP_UTF8 == dbcsCodePage) { + if (increment == 1) { + // Simple forward movement case so can avoid some checks + const unsigned char leadByte = static_cast<unsigned char>(cb.CharAt(pos)); + if (UTF8IsAscii(leadByte)) { + // Single byte character or invalid + pos++; + } else { + const int widthCharBytes = UTF8BytesOfLead[leadByte]; + char charBytes[UTF8MaxBytes] = {static_cast<char>(leadByte),0,0,0}; + for (int b=1; b<widthCharBytes; b++) + charBytes[b] = cb.CharAt(static_cast<int>(pos+b)); + int utf8status = UTF8Classify(reinterpret_cast<const unsigned char *>(charBytes), widthCharBytes); + if (utf8status & UTF8MaskInvalid) + pos++; + else + pos += utf8status & UTF8MaskWidth; + } + } else { + // Examine byte before position + pos--; + unsigned char ch = static_cast<unsigned char>(cb.CharAt(pos)); + // If ch is not a trail byte then pos is valid intercharacter position + if (UTF8IsTrailByte(ch)) { + // If ch is a trail byte in a valid UTF-8 character then return start of character + int startUTF = pos; + int endUTF = pos; + if (InGoodUTF8(pos, startUTF, endUTF)) { + pos = startUTF; + } + // Else invalid UTF-8 so return position of isolated trail byte + } + } + } else { + if (moveDir > 0) { + int mbsize = IsDBCSLeadByte(cb.CharAt(pos)) ? 2 : 1; + pos += mbsize; + if (pos > Length()) + pos = Length(); + } else { + // Anchor DBCS calculations at start of line because start of line can + // not be a DBCS trail byte. + int posStartLine = LineStart(LineFromPosition(pos)); + // See http://msdn.microsoft.com/en-us/library/cc194792%28v=MSDN.10%29.aspx + // http://msdn.microsoft.com/en-us/library/cc194790.aspx + if ((pos - 1) <= posStartLine) { + return pos - 1; + } else if (IsDBCSLeadByte(cb.CharAt(pos - 1))) { + // Must actually be trail byte + return pos - 2; + } else { + // Otherwise, step back until a non-lead-byte is found. + int posTemp = pos - 1; + while (posStartLine <= --posTemp && IsDBCSLeadByte(cb.CharAt(posTemp))) + ; + // Now posTemp+1 must point to the beginning of a character, + // so figure out whether we went back an even or an odd + // number of bytes and go back 1 or 2 bytes, respectively. + return (pos - 1 - ((pos - posTemp) & 1)); + } + } + } + } else { + pos += increment; + } + + return pos; +} + +bool Document::NextCharacter(int &pos, int moveDir) { + // Returns true if pos changed + int posNext = NextPosition(pos, moveDir); + if (posNext == pos) { + return false; + } else { + pos = posNext; + return true; + } +} + +int SCI_METHOD Document::CodePage() const { + return dbcsCodePage; +} + +bool SCI_METHOD Document::IsDBCSLeadByte(char ch) const { + // Byte ranges found in Wikipedia articles with relevant search strings in each case + unsigned char uch = static_cast<unsigned char>(ch); + switch (dbcsCodePage) { + case 932: + // Shift_jis + return ((uch >= 0x81) && (uch <= 0x9F)) || + ((uch >= 0xE0) && (uch <= 0xFC)); + // Lead bytes F0 to FC may be a Microsoft addition. + case 936: + // GBK + return (uch >= 0x81) && (uch <= 0xFE); + case 949: + // Korean Wansung KS C-5601-1987 + return (uch >= 0x81) && (uch <= 0xFE); + case 950: + // Big5 + return (uch >= 0x81) && (uch <= 0xFE); + case 1361: + // Korean Johab KS C-5601-1992 + return + ((uch >= 0x84) && (uch <= 0xD3)) || + ((uch >= 0xD8) && (uch <= 0xDE)) || + ((uch >= 0xE0) && (uch <= 0xF9)); + } + return false; +} + +static inline bool IsSpaceOrTab(int ch) { + return ch == ' ' || ch == '\t'; +} + +// Need to break text into segments near lengthSegment but taking into +// account the encoding to not break inside a UTF-8 or DBCS character +// and also trying to avoid breaking inside a pair of combining characters. +// The segment length must always be long enough (more than 4 bytes) +// so that there will be at least one whole character to make a segment. +// For UTF-8, text must consist only of valid whole characters. +// In preference order from best to worst: +// 1) Break after space +// 2) Break before punctuation +// 3) Break after whole character + +int Document::SafeSegment(const char *text, int length, int lengthSegment) { + if (length <= lengthSegment) + return length; + int lastSpaceBreak = -1; + int lastPunctuationBreak = -1; + int lastEncodingAllowedBreak = -1; + for (int j=0; j < lengthSegment;) { + unsigned char ch = static_cast<unsigned char>(text[j]); + if (j > 0) { + if (IsSpaceOrTab(text[j - 1]) && !IsSpaceOrTab(text[j])) { + lastSpaceBreak = j; + } + if (ch < 'A') { + lastPunctuationBreak = j; + } + } + lastEncodingAllowedBreak = j; + + if (dbcsCodePage == SC_CP_UTF8) { + j += UTF8BytesOfLead[ch]; + } else if (dbcsCodePage) { + j += IsDBCSLeadByte(ch) ? 2 : 1; + } else { + j++; + } + } + if (lastSpaceBreak >= 0) { + return lastSpaceBreak; + } else if (lastPunctuationBreak >= 0) { + return lastPunctuationBreak; + } + return lastEncodingAllowedBreak; +} + void Document::ModifiedAt(int pos) { if (endStyled > pos) endStyled = pos; @@ -477,7 +734,7 @@ void Document::CheckReadOnly() { // SetStyleAt does not change the persistent state of a document bool Document::DeleteChars(int pos, int len) { - if (len == 0) + if (len <= 0) return false; if ((pos + len) > Length()) return false; @@ -549,6 +806,22 @@ bool Document::InsertString(int position, const char *s, int insertLength) { return !cb.IsReadOnly(); } +int SCI_METHOD Document::AddData(char *data, int length) { + try { + int position = Length(); + InsertString(position,data, length); + } catch (std::bad_alloc &) { + return SC_STATUS_BADALLOC; + } catch (...) { + return SC_STATUS_FAILURE; + } + return 0; +} + +void * SCI_METHOD Document::ConvertToDocument() { + return this; +} + int Document::Undo() { int newPos = -1; CheckReadOnly(); @@ -559,6 +832,10 @@ int Document::Undo() { bool multiLine = false; int steps = cb.StartUndo(); //Platform::DebugPrintf("Steps=%d\n", steps); + int coalescedRemovePos = -1; + int coalescedRemoveLen = 0; + int prevRemoveActionPos = -1; + int prevRemoveActionLen = 0; for (int step = 0; step < steps; step++) { const int prevLinesTotal = LinesTotal(); const Action &action = cb.GetUndoStep(); @@ -569,15 +846,20 @@ int Document::Undo() { DocModification dm(SC_MOD_CONTAINER | SC_PERFORMED_UNDO); dm.token = action.position; NotifyModified(dm); + if (!action.mayCoalesce) { + coalescedRemovePos = -1; + coalescedRemoveLen = 0; + prevRemoveActionPos = -1; + prevRemoveActionLen = 0; + } } else { NotifyModified(DocModification( SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action)); } cb.PerformUndoStep(); - int cellPosition = action.position; if (action.at != containerAction) { - ModifiedAt(cellPosition); - newPos = cellPosition; + ModifiedAt(action.position); + newPos = action.position; } int modFlags = SC_PERFORMED_UNDO; @@ -585,8 +867,22 @@ int Document::Undo() { if (action.at == removeAction) { newPos += action.lenData; modFlags |= SC_MOD_INSERTTEXT; + if ((coalescedRemoveLen > 0) && + (action.position == prevRemoveActionPos || action.position == (prevRemoveActionPos + prevRemoveActionLen))) { + coalescedRemoveLen += action.lenData; + newPos = coalescedRemovePos + coalescedRemoveLen; + } else { + coalescedRemovePos = action.position; + coalescedRemoveLen = action.lenData; + } + prevRemoveActionPos = action.position; + prevRemoveActionLen = action.lenData; } else if (action.at == insertAction) { modFlags |= SC_MOD_DELETETEXT; + coalescedRemovePos = -1; + coalescedRemoveLen = 0; + prevRemoveActionPos = -1; + prevRemoveActionLen = 0; } if (steps > 1) modFlags |= SC_MULTISTEPUNDOREDO; @@ -598,7 +894,7 @@ int Document::Undo() { if (multiLine) modFlags |= SC_MULTILINEUNDOREDO; } - NotifyModified(DocModification(modFlags, cellPosition, action.lenData, + NotifyModified(DocModification(modFlags, action.position, action.lenData, linesAdded, action.data)); } @@ -684,7 +980,7 @@ bool Document::InsertChar(int pos, char ch) { * Insert a null terminated string. */ bool Document::InsertCString(int position, const char *s) { - return InsertString(position, s, strlen(s)); + return InsertString(position, s, static_cast<int>(s ? strlen(s) : 0)); } void Document::ChangeChar(int pos, char ch) { @@ -702,44 +998,38 @@ void Document::DelCharBack(int pos) { } else if (IsCrLf(pos - 2)) { DeleteChars(pos - 2, 2); } else if (dbcsCodePage) { - int startChar = MovePositionOutsideChar(pos - 1, -1, false); + int startChar = NextPosition(pos, -1); DeleteChars(startChar, pos - startChar); } else { DeleteChars(pos - 1, 1); } } -static bool isindentchar(char ch) { - return (ch == ' ') || (ch == '\t'); -} - static int NextTab(int pos, int tabSize) { return ((pos / tabSize) + 1) * tabSize; } -static void CreateIndentation(char *linebuf, int length, int indent, int tabSize, bool insertSpaces) { - length--; // ensure space for \0 +static std::string CreateIndentation(int indent, int tabSize, bool insertSpaces) { + std::string indentation; if (!insertSpaces) { - while ((indent >= tabSize) && (length > 0)) { - *linebuf++ = '\t'; + while (indent >= tabSize) { + indentation += '\t'; indent -= tabSize; - length--; } } - while ((indent > 0) && (length > 0)) { - *linebuf++ = ' '; + while (indent > 0) { + indentation += ' '; indent--; - length--; } - *linebuf = '\0'; + return indentation; } -int Document::GetLineIndentation(int line) { +int SCI_METHOD Document::GetLineIndentation(int line) { int indent = 0; if ((line >= 0) && (line < LinesTotal())) { int lineStart = LineStart(line); int length = Length(); - for (int i = lineStart;i < length;i++) { + for (int i = lineStart; i < length; i++) { char ch = cb.CharAt(i); if (ch == ' ') indent++; @@ -757,13 +1047,12 @@ void Document::SetLineIndentation(int line, int indent) { if (indent < 0) indent = 0; if (indent != indentOfLine) { - char linebuf[1000]; - CreateIndentation(linebuf, sizeof(linebuf), indent, tabInChars, !useTabs); + std::string linebuf = CreateIndentation(indent, tabInChars, !useTabs); int thisLineStart = LineStart(line); int indentPos = GetLineIndentPosition(line); UndoGroup ug(this); DeleteChars(thisLineStart, indentPos - thisLineStart); - InsertCString(thisLineStart, linebuf); + InsertCString(thisLineStart, linebuf.c_str()); } } @@ -772,7 +1061,7 @@ int Document::GetLineIndentPosition(int line) const { return 0; int pos = LineStart(line); int length = Length(); - while ((pos < length) && isindentchar(cb.CharAt(pos))) { + while ((pos < length) && IsSpaceOrTab(cb.CharAt(pos))) { pos++; } return pos; @@ -782,7 +1071,7 @@ int Document::GetColumn(int pos) { int column = 0; int line = LineFromPosition(pos); if ((line >= 0) && (line < LinesTotal())) { - for (int i = LineStart(line);i < pos;) { + for (int i = LineStart(line); i < pos;) { char ch = cb.CharAt(i); if (ch == '\t') { column = NextTab(column, tabInChars); @@ -795,13 +1084,27 @@ int Document::GetColumn(int pos) { return column; } else { column++; - i = MovePositionOutsideChar(i + 1, 1, false); + i = NextPosition(i, 1); } } } return column; } +int Document::CountCharacters(int startPos, int endPos) { + startPos = MovePositionOutsideChar(startPos, 1, false); + endPos = MovePositionOutsideChar(endPos, -1, false); + int count = 0; + int i = startPos; + while (i < endPos) { + count++; + if (IsCrLf(i)) + i++; + i = NextPosition(i, 1); + } + return count; +} + int Document::FindColumn(int line, int column) { int position = LineStart(line); if ((line >= 0) && (line < LinesTotal())) { @@ -810,6 +1113,8 @@ int Document::FindColumn(int line, int column) { char ch = cb.CharAt(position); if (ch == '\t') { columnCurrent = NextTab(columnCurrent, tabInChars); + if (columnCurrent > column) + return position; position++; } else if (ch == '\r') { return position; @@ -817,7 +1122,7 @@ int Document::FindColumn(int line, int column) { return position; } else { columnCurrent++; - position = MovePositionOutsideChar(position + 1, 1, false); + position = NextPosition(position, 1); } } } @@ -841,17 +1146,17 @@ void Document::Indent(bool forwards, int lineBottom, int lineTop) { // Convert line endings for a piece of text to a particular mode. // Stop at len or when a NUL is found. // Caller must delete the returned pointer. -char *Document::TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolMode) { +char *Document::TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolModeWanted) { char *dest = new char[2 * len + 1]; const char *sptr = s; char *dptr = dest; for (size_t i = 0; (i < len) && (*sptr != '\0'); i++) { if (*sptr == '\n' || *sptr == '\r') { - if (eolMode == SC_EOL_CR) { + if (eolModeWanted == SC_EOL_CR) { *dptr++ = '\r'; - } else if (eolMode == SC_EOL_LF) { + } else if (eolModeWanted == SC_EOL_LF) { *dptr++ = '\n'; - } else { // eolMode == SC_EOL_CRLF + } else { // eolModeWanted == SC_EOL_CRLF *dptr++ = '\r'; *dptr++ = '\n'; } @@ -947,7 +1252,7 @@ int Document::ParaDown(int pos) { } CharClassify::cc Document::WordCharClass(unsigned char ch) { - if ((SC_CP_UTF8 == dbcsCodePage) && (ch >= 0x80)) + if ((SC_CP_UTF8 == dbcsCodePage) && (!UTF8IsAscii(ch))) return CharClassify::ccWord; return charClass.GetClass(ch); } @@ -969,7 +1274,7 @@ int Document::ExtendWordSelect(int pos, int delta, bool onlyWordCharacters) { while (pos < (Length()) && (WordCharClass(cb.CharAt(pos)) == ccStart)) pos++; } - return MovePositionOutsideChar(pos, delta); + return MovePositionOutsideChar(pos, delta, true); } /** @@ -1074,79 +1379,200 @@ static inline char MakeLowerCase(char ch) { return static_cast<char>(ch - 'A' + 'a'); } +CaseFolderTable::CaseFolderTable() { + for (size_t iChar=0; iChar<sizeof(mapping); iChar++) { + mapping[iChar] = static_cast<char>(iChar); + } +} + +CaseFolderTable::~CaseFolderTable() { +} + +size_t CaseFolderTable::Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) { + if (lenMixed > sizeFolded) { + return 0; + } else { + for (size_t i=0; i<lenMixed; i++) { + folded[i] = mapping[static_cast<unsigned char>(mixed[i])]; + } + return lenMixed; + } +} + +void CaseFolderTable::SetTranslation(char ch, char chTranslation) { + mapping[static_cast<unsigned char>(ch)] = chTranslation; +} + +void CaseFolderTable::StandardASCII() { + for (size_t iChar=0; iChar<sizeof(mapping); iChar++) { + if (iChar >= 'A' && iChar <= 'Z') { + mapping[iChar] = static_cast<char>(iChar - 'A' + 'a'); + } else { + mapping[iChar] = static_cast<char>(iChar); + } + } +} + +bool Document::MatchesWordOptions(bool word, bool wordStart, int pos, int length) { + return (!word && !wordStart) || + (word && IsWordAt(pos, pos + length)) || + (wordStart && IsWordStartAt(pos)); +} + /** * Find text in document, supporting both forward and backward * searches (just pass minPos > maxPos to do a backward search) * Has not been tested with backwards DBCS searches yet. */ -long Document::FindText(int minPos, int maxPos, const char *s, +long Document::FindText(int minPos, int maxPos, const char *search, bool caseSensitive, bool word, bool wordStart, bool regExp, int flags, - int *length) { + int *length, CaseFolder *pcf) { + if (*length <= 0) + return minPos; if (regExp) { if (!regex) regex = CreateRegexSearch(&charClass); - return regex->FindText(this, minPos, maxPos, s, caseSensitive, word, wordStart, flags, length); + return regex->FindText(this, minPos, maxPos, search, caseSensitive, word, wordStart, flags, length); } else { - bool forward = minPos <= maxPos; - int increment = forward ? 1 : -1; + const bool forward = minPos <= maxPos; + const int increment = forward ? 1 : -1; // Range endpoints should not be inside DBCS characters, but just in case, move them. - int startPos = MovePositionOutsideChar(minPos, increment, false); - int endPos = MovePositionOutsideChar(maxPos, increment, false); + const int startPos = MovePositionOutsideChar(minPos, increment, false); + const int endPos = MovePositionOutsideChar(maxPos, increment, false); // Compute actual search ranges needed - int lengthFind = *length; - if (lengthFind == -1) - lengthFind = static_cast<int>(strlen(s)); - int endSearch = endPos; - if (startPos <= endPos) { - endSearch = endPos - lengthFind + 1; - } + const int lengthFind = *length; + //Platform::DebugPrintf("Find %d %d %s %d\n", startPos, endPos, ft->lpstrText, lengthFind); - char firstChar = s[0]; - if (!caseSensitive) - firstChar = static_cast<char>(MakeUpperCase(firstChar)); - int pos = forward ? startPos : (startPos - 1); - while (forward ? (pos < endSearch) : (pos >= endSearch)) { - char ch = CharAt(pos); - if (caseSensitive) { - if (ch == firstChar) { - bool found = true; - if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false; - for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) { - ch = CharAt(pos + posMatch); - if (ch != s[posMatch]) - found = false; + const int limitPos = Platform::Maximum(startPos, endPos); + int pos = startPos; + if (!forward) { + // Back all of a character + pos = NextPosition(pos, increment); + } + if (caseSensitive) { + const int endSearch = (startPos <= endPos) ? endPos - lengthFind + 1 : endPos; + const char charStartSearch = search[0]; + while (forward ? (pos < endSearch) : (pos >= endSearch)) { + if (CharAt(pos) == charStartSearch) { + bool found = (pos + lengthFind) <= limitPos; + for (int indexSearch = 1; (indexSearch < lengthFind) && found; indexSearch++) { + found = CharAt(pos + indexSearch) == search[indexSearch]; } - if (found) { - if ((!word && !wordStart) || - (word && IsWordAt(pos, pos + lengthFind)) || - (wordStart && IsWordStartAt(pos))) - return pos; + if (found && MatchesWordOptions(word, wordStart, pos, lengthFind)) { + return pos; } } - } else { - if (MakeUpperCase(ch) == firstChar) { - bool found = true; - if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false; - for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) { - ch = CharAt(pos + posMatch); - if (MakeUpperCase(ch) != MakeUpperCase(s[posMatch])) - found = false; + if (!NextCharacter(pos, increment)) + break; + } + } else if (SC_CP_UTF8 == dbcsCodePage) { + const size_t maxFoldingExpansion = 4; + std::vector<char> searchThing(lengthFind * UTF8MaxBytes * maxFoldingExpansion + 1); + const int lenSearch = static_cast<int>( + pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind)); + char bytes[UTF8MaxBytes + 1]; + char folded[UTF8MaxBytes * maxFoldingExpansion + 1]; + while (forward ? (pos < endPos) : (pos >= endPos)) { + int widthFirstCharacter = 0; + int posIndexDocument = pos; + int indexSearch = 0; + bool characterMatches = true; + for (;;) { + const unsigned char leadByte = static_cast<unsigned char>(cb.CharAt(posIndexDocument)); + bytes[0] = leadByte; + int widthChar = 1; + if (!UTF8IsAscii(leadByte)) { + const int widthCharBytes = UTF8BytesOfLead[leadByte]; + for (int b=1; b<widthCharBytes; b++) { + bytes[b] = cb.CharAt(posIndexDocument+b); + } + widthChar = UTF8Classify(reinterpret_cast<const unsigned char *>(bytes), widthCharBytes) & UTF8MaskWidth; } - if (found) { - if ((!word && !wordStart) || - (word && IsWordAt(pos, pos + lengthFind)) || - (wordStart && IsWordStartAt(pos))) - return pos; + if (!widthFirstCharacter) + widthFirstCharacter = widthChar; + if ((posIndexDocument + widthChar) > limitPos) + break; + const int lenFlat = static_cast<int>(pcf->Fold(folded, sizeof(folded), bytes, widthChar)); + folded[lenFlat] = 0; + // Does folded match the buffer + characterMatches = 0 == memcmp(folded, &searchThing[0] + indexSearch, lenFlat); + if (!characterMatches) + break; + posIndexDocument += widthChar; + indexSearch += lenFlat; + if (indexSearch >= lenSearch) + break; + } + if (characterMatches && (indexSearch == static_cast<int>(lenSearch))) { + if (MatchesWordOptions(word, wordStart, pos, posIndexDocument - pos)) { + *length = posIndexDocument - pos; + return pos; } } + if (forward) { + pos += widthFirstCharacter; + } else { + if (!NextCharacter(pos, increment)) + break; + } } - pos += increment; - if (dbcsCodePage && (pos >= 0)) { - // Ensure trying to match from start of character - pos = MovePositionOutsideChar(pos, increment, false); + } else if (dbcsCodePage) { + const size_t maxBytesCharacter = 2; + const size_t maxFoldingExpansion = 4; + std::vector<char> searchThing(lengthFind * maxBytesCharacter * maxFoldingExpansion + 1); + const int lenSearch = static_cast<int>( + pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind)); + while (forward ? (pos < endPos) : (pos >= endPos)) { + int indexDocument = 0; + int indexSearch = 0; + bool characterMatches = true; + while (characterMatches && + ((pos + indexDocument) < limitPos) && + (indexSearch < lenSearch)) { + char bytes[maxBytesCharacter + 1]; + bytes[0] = cb.CharAt(pos + indexDocument); + const int widthChar = IsDBCSLeadByte(bytes[0]) ? 2 : 1; + if (widthChar == 2) + bytes[1] = cb.CharAt(pos + indexDocument + 1); + if ((pos + indexDocument + widthChar) > limitPos) + break; + char folded[maxBytesCharacter * maxFoldingExpansion + 1]; + const int lenFlat = static_cast<int>(pcf->Fold(folded, sizeof(folded), bytes, widthChar)); + folded[lenFlat] = 0; + // Does folded match the buffer + characterMatches = 0 == memcmp(folded, &searchThing[0] + indexSearch, lenFlat); + indexDocument += widthChar; + indexSearch += lenFlat; + } + if (characterMatches && (indexSearch == static_cast<int>(lenSearch))) { + if (MatchesWordOptions(word, wordStart, pos, indexDocument)) { + *length = indexDocument; + return pos; + } + } + if (!NextCharacter(pos, increment)) + break; + } + } else { + const int endSearch = (startPos <= endPos) ? endPos - lengthFind + 1 : endPos; + std::vector<char> searchThing(lengthFind + 1); + pcf->Fold(&searchThing[0], searchThing.size(), search, lengthFind); + while (forward ? (pos < endSearch) : (pos >= endSearch)) { + bool found = (pos + lengthFind) <= limitPos; + for (int indexSearch = 0; (indexSearch < lengthFind) && found; indexSearch++) { + char ch = CharAt(pos + indexSearch); + char folded[2]; + pcf->Fold(folded, sizeof(folded), &ch, 1); + found = folded[0] == searchThing[indexSearch]; + } + if (found && MatchesWordOptions(word, wordStart, pos, lengthFind)) { + return pos; + } + if (!NextCharacter(pos, increment)) + break; } } } @@ -1155,7 +1581,10 @@ long Document::FindText(int minPos, int maxPos, const char *s, } const char *Document::SubstituteByPosition(const char *text, int *length) { - return regex->SubstituteByPosition(this, text, length); + if (regex) + return regex->SubstituteByPosition(this, text, length); + else + return 0; } int Document::LinesTotal() const { @@ -1189,17 +1618,21 @@ void Document::SetCharClasses(const unsigned char *chars, CharClassify::cc newCh charClass.SetCharClasses(chars, newCharClass); } +int Document::GetCharsOfClass(CharClassify::cc characterClass, unsigned char *buffer) { + return charClass.GetCharsOfClass(characterClass, buffer); +} + void Document::SetStylingBits(int bits) { stylingBits = bits; stylingBitsMask = (1 << stylingBits) - 1; } -void Document::StartStyling(int position, char mask) { +void SCI_METHOD Document::StartStyling(int position, char mask) { stylingMask = mask; endStyled = position; } -bool Document::SetStyleFor(int length, char style) { +bool SCI_METHOD Document::SetStyleFor(int length, char style) { if (enteredStyling != 0) { return false; } else { @@ -1217,7 +1650,7 @@ bool Document::SetStyleFor(int length, char style) { } } -bool Document::SetStyles(int length, const char *styles) { +bool SCI_METHOD Document::SetStyles(int length, const char *styles) { if (enteredStyling != 0) { return false; } else { @@ -1248,110 +1681,136 @@ bool Document::SetStyles(int length, const char *styles) { void Document::EnsureStyledTo(int pos) { if ((enteredStyling == 0) && (pos > GetEndStyled())) { IncrementStyleClock(); - // Ask the watchers to style, and stop as soon as one responds. - for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) { - watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos); + if (pli && !pli->UseContainerLexing()) { + int lineEndStyled = LineFromPosition(GetEndStyled()); + int endStyledTo = LineStart(lineEndStyled); + pli->Colourise(endStyledTo, pos); + } else { + // Ask the watchers to style, and stop as soon as one responds. + for (int i = 0; pos > GetEndStyled() && i < lenWatchers; i++) { + watchers[i].watcher->NotifyStyleNeeded(this, watchers[i].userData, pos); + } } } } -int Document::SetLineState(int line, int state) { - int statePrevious = static_cast<LineState*>(perLineData[ldState])->SetLineState(line, state); +void Document::LexerChanged() { + // Tell the watchers the lexer has changed. + for (int i = 0; i < lenWatchers; i++) { + watchers[i].watcher->NotifyLexerChanged(this, watchers[i].userData); + } +} + +int SCI_METHOD Document::SetLineState(int line, int state) { + int statePrevious = static_cast<LineState *>(perLineData[ldState])->SetLineState(line, state); if (state != statePrevious) { - DocModification mh(SC_MOD_CHANGELINESTATE, 0, 0, 0, 0, line); + DocModification mh(SC_MOD_CHANGELINESTATE, LineStart(line), 0, 0, 0, line); NotifyModified(mh); } return statePrevious; } -int Document::GetLineState(int line) { - return static_cast<LineState*>(perLineData[ldState])->GetLineState(line); +int SCI_METHOD Document::GetLineState(int line) const { + return static_cast<LineState *>(perLineData[ldState])->GetLineState(line); +} + +int Document::GetMaxLineState() { + return static_cast<LineState *>(perLineData[ldState])->GetMaxLineState(); } -int Document::GetMaxLineState() { - return static_cast<LineState*>(perLineData[ldState])->GetMaxLineState(); +void SCI_METHOD Document::ChangeLexerState(int start, int end) { + DocModification mh(SC_MOD_LEXERSTATE, start, end-start, 0, 0, 0); + NotifyModified(mh); } StyledText Document::MarginStyledText(int line) { - LineAnnotation *pla = static_cast<LineAnnotation*>(perLineData[ldMargin]); - return StyledText(pla->Length(line), pla->Text(line), + LineAnnotation *pla = static_cast<LineAnnotation *>(perLineData[ldMargin]); + return StyledText(pla->Length(line), pla->Text(line), pla->MultipleStyles(line), pla->Style(line), pla->Styles(line)); } void Document::MarginSetText(int line, const char *text) { - static_cast<LineAnnotation*>(perLineData[ldMargin])->SetText(line, text); + static_cast<LineAnnotation *>(perLineData[ldMargin])->SetText(line, text); DocModification mh(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line); NotifyModified(mh); } void Document::MarginSetStyle(int line, int style) { - static_cast<LineAnnotation*>(perLineData[ldMargin])->SetStyle(line, style); + static_cast<LineAnnotation *>(perLineData[ldMargin])->SetStyle(line, style); + NotifyModified(DocModification(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line)); } void Document::MarginSetStyles(int line, const unsigned char *styles) { - static_cast<LineAnnotation*>(perLineData[ldMargin])->SetStyles(line, styles); + static_cast<LineAnnotation *>(perLineData[ldMargin])->SetStyles(line, styles); + NotifyModified(DocModification(SC_MOD_CHANGEMARGIN, LineStart(line), 0, 0, 0, line)); } int Document::MarginLength(int line) const { - return static_cast<LineAnnotation*>(perLineData[ldMargin])->Length(line); + return static_cast<LineAnnotation *>(perLineData[ldMargin])->Length(line); } void Document::MarginClearAll() { int maxEditorLine = LinesTotal(); - for (int l=0;l<maxEditorLine;l++) + for (int l=0; l<maxEditorLine; l++) MarginSetText(l, 0); // Free remaining data - static_cast<LineAnnotation*>(perLineData[ldMargin])->ClearAll(); + static_cast<LineAnnotation *>(perLineData[ldMargin])->ClearAll(); } bool Document::AnnotationAny() const { - return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->AnySet(); + return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->AnySet(); } StyledText Document::AnnotationStyledText(int line) { - LineAnnotation *pla = static_cast<LineAnnotation*>(perLineData[ldAnnotation]); - return StyledText(pla->Length(line), pla->Text(line), + LineAnnotation *pla = static_cast<LineAnnotation *>(perLineData[ldAnnotation]); + return StyledText(pla->Length(line), pla->Text(line), pla->MultipleStyles(line), pla->Style(line), pla->Styles(line)); } void Document::AnnotationSetText(int line, const char *text) { - const int linesBefore = AnnotationLines(line); - static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetText(line, text); - const int linesAfter = AnnotationLines(line); - DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line); - mh.annotationLinesAdded = linesAfter - linesBefore; - NotifyModified(mh); + if (line >= 0 && line < LinesTotal()) { + const int linesBefore = AnnotationLines(line); + static_cast<LineAnnotation *>(perLineData[ldAnnotation])->SetText(line, text); + const int linesAfter = AnnotationLines(line); + DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line); + mh.annotationLinesAdded = linesAfter - linesBefore; + NotifyModified(mh); + } } void Document::AnnotationSetStyle(int line, int style) { - static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetStyle(line, style); + static_cast<LineAnnotation *>(perLineData[ldAnnotation])->SetStyle(line, style); + DocModification mh(SC_MOD_CHANGEANNOTATION, LineStart(line), 0, 0, 0, line); + NotifyModified(mh); } void Document::AnnotationSetStyles(int line, const unsigned char *styles) { - static_cast<LineAnnotation*>(perLineData[ldAnnotation])->SetStyles(line, styles); + if (line >= 0 && line < LinesTotal()) { + static_cast<LineAnnotation *>(perLineData[ldAnnotation])->SetStyles(line, styles); + } } int Document::AnnotationLength(int line) const { - return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Length(line); + return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->Length(line); } int Document::AnnotationLines(int line) const { - return static_cast<LineAnnotation*>(perLineData[ldAnnotation])->Lines(line); + return static_cast<LineAnnotation *>(perLineData[ldAnnotation])->Lines(line); } void Document::AnnotationClearAll() { int maxEditorLine = LinesTotal(); - for (int l=0;l<maxEditorLine;l++) + for (int l=0; l<maxEditorLine; l++) AnnotationSetText(l, 0); // Free remaining data - static_cast<LineAnnotation*>(perLineData[ldAnnotation])->ClearAll(); + static_cast<LineAnnotation *>(perLineData[ldAnnotation])->ClearAll(); } void Document::IncrementStyleClock() { styleClock = (styleClock + 1) % 0x100000; } -void Document::DecorationFillRange(int position, int value, int fillLength) { +void SCI_METHOD Document::DecorationFillRange(int position, int value, int fillLength) { if (decorations.FillRange(position, value, fillLength)) { DocModification mh(SC_MOD_CHANGEINDICATOR | SC_PERFORMED_USER, position, fillLength); @@ -1523,11 +1982,11 @@ bool IsLineEndChar(char c) { int Document::ExtendStyleRange(int pos, int delta, bool singleLine) { int sStart = cb.StyleAt(pos); if (delta < 0) { - while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))) ) + while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos)))) pos--; pos++; } else { - while (pos < (Length()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))) ) + while (pos < (Length()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos)))) pos++; } return pos; @@ -1567,9 +2026,8 @@ int Document::BraceMatch(int position, int /*maxReStyle*/) { if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<') direction = 1; int depth = 1; - position = position + direction; + position = NextPosition(position, direction); while ((position >= 0) && (position < Length())) { - position = MovePositionOutsideChar(position, direction); char chAtPos = CharAt(position); char styAtPos = static_cast<char>(StyleAt(position) & stylingBitsMask); if ((position > GetEndStyled()) || (styAtPos == styBrace)) { @@ -1580,7 +2038,10 @@ int Document::BraceMatch(int position, int /*maxReStyle*/) { if (depth == 0) return position; } - position = position + direction; + int positionBeforeMove = position; + position = NextPosition(position, direction); + if (position == positionBeforeMove) + break; } return - 1; } @@ -1600,7 +2061,7 @@ public: bool caseSensitive, bool word, bool wordStart, int flags, int *length); - virtual const char *SubstituteByPosition(Document* doc, const char *text, int *length); + virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length); private: RESearch search; @@ -1656,10 +2117,17 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s // the start position is at end of line or between line end characters. lineRangeStart++; startPos = doc->LineStart(lineRangeStart); + } else if ((increment == -1) && + (startPos <= doc->LineStart(lineRangeStart)) && + (lineRangeStart > lineRangeEnd)) { + // the start position is at beginning of line. + lineRangeStart--; + startPos = doc->LineEnd(lineRangeStart); } int pos = -1; int lenRet = 0; char searchEnd = s[*length - 1]; + char searchEndPrev = (*length > 1) ? s[*length - 2] : '\0'; int lineRangeBreak = lineRangeEnd + increment; for (int line = lineRangeStart; line != lineRangeBreak; line += increment) { int startOfLine = doc->LineStart(line); @@ -1671,7 +2139,7 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s startOfLine = startPos; } if (line == lineRangeEnd) { - if ((endPos != endOfLine) && (searchEnd == '$')) + if ((endPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\')) continue; // Can't match end of line if end position before end of line endOfLine = endPos; } @@ -1682,7 +2150,7 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s startOfLine = endPos; } if (line == lineRangeStart) { - if ((startPos != endOfLine) && (searchEnd == '$')) + if ((startPos != endOfLine) && (searchEnd == '$') && (searchEndPrev != '\\')) continue; // Can't match end of line if start position before end of line endOfLine = startPos; } @@ -1693,7 +2161,8 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s if (success) { pos = search.bopat[0]; lenRet = search.eopat[0] - search.bopat[0]; - if (increment == -1) { + // There can be only one start of a line, so no need to look for last match in line + if ((increment == -1) && (s[0] != '^')) { // Check for the last match on this line. int repetitions = 1000; // Break out of infinite loop while (success && (search.eopat[0] <= endOfLine) && (repetitions--)) { @@ -1715,7 +2184,7 @@ long BuiltinRegex::FindText(Document *doc, int minPos, int maxPos, const char *s return pos; } -const char *BuiltinRegex::SubstituteByPosition(Document* doc, const char *text, int *length) { +const char *BuiltinRegex::SubstituteByPosition(Document *doc, const char *text, int *length) { delete []substituted; substituted = 0; DocumentIndexer di(doc, doc->Length()); @@ -1724,7 +2193,7 @@ const char *BuiltinRegex::SubstituteByPosition(Document* doc, const char *text, unsigned int lenResult = 0; for (int i = 0; i < *length; i++) { if (text[i] == '\\') { - if (text[i + 1] >= '1' && text[i + 1] <= '9') { + if (text[i + 1] >= '0' && text[i + 1] <= '9') { unsigned int patNum = text[i + 1] - '0'; lenResult += search.eopat[patNum] - search.bopat[patNum]; i++; @@ -1737,6 +2206,7 @@ const char *BuiltinRegex::SubstituteByPosition(Document* doc, const char *text, case 'r': case 't': case 'v': + case '\\': i++; } lenResult++; @@ -1749,7 +2219,7 @@ const char *BuiltinRegex::SubstituteByPosition(Document* doc, const char *text, char *o = substituted; for (int j = 0; j < *length; j++) { if (text[j] == '\\') { - if (text[j + 1] >= '1' && text[j + 1] <= '9') { + if (text[j + 1] >= '0' && text[j + 1] <= '9') { unsigned int patNum = text[j + 1] - '0'; unsigned int len = search.eopat[patNum] - search.bopat[patNum]; if (search.pat[patNum]) // Will be null if try for a match that did not occur @@ -1780,6 +2250,9 @@ const char *BuiltinRegex::SubstituteByPosition(Document* doc, const char *text, case 'v': *o++ = '\v'; break; + case '\\': + *o++ = '\\'; + break; default: *o++ = '\\'; j--; diff --git a/src/stc/scintilla/src/Document.h b/src/stc/scintilla/src/Document.h index 240d59e390..30c6aee1cd 100644 --- a/src/stc/scintilla/src/Document.h +++ b/src/stc/scintilla/src/Document.h @@ -2,7 +2,7 @@ /** @file Document.h ** Text document that handles notifications, DBCS, styling, words and end of line. **/ -// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> +// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. #ifndef DOCUMENT_H @@ -32,10 +32,10 @@ public: Range(Position pos=0) : start(pos), end(pos) { - }; + } Range(Position start_, Position end_) : start(start_), end(end_) { - }; + } bool Valid() const { return (start != invalidPosition) && (end != invalidPosition); @@ -81,17 +81,17 @@ class Document; */ class RegexSearchBase { public: - virtual ~RegexSearchBase(){} + virtual ~RegexSearchBase() {} - virtual long FindText(Document* doc, int minPos, int maxPos, const char *s, + virtual long FindText(Document *doc, int minPos, int maxPos, const char *s, bool caseSensitive, bool word, bool wordStart, int flags, int *length) = 0; ///@return String with the substitutions, must remain valid until the next call or destruction - virtual const char *SubstituteByPosition(Document* doc, const char *text, int *length) = 0; + virtual const char *SubstituteByPosition(Document *doc, const char *text, int *length) = 0; }; /// Factory function for RegexSearchBase -extern RegexSearchBase* CreateRegexSearch(CharClassify *charClassTable); +extern RegexSearchBase *CreateRegexSearch(CharClassify *charClassTable); struct StyledText { size_t length; @@ -99,7 +99,7 @@ struct StyledText { bool multipleStyles; size_t style; const unsigned char *styles; - StyledText( size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) : + StyledText(size_t length_, const char *text_, bool multipleStyles_, int style_, const unsigned char *styles_) : length(length_), text(text_), multipleStyles(multipleStyles_), style(style_), styles(styles_) { } // Return number of bytes from start to before '\n' or end of text. @@ -115,9 +115,85 @@ struct StyledText { } }; +class HighlightDelimiter { +public: + HighlightDelimiter() : isEnabled(false) { + Clear(); + } + + void Clear() { + beginFoldBlock = -1; + endFoldBlock = -1; + firstChangeableLineBefore = -1; + firstChangeableLineAfter = -1; + } + + bool NeedsDrawing(int line) { + return isEnabled && (line <= firstChangeableLineBefore || line >= firstChangeableLineAfter); + } + + bool IsFoldBlockHighlighted(int line) { + return isEnabled && beginFoldBlock != -1 && beginFoldBlock <= line && line <= endFoldBlock; + } + + bool IsHeadOfFoldBlock(int line) { + return beginFoldBlock == line && line < endFoldBlock; + } + + bool IsBodyOfFoldBlock(int line) { + return beginFoldBlock != -1 && beginFoldBlock < line && line < endFoldBlock; + } + + bool IsTailOfFoldBlock(int line) { + return beginFoldBlock != -1 && beginFoldBlock < line && line == endFoldBlock; + } + + int beginFoldBlock; // Begin of current fold block + int endFoldBlock; // End of current fold block + int firstChangeableLineBefore; // First line that triggers repaint before starting line that determined current fold block + int firstChangeableLineAfter; // First line that triggers repaint after starting line that determined current fold block + bool isEnabled; +}; + +class CaseFolder { +public: + virtual ~CaseFolder() { + } + virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) = 0; +}; + +class CaseFolderTable : public CaseFolder { +protected: + char mapping[256]; +public: + CaseFolderTable(); + virtual ~CaseFolderTable(); + virtual size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed); + void SetTranslation(char ch, char chTranslation); + void StandardASCII(); +}; + +class Document; + +class LexInterface { +protected: + Document *pdoc; + ILexer *instance; + bool performingStyle; ///< Prevent reentrance +public: + LexInterface(Document *pdoc_) : pdoc(pdoc_), instance(0), performingStyle(false) { + } + virtual ~LexInterface() { + } + void Colourise(int start, int end); + bool UseContainerLexing() const { + return instance == 0; + } +}; + /** */ -class Document : PerLine { +class Document : PerLine, public IDocument, public ILoader { public: /** Used to pair watcher pointer with user data. */ @@ -147,13 +223,16 @@ private: int lenWatchers; // ldSize is not real data - it is for dimensions and loops - enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize }; + enum lineData { ldMarkers, ldLevels, ldState, ldMargin, ldAnnotation, ldSize }; PerLine *perLineData[ldSize]; bool matchesValid; - RegexSearchBase* regex; + RegexSearchBase *regex; public: + + LexInterface *pli; + int stylingBits; int stylingBitsMask; @@ -173,24 +252,37 @@ public: virtual ~Document(); int AddRef(); - int Release(); + int SCI_METHOD Release(); virtual void Init(); virtual void InsertLine(int line); virtual void RemoveLine(int line); - int LineFromPosition(int pos) const; + int SCI_METHOD Version() const { + return dvOriginal; + } + + void SCI_METHOD SetErrorStatus(int status); + + int SCI_METHOD LineFromPosition(int pos) const; int ClampPositionIntoDocument(int pos); bool IsCrLf(int pos); int LenChar(int pos); - bool InGoodUTF8(int pos, int &start, int &end); + bool InGoodUTF8(int pos, int &start, int &end) const; int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true); + int NextPosition(int pos, int moveDir) const; + bool NextCharacter(int &pos, int moveDir); // Returns true if pos changed + int SCI_METHOD CodePage() const; + bool SCI_METHOD IsDBCSLeadByte(char ch) const; + int SafeSegment(const char *text, int length, int lengthSegment); // Gateways to modifying document void ModifiedAt(int pos); void CheckReadOnly(); bool DeleteChars(int pos, int len); bool InsertString(int position, const char *s, int insertLength); + int SCI_METHOD AddData(char *data, int length); + void * SCI_METHOD ConvertToDocument(); int Undo(); int Redo(); bool CanUndo() { return cb.CanUndo(); } @@ -205,15 +297,18 @@ public: void AddUndoAction(int token, bool mayCoalesce) { cb.AddUndoAction(token, mayCoalesce); } void SetSavePoint(); bool IsSavePoint() { return cb.IsSavePoint(); } - const char *BufferPointer() { return cb.BufferPointer(); } + const char * SCI_METHOD BufferPointer() { return cb.BufferPointer(); } + const char *RangePointer(int position, int rangeLength) { return cb.RangePointer(position, rangeLength); } + int GapPosition() const { return cb.GapPosition(); } - int GetLineIndentation(int line); + int SCI_METHOD GetLineIndentation(int line); void SetLineIndentation(int line, int indent); int GetLineIndentPosition(int line) const; int GetColumn(int position); + int CountCharacters(int startPos, int endPos); int FindColumn(int line, int column); void Indent(bool forwards, int lineBottom, int lineTop); - static char *TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolMode); + static char *TransformLineEnds(int *pLenOut, const char *s, size_t len, int eolModeWanted); void ConvertLineEnds(int eolModeSet); void SetReadOnly(bool set) { cb.SetReadOnly(set); } bool IsReadOnly() { return cb.IsReadOnly(); } @@ -225,38 +320,43 @@ public: void DelCharBack(int pos); char CharAt(int position) { return cb.CharAt(position); } - void GetCharRange(char *buffer, int position, int lengthRetrieve) { + void SCI_METHOD GetCharRange(char *buffer, int position, int lengthRetrieve) const { cb.GetCharRange(buffer, position, lengthRetrieve); } - char StyleAt(int position) { return cb.StyleAt(position); } + char SCI_METHOD StyleAt(int position) const { return cb.StyleAt(position); } + void GetStyleRange(unsigned char *buffer, int position, int lengthRetrieve) const { + cb.GetStyleRange(buffer, position, lengthRetrieve); + } int GetMark(int line); + int MarkerNext(int lineStart, int mask) const; int AddMark(int line, int markerNum); void AddMarkSet(int line, int valueSet); void DeleteMark(int line, int markerNum); void DeleteMarkFromHandle(int markerHandle); void DeleteAllMarks(int markerNum); int LineFromHandle(int markerHandle); - int LineStart(int line) const; + int SCI_METHOD LineStart(int line) const; int LineEnd(int line) const; int LineEndPosition(int position) const; bool IsLineEndPosition(int position) const; int VCHomePosition(int position) const; - int SetLevel(int line, int level); - int GetLevel(int line); + int SCI_METHOD SetLevel(int line, int level); + int SCI_METHOD GetLevel(int line) const; void ClearLevels(); - int GetLastChild(int lineParent, int level=-1); + int GetLastChild(int lineParent, int level=-1, int lastLine=-1); int GetFoldParent(int line); + void GetHighlightDelimiters(HighlightDelimiter &hDelimiter, int line, int lastLine); void Indent(bool forwards); int ExtendWordSelect(int pos, int delta, bool onlyWordCharacters=false); int NextWordStart(int pos, int delta); int NextWordEnd(int pos, int delta); - int Length() const { return cb.Length(); } + int SCI_METHOD Length() const { return cb.Length(); } void Allocate(int newSize) { cb.Allocate(newSize); } - long FindText(int minPos, int maxPos, const char *s, - bool caseSensitive, bool word, bool wordStart, bool regExp, int flags, int *length); - long FindText(int iMessage, unsigned long wParam, long lParam); + bool MatchesWordOptions(bool word, bool wordStart, int pos, int length); + long FindText(int minPos, int maxPos, const char *search, bool caseSensitive, bool word, + bool wordStart, bool regExp, int flags, int *length, CaseFolder *pcf); const char *SubstituteByPosition(const char *text, int *length); int LinesTotal() const; @@ -264,19 +364,25 @@ public: void SetDefaultCharClasses(bool includeWordClass); void SetCharClasses(const unsigned char *chars, CharClassify::cc newCharClass); + int GetCharsOfClass(CharClassify::cc charClass, unsigned char *buffer); void SetStylingBits(int bits); - void StartStyling(int position, char mask); - bool SetStyleFor(int length, char style); - bool SetStyles(int length, const char *styles); + void SCI_METHOD StartStyling(int position, char mask); + bool SCI_METHOD SetStyleFor(int length, char style); + bool SCI_METHOD SetStyles(int length, const char *styles); int GetEndStyled() { return endStyled; } void EnsureStyledTo(int pos); + void LexerChanged(); int GetStyleClock() { return styleClock; } void IncrementStyleClock(); - void DecorationFillRange(int position, int value, int fillLength); + void SCI_METHOD DecorationSetCurrentIndicator(int indicator) { + decorations.SetCurrentIndicator(indicator); + } + void SCI_METHOD DecorationFillRange(int position, int value, int fillLength); - int SetLineState(int line, int state); - int GetLineState(int line); + int SCI_METHOD SetLineState(int line, int state); + int SCI_METHOD GetLineState(int line) const; int GetMaxLineState(); + void SCI_METHOD ChangeLexerState(int start, int end); StyledText MarginStyledText(int line); void MarginSetStyle(int line, int style); @@ -299,6 +405,7 @@ public: const WatcherWithUserData *GetWatchers() const { return watchers; } int GetLenWatchers() const { return lenWatchers; } + CharClassify::cc WordCharClass(unsigned char ch); bool IsWordPartSeparator(char ch); int WordPartLeft(int pos); int WordPartRight(int pos); @@ -310,7 +417,6 @@ public: int BraceMatch(int position, int maxReStyle); private: - CharClassify::cc WordCharClass(unsigned char ch); bool IsWordStartAt(int pos); bool IsWordEndAt(int pos); bool IsWordAt(int start, int end); @@ -324,7 +430,7 @@ class UndoGroup { Document *pdoc; bool groupNeeded; public: - UndoGroup(Document *pdoc_, bool groupNeeded_=true) : + UndoGroup(Document *pdoc_, bool groupNeeded_=true) : pdoc(pdoc_), groupNeeded(groupNeeded_) { if (groupNeeded) { pdoc->BeginUndoAction(); @@ -398,6 +504,8 @@ public: virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0; virtual void NotifyDeleted(Document *doc, void *userData) = 0; virtual void NotifyStyleNeeded(Document *doc, void *userData, int endPos) = 0; + virtual void NotifyLexerChanged(Document *doc, void *userData) = 0; + virtual void NotifyErrorOccurred(Document *doc, void *userData, int status) = 0; }; #ifdef SCI_NAMESPACE diff --git a/src/stc/scintilla/src/DocumentAccessor.cxx b/src/stc/scintilla/src/DocumentAccessor.cxx deleted file mode 100644 index a25979dc2c..0000000000 --- a/src/stc/scintilla/src/DocumentAccessor.cxx +++ /dev/null @@ -1,199 +0,0 @@ -// Scintilla source code edit control -/** @file DocumentAccessor.cxx - ** Rapid easy access to contents of a Scintilla. - **/ -// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "DocumentAccessor.h" -#include "SplitVector.h" -#include "Partitioning.h" -#include "RunStyles.h" -#include "CellBuffer.h" -#include "Scintilla.h" -#include "CharClassify.h" -#include "Decoration.h" -#include "Document.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -DocumentAccessor::~DocumentAccessor() { -} - -bool DocumentAccessor::InternalIsLeadByte(char ch) { - if (SC_CP_UTF8 == codePage) - // For lexing, all characters >= 0x80 are treated the - // same so none is considered a lead byte. - return false; - else - return Platform::IsDBCSLeadByte(codePage, ch); -} - -void DocumentAccessor::Fill(int position) { - if (lenDoc == -1) - lenDoc = pdoc->Length(); - startPos = position - slopSize; - if (startPos + bufferSize > lenDoc) - startPos = lenDoc - bufferSize; - if (startPos < 0) - startPos = 0; - endPos = startPos + bufferSize; - if (endPos > lenDoc) - endPos = lenDoc; - - pdoc->GetCharRange(buf, startPos, endPos-startPos); - buf[endPos-startPos] = '\0'; -} - -bool DocumentAccessor::Match(int pos, const char *s) { - for (int i=0; *s; i++) { - if (*s != SafeGetCharAt(pos+i)) - return false; - s++; - } - return true; -} - -char DocumentAccessor::StyleAt(int position) { - // Mask off all bits which aren't in the 'mask'. - return static_cast<char>(pdoc->StyleAt(position) & mask); -} - -int DocumentAccessor::GetLine(int position) { - return pdoc->LineFromPosition(position); -} - -int DocumentAccessor::LineStart(int line) { - return pdoc->LineStart(line); -} - -int DocumentAccessor::LevelAt(int line) { - return pdoc->GetLevel(line); -} - -int DocumentAccessor::Length() { - if (lenDoc == -1) - lenDoc = pdoc->Length(); - return lenDoc; -} - -int DocumentAccessor::GetLineState(int line) { - return pdoc->GetLineState(line); -} - -int DocumentAccessor::SetLineState(int line, int state) { - return pdoc->SetLineState(line, state); -} - -void DocumentAccessor::StartAt(unsigned int start, char chMask) { - // Store the mask specified for use with StyleAt. - mask = chMask; - pdoc->StartStyling(start, chMask); - startPosStyling = start; -} - -void DocumentAccessor::StartSegment(unsigned int pos) { - startSeg = pos; -} - -void DocumentAccessor::ColourTo(unsigned int pos, int chAttr) { - // Only perform styling if non empty range - if (pos != startSeg - 1) { - PLATFORM_ASSERT(pos >= startSeg); - if (pos < startSeg) { - return; - } - - if (validLen + (pos - startSeg + 1) >= bufferSize) - Flush(); - if (validLen + (pos - startSeg + 1) >= bufferSize) { - // Too big for buffer so send directly - pdoc->SetStyleFor(pos - startSeg + 1, static_cast<char>(chAttr)); - } else { - if (chAttr != chWhile) - chFlags = 0; - chAttr |= chFlags; - for (unsigned int i = startSeg; i <= pos; i++) { - PLATFORM_ASSERT((startPosStyling + validLen) < Length()); - styleBuf[validLen++] = static_cast<char>(chAttr); - } - } - } - startSeg = pos+1; -} - -void DocumentAccessor::SetLevel(int line, int level) { - pdoc->SetLevel(line, level); -} - -void DocumentAccessor::Flush() { - startPos = extremePosition; - lenDoc = -1; - if (validLen > 0) { - pdoc->SetStyles(validLen, styleBuf); - startPosStyling += validLen; - validLen = 0; - } -} - -int DocumentAccessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) { - int end = Length(); - int spaceFlags = 0; - - // Determines the indentation level of the current line and also checks for consistent - // indentation compared to the previous line. - // Indentation is judged consistent when the indentation whitespace of each line lines - // the same or the indentation of one line is a prefix of the other. - - int pos = LineStart(line); - char ch = (*this)[pos]; - int indent = 0; - bool inPrevPrefix = line > 0; - int posPrev = inPrevPrefix ? LineStart(line-1) : 0; - while ((ch == ' ' || ch == '\t') && (pos < end)) { - if (inPrevPrefix) { - char chPrev = (*this)[posPrev++]; - if (chPrev == ' ' || chPrev == '\t') { - if (chPrev != ch) - spaceFlags |= wsInconsistent; - } else { - inPrevPrefix = false; - } - } - if (ch == ' ') { - spaceFlags |= wsSpace; - indent++; - } else { // Tab - spaceFlags |= wsTab; - if (spaceFlags & wsSpace) - spaceFlags |= wsSpaceTab; - indent = (indent / 8 + 1) * 8; - } - ch = (*this)[++pos]; - } - - *flags = spaceFlags; - indent += SC_FOLDLEVELBASE; - // if completely empty line or the start of a comment... - if ((ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') || - (pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)) ) - return indent | SC_FOLDLEVELWHITEFLAG; - else - return indent; -} - -void DocumentAccessor::IndicatorFill(int start, int end, int indicator, int value) { - pdoc->decorations.SetCurrentIndicator(indicator); - pdoc->DecorationFillRange(start, value, end - start); -} diff --git a/src/stc/scintilla/src/DocumentAccessor.h b/src/stc/scintilla/src/DocumentAccessor.h deleted file mode 100644 index 899865fc1a..0000000000 --- a/src/stc/scintilla/src/DocumentAccessor.h +++ /dev/null @@ -1,77 +0,0 @@ -// Scintilla source code edit control -/** @file DocumentAccessor.h - ** Implementation of BufferAccess and StylingAccess on a Scintilla - ** rapid easy access to contents of a Scintilla. - **/ -// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#ifdef SCI_NAMESPACE -namespace Scintilla { -#endif - -class Document; - -/** - */ - -class DocumentAccessor : public Accessor { - // Private so DocumentAccessor objects can not be copied - DocumentAccessor(const DocumentAccessor &source); - DocumentAccessor &operator=(const DocumentAccessor &); - -protected: - Document *pdoc; - PropertyGet &props; - WindowID id; - int lenDoc; - - char styleBuf[bufferSize]; - int validLen; - char chFlags; - char chWhile; - unsigned int startSeg; - int startPosStyling; - int mask; - - bool InternalIsLeadByte(char ch); - void Fill(int position); - -public: - DocumentAccessor(Document *pdoc_, PropertyGet &props_, WindowID id_=0) : - Accessor(), pdoc(pdoc_), props(props_), id(id_), - lenDoc(-1), validLen(0), chFlags(0), chWhile(0), - startSeg(0), startPosStyling(0), - mask(127) { // Initialize the mask to be big enough for any lexer. - } - ~DocumentAccessor(); - bool Match(int pos, const char *s); - char StyleAt(int position); - int GetLine(int position); - int LineStart(int line); - int LevelAt(int line); - int Length(); - void Flush(); - int GetLineState(int line); - int SetLineState(int line, int state); - int GetPropertyInt(const char *key, int defaultValue=0) { - return props.GetInt(key, defaultValue); - } - char *GetProperties() { - return props.ToString(); - } - WindowID GetWindow() { return id; } - - void StartAt(unsigned int start, char chMask=31); - void SetFlags(char chFlags_, char chWhile_) {chFlags = chFlags_; chWhile = chWhile_; }; - unsigned int GetStartSegment() { return startSeg; } - void StartSegment(unsigned int pos); - void ColourTo(unsigned int pos, int chAttr); - void SetLevel(int line, int level); - int IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0); - void IndicatorFill(int start, int end, int indicator, int value); -}; - -#ifdef SCI_NAMESPACE -} -#endif diff --git a/src/stc/scintilla/src/Editor.cxx b/src/stc/scintilla/src/Editor.cxx index 9cd4309c53..cd72953ae7 100644 --- a/src/stc/scintilla/src/Editor.cxx +++ b/src/stc/scintilla/src/Editor.cxx @@ -2,26 +2,24 @@ /** @file Editor.cxx ** Main code for the edit control. **/ -// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org> +// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. #include <stdlib.h> #include <string.h> #include <stdio.h> #include <ctype.h> +#include <assert.h> #include <string> - -// With Borland C++ 5.5, including <string> includes Windows.h leading to defining -// FindText to FindTextA which makes calls here to Document::FindText fail. -#ifdef __BORLANDC__ -#ifdef FindText -#undef FindText -#endif -#endif +#include <vector> +#include <map> +#include <algorithm> +#include <memory> #include "Platform.h" +#include "ILexer.h" #include "Scintilla.h" #include "SplitVector.h" @@ -38,6 +36,7 @@ #include "CharClassify.h" #include "Decoration.h" #include "Document.h" +#include "UniConversion.h" #include "Selection.h" #include "PositionCache.h" #include "Editor.h" @@ -50,7 +49,7 @@ using namespace Scintilla; return whether this modification represents an operation that may reasonably be deferred (not done now OR [possibly] at all) */ -static bool CanDeferToLastStep(const DocModification& mh) { +static bool CanDeferToLastStep(const DocModification &mh) { if (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) return true; // CAN skip if (!(mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO))) @@ -60,7 +59,7 @@ static bool CanDeferToLastStep(const DocModification& mh) { return false; // PRESUMABLY must do } -static bool CanEliminate(const DocModification& mh) { +static bool CanEliminate(const DocModification &mh) { return (mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) != 0; } @@ -69,7 +68,7 @@ static bool CanEliminate(const DocModification& mh) { return whether this modification represents the FINAL step in a [possibly lengthy] multi-step Undo/Redo sequence */ -static bool IsLastStep(const DocModification& mh) { +static bool IsLastStep(const DocModification &mh) { return (mh.modificationType & (SC_PERFORMED_UNDO | SC_PERFORMED_REDO)) != 0 && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0 @@ -91,11 +90,21 @@ static inline bool IsControlCharacter(int ch) { return ch >= 0 && ch < ' '; } +static inline bool IsAllSpacesOrTabs(char *s, unsigned int len) { + for (unsigned int i = 0; i < len; i++) { + // This is safe because IsSpaceOrTab() will return false for null terminators + if (!IsSpaceOrTab(s[i])) + return false; + } + return true; +} + Editor::Editor() { ctrlID = 0; stylesValid = false; - + technology = SC_TECHNOLOGY_DEFAULT; + printMagnification = 0; printColourMode = SC_PRINT_NORMAL; printWrapState = eWrapWord; @@ -121,11 +130,15 @@ Editor::Editor() { dropWentOutside = false; posDrag = SelectionPosition(invalidPosition); posDrop = SelectionPosition(invalidPosition); + hotSpotClickPos = INVALID_POSITION; selectionType = selChar; lastXChosen = 0; - lineAnchor = 0; + lineAnchorPos = 0; originalAnchorPos = 0; + wordSelectAnchorStartPos = 0; + wordSelectAnchorEndPos = 0; + wordSelectInitialCaretPos = -1; primarySelection = true; @@ -134,6 +147,9 @@ Editor::Editor() { caretYPolicy = CARET_EVEN; caretYSlop = 0; + + visiblePolicy = 0; + visibleSlop = 0; searchAnchor = 0; @@ -145,18 +161,20 @@ Editor::Editor() { lineWidthMaxSeen = 0; verticalScrollBarVisible = true; endAtLastLine = true; - caretSticky = false; + caretSticky = SC_CARETSTICKY_OFF; + marginOptions = SC_MARGINOPTION_NONE; multipleSelection = false; additionalSelectionTyping = false; + multiPasteMode = SC_MULTIPASTE_ONCE; additionalCaretsBlink = true; additionalCaretsVisible = true; virtualSpaceOptions = SCVS_NONE; - pixmapLine = Surface::Allocate(); - pixmapSelMargin = Surface::Allocate(); - pixmapSelPattern = Surface::Allocate(); - pixmapIndentGuide = Surface::Allocate(); - pixmapIndentGuideHighlight = Surface::Allocate(); + pixmapLine = 0; + pixmapSelMargin = 0; + pixmapSelPattern = 0; + pixmapIndentGuide = 0; + pixmapIndentGuideHighlight = 0; targetStart = 0; targetEnd = 0; @@ -167,7 +185,8 @@ Editor::Editor() { lengthForEncode = -1; - needUpdateUI = true; + needUpdateUI = 0; + ContainerNeedsUpdate(SC_UPDATE_CONTENT); braces[0] = invalidPosition; braces[1] = invalidPosition; bracesMatchStyle = STYLE_BRACEBAD; @@ -176,6 +195,7 @@ Editor::Editor() { theEdge = 0; paintState = notPainting; + willRedrawAll = false; modEventMask = SC_MODEVENTMASKALL; @@ -194,7 +214,6 @@ Editor::Editor() { wrapVisualFlagsLocation = 0; wrapVisualStartIndent = 0; wrapIndentMode = SC_WRAPINDENT_FIXED; - wrapAddIndent = 0; convertPastes = true; @@ -209,12 +228,7 @@ Editor::~Editor() { pdoc->RemoveWatcher(this, 0); pdoc->Release(); pdoc = 0; - DropGraphics(); - delete pixmapLine; - delete pixmapSelMargin; - delete pixmapSelPattern; - delete pixmapIndentGuide; - delete pixmapIndentGuideHighlight; + DropGraphics(true); } void Editor::Finalise() { @@ -222,18 +236,50 @@ void Editor::Finalise() { CancelModes(); } -void Editor::DropGraphics() { - pixmapLine->Release(); - pixmapSelMargin->Release(); - pixmapSelPattern->Release(); - pixmapIndentGuide->Release(); - pixmapIndentGuideHighlight->Release(); +void Editor::DropGraphics(bool freeObjects) { + if (freeObjects) { + delete pixmapLine; + pixmapLine = 0; + delete pixmapSelMargin; + pixmapSelMargin = 0; + delete pixmapSelPattern; + pixmapSelPattern = 0; + delete pixmapIndentGuide; + pixmapIndentGuide = 0; + delete pixmapIndentGuideHighlight; + pixmapIndentGuideHighlight = 0; + } else { + if (pixmapLine) + pixmapLine->Release(); + if (pixmapSelMargin) + pixmapSelMargin->Release(); + if (pixmapSelPattern) + pixmapSelPattern->Release(); + if (pixmapIndentGuide) + pixmapIndentGuide->Release(); + if (pixmapIndentGuideHighlight) + pixmapIndentGuideHighlight->Release(); + } +} + +void Editor::AllocateGraphics() { + if (!pixmapLine) + pixmapLine = Surface::Allocate(technology); + if (!pixmapSelMargin) + pixmapSelMargin = Surface::Allocate(technology); + if (!pixmapSelPattern) + pixmapSelPattern = Surface::Allocate(technology); + if (!pixmapIndentGuide) + pixmapIndentGuide = Surface::Allocate(technology); + if (!pixmapIndentGuideHighlight) + pixmapIndentGuideHighlight = Surface::Allocate(technology); } void Editor::InvalidateStyleData() { stylesValid = false; - DropGraphics(); - palette.Release(); + vs.technology = technology; + DropGraphics(false); + AllocateGraphics(); llc.Invalidate(LineLayout::llInvalid); posCache.Clear(); } @@ -244,28 +290,12 @@ void Editor::InvalidateStyleRedraw() { Redraw(); } -void Editor::RefreshColourPalette(Palette &pal, bool want) { - vs.RefreshColourPalette(pal, want); -} - void Editor::RefreshStyleData() { if (!stylesValid) { stylesValid = true; AutoSurface surface(this); if (surface) { vs.Refresh(*surface); - RefreshColourPalette(palette, true); - palette.Allocate(wMain); - RefreshColourPalette(palette, false); - } - if (wrapIndentMode == SC_WRAPINDENT_INDENT) { - wrapAddIndent = pdoc->IndentSize() * vs.spaceWidth; - } else if (wrapIndentMode == SC_WRAPINDENT_SAME) { - wrapAddIndent = 0; - } else { //SC_WRAPINDENT_FIXED - wrapAddIndent = wrapVisualStartIndent * vs.aveCharWidth; - if ((wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (wrapAddIndent <= 0)) - wrapAddIndent = vs.aveCharWidth; // must indent to show start visual } SetScrollBars(); SetRectangularRange(); @@ -403,7 +433,7 @@ Point Editor::LocationFromPosition(SelectionPosition pos) { } pt.x += vs.fixedColumnWidth - xOffset; } - pt.x += pos.VirtualSpace() * static_cast<int>(vs.styles[ll->EndLineStyle()].spaceWidth); + pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth; return pt; } @@ -426,7 +456,10 @@ int Editor::LineFromLocation(Point pt) { } void Editor::SetTopLine(int topLineNew) { - topLine = topLineNew; + if (topLine != topLineNew) { + topLine = topLineNew; + ContainerNeedsUpdate(SC_UPDATE_V_SCROLL); + } posTopLine = pdoc->LineStart(cs.DocFromDisplay(topLine)); } @@ -444,7 +477,7 @@ SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, pt.x = pt.x - vs.fixedColumnWidth + xOffset; int visibleLine = pt.y / vs.lineHeight + topLine; if (pt.y < 0) { // Division rounds towards 0 - visibleLine = (pt.y - (vs.lineHeight - 1)) / vs.lineHeight + topLine; + visibleLine = (static_cast<int>(pt.y) - (vs.lineHeight - 1)) / vs.lineHeight + topLine; } if (!canReturnInvalid && (visibleLine < 0)) visibleLine = 0; @@ -464,7 +497,7 @@ SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, if (subLine < ll->lines) { int lineStart = ll->LineStart(subLine); int lineEnd = ll->LineLastVisible(subLine); - int subLineStart = ll->positions[lineStart]; + XYPOSITION subLineStart = ll->positions[lineStart]; if (ll->wrapIndent != 0) { if (lineStart != 0) // Wrapped @@ -484,7 +517,7 @@ SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, i++; } if (virtualSpace) { - const int spaceWidth = static_cast<int>(vs.styles[ll->EndLineStyle()].spaceWidth); + const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; int spaceOffset = (pt.x + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) / spaceWidth; return SelectionPosition(lineEnd + posLineStart, spaceOffset); @@ -506,43 +539,6 @@ int Editor::PositionFromLocation(Point pt, bool canReturnInvalid, bool charPosit return SPositionFromLocation(pt, canReturnInvalid, charPosition, false).Position(); } -/** - * Find the document position corresponding to an x coordinate on a particular document line. - * Ensure is between whole characters when document is in multi-byte or UTF-8 mode. - */ -int Editor::PositionFromLineX(int lineDoc, int x) { - RefreshStyleData(); - if (lineDoc >= pdoc->LinesTotal()) - return pdoc->Length(); - //Platform::DebugPrintf("Position of (%d,%d) line = %d top=%d\n", pt.x, pt.y, line, topLine); - AutoSurface surface(this); - AutoLineLayout ll(llc, RetrieveLineLayout(lineDoc)); - int retVal = 0; - if (surface && ll) { - unsigned int posLineStart = pdoc->LineStart(lineDoc); - LayoutLine(lineDoc, surface, vs, ll, wrapWidth); - retVal = ll->numCharsBeforeEOL + posLineStart; - int subLine = 0; - int lineStart = ll->LineStart(subLine); - int lineEnd = ll->LineLastVisible(subLine); - int subLineStart = ll->positions[lineStart]; - - if (ll->wrapIndent != 0) { - if (lineStart != 0) // Wrapped - x -= ll->wrapIndent; - } - int i = ll->FindBefore(x + subLineStart, lineStart, lineEnd); - while (i < lineEnd) { - if ((x + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) { - retVal = pdoc->MovePositionOutsideChar(i + posLineStart, 1); - break; - } - i++; - } - } - return retVal; -} - /** * Find the document position corresponding to an x coordinate on a particular document line. * Ensure is between whole characters when document is in multi-byte or UTF-8 mode. @@ -561,27 +557,32 @@ SelectionPosition Editor::SPositionFromLineX(int lineDoc, int x) { int subLine = 0; int lineStart = ll->LineStart(subLine); int lineEnd = ll->LineLastVisible(subLine); - int subLineStart = ll->positions[lineStart]; + XYPOSITION subLineStart = ll->positions[lineStart]; + XYPOSITION newX = x; if (ll->wrapIndent != 0) { if (lineStart != 0) // Wrapped - x -= ll->wrapIndent; + newX -= ll->wrapIndent; } - int i = ll->FindBefore(x + subLineStart, lineStart, lineEnd); + int i = ll->FindBefore(newX + subLineStart, lineStart, lineEnd); while (i < lineEnd) { - if ((x + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) { + if ((newX + subLineStart) < ((ll->positions[i] + ll->positions[i + 1]) / 2)) { retVal = pdoc->MovePositionOutsideChar(i + posLineStart, 1); return SelectionPosition(retVal); } i++; } - const int spaceWidth = static_cast<int>(vs.styles[ll->EndLineStyle()].spaceWidth); - int spaceOffset = (x + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) / spaceWidth; + const XYPOSITION spaceWidth = vs.styles[ll->EndLineStyle()].spaceWidth; + int spaceOffset = (newX + subLineStart - ll->positions[lineEnd] + spaceWidth / 2) / spaceWidth; return SelectionPosition(lineEnd + posLineStart, spaceOffset); } return SelectionPosition(retVal); } +int Editor::PositionFromLineX(int lineDoc, int x) { + return SPositionFromLineX(lineDoc, x).Position(); +} + /** * If painting then abandon the painting because a wider redraw is needed. * @return true if calling code should stop drawing. @@ -619,7 +620,7 @@ void Editor::Redraw() { //wMain.InvalidateAll(); } -void Editor::RedrawSelMargin(int line) { +void Editor::RedrawSelMargin(int line, bool allAfter) { if (!AbandonPaint()) { if (vs.maskInLine) { Redraw(); @@ -629,8 +630,21 @@ void Editor::RedrawSelMargin(int line) { if (line != -1) { int position = pdoc->LineStart(line); PRectangle rcLine = RectangleFromRange(position, position); + + // Inflate line rectangle if there are image markers with height larger than line height + if (vs.largestMarkerHeight > vs.lineHeight) { + int delta = (vs.largestMarkerHeight - vs.lineHeight + 1) / 2; + rcLine.top -= delta; + rcLine.bottom += delta; + if (rcLine.top < rcSelMargin.top) + rcLine.top = rcSelMargin.top; + if (rcLine.bottom > rcSelMargin.bottom) + rcLine.bottom = rcSelMargin.bottom; + } + rcSelMargin.top = rcLine.top; - rcSelMargin.bottom = rcLine.bottom; + if (!allAfter) + rcSelMargin.bottom = rcLine.bottom; } wMain.InvalidateRectangle(rcSelMargin); } @@ -649,7 +663,8 @@ PRectangle Editor::RectangleFromRange(int start, int end) { int maxLine = cs.DisplayFromDoc(lineDocMax) + cs.GetHeight(lineDocMax) - 1; PRectangle rcClient = GetTextRectangle(); PRectangle rc; - rc.left = vs.fixedColumnWidth; + const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0; + rc.left = vs.fixedColumnWidth - leftTextOverlap; rc.top = (minLine - topLine) * vs.lineHeight; if (rc.top < 0) rc.top = 0; @@ -699,7 +714,7 @@ void Editor::SetRectangularRange() { if (line == lineAnchorRect) sel.SetSelection(range); else - sel.AddSelection(range); + sel.AddSelectionWithoutTrim(range); } } } @@ -732,19 +747,36 @@ void Editor::InvalidateSelection(SelectionRange newMain, bool invalidateWholeSel lastAffected = Platform::Maximum(lastAffected, sel.Range(r).anchor.Position()); } } - needUpdateUI = true; + ContainerNeedsUpdate(SC_UPDATE_SELECTION); InvalidateRange(firstAffected, lastAffected); } void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_) { - SelectionRange rangeNew(ClampPositionIntoDocument(currentPos_), - ClampPositionIntoDocument(anchor_)); + currentPos_ = ClampPositionIntoDocument(currentPos_); + anchor_ = ClampPositionIntoDocument(anchor_); + int currentLine = pdoc->LineFromPosition(currentPos_.Position()); + /* For Line selection - ensure the anchor and caret are always + at the beginning and end of the region lines. */ + if (sel.selType == Selection::selLines) { + if (currentPos_ > anchor_) { + anchor_ = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(anchor_.Position()))); + currentPos_ = SelectionPosition(pdoc->LineEnd(pdoc->LineFromPosition(currentPos_.Position()))); + } else { + currentPos_ = SelectionPosition(pdoc->LineStart(pdoc->LineFromPosition(currentPos_.Position()))); + anchor_ = SelectionPosition(pdoc->LineEnd(pdoc->LineFromPosition(anchor_.Position()))); + } + } + SelectionRange rangeNew(currentPos_, anchor_); if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) { InvalidateSelection(rangeNew); } sel.RangeMain() = rangeNew; SetRectangularRange(); ClaimSelection(); + + if (highlightDelimiter.NeedsDrawing(currentLine)) { + RedrawSelMargin(); + } } void Editor::SetSelection(int currentPos_, int anchor_) { @@ -754,6 +786,7 @@ void Editor::SetSelection(int currentPos_, int anchor_) { // Just move the caret on the main selection void Editor::SetSelection(SelectionPosition currentPos_) { currentPos_ = ClampPositionIntoDocument(currentPos_); + int currentLine = pdoc->LineFromPosition(currentPos_.Position()); if (sel.Count() > 1 || !(sel.RangeMain().caret == currentPos_)) { InvalidateSelection(SelectionRange(currentPos_)); } @@ -766,6 +799,10 @@ void Editor::SetSelection(SelectionPosition currentPos_) { SelectionRange(SelectionPosition(currentPos_), sel.RangeMain().anchor); } ClaimSelection(); + + if (highlightDelimiter.NeedsDrawing(currentLine)) { + RedrawSelMargin(); + } } void Editor::SetSelection(int currentPos_) { @@ -773,6 +810,7 @@ void Editor::SetSelection(int currentPos_) { } void Editor::SetEmptySelection(SelectionPosition currentPos_) { + int currentLine = pdoc->LineFromPosition(currentPos_.Position()); SelectionRange rangeNew(ClampPositionIntoDocument(currentPos_)); if (sel.Count() > 1 || !(sel.RangeMain() == rangeNew)) { InvalidateSelection(rangeNew); @@ -782,6 +820,9 @@ void Editor::SetEmptySelection(SelectionPosition currentPos_) { SetRectangularRange(); ClaimSelection(); + if (highlightDelimiter.NeedsDrawing(currentLine)) { + RedrawSelMargin(); + } } void Editor::SetEmptySelection(int currentPos_) { @@ -845,9 +886,18 @@ SelectionPosition Editor::MovePositionOutsideChar(SelectionPosition pos, int mov } int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, bool ensureVisible) { + bool simpleCaret = (sel.Count() == 1) && sel.Empty(); + SelectionPosition spCaret = sel.Last(); + int delta = newPos.Position() - sel.MainCaret(); newPos = ClampPositionIntoDocument(newPos); newPos = MovePositionOutsideChar(newPos, delta); + if (!multipleSelection && sel.IsRectangular() && (selt == Selection::selStream)) { + // Can't turn into multiple selection so clear additional selections + InvalidateSelection(SelectionRange(newPos), true); + SelectionRange rangeMain = sel.RangeMain(); + sel.SetSelection(rangeMain); + } if (!sel.IsRectangular() && (selt == Selection::selRectangle)) { // Switching to rectangular SelectionRange rangeMain = sel.RangeMain(); @@ -863,8 +913,24 @@ int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, b SetEmptySelection(newPos); } ShowCaretAtCurrentPosition(); + + int currentLine = pdoc->LineFromPosition(newPos.Position()); if (ensureVisible) { - EnsureCaretVisible(); + // In case in need of wrapping to ensure DisplayFromDoc works. + if (currentLine >= wrapStart) + WrapLines(true, -1); + XYScrollPosition newXY = XYScrollToMakeVisible(true, true, true); + if (simpleCaret && (newXY.xOffset == xOffset)) { + // simple vertical scroll then invalidate + ScrollTo(newXY.topLine); + InvalidateSelection(SelectionRange(spCaret), true); + } else { + SetXYScroll(newXY); + } + } + + if (highlightDelimiter.NeedsDrawing(currentLine)) { + RedrawSelMargin(); } return 0; } @@ -906,23 +972,30 @@ Point Editor::PointMainCaret() { */ void Editor::SetLastXChosen() { Point pt = PointMainCaret(); - lastXChosen = pt.x; + lastXChosen = pt.x + xOffset; } void Editor::ScrollTo(int line, bool moveThumb) { int topLineNew = Platform::Clamp(line, 0, MaxScrollPos()); if (topLineNew != topLine) { // Try to optimise small scrolls +#ifndef UNDER_CE int linesToMove = topLine - topLineNew; + bool performBlit = (abs(linesToMove) <= 10) && (paintState == notPainting); + willRedrawAll = !performBlit; +#endif SetTopLine(topLineNew); - ShowCaretAtCurrentPosition(); - // Perform redraw rather than scroll if many lines would be redrawn anyway. + // Optimize by styling the view as this will invalidate any needed area + // which could abort the initial paint if discovered later. + StyleToPositionInView(PositionAfterArea(GetClientRectangle())); #ifndef UNDER_CE - if ((abs(linesToMove) <= 10) && (paintState == notPainting)) { + // Perform redraw rather than scroll if many lines would be redrawn anyway. + if (performBlit) { ScrollText(linesToMove); } else { Redraw(); } + willRedrawAll = false; #else Redraw(); #endif @@ -943,22 +1016,111 @@ void Editor::HorizontalScrollTo(int xPos) { xPos = 0; if ((wrapState == eWrapNone) && (xOffset != xPos)) { xOffset = xPos; + ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); SetHorizontalScrollPos(); RedrawRect(GetClientRectangle()); } } +void Editor::VerticalCentreCaret() { + int lineDoc = pdoc->LineFromPosition(sel.IsRectangular() ? sel.Rectangular().caret.Position() : sel.MainCaret()); + int lineDisplay = cs.DisplayFromDoc(lineDoc); + int newTop = lineDisplay - (LinesOnScreen() / 2); + if (topLine != newTop) { + SetTopLine(newTop > 0 ? newTop : 0); + RedrawRect(GetClientRectangle()); + } +} + +// Avoid 64 bit compiler warnings. +// Scintilla does not support text buffers larger than 2**31 +static int istrlen(const char *s) { + return static_cast<int>(strlen(s)); +} + +void Editor::MoveSelectedLines(int lineDelta) { + + // if selection doesn't start at the beginning of the line, set the new start + int selectionStart = SelectionStart().Position(); + int startLine = pdoc->LineFromPosition(selectionStart); + int beginningOfStartLine = pdoc->LineStart(startLine); + selectionStart = beginningOfStartLine; + + // if selection doesn't end at the beginning of a line greater than that of the start, + // then set it at the beginning of the next one + int selectionEnd = SelectionEnd().Position(); + int endLine = pdoc->LineFromPosition(selectionEnd); + int beginningOfEndLine = pdoc->LineStart(endLine); + bool appendEol = false; + if (selectionEnd > beginningOfEndLine + || selectionStart == selectionEnd) { + selectionEnd = pdoc->LineStart(endLine + 1); + appendEol = (selectionEnd == pdoc->Length() && pdoc->LineFromPosition(selectionEnd) == endLine); + } + + // if there's nowhere for the selection to move + // (i.e. at the beginning going up or at the end going down), + // stop it right there! + if ((selectionStart == 0 && lineDelta < 0) + || (selectionEnd == pdoc->Length() && lineDelta > 0) + || selectionStart == selectionEnd) { + return; + } + + UndoGroup ug(pdoc); + + if (lineDelta > 0 && selectionEnd == pdoc->LineStart(pdoc->LinesTotal() - 1)) { + SetSelection(pdoc->MovePositionOutsideChar(selectionEnd - 1, -1), selectionEnd); + ClearSelection(); + selectionEnd = CurrentPosition(); + } + SetSelection(selectionStart, selectionEnd); + + SelectionText selectedText; + CopySelectionRange(&selectedText); + + int selectionLength = SelectionRange(selectionStart, selectionEnd).Length(); + Point currentLocation = LocationFromPosition(CurrentPosition()); + int currentLine = LineFromLocation(currentLocation); + + if (appendEol) + SetSelection(pdoc->MovePositionOutsideChar(selectionStart - 1, -1), selectionEnd); + ClearSelection(); + + const char *eol = StringFromEOLMode(pdoc->eolMode); + if (currentLine + lineDelta >= pdoc->LinesTotal()) + pdoc->InsertCString(pdoc->Length(), eol); + GoToLine(currentLine + lineDelta); + + pdoc->InsertCString(CurrentPosition(), selectedText.s); + if (appendEol) { + pdoc->InsertCString(CurrentPosition() + selectionLength, eol); + selectionLength += istrlen(eol); + } + SetSelection(CurrentPosition(), CurrentPosition() + selectionLength); +} + +void Editor::MoveSelectedLinesUp() { + MoveSelectedLines(-1); +} + +void Editor::MoveSelectedLinesDown() { + MoveSelectedLines(1); +} + void Editor::MoveCaretInsideView(bool ensureVisible) { PRectangle rcClient = GetTextRectangle(); Point pt = PointMainCaret(); if (pt.y < rcClient.top) { MovePositionTo(SPositionFromLocation( - Point(lastXChosen, rcClient.top)), + Point(lastXChosen - xOffset, rcClient.top), + false, false, UserVirtualSpace()), Selection::noSel, ensureVisible); } else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) { int yOfLastLineFullyDisplayed = rcClient.top + (LinesOnScreen() - 1) * vs.lineHeight; MovePositionTo(SPositionFromLocation( - Point(lastXChosen, rcClient.top + yOfLastLineFullyDisplayed)), + Point(lastXChosen - xOffset, rcClient.top + yOfLastLineFullyDisplayed), + false, false, UserVirtualSpace()), Selection::noSel, ensureVisible); } } @@ -1027,29 +1189,24 @@ slop | strict | jumps | even | Caret can go to the margin | When 1 | 1 | 0 | 1 | No, kept out of UZ | moved by one position 1 | 1 | 1 | 1 | No, kept out of UZ | moved to put caret at 3UZ of the margin */ -void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { - //Platform::DebugPrintf("EnsureCaretVisible %d %s\n", xOffset, useMargin ? " margin" : " "); + +Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, const bool vert, const bool horiz) { PRectangle rcClient = GetTextRectangle(); - //int rcClientFullWidth = rcClient.Width(); - SelectionPosition posCaret = sel.RangeMain().caret; - if (posDrag.IsValid()) { - posCaret = posDrag; - } - Point pt = LocationFromPosition(posCaret); - Point ptBottomCaret = pt; - ptBottomCaret.y += vs.lineHeight - 1; - int lineCaret = DisplayFromPosition(posCaret.Position()); - bool bSlop, bStrict, bJump, bEven; + const SelectionPosition posCaret = posDrag.IsValid() ? posDrag : sel.RangeMain().caret; + const Point pt = LocationFromPosition(posCaret); + const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1); + const int lineCaret = DisplayFromPosition(posCaret.Position()); + + XYScrollPosition newXY(xOffset, topLine); // Vertical positioning - if (vert && (pt.y < rcClient.top || ptBottomCaret.y > rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) { - int linesOnScreen = LinesOnScreen(); - int halfScreen = Platform::Maximum(linesOnScreen - 1, 2) / 2; - int newTopLine = topLine; - bSlop = (caretYPolicy & CARET_SLOP) != 0; - bStrict = (caretYPolicy & CARET_STRICT) != 0; - bJump = (caretYPolicy & CARET_JUMPS) != 0; - bEven = (caretYPolicy & CARET_EVEN) != 0; + if (vert && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) { + const int linesOnScreen = LinesOnScreen(); + const int halfScreen = Platform::Maximum(linesOnScreen - 1, 2) / 2; + const bool bSlop = (caretYPolicy & CARET_SLOP) != 0; + const bool bStrict = (caretYPolicy & CARET_STRICT) != 0; + const bool bJump = (caretYPolicy & CARET_JUMPS) != 0; + const bool bEven = (caretYPolicy & CARET_EVEN) != 0; // It should be possible to scroll the window to show the caret, // but this fails to remove the caret on GTK+ @@ -1082,10 +1239,10 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { } if (lineCaret < topLine + yMarginT) { // Caret goes too high - newTopLine = lineCaret - yMoveT; + newXY.topLine = lineCaret - yMoveT; } else if (lineCaret > topLine + linesOnScreen - 1 - yMarginB) { // Caret goes too low - newTopLine = lineCaret - linesOnScreen + 1 + yMoveB; + newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB; } } else { // Not strict yMoveT = bJump ? caretYSlop * 3 : caretYSlop; @@ -1097,10 +1254,10 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { } if (lineCaret < topLine) { // Caret goes too high - newTopLine = lineCaret - yMoveT; + newXY.topLine = lineCaret - yMoveT; } else if (lineCaret > topLine + linesOnScreen - 1) { // Caret goes too low - newTopLine = lineCaret - linesOnScreen + 1 + yMoveB; + newXY.topLine = lineCaret - linesOnScreen + 1 + yMoveB; } } } else { // No slop @@ -1108,41 +1265,35 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { // Minimal move if (lineCaret < topLine) { // Caret goes too high - newTopLine = lineCaret; + newXY.topLine = lineCaret; } else if (lineCaret > topLine + linesOnScreen - 1) { // Caret goes too low if (bEven) { - newTopLine = lineCaret - linesOnScreen + 1; + newXY.topLine = lineCaret - linesOnScreen + 1; } else { - newTopLine = lineCaret; + newXY.topLine = lineCaret; } } } else { // Strict or going out of display if (bEven) { // Always center caret - newTopLine = lineCaret - halfScreen; + newXY.topLine = lineCaret - halfScreen; } else { // Always put caret on top of display - newTopLine = lineCaret; + newXY.topLine = lineCaret; } } } - newTopLine = Platform::Clamp(newTopLine, 0, MaxScrollPos()); - if (newTopLine != topLine) { - Redraw(); - SetTopLine(newTopLine); - SetVerticalScrollPos(); - } + newXY.topLine = Platform::Clamp(newXY.topLine, 0, MaxScrollPos()); } // Horizontal positioning if (horiz && (wrapState == eWrapNone)) { - int halfScreen = Platform::Maximum(rcClient.Width() - 4, 4) / 2; - int xOffsetNew = xOffset; - bSlop = (caretXPolicy & CARET_SLOP) != 0; - bStrict = (caretXPolicy & CARET_STRICT) != 0; - bJump = (caretXPolicy & CARET_JUMPS) != 0; - bEven = (caretXPolicy & CARET_EVEN) != 0; + const int halfScreen = Platform::Maximum(rcClient.Width() - 4, 4) / 2; + const bool bSlop = (caretXPolicy & CARET_SLOP) != 0; + const bool bStrict = (caretXPolicy & CARET_STRICT) != 0; + const bool bJump = (caretXPolicy & CARET_JUMPS) != 0; + const bool bEven = (caretXPolicy & CARET_EVEN) != 0; if (bSlop) { // A margin is defined int xMoveL, xMoveR; @@ -1171,18 +1322,18 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { if (pt.x < rcClient.left + xMarginL) { // Caret is on the left of the display if (bJump && bEven) { - xOffsetNew -= xMoveL; + newXY.xOffset -= xMoveL; } else { // Move just enough to allow to display the caret - xOffsetNew -= (rcClient.left + xMarginL) - pt.x; + newXY.xOffset -= (rcClient.left + xMarginL) - pt.x; } } else if (pt.x >= rcClient.right - xMarginR) { // Caret is on the right of the display if (bJump && bEven) { - xOffsetNew += xMoveR; + newXY.xOffset += xMoveR; } else { // Move just enough to allow to display the caret - xOffsetNew += pt.x - (rcClient.right - xMarginR) + 1; + newXY.xOffset += pt.x - (rcClient.right - xMarginR) + 1; } } } else { // Not strict @@ -1195,10 +1346,10 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { } if (pt.x < rcClient.left) { // Caret is on the left of the display - xOffsetNew -= xMoveL; + newXY.xOffset -= xMoveL; } else if (pt.x >= rcClient.right) { // Caret is on the right of the display - xOffsetNew += xMoveR; + newXY.xOffset += xMoveR; } } } else { // No slop @@ -1207,54 +1358,70 @@ void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { // Strict or going out of display if (bEven) { // Center caret - xOffsetNew += pt.x - rcClient.left - halfScreen; + newXY.xOffset += pt.x - rcClient.left - halfScreen; } else { // Put caret on right - xOffsetNew += pt.x - rcClient.right + 1; + newXY.xOffset += pt.x - rcClient.right + 1; } } else { // Move just enough to allow to display the caret if (pt.x < rcClient.left) { // Caret is on the left of the display if (bEven) { - xOffsetNew -= rcClient.left - pt.x; + newXY.xOffset -= rcClient.left - pt.x; } else { - xOffsetNew += pt.x - rcClient.right + 1; + newXY.xOffset += pt.x - rcClient.right + 1; } } else if (pt.x >= rcClient.right) { // Caret is on the right of the display - xOffsetNew += pt.x - rcClient.right + 1; + newXY.xOffset += pt.x - rcClient.right + 1; } } } // In case of a jump (find result) largely out of display, adjust the offset to display the caret - if (pt.x + xOffset < rcClient.left + xOffsetNew) { - xOffsetNew = pt.x + xOffset - rcClient.left; - } else if (pt.x + xOffset >= rcClient.right + xOffsetNew) { - xOffsetNew = pt.x + xOffset - rcClient.right + 1; + if (pt.x + xOffset < rcClient.left + newXY.xOffset) { + newXY.xOffset = pt.x + xOffset - rcClient.left; + } else if (pt.x + xOffset >= rcClient.right + newXY.xOffset) { + newXY.xOffset = pt.x + xOffset - rcClient.right + 1; if (vs.caretStyle == CARETSTYLE_BLOCK) { // Ensure we can see a good portion of the block caret - xOffsetNew += vs.aveCharWidth; + newXY.xOffset += static_cast<int>(vs.aveCharWidth); } } - if (xOffsetNew < 0) { - xOffsetNew = 0; + if (newXY.xOffset < 0) { + newXY.xOffset = 0; + } + } + + return newXY; +} + +void Editor::SetXYScroll(XYScrollPosition newXY) { + if ((newXY.topLine != topLine) || (newXY.xOffset != xOffset)) { + if (newXY.topLine != topLine) { + SetTopLine(newXY.topLine); + SetVerticalScrollPos(); } - if (xOffset != xOffsetNew) { - xOffset = xOffsetNew; - if (xOffsetNew > 0) { + if (newXY.xOffset != xOffset) { + xOffset = newXY.xOffset; + ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); + if (newXY.xOffset > 0) { PRectangle rcText = GetTextRectangle(); if (horizontalScrollBarVisible && - rcText.Width() + xOffset > scrollWidth) { + rcText.Width() + xOffset > scrollWidth) { scrollWidth = xOffset + rcText.Width(); SetScrollBars(); } } SetHorizontalScrollPos(); - Redraw(); } + Redraw(); + UpdateSystemCaret(); } - UpdateSystemCaret(); +} + +void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) { + SetXYScroll(XYScrollToMakeVisible(useMargin, vert, horiz)); } void Editor::ShowCaretAtCurrentPosition() { @@ -1328,6 +1495,12 @@ bool Editor::WrapOneLine(Surface *surface, int lineToWrap) { bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) { // If there are any pending wraps, do them during idle if possible. int linesInOneCall = LinesOnScreen() + 100; + if (priorityWrapLineStart >= 0) { + // Using DocFromDisplay() here may result in chicken and egg problem in certain corner cases, + // which will hopefully be handled by added 100 lines. If some lines are still missed, idle wrapping will catch on. + int docLinesInOneCall = cs.DocFromDisplay(topLine + LinesOnScreen() + 100) - cs.DocFromDisplay(topLine); + linesInOneCall = Platform::Maximum(linesInOneCall, docLinesInOneCall); + } if (wrapState != eWrapNone) { if (wrapStart < wrapEnd) { if (!SetIdle(true)) { @@ -1367,8 +1540,6 @@ bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) { rcTextArea.left = vs.fixedColumnWidth; rcTextArea.right -= vs.rightMarginWidth; wrapWidth = rcTextArea.Width(); - // Ensure all of the document is styled. - pdoc->EnsureStyledTo(pdoc->Length()); RefreshStyleData(); AutoSurface surface(this); if (surface) { @@ -1389,6 +1560,9 @@ bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) { lastLineToWrap = wrapEnd; } // else do a fullWrap. + // Ensure all lines being wrapped are styled. + pdoc->EnsureStyledTo(pdoc->LineEnd(lastLineToWrap)); + // Platform::DebugPrintf("Wraplines: full = %d, priorityStart = %d (wrapping: %d to %d)\n", fullWrap, priorityWrapLineStart, lineToWrap, lastLineToWrap); // Platform::DebugPrintf("Pending wraps: %d to %d\n", wrapStart, wrapEnd); while (lineToWrap < lastLineToWrap) { @@ -1469,8 +1643,10 @@ void Editor::LinesSplit(int pixelWidth) { unsigned int posLineStart = pdoc->LineStart(line); LayoutLine(line, surface, vs, ll, pixelWidth); for (int subLine = 1; subLine < ll->lines; subLine++) { - pdoc->InsertCString(posLineStart + (subLine - 1) * strlen(eol) + - ll->LineStart(subLine), eol); + pdoc->InsertCString( + static_cast<int>(posLineStart + (subLine - 1) * strlen(eol) + + ll->LineStart(subLine)), + eol); targetEnd += static_cast<int>(strlen(eol)); } } @@ -1485,15 +1661,9 @@ int Editor::SubstituteMarkerIfEmpty(int markerCheck, int markerDefault) { return markerCheck; } -// Avoid 64 bit compiler warnings. -// Scintilla does not support text buffers larger than 2**31 -static int istrlen(const char *s) { - return static_cast<int>(strlen(s)); -} - bool ValidStyledText(ViewStyle &vs, size_t styleOffset, const StyledText &st) { if (st.multipleStyles) { - for (size_t iStyle=0;iStyle<st.length; iStyle++) { + for (size_t iStyle=0; iStyle<st.length; iStyle++) { if (!vs.ValidStyle(styleOffset + st.styles[iStyle])) return false; } @@ -1513,7 +1683,8 @@ static int WidthStyledText(Surface *surface, ViewStyle &vs, int styleOffset, size_t endSegment = start; while ((endSegment+1 < len) && (static_cast<size_t>(styles[endSegment+1]) == style)) endSegment++; - width += surface->WidthText(vs.styles[style+styleOffset].font, text + start, endSegment - start + 1); + width += surface->WidthText(vs.styles[style+styleOffset].font, text + start, + static_cast<int>(endSegment - start + 1)); start = endSegment + 1; } return width; @@ -1528,7 +1699,8 @@ static int WidestLineWidth(Surface *surface, ViewStyle &vs, int styleOffset, con if (st.multipleStyles) { widthSubLine = WidthStyledText(surface, vs, styleOffset, st.text + start, st.styles + start, lenLine); } else { - widthSubLine = surface->WidthText(vs.styles[styleOffset + st.style].font, st.text + start, lenLine); + widthSubLine = surface->WidthText(vs.styles[styleOffset + st.style].font, + st.text + start, static_cast<int>(lenLine)); } if (widthSubLine > widthMax) widthMax = widthSubLine; @@ -1549,23 +1721,26 @@ void DrawStyledText(Surface *surface, ViewStyle &vs, int styleOffset, PRectangle while (end < length-1 && st.styles[start+end+1] == style) end++; style += styleOffset; - int width = surface->WidthText(vs.styles[style].font, st.text + start + i, end - i + 1); + int width = surface->WidthText(vs.styles[style].font, + st.text + start + i, static_cast<int>(end - i + 1)); PRectangle rcSegment = rcText; rcSegment.left = x; rcSegment.right = x + width + 1; surface->DrawTextNoClip(rcSegment, vs.styles[style].font, - ascent, st.text + start + i, end - i + 1, - vs.styles[style].fore.allocated, - vs.styles[style].back.allocated); + ascent, st.text + start + i, + static_cast<int>(end - i + 1), + vs.styles[style].fore, + vs.styles[style].back); x += width; i = end + 1; } } else { - int style = st.style + styleOffset; + size_t style = st.style + styleOffset; surface->DrawTextNoClip(rcText, vs.styles[style].font, - rcText.top + vs.maxAscent, st.text + start, length, - vs.styles[style].fore.allocated, - vs.styles[style].back.allocated); + rcText.top + vs.maxAscent, st.text + start, + static_cast<int>(length), + vs.styles[style].fore, + vs.styles[style].back); } } @@ -1586,6 +1761,12 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { surface = surfWindow; } + // Clip vertically to paint area to avoid drawing line numbers + if (rcMargin.bottom > rc.bottom) + rcMargin.bottom = rc.bottom; + if (rcMargin.top < rc.top) + rcMargin.top = rc.top; + PRectangle rcSelMargin = rcMargin; rcSelMargin.right = rcMargin.left; @@ -1596,53 +1777,52 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width; if (vs.ms[margin].style != SC_MARGIN_NUMBER) { - /* alternate scheme: - if (vs.ms[margin].mask & SC_MASK_FOLDERS) - surface->FillRectangle(rcSelMargin, vs.styles[STYLE_DEFAULT].back.allocated); - else - // Required because of special way brush is created for selection margin - surface->FillRectangle(rcSelMargin, pixmapSelPattern); - */ if (vs.ms[margin].mask & SC_MASK_FOLDERS) // Required because of special way brush is created for selection margin surface->FillRectangle(rcSelMargin, *pixmapSelPattern); else { - ColourAllocated colour; + ColourDesired colour; switch (vs.ms[margin].style) { case SC_MARGIN_BACK: - colour = vs.styles[STYLE_DEFAULT].back.allocated; + colour = vs.styles[STYLE_DEFAULT].back; break; case SC_MARGIN_FORE: - colour = vs.styles[STYLE_DEFAULT].fore.allocated; + colour = vs.styles[STYLE_DEFAULT].fore; break; default: - colour = vs.styles[STYLE_LINENUMBER].back.allocated; + colour = vs.styles[STYLE_LINENUMBER].back; break; } surface->FillRectangle(rcSelMargin, colour); } } else { - surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back.allocated); + surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back); } - int visibleLine = topLine; - int yposScreen = 0; - + const int lineStartPaint = rcMargin.top / vs.lineHeight; + int visibleLine = topLine + lineStartPaint; + int yposScreen = lineStartPaint * vs.lineHeight; // Work out whether the top line is whitespace located after a // lessening of fold level which implies a 'fold tail' but which should not // be displayed until the last of a sequence of whitespace. bool needWhiteClosure = false; - int level = pdoc->GetLevel(cs.DocFromDisplay(topLine)); - if (level & SC_FOLDLEVELWHITEFLAG) { - int lineBack = cs.DocFromDisplay(topLine); - int levelPrev = level; - while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) { - lineBack--; - levelPrev = pdoc->GetLevel(lineBack); + if (vs.ms[margin].mask & SC_MASK_FOLDERS) { + int level = pdoc->GetLevel(cs.DocFromDisplay(visibleLine)); + if (level & SC_FOLDLEVELWHITEFLAG) { + int lineBack = cs.DocFromDisplay(visibleLine); + int levelPrev = level; + while ((lineBack > 0) && (levelPrev & SC_FOLDLEVELWHITEFLAG)) { + lineBack--; + levelPrev = pdoc->GetLevel(lineBack); + } + if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) { + if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK)) + needWhiteClosure = true; + } } - if (!(levelPrev & SC_FOLDLEVELHEADERFLAG)) { - if ((level & SC_FOLDLEVELNUMBERMASK) < (levelPrev & SC_FOLDLEVELNUMBERMASK)) - needWhiteClosure = true; + if (highlightDelimiter.isEnabled) { + int lastLine = cs.DocFromDisplay(topLine + LinesOnScreen()) + 1; + pdoc->GetHighlightDelimiters(highlightDelimiter, pdoc->LineFromPosition(CurrentPosition()), lastLine); } } @@ -1655,107 +1835,145 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rcMargin.bottom) { PLATFORM_ASSERT(visibleLine < cs.LinesDisplayed()); - int lineDoc = cs.DocFromDisplay(visibleLine); PLATFORM_ASSERT(cs.GetVisible(lineDoc)); bool firstSubLine = visibleLine == cs.DisplayFromDoc(lineDoc); + bool lastSubLine = visibleLine == (cs.DisplayFromDoc(lineDoc + 1) - 1); - // Decide which fold indicator should be displayed - level = pdoc->GetLevel(lineDoc); - int levelNext = pdoc->GetLevel(lineDoc + 1); int marks = pdoc->GetMark(lineDoc); if (!firstSubLine) marks = 0; - int levelNum = level & SC_FOLDLEVELNUMBERMASK; - int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK; - if (level & SC_FOLDLEVELHEADERFLAG) { - if (firstSubLine) { - if (cs.GetExpanded(lineDoc)) { - if (levelNum == SC_FOLDLEVELBASE) - marks |= 1 << SC_MARKNUM_FOLDEROPEN; - else - marks |= 1 << folderOpenMid; + + bool headWithTail = false; + + if (vs.ms[margin].mask & SC_MASK_FOLDERS) { + // Decide which fold indicator should be displayed + int level = pdoc->GetLevel(lineDoc); + int levelNext = pdoc->GetLevel(lineDoc + 1); + int levelNum = level & SC_FOLDLEVELNUMBERMASK; + int levelNextNum = levelNext & SC_FOLDLEVELNUMBERMASK; + if (level & SC_FOLDLEVELHEADERFLAG) { + if (firstSubLine) { + if (levelNum < levelNextNum) { + if (cs.GetExpanded(lineDoc)) { + if (levelNum == SC_FOLDLEVELBASE) + marks |= 1 << SC_MARKNUM_FOLDEROPEN; + else + marks |= 1 << folderOpenMid; + } else { + if (levelNum == SC_FOLDLEVELBASE) + marks |= 1 << SC_MARKNUM_FOLDER; + else + marks |= 1 << folderEnd; + } + } else if (levelNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } } else { - if (levelNum == SC_FOLDLEVELBASE) - marks |= 1 << SC_MARKNUM_FOLDER; - else - marks |= 1 << folderEnd; + if (levelNum < levelNextNum) { + if (cs.GetExpanded(lineDoc)) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } else if (levelNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } + } else if (levelNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } } - } else { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } - needWhiteClosure = false; - } else if (level & SC_FOLDLEVELWHITEFLAG) { - if (needWhiteClosure) { - if (levelNext & SC_FOLDLEVELWHITEFLAG) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; + needWhiteClosure = false; + int firstFollowupLine = cs.DocFromDisplay(cs.DisplayFromDoc(lineDoc + 1)); + int firstFollowupLineLevel = pdoc->GetLevel(firstFollowupLine); + int secondFollowupLineLevelNum = pdoc->GetLevel(firstFollowupLine + 1) & SC_FOLDLEVELNUMBERMASK; + if (!cs.GetExpanded(lineDoc)) { + if ((firstFollowupLineLevel & SC_FOLDLEVELWHITEFLAG) && + (levelNum > secondFollowupLineLevelNum)) + needWhiteClosure = true; + + if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine)) + headWithTail = true; + } + } else if (level & SC_FOLDLEVELWHITEFLAG) { + if (needWhiteClosure) { + if (levelNext & SC_FOLDLEVELWHITEFLAG) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } else if (levelNextNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + needWhiteClosure = false; + } else { + marks |= 1 << SC_MARKNUM_FOLDERTAIL; + needWhiteClosure = false; + } } else if (levelNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; - needWhiteClosure = false; - } else { - marks |= 1 << SC_MARKNUM_FOLDERTAIL; - needWhiteClosure = false; + if (levelNextNum < levelNum) { + if (levelNextNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + } else { + marks |= 1 << SC_MARKNUM_FOLDERTAIL; + } + } else { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + } } } else if (levelNum > SC_FOLDLEVELBASE) { if (levelNextNum < levelNum) { - if (levelNextNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + needWhiteClosure = false; + if (levelNext & SC_FOLDLEVELWHITEFLAG) { + marks |= 1 << SC_MARKNUM_FOLDERSUB; + needWhiteClosure = true; + } else if (lastSubLine) { + if (levelNextNum > SC_FOLDLEVELBASE) { + marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; + } else { + marks |= 1 << SC_MARKNUM_FOLDERTAIL; + } } else { - marks |= 1 << SC_MARKNUM_FOLDERTAIL; + marks |= 1 << SC_MARKNUM_FOLDERSUB; } } else { marks |= 1 << SC_MARKNUM_FOLDERSUB; } } - } else if (levelNum > SC_FOLDLEVELBASE) { - if (levelNextNum < levelNum) { - needWhiteClosure = false; - if (levelNext & SC_FOLDLEVELWHITEFLAG) { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - needWhiteClosure = true; - } else if (levelNextNum > SC_FOLDLEVELBASE) { - marks |= 1 << SC_MARKNUM_FOLDERMIDTAIL; - } else { - marks |= 1 << SC_MARKNUM_FOLDERTAIL; - } - } else { - marks |= 1 << SC_MARKNUM_FOLDERSUB; - } } marks &= vs.ms[margin].mask; + PRectangle rcMarker = rcSelMargin; rcMarker.top = yposScreen; rcMarker.bottom = yposScreen + vs.lineHeight; if (vs.ms[margin].style == SC_MARGIN_NUMBER) { - char number[100]; - number[0] = '\0'; - if (firstSubLine) + if (firstSubLine) { + char number[100]; sprintf(number, "%d", lineDoc + 1); - if (foldFlags & SC_FOLDFLAG_LEVELNUMBERS) { - int lev = pdoc->GetLevel(lineDoc); - sprintf(number, "%c%c %03X %03X", - (lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_', - (lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_', - lev & SC_FOLDLEVELNUMBERMASK, - lev >> 16 - ); + if (foldFlags & SC_FOLDFLAG_LEVELNUMBERS) { + int lev = pdoc->GetLevel(lineDoc); + sprintf(number, "%c%c %03X %03X", + (lev & SC_FOLDLEVELHEADERFLAG) ? 'H' : '_', + (lev & SC_FOLDLEVELWHITEFLAG) ? 'W' : '_', + lev & SC_FOLDLEVELNUMBERMASK, + lev >> 16 + ); + } + PRectangle rcNumber = rcMarker; + // Right justify + XYPOSITION width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, istrlen(number)); + XYPOSITION xpos = rcNumber.right - width - 3; + rcNumber.left = xpos; + surface->DrawTextNoClip(rcNumber, vs.styles[STYLE_LINENUMBER].font, + rcNumber.top + vs.maxAscent, number, istrlen(number), + vs.styles[STYLE_LINENUMBER].fore, + vs.styles[STYLE_LINENUMBER].back); + } else if (wrapVisualFlags & SC_WRAPVISUALFLAG_MARGIN) { + PRectangle rcWrapMarker = rcMarker; + rcWrapMarker.right -= 3; + rcWrapMarker.left = rcWrapMarker.right - vs.styles[STYLE_LINENUMBER].aveCharWidth; + DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[STYLE_LINENUMBER].fore); } - PRectangle rcNumber = rcMarker; - // Right justify - int width = surface->WidthText(vs.styles[STYLE_LINENUMBER].font, number, istrlen(number)); - int xpos = rcNumber.right - width - 3; - rcNumber.left = xpos; - surface->DrawTextNoClip(rcNumber, vs.styles[STYLE_LINENUMBER].font, - rcNumber.top + vs.maxAscent, number, istrlen(number), - vs.styles[STYLE_LINENUMBER].fore.allocated, - vs.styles[STYLE_LINENUMBER].back.allocated); } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) { if (firstSubLine) { const StyledText stMargin = pdoc->MarginStyledText(lineDoc); if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) { surface->FillRectangle(rcMarker, - vs.styles[stMargin.StyleAt(0)+vs.marginStyleOffset].back.allocated); + vs.styles[stMargin.StyleAt(0)+vs.marginStyleOffset].back); if (vs.ms[margin].style == SC_MARGIN_RTEXT) { int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin); rcMarker.left = rcMarker.right - width - 3; @@ -1769,7 +1987,25 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { if (marks) { for (int markBit = 0; (markBit < 32) && marks; markBit++) { if (marks & 1) { - vs.markers[markBit].Draw(surface, rcMarker, vs.styles[STYLE_LINENUMBER].font); + LineMarker::typeOfFold tFold = LineMarker::undefined; + if ((vs.ms[margin].mask & SC_MASK_FOLDERS) && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) { + if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) { + tFold = LineMarker::body; + } else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) { + if (firstSubLine) { + tFold = headWithTail ? LineMarker::headWithTail : LineMarker::head; + } else { + if (cs.GetExpanded(lineDoc) || headWithTail) { + tFold = LineMarker::body; + } else { + tFold = LineMarker::undefined; + } + } + } else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) { + tFold = LineMarker::tail; + } + } + vs.markers[markBit].Draw(surface, rcMarker, vs.styles[STYLE_LINENUMBER].font, tFold, vs.ms[margin].style); } marks >>= 1; } @@ -1783,10 +2019,10 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { PRectangle rcBlankMargin = rcMargin; rcBlankMargin.left = rcSelMargin.right; - surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back.allocated); + surface->FillRectangle(rcBlankMargin, vs.styles[STYLE_DEFAULT].back); if (bufferedDraw) { - surfWindow->Copy(rcMargin, Point(), *pixmapSelMargin); + surfWindow->Copy(rcMargin, Point(rcMargin.left, rcMargin.top), *pixmapSelMargin); } } @@ -1817,58 +2053,18 @@ LineLayout *Editor::RetrieveLineLayout(int lineNumber) { LinesOnScreen() + 1, pdoc->LinesTotal()); } -static bool GoodTrailByte(int v) { - return (v >= 0x80) && (v < 0xc0); -} - bool BadUTF(const char *s, int len, int &trailBytes) { + // For the rules: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 if (trailBytes) { trailBytes--; return false; } - const unsigned char *us = reinterpret_cast<const unsigned char *>(s); - if (*us < 0x80) { - // Single bytes easy - return false; - } else if (*us > 0xF4) { - // Characters longer than 4 bytes not possible in current UTF-8 - return true; - } else if (*us >= 0xF0) { - // 4 bytes - if (len < 4) - return true; - if (GoodTrailByte(us[1]) && GoodTrailByte(us[2]) && GoodTrailByte(us[3])) { - trailBytes = 3; - return false; - } else { - return true; - } - } else if (*us >= 0xE0) { - // 3 bytes - if (len < 3) - return true; - if (GoodTrailByte(us[1]) && GoodTrailByte(us[2])) { - trailBytes = 2; - return false; - } else { - return true; - } - } else if (*us >= 0xC2) { - // 2 bytes - if (len < 2) - return true; - if (GoodTrailByte(us[1])) { - trailBytes = 1; - return false; - } else { - return true; - } - } else if (*us >= 0xC0) { - // Overlong encoding + int utf8status = UTF8Classify(reinterpret_cast<const unsigned char *>(s), len); + if (utf8status & UTF8MaskInvalid) { return true; } else { - // Trail byte - return true; + trailBytes = (utf8status & UTF8MaskWidth) - 1; + return false; } } @@ -1892,11 +2088,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou if (ll->validity == LineLayout::llCheckTextAndStyle) { int lineLength = posLineEnd - posLineStart; if (!vstyle.viewEOL) { - int cid = posLineEnd - 1; - while ((cid > posLineStart) && IsEOLChar(pdoc->CharAt(cid))) { - cid--; - lineLength--; - } + lineLength = pdoc->LineEnd(line) - posLineStart; } if (lineLength == ll->numCharsInLine) { // See if chars, styles, indicators, are all the same @@ -1937,8 +2129,6 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou if (ll->validity == LineLayout::llInvalid) { ll->widthLine = LineLayout::wrapWidthInfinite; ll->lines = 1; - int numCharsInLine = 0; - int numCharsBeforeEOL = 0; if (vstyle.edgeState == EDGE_BACKGROUND) { ll->edgeColumn = pdoc->FindColumn(line, theEdge); if (ll->edgeColumn >= posLineStart) { @@ -1948,25 +2138,29 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou ll->edgeColumn = -1; } - char styleByte = 0; - int styleMask = pdoc->stylingBitsMask; + char styleByte; + const int styleMask = pdoc->stylingBitsMask; ll->styleBitsSet = 0; // Fill base line layout - for (int charInDoc = posLineStart; charInDoc < posLineEnd; charInDoc++) { - char chDoc = pdoc->CharAt(charInDoc); - styleByte = pdoc->StyleAt(charInDoc); + const int lineLength = posLineEnd - posLineStart; + pdoc->GetCharRange(ll->chars, posLineStart, lineLength); + pdoc->GetStyleRange(ll->styles, posLineStart, lineLength); + int numCharsBeforeEOL = pdoc->LineEnd(line) - posLineStart; + const int numCharsInLine = (vstyle.viewEOL) ? lineLength : numCharsBeforeEOL; + for (int styleInLine = 0; styleInLine < numCharsInLine; styleInLine++) { + styleByte = ll->styles[styleInLine]; ll->styleBitsSet |= styleByte; - if (vstyle.viewEOL || (!IsEOLChar(chDoc))) { - ll->chars[numCharsInLine] = chDoc; - ll->styles[numCharsInLine] = static_cast<char>(styleByte & styleMask); - ll->indicators[numCharsInLine] = static_cast<char>(styleByte & ~styleMask); - if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseUpper) - ll->chars[numCharsInLine] = static_cast<char>(toupper(chDoc)); - else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower) - ll->chars[numCharsInLine] = static_cast<char>(tolower(chDoc)); - numCharsInLine++; - if (!IsEOLChar(chDoc)) - numCharsBeforeEOL++; + ll->styles[styleInLine] = static_cast<char>(styleByte & styleMask); + ll->indicators[styleInLine] = static_cast<char>(styleByte & ~styleMask); + } + styleByte = static_cast<char>(((lineLength > 0) ? ll->styles[lineLength-1] : 0) & styleMask); + if (vstyle.someStylesForceCase) { + for (int charInLine = 0; charInLine<lineLength; charInLine++) { + char chDoc = ll->chars[charInLine]; + if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseUpper) + ll->chars[charInLine] = static_cast<char>(toupper(chDoc)); + else if (vstyle.styles[ll->styles[charInLine]].caseForce == Style::caseLower) + ll->chars[charInLine] = static_cast<char>(tolower(chDoc)); } } ll->xHighlightGuide = 0; @@ -1978,13 +2172,13 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou // Layout the line, determining the position of each character, // with an extra element at the end for the end of the line. int startseg = 0; // Start of the current segment, in char. number - int startsegx = 0; // Start of the current segment, in pixels + XYACCUMULATOR startsegx = 0; // Start of the current segment, in pixels ll->positions[0] = 0; - unsigned int tabWidth = vstyle.spaceWidth * pdoc->tabInChars; + XYPOSITION tabWidth = vstyle.spaceWidth * pdoc->tabInChars; bool lastSegItalics = false; Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font; - int ctrlCharWidth[32] = {0}; + XYPOSITION ctrlCharWidth[32] = {0}; bool isControlNext = IsControlCharacter(ll->chars[0]); int trailBytes = 0; bool isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars, numCharsInLine, trailBytes); @@ -1999,8 +2193,8 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou if (vstyle.styles[ll->styles[charInLine]].visible) { if (isControl) { if (ll->chars[charInLine] == '\t') { - ll->positions[charInLine + 1] = ((((startsegx + 2) / - tabWidth) + 1) * tabWidth) - startsegx; + ll->positions[charInLine + 1] = + ((static_cast<int>((startsegx + 2) / tabWidth) + 1) * tabWidth) - startsegx; } else if (controlCharSymbol < 32) { if (ctrlCharWidth[ll->chars[charInLine]] == 0) { const char *ctrlChar = ControlCharacterString(ll->chars[charInLine]); @@ -2016,8 +2210,8 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou } lastSegItalics = false; } else if (isBadUTF) { - char hexits[3]; - sprintf(hexits, "%2X", ll->chars[charInLine] & 0xff); + char hexits[4]; + sprintf(hexits, "x%2X", ll->chars[charInLine] & 0xff); ll->positions[charInLine + 1] = surface->WidthText(ctrlCharsFont, hexits, istrlen(hexits)) + 3; } else { // Regular character @@ -2029,7 +2223,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou } else { lastSegItalics = vstyle.styles[ll->styles[charInLine]].italic; posCache.MeasureWidths(surface, vstyle, ll->styles[charInLine], ll->chars + startseg, - lenSeg, ll->positions + startseg + 1); + lenSeg, ll->positions + startseg + 1, pdoc); } } } else { // invisible @@ -2065,7 +2259,13 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou ll->lines = 1; } else { if (wrapVisualFlags & SC_WRAPVISUALFLAG_END) { - width -= vstyle.aveCharWidth; // take into account the space for end wrap mark + width -= static_cast<int>(vstyle.aveCharWidth); // take into account the space for end wrap mark + } + XYPOSITION wrapAddIndent = 0; // This will be added to initial indent of line + if (wrapIndentMode == SC_WRAPINDENT_INDENT) { + wrapAddIndent = pdoc->IndentSize() * vstyle.spaceWidth; + } else if (wrapIndentMode == SC_WRAPINDENT_FIXED) { + wrapAddIndent = wrapVisualStartIndent * vstyle.aveCharWidth; } ll->wrapIndent = wrapAddIndent; if (wrapIndentMode != SC_WRAPINDENT_FIXED) @@ -2079,13 +2279,13 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou if (ll->wrapIndent > width - static_cast<int>(vstyle.aveCharWidth) * 15) ll->wrapIndent = wrapAddIndent; // Check for wrapIndent minimum - if ((wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < static_cast<int>(vstyle.aveCharWidth))) + if ((wrapVisualFlags & SC_WRAPVISUALFLAG_START) && (ll->wrapIndent < vstyle.aveCharWidth)) ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual ll->lines = 0; // Calculate line start positions based upon width. int lastGoodBreak = 0; int lastLineStart = 0; - int startOffset = 0; + XYACCUMULATOR startOffset = 0; int p = 0; while (p < ll->numCharsInLine) { if ((ll->positions[p + 1] - startOffset) >= width) { @@ -2130,14 +2330,14 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou } } -ColourAllocated Editor::SelectionBackground(ViewStyle &vsDraw, bool main) { +ColourDesired Editor::SelectionBackground(ViewStyle &vsDraw, bool main) { return main ? - (primarySelection ? vsDraw.selbackground.allocated : vsDraw.selbackground2.allocated) : - vsDraw.selAdditionalBackground.allocated; + (primarySelection ? vsDraw.selbackground : vsDraw.selbackground2) : + vsDraw.selAdditionalBackground; } -ColourAllocated Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackground, - ColourAllocated background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) { +ColourDesired Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackground, + ColourDesired background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll) { if (inSelection == 1) { if (vsDraw.selbackset && (vsDraw.selAlpha == SC_ALPHA_NOALPHA)) { return SelectionBackground(vsDraw, true); @@ -2149,14 +2349,16 @@ ColourAllocated Editor::TextBackground(ViewStyle &vsDraw, bool overrideBackgroun } else { if ((vsDraw.edgeState == EDGE_BACKGROUND) && (i >= ll->edgeColumn) && - !IsEOLChar(ll->chars[i])) - return vsDraw.edgecolour.allocated; + (i < ll->numCharsBeforeEOL)) + return vsDraw.edgecolour; if (inHotspot && vsDraw.hotspotBackgroundSet) - return vsDraw.hotspotBackground.allocated; - if (overrideBackground && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) - return background; + return vsDraw.hotspotBackground; + } + if (overrideBackground && (styleMain != STYLE_BRACELIGHT) && (styleMain != STYLE_BRACEBAD)) { + return background; + } else { + return vsDraw.styles[styleMain].back; } - return vsDraw.styles[styleMain].back.allocated; } void Editor::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight) { @@ -2167,7 +2369,7 @@ void Editor::DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, } void Editor::DrawWrapMarker(Surface *surface, PRectangle rcPlace, - bool isEndMarker, ColourAllocated wrapColour) { + bool isEndMarker, ColourDesired wrapColour) { surface->PenColour(wrapColour); enum { xa = 1 }; // gap before start @@ -2212,14 +2414,14 @@ void Editor::DrawWrapMarker(Surface *surface, PRectangle rcPlace, y - 2 * dy); } -static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourAllocated fill, int alpha) { +static void SimpleAlphaRectangle(Surface *surface, PRectangle rc, ColourDesired fill, int alpha) { if (alpha != SC_ALPHA_NOALPHA) { surface->AlphaRectangle(rc, 0, fill, alpha, fill, alpha, 0); } } void DrawTextBlob(Surface *surface, ViewStyle &vsDraw, PRectangle rcSegment, - const char *s, ColourAllocated textBack, ColourAllocated textFore, bool twoPhaseDraw) { + const char *s, ColourDesired textBack, ColourDesired textFore, bool twoPhaseDraw) { if (!twoPhaseDraw) { surface->FillRectangle(rcSegment, textBack); } @@ -2243,30 +2445,27 @@ void DrawTextBlob(Surface *surface, ViewStyle &vsDraw, PRectangle rcSegment, } void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll, - int line, int lineEnd, int xStart, int subLine, int subLineStart, - bool overrideBackground, ColourAllocated background, - bool drawWrapMarkEnd, ColourAllocated wrapColour) { + int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, + bool overrideBackground, ColourDesired background, + bool drawWrapMarkEnd, ColourDesired wrapColour) { const int posLineStart = pdoc->LineStart(line); const int styleMask = pdoc->stylingBitsMask; PRectangle rcSegment = rcLine; const bool lastSubLine = subLine == (ll->lines - 1); - int virtualSpace = 0; + XYPOSITION virtualSpace = 0; if (lastSubLine) { - const int spaceWidth = static_cast<int>(vsDraw.styles[ll->EndLineStyle()].spaceWidth); + const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; virtualSpace = sel.VirtualSpaceFor(pdoc->LineEnd(line)) * spaceWidth; } - - // Fill in a PRectangle representing the end of line characters - - int xEol = ll->positions[lineEnd] - subLineStart; + XYPOSITION xEol = ll->positions[lineEnd] - subLineStart; // Fill the virtual space and show selections within it if (virtualSpace) { rcSegment.left = xEol + xStart; rcSegment.right = xEol + xStart + virtualSpace; - surface->FillRectangle(rcSegment, overrideBackground ? background : vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back.allocated); + surface->FillRectangle(rcSegment, overrideBackground ? background : vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back); if (!hideSelection && ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA))) { SelectionSegment virtualSpaceRange(SelectionPosition(pdoc->LineEnd(line)), SelectionPosition(pdoc->LineEnd(line), sel.VirtualSpaceFor(pdoc->LineEnd(line)))); for (size_t r=0; r<sel.Count(); r++) { @@ -2274,11 +2473,11 @@ void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, Lin if (alpha == SC_ALPHA_NOALPHA) { SelectionSegment portion = sel.Range(r).Intersect(virtualSpaceRange); if (!portion.Empty()) { - const int spaceWidth = static_cast<int>(vsDraw.styles[ll->EndLineStyle()].spaceWidth); + const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - subLineStart + portion.start.VirtualSpace() * spaceWidth; rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth; - rcSegment.left = Platform::Maximum(rcSegment.left, rcLine.left); - rcSegment.right = Platform::Minimum(rcSegment.right, rcLine.right); + rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; + rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, r == sel.Main())); } } @@ -2286,73 +2485,82 @@ void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, Lin } } - int posAfterLineEnd = pdoc->LineStart(line + 1); - int eolInSelection = (subLine == (ll->lines - 1)) ? sel.InSelectionForEOL(posAfterLineEnd) : 0; - int alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; + int eolInSelection = 0; + int alpha = SC_ALPHA_NOALPHA; + if (!hideSelection) { + int posAfterLineEnd = pdoc->LineStart(line + 1); + eolInSelection = (subLine == (ll->lines - 1)) ? sel.InSelectionForEOL(posAfterLineEnd) : 0; + alpha = (eolInSelection == 1) ? vsDraw.selAlpha : vsDraw.selAdditionalAlpha; + } // Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on - int blobsWidth = 0; + XYPOSITION blobsWidth = 0; if (lastSubLine) { for (int eolPos=ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine; eolPos++) { rcSegment.left = xStart + ll->positions[eolPos] - subLineStart + virtualSpace; rcSegment.right = xStart + ll->positions[eolPos+1] - subLineStart + virtualSpace; blobsWidth += rcSegment.Width(); const char *ctrlChar = ControlCharacterString(ll->chars[eolPos]); - int inSelection = 0; - bool inHotspot = false; int styleMain = ll->styles[eolPos]; - ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, eolPos, ll); - ColourAllocated textFore = vsDraw.styles[styleMain].fore.allocated; - if (!hideSelection && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1)) { + ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, eolInSelection, false, styleMain, eolPos, ll); + ColourDesired textFore = vsDraw.styles[styleMain].fore; + if (eolInSelection && vsDraw.selforeset) { + textFore = (eolInSelection == 1) ? vsDraw.selforeground : vsDraw.selAdditionalForeground; + } + if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1)) { if (alpha == SC_ALPHA_NOALPHA) { surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1)); } else { surface->FillRectangle(rcSegment, textBack); - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha); } } else { surface->FillRectangle(rcSegment, textBack); } DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, textBack, textFore, twoPhaseDraw); + if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { + SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha); + } } } // Draw the eol-is-selected rectangle rcSegment.left = xEol + xStart + virtualSpace + blobsWidth; - rcSegment.right = xEol + xStart + virtualSpace + blobsWidth + vsDraw.aveCharWidth; + rcSegment.right = rcSegment.left + vsDraw.aveCharWidth; - if (!hideSelection && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { + if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1)); } else { if (overrideBackground) { surface->FillRectangle(rcSegment, background); } else if (line < pdoc->LinesTotal() - 1) { - surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back.allocated); + surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back); } else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) { - surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back.allocated); + surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back); } else { - surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back.allocated); + surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); } - if (!hideSelection && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { + if (eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha); } } // Fill the remainder of the line - rcSegment.left = xEol + xStart + virtualSpace + blobsWidth + vsDraw.aveCharWidth; + rcSegment.left = rcSegment.right; + if (rcSegment.left < rcLine.left) + rcSegment.left = rcLine.left; rcSegment.right = rcLine.right; - if (!hideSelection && vsDraw.selEOLFilled && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { + if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha == SC_ALPHA_NOALPHA)) { surface->FillRectangle(rcSegment, SelectionBackground(vsDraw, eolInSelection == 1)); } else { if (overrideBackground) { surface->FillRectangle(rcSegment, background); } else if (vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].eolFilled) { - surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back.allocated); + surface->FillRectangle(rcSegment, vsDraw.styles[ll->styles[ll->numCharsInLine] & styleMask].back); } else { - surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back.allocated); + surface->FillRectangle(rcSegment, vsDraw.styles[STYLE_DEFAULT].back); } - if (!hideSelection && vsDraw.selEOLFilled && eolInSelection && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { + if (eolInSelection && vsDraw.selEOLFilled && vsDraw.selbackset && (line < pdoc->LinesTotal() - 1) && (alpha != SC_ALPHA_NOALPHA)) { SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, eolInSelection == 1), alpha); } } @@ -2364,20 +2572,30 @@ void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, Lin rcPlace.left = xEol + xStart + virtualSpace; rcPlace.right = rcPlace.left + vsDraw.aveCharWidth; } else { - // draw left of the right text margin, to avoid clipping by the current clip rect - rcPlace.right = rcLine.right - vs.rightMarginWidth; + // rcLine is clipped to text area + rcPlace.right = rcLine.right; rcPlace.left = rcPlace.right - vsDraw.aveCharWidth; } DrawWrapMarker(surface, rcPlace, true, wrapColour); } } +void Editor::DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, ViewStyle &vsDraw, + int xStart, PRectangle rcLine, LineLayout *ll, int subLine) { + const XYPOSITION subLineStart = ll->positions[ll->LineStart(subLine)]; + PRectangle rcIndic( + ll->positions[startPos] + xStart - subLineStart, + rcLine.top + vsDraw.maxAscent, + ll->positions[endPos] + xStart - subLineStart, + rcLine.top + vsDraw.maxAscent + 3); + vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine); +} + void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under) { // Draw decorators const int posLineStart = pdoc->LineStart(line); const int lineStart = ll->LineStart(subLine); - const int subLineStart = ll->positions[lineStart]; const int posLineEnd = posLineStart + lineEnd; if (!under) { @@ -2402,12 +2620,7 @@ void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int x // IN indicator run, looking for END if (indicPos >= lineEnd || !(ll->indicators[indicPos] & mask)) { // AT end of indicator run, DRAW it! - PRectangle rcIndic( - ll->positions[startPos] + xStart - subLineStart, - rcLine.top + vsDraw.maxAscent, - ll->positions[indicPos] + xStart - subLineStart, - rcLine.top + vsDraw.maxAscent + 3); - vsDraw.indicators[indicnum].Draw(surface, rcIndic, rcLine); + DrawIndicator(indicnum, startPos, indicPos, surface, vsDraw, xStart, rcLine, ll, subLine); // RESET control var startPos = -1; } @@ -2427,16 +2640,33 @@ void Editor::DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int x int endPos = deco->rs.EndRun(startPos); if (endPos > posLineEnd) endPos = posLineEnd; - PRectangle rcIndic( - ll->positions[startPos - posLineStart] + xStart - subLineStart, - rcLine.top + vsDraw.maxAscent, - ll->positions[endPos - posLineStart] + xStart - subLineStart, - rcLine.top + vsDraw.maxAscent + 3); - vsDraw.indicators[deco->indicator].Draw(surface, rcIndic, rcLine); + DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart, + surface, vsDraw, xStart, rcLine, ll, subLine); startPos = deco->rs.EndRun(endPos); } } } + + // Use indicators to highlight matching braces + if ((vs.braceHighlightIndicatorSet && (bracesMatchStyle == STYLE_BRACELIGHT)) || + (vs.braceBadLightIndicatorSet && (bracesMatchStyle == STYLE_BRACEBAD))) { + int braceIndicator = (bracesMatchStyle == STYLE_BRACELIGHT) ? vs.braceHighlightIndicator : vs.braceBadLightIndicator; + if (under == vsDraw.indicators[braceIndicator].under) { + Range rangeLine(posLineStart + lineStart, posLineEnd); + if (rangeLine.ContainsCharacter(braces[0])) { + int braceOffset = braces[0] - posLineStart; + if (braceOffset < ll->numCharsInLine) { + DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine); + } + } + if (rangeLine.ContainsCharacter(braces[1])) { + int braceOffset = braces[1] - posLineStart; + if (braceOffset < ll->numCharsInLine) { + DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, xStart, rcLine, ll, subLine); + } + } + } + } } void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart, @@ -2446,14 +2676,13 @@ void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int x int annotationLine = subLine - ll->lines; const StyledText stAnnotation = pdoc->AnnotationStyledText(line); if (stAnnotation.text && ValidStyledText(vsDraw, vsDraw.annotationStyleOffset, stAnnotation)) { - surface->FillRectangle(rcSegment, vsDraw.styles[0].back.allocated); + surface->FillRectangle(rcSegment, vsDraw.styles[0].back); if (vs.annotationVisible == ANNOTATION_BOXED) { // Only care about calculating width if need to draw box int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation); widthAnnotation += vsDraw.spaceWidth * 2; // Margins rcSegment.left = xStart + indent; rcSegment.right = rcSegment.left + widthAnnotation; - surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore.allocated); } else { rcSegment.left = xStart; } @@ -2469,17 +2698,18 @@ void Editor::DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int x PRectangle rcText = rcSegment; if (vs.annotationVisible == ANNOTATION_BOXED) { surface->FillRectangle(rcText, - vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back.allocated); + vsDraw.styles[stAnnotation.StyleAt(start) + vsDraw.annotationStyleOffset].back); rcText.left += vsDraw.spaceWidth; } DrawStyledText(surface, vsDraw, vsDraw.annotationStyleOffset, rcText, rcText.top + vsDraw.maxAscent, stAnnotation, start, lengthAnnotation); if (vs.annotationVisible == ANNOTATION_BOXED) { + surface->PenColour(vsDraw.styles[vsDraw.annotationStyleOffset].fore); surface->MoveTo(rcSegment.left, rcSegment.top); surface->LineTo(rcSegment.left, rcSegment.bottom); surface->MoveTo(rcSegment.right, rcSegment.top); surface->LineTo(rcSegment.right, rcSegment.bottom); - if (subLine == ll->lines){ + if (subLine == ll->lines) { surface->MoveTo(rcSegment.left, rcSegment.top); surface->LineTo(rcSegment.right, rcSegment.top); } @@ -2508,17 +2738,17 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis // with the earlier taking precedence. When multiple markers cause background override, // the color for the highest numbered one is used. bool overrideBackground = false; - ColourAllocated background; + ColourDesired background; if (caret.active && vsDraw.showCaretLineBackground && (vsDraw.caretLineAlpha == SC_ALPHA_NOALPHA) && ll->containsCaret) { overrideBackground = true; - background = vsDraw.caretLineBackground.allocated; + background = vsDraw.caretLineBackground; } if (!overrideBackground) { int marks = pdoc->GetMark(line); for (int markBit = 0; (markBit < 32) && marks; markBit++) { if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND) && (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) { - background = vsDraw.markers[markBit].back.allocated; + background = vsDraw.markers[markBit].back; overrideBackground = true; } marks >>= 1; @@ -2532,7 +2762,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY) && (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) { overrideBackground = true; - background = vsDraw.markers[markBit].back.allocated; + background = vsDraw.markers[markBit].back; } marksMasked >>= 1; } @@ -2544,12 +2774,13 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis (!overrideBackground) && (vsDraw.whitespaceBackgroundSet); bool inIndentation = subLine == 0; // Do not handle indentation except on first subline. - int indentWidth = pdoc->IndentSize() * vsDraw.spaceWidth; + const XYPOSITION indentWidth = pdoc->IndentSize() * vsDraw.spaceWidth; + const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point precision issues int posLineStart = pdoc->LineStart(line); int startseg = ll->LineStart(subLine); - int subLineStart = ll->positions[startseg]; + XYACCUMULATOR subLineStart = ll->positions[startseg]; if (subLine >= ll->lines) { DrawAnnotation(surface, vsDraw, line, xStart, rcLine, ll, subLine); return; // No further drawing @@ -2564,9 +2795,9 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } } - ColourAllocated wrapColour = vsDraw.styles[STYLE_DEFAULT].fore.allocated; + ColourDesired wrapColour = vsDraw.styles[STYLE_DEFAULT].fore; if (vsDraw.whitespaceForegroundSet) - wrapColour = vsDraw.whitespaceForeground.allocated; + wrapColour = vsDraw.whitespaceForeground; bool drawWrapMarkEnd = false; @@ -2592,12 +2823,12 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis // default bgnd here.. surface->FillRectangle(rcSegment, overrideBackground ? background : - vsDraw.styles[STYLE_DEFAULT].back.allocated); + vsDraw.styles[STYLE_DEFAULT].back); // main line style would be below but this would be inconsistent with end markers // also would possibly not be the style at wrap point //int styleMain = ll->styles[lineStart]; - //surface->FillRectangle(rcPlace, vsDraw.styles[styleMain].back.allocated); + //surface->FillRectangle(rcPlace, vsDraw.styles[styleMain].back); if (wrapVisualFlags & SC_WRAPVISUALFLAG_START) { @@ -2609,7 +2840,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis DrawWrapMarker(surface, rcPlace, false, wrapColour); } - xStart += ll->wrapIndent; + xStart += static_cast<int>(ll->wrapIndent); } } @@ -2617,11 +2848,11 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis ((vsDraw.selAlpha == SC_ALPHA_NOALPHA) || (vsDraw.selAdditionalAlpha == SC_ALPHA_NOALPHA)); // Does not take margin into account but not significant - int xStartVisible = subLineStart - xStart; + int xStartVisible = static_cast<int>(subLineStart) - xStart; ll->psel = &sel; - BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, IsUnicodeMode(), xStartVisible, selBackDrawn); + BreakFinder bfBack(ll, lineStart, lineEnd, posLineStart, xStartVisible, selBackDrawn, pdoc); int next = bfBack.First(); // Background drawing loop @@ -2638,18 +2869,20 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis // draw strings that are completely past the right side of the window. if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) { // Clip to line rectangle, since may have a huge position which will not work with some platforms - rcSegment.left = Platform::Maximum(rcSegment.left, rcLine.left); - rcSegment.right = Platform::Minimum(rcSegment.right, rcLine.right); + if (rcSegment.left < rcLine.left) + rcSegment.left = rcLine.left; + if (rcSegment.right > rcLine.right) + rcSegment.right = rcLine.right; int styleMain = ll->styles[i]; const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc); bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd); - ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll); + ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll); if (ll->chars[i] == '\t') { // Tab display if (drawWhitespaceBackground && (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) - textBack = vsDraw.whitespaceBackground.allocated; + textBack = vsDraw.whitespaceBackground; surface->FillRectangle(rcSegment, textBack); } else if (IsControlCharacter(ll->chars[i])) { // Control character display @@ -2668,7 +2901,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis rcSegment.top, ll->positions[cpos + startseg + 1] + xStart - subLineStart, rcSegment.bottom); - surface->FillRectangle(rcSpace, vsDraw.whitespaceBackground.allocated); + surface->FillRectangle(rcSpace, vsDraw.whitespaceBackground); } } else { inIndentation = false; @@ -2692,8 +2925,10 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis if (vsDraw.edgeState == EDGE_LINE) { int edgeX = theEdge * vsDraw.spaceWidth; rcSegment.left = edgeX + xStart; + if ((ll->wrapIndent != 0) && (lineStart != 0)) + rcSegment.left -= ll->wrapIndent; rcSegment.right = rcSegment.left + 1; - surface->FillRectangle(rcSegment, vsDraw.edgecolour.allocated); + surface->FillRectangle(rcSegment, vsDraw.edgecolour); } // Draw underline mark as part of background if not transparent @@ -2704,15 +2939,15 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis (vsDraw.markers[markBit].alpha == SC_ALPHA_NOALPHA)) { PRectangle rcUnderline = rcLine; rcUnderline.top = rcUnderline.bottom - 2; - surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back.allocated); + surface->FillRectangle(rcUnderline, vsDraw.markers[markBit].back); } marks >>= 1; } inIndentation = subLine == 0; // Do not handle indentation except on first subline. // Foreground drawing loop - BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, IsUnicodeMode(), xStartVisible, - ((!twoPhaseDraw && selBackDrawn) || vsDraw.selforeset)); + BreakFinder bfFore(ll, lineStart, lineEnd, posLineStart, xStartVisible, + ((!twoPhaseDraw && selBackDrawn) || vsDraw.selforeset), pdoc); next = bfFore.First(); while (next < lineEnd) { @@ -2729,38 +2964,41 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis // draw strings that are completely past the right side of the window. if ((rcSegment.left <= rcLine.right) && (rcSegment.right >= rcLine.left)) { int styleMain = ll->styles[i]; - ColourAllocated textFore = vsDraw.styles[styleMain].fore.allocated; + ColourDesired textFore = vsDraw.styles[styleMain].fore; Font &textFont = vsDraw.styles[styleMain].font; //hotspot foreground if (ll->hsStart != -1 && iDoc >= ll->hsStart && iDoc < hsEnd) { if (vsDraw.hotspotForegroundSet) - textFore = vsDraw.hotspotForeground.allocated; + textFore = vsDraw.hotspotForeground; } const int inSelection = hideSelection ? 0 : sel.CharacterInSelection(iDoc); if (inSelection && (vsDraw.selforeset)) { - textFore = (inSelection == 1) ? vsDraw.selforeground.allocated : vsDraw.selAdditionalForeground.allocated; + textFore = (inSelection == 1) ? vsDraw.selforeground : vsDraw.selAdditionalForeground; } bool inHotspot = (ll->hsStart != -1) && (iDoc >= ll->hsStart) && (iDoc < ll->hsEnd); - ColourAllocated textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll); + ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, inSelection, inHotspot, styleMain, i, ll); if (ll->chars[i] == '\t') { // Tab display if (!twoPhaseDraw) { if (drawWhitespaceBackground && (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) - textBack = vsDraw.whitespaceBackground.allocated; + textBack = vsDraw.whitespaceBackground; surface->FillRectangle(rcSegment, textBack); } if ((vsDraw.viewWhitespace != wsInvisible) || (inIndentation && vsDraw.viewIndentationGuides != ivNone)) { if (vsDraw.whitespaceForegroundSet) - textFore = vsDraw.whitespaceForeground.allocated; + textFore = vsDraw.whitespaceForeground; surface->PenColour(textFore); } if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { - for (int xIG = ll->positions[i] / indentWidth * indentWidth; xIG < ll->positions[i + 1]; xIG += indentWidth) { - if (xIG >= ll->positions[i] && xIG > 0) { - DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIG + xStart, rcSegment, - (ll->xHighlightGuide == xIG)); + for (int indentCount = (ll->positions[i] + epsilon) / indentWidth; + indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth; + indentCount++) { + if (indentCount > 0) { + int xIndent = indentCount * indentWidth; + DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, + (ll->xHighlightGuide == xIndent)); } } } @@ -2785,8 +3023,9 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis cc, 1, textBack, textFore); } } else if ((i == startseg) && (static_cast<unsigned char>(ll->chars[i]) >= 0x80) && IsUnicodeMode()) { - char hexits[3]; - sprintf(hexits, "%2X", ll->chars[i] & 0xff); + // A single byte >= 0x80 in UTF-8 is a bad byte and is displayed as its hex value + char hexits[4]; + sprintf(hexits, "x%2X", ll->chars[i] & 0xff); DrawTextBlob(surface, vsDraw, rcSegment, hexits, textBack, textFore, twoPhaseDraw); } else { // Normal text display @@ -2807,12 +3046,12 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis if (ll->chars[cpos + startseg] == ' ') { if (vsDraw.viewWhitespace != wsInvisible) { if (vsDraw.whitespaceForegroundSet) - textFore = vsDraw.whitespaceForeground.allocated; + textFore = vsDraw.whitespaceForeground; if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) { - int xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2; + XYPOSITION xmid = (ll->positions[cpos + startseg] + ll->positions[cpos + startseg + 1]) / 2; if (!twoPhaseDraw && drawWhitespaceBackground && (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways)) { - textBack = vsDraw.whitespaceBackground.allocated; + textBack = vsDraw.whitespaceBackground; PRectangle rcSpace(ll->positions[cpos + startseg] + xStart - subLineStart, rcSegment.top, ll->positions[cpos + startseg + 1] + xStart - subLineStart, @@ -2826,10 +3065,14 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } } if (inIndentation && vsDraw.viewIndentationGuides == ivReal) { - int startSpace = ll->positions[cpos + startseg]; - if (startSpace > 0 && (startSpace % indentWidth == 0)) { - DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, startSpace + xStart, rcSegment, - (ll->xHighlightGuide == ll->positions[cpos + startseg])); + for (int indentCount = (ll->positions[cpos + startseg] + epsilon) / indentWidth; + indentCount <= (ll->positions[cpos + startseg + 1] - epsilon) / indentWidth; + indentCount++) { + if (indentCount > 0) { + int xIndent = indentCount * indentWidth; + DrawIndentGuide(surface, lineVisible, vsDraw.lineHeight, xIndent + xStart, rcSegment, + (ll->xHighlightGuide == xIndent)); + } } } } else { @@ -2838,12 +3081,12 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } } } - if (ll->hsStart != -1 && vsDraw.hotspotUnderline && iDoc >= ll->hsStart && iDoc < ll->hsEnd ) { + if (ll->hsStart != -1 && vsDraw.hotspotUnderline && iDoc >= ll->hsStart && iDoc < ll->hsEnd) { PRectangle rcUL = rcSegment; rcUL.top = rcUL.top + vsDraw.maxAscent + 1; rcUL.bottom = rcUL.top + 1; if (vsDraw.hotspotForegroundSet) - surface->FillRectangle(rcUL, vsDraw.hotspotForeground.allocated); + surface->FillRectangle(rcUL, vsDraw.hotspotForeground); else surface->FillRectangle(rcUL, textFore); } else if (vsDraw.styles[styleMain].underline) { @@ -2891,7 +3134,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis lineNextWithText++; } if (lineNextWithText > line) { - // This line is empty, so use indentation of last line with text + xStartText = 100000; // Don't limit to visible indentation on empty line + // This line is empty, so use indentation of first next line with text indentSpace = Platform::Maximum(indentSpace, pdoc->GetLineIndentation(lineNextWithText)); } @@ -2919,7 +3163,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis if (subLine == (ll->lines - 1)) { virtualSpaces = sel.VirtualSpaceFor(pdoc->LineEnd(line)); } - SelectionPosition posStart(posLineStart); + SelectionPosition posStart(posLineStart + lineStart); SelectionPosition posEnd(posLineStart + lineEnd, virtualSpaces); SelectionSegment virtualSpaceRange(posStart, posEnd); for (size_t r=0; r<sel.Count(); r++) { @@ -2927,31 +3171,35 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis if (alpha != SC_ALPHA_NOALPHA) { SelectionSegment portion = sel.Range(r).Intersect(virtualSpaceRange); if (!portion.Empty()) { - const int spaceWidth = static_cast<int>(vsDraw.styles[ll->EndLineStyle()].spaceWidth); + const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] - subLineStart + portion.start.VirtualSpace() * spaceWidth; rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] - subLineStart + portion.end.VirtualSpace() * spaceWidth; - rcSegment.left = Platform::Maximum(rcSegment.left, rcLine.left); - rcSegment.right = Platform::Minimum(rcSegment.right, rcLine.right); - SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == sel.Main()), alpha); + if ((ll->wrapIndent != 0) && (lineStart != 0)) { + if ((portion.start.Position() - posLineStart) == lineStart && sel.Range(r).ContainsCharacter(portion.start.Position() - 1)) + rcSegment.left -= static_cast<int>(ll->wrapIndent); // indentation added to xStart was truncated to int, so we do the same here + } + rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left; + rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right; + if (rcSegment.right > rcLine.left) + SimpleAlphaRectangle(surface, rcSegment, SelectionBackground(vsDraw, r == sel.Main()), alpha); } } } } // Draw any translucent whole line states - rcSegment.left = xStart; - rcSegment.right = rcLine.right - 1; + rcSegment = rcLine; if (caret.active && vsDraw.showCaretLineBackground && ll->containsCaret) { - SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground.allocated, vsDraw.caretLineAlpha); + SimpleAlphaRectangle(surface, rcSegment, vsDraw.caretLineBackground, vsDraw.caretLineAlpha); } marks = pdoc->GetMark(line); for (markBit = 0; (markBit < 32) && marks; markBit++) { if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_BACKGROUND)) { - SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back.allocated, vsDraw.markers[markBit].alpha); + SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); } else if ((marks & 1) && (vsDraw.markers[markBit].markType == SC_MARK_UNDERLINE)) { PRectangle rcUnderline = rcSegment; rcUnderline.top = rcUnderline.bottom - 2; - SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back.allocated, vsDraw.markers[markBit].alpha); + SimpleAlphaRectangle(surface, rcUnderline, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); } marks >>= 1; } @@ -2960,7 +3208,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis if (marksMasked) { for (markBit = 0; (markBit < 32) && marksMasked; markBit++) { if ((marksMasked & 1) && (vsDraw.markers[markBit].markType != SC_MARK_EMPTY)) { - SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back.allocated, vsDraw.markers[markBit].alpha); + SimpleAlphaRectangle(surface, rcSegment, vsDraw.markers[markBit].back, vsDraw.markers[markBit].alpha); } marksMasked >>= 1; } @@ -2969,7 +3217,7 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis } void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, - int xStart, int offset, int posCaret, PRectangle rcCaret, ColourAllocated caretColour) { + int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour) { int lineStart = ll->LineStart(subLine); int posBefore = posCaret; @@ -2981,7 +3229,7 @@ void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, // glyph / combining character. If so we'll need to draw that too. int offsetFirstChar = offset; int offsetLastChar = offset + (posAfter - posCaret); - while ((offsetLastChar - numCharsToDraw) >= lineStart) { + while ((posBefore > 0) && ((offsetLastChar - numCharsToDraw) >= lineStart)) { if ((ll->positions[offsetLastChar] - ll->positions[offsetLastChar - numCharsToDraw]) > 0) { // The char does not share horizontal space break; @@ -2995,6 +3243,8 @@ void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, // See if the next character shares horizontal space, if so we'll // need to draw that too. + if (offsetFirstChar < 0) + offsetFirstChar = 0; numCharsToDraw = offsetLastChar - offsetFirstChar; while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) { // Update posAfter to point to the 2nd next char, this is where @@ -3017,7 +3267,7 @@ void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, // Adjust caret position to take into account any word wrapping symbols. if ((ll->wrapIndent != 0) && (lineStart != 0)) { - int wordWrapCharWidth = ll->wrapIndent; + XYPOSITION wordWrapCharWidth = ll->wrapIndent; rcCaret.left += wordWrapCharWidth; rcCaret.right += wordWrapCharWidth; } @@ -3027,7 +3277,7 @@ void Editor::DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int styleMain = ll->styles[offsetFirstChar]; surface->DrawTextClipped(rcCaret, vsDraw.styles[styleMain].font, rcCaret.top + vsDraw.maxAscent, ll->chars + offsetFirstChar, - numCharsToDraw, vsDraw.styles[styleMain].back.allocated, + numCharsToDraw, vsDraw.styles[styleMain].back, caretColour); } @@ -3042,30 +3292,30 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) { PRectangle rcPattern(0, 0, patternSize, patternSize); // Initialize default colours based on the chrome colour scheme. Typically the highlight is white. - ColourAllocated colourFMFill = vs.selbar.allocated; - ColourAllocated colourFMStripes = vs.selbarlight.allocated; + ColourDesired colourFMFill = vs.selbar; + ColourDesired colourFMStripes = vs.selbarlight; - if (!(vs.selbarlight.desired == ColourDesired(0xff, 0xff, 0xff))) { + if (!(vs.selbarlight == ColourDesired(0xff, 0xff, 0xff))) { // User has chosen an unusual chrome colour scheme so just use the highlight edge colour. // (Typically, the highlight colour is white.) - colourFMFill = vs.selbarlight.allocated; + colourFMFill = vs.selbarlight; } if (vs.foldmarginColourSet) { // override default fold margin colour - colourFMFill = vs.foldmarginColour.allocated; + colourFMFill = vs.foldmarginColour; } if (vs.foldmarginHighlightColourSet) { // override default fold margin highlight colour - colourFMStripes = vs.foldmarginHighlightColour.allocated; + colourFMStripes = vs.foldmarginHighlightColour; } pixmapSelPattern->FillRectangle(rcPattern, colourFMFill); - pixmapSelPattern->PenColour(colourFMStripes); - for (int stripe = 0; stripe < patternSize; stripe++) { - // Alternating 1 pixel stripes is same as checkerboard. - pixmapSelPattern->MoveTo(0, stripe * 2); - pixmapSelPattern->LineTo(patternSize, stripe * 2 - patternSize); + for (int y = 0; y < patternSize; y++) { + for (int x = y % 2; x < patternSize; x+=2) { + PRectangle rcPixel(x, y, x+1, y+1); + pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes); + } } } @@ -3074,15 +3324,14 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) { pixmapIndentGuide->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID()); pixmapIndentGuideHighlight->InitPixMap(1, vs.lineHeight + 1, surfaceWindow, wMain.GetID()); PRectangle rcIG(0, 0, 1, vs.lineHeight); - pixmapIndentGuide->FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back.allocated); - pixmapIndentGuide->PenColour(vs.styles[STYLE_INDENTGUIDE].fore.allocated); - pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back.allocated); - pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore.allocated); + pixmapIndentGuide->FillRectangle(rcIG, vs.styles[STYLE_INDENTGUIDE].back); + pixmapIndentGuide->PenColour(vs.styles[STYLE_INDENTGUIDE].fore); + pixmapIndentGuideHighlight->FillRectangle(rcIG, vs.styles[STYLE_BRACELIGHT].back); + pixmapIndentGuideHighlight->PenColour(vs.styles[STYLE_BRACELIGHT].fore); for (int stripe = 1; stripe < vs.lineHeight + 1; stripe += 2) { - pixmapIndentGuide->MoveTo(0, stripe); - pixmapIndentGuide->LineTo(2, stripe); - pixmapIndentGuideHighlight->MoveTo(0, stripe); - pixmapIndentGuideHighlight->LineTo(2, stripe); + PRectangle rcPixel(0, stripe, 1, stripe+1); + pixmapIndentGuide->FillRectangle(rcPixel, vs.styles[STYLE_INDENTGUIDE].fore); + pixmapIndentGuideHighlight->FillRectangle(rcPixel, vs.styles[STYLE_BRACELIGHT].fore); } } @@ -3109,10 +3358,10 @@ void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xS const bool mainCaret = r == sel.Main(); const SelectionPosition posCaret = (drawDrag ? posDrag : sel.Range(r).caret); const int offset = posCaret.Position() - posLineStart; - const int spaceWidth = static_cast<int>(vsDraw.styles[ll->EndLineStyle()].spaceWidth); - const int virtualOffset = posCaret.VirtualSpace() * spaceWidth; + const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth; + const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth; if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) { - int xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)]; + XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)]; if (ll->wrapIndent != 0) { int lineStart = ll->LineStart(subLine); if (lineStart != 0) // Wrapped @@ -3125,7 +3374,7 @@ void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xS bool caretAtEOF = false; bool caretAtEOL = false; bool drawBlockCaret = false; - int widthOverstrikeCaret; + XYPOSITION widthOverstrikeCaret; int caretWidthOffset = 0; PRectangle rcCaret = rcLine; @@ -3167,7 +3416,7 @@ void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xS rcCaret.left = xposCaret - caretWidthOffset; rcCaret.right = rcCaret.left + vsDraw.caretWidth; } - ColourAllocated caretColour = mainCaret ? vsDraw.caretcolour.allocated : vsDraw.additionalCaretColour.allocated; + ColourDesired caretColour = mainCaret ? vsDraw.caretcolour : vsDraw.additionalCaretColour; if (drawBlockCaret) { DrawBlockCaret(surface, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour); } else { @@ -3183,26 +3432,18 @@ void Editor::DrawCarets(Surface *surface, ViewStyle &vsDraw, int lineDoc, int xS void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { //Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n", // paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom); + AllocateGraphics(); - pixmapLine->Release(); RefreshStyleData(); RefreshPixMaps(surfaceWindow); + StyleToPositionInView(PositionAfterArea(rcArea)); + PRectangle rcClient = GetClientRectangle(); //Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n", // rcClient.left, rcClient.top, rcClient.right, rcClient.bottom); - surfaceWindow->SetPalette(&palette, true); - pixmapLine->SetPalette(&palette, !hasFocus); - int screenLinePaintFirst = rcArea.top / vs.lineHeight; - // The area to be painted plus one extra line is styled. - // The extra line is to determine when a style change, such as starting a comment flows on to other lines. - int lineStyleLast = topLine + (rcArea.bottom - 1) / vs.lineHeight + 1; - //Platform::DebugPrintf("Paint lines = %d .. %d\n", topLine + screenLinePaintFirst, lineStyleLast); - int endPosPaint = pdoc->Length(); - if (lineStyleLast < cs.LinesDisplayed()) - endPosPaint = pdoc->LineStart(cs.DocFromDisplay(lineStyleLast) + 1); int xStart = vs.fixedColumnWidth - xOffset; int ypos = 0; @@ -3210,21 +3451,13 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { ypos += screenLinePaintFirst * vs.lineHeight; int yposScreen = screenLinePaintFirst * vs.lineHeight; - // Ensure we are styled as far as we are painting. - pdoc->EnsureStyledTo(endPosPaint); bool paintAbandonedByStyling = paintState == paintAbandoned; if (needUpdateUI) { - // Deselect palette by selecting a temporary palette - Palette palTemp; - surfaceWindow->SetPalette(&palTemp, true); - NotifyUpdateUI(); - needUpdateUI = false; + needUpdateUI = 0; RefreshStyleData(); RefreshPixMaps(surfaceWindow); - surfaceWindow->SetPalette(&palette, true); - pixmapLine->SetPalette(&palette, !hasFocus); } // Call priority lines wrap on a window of lines which are likely @@ -3243,12 +3476,17 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { } PLATFORM_ASSERT(pixmapSelPattern->Initialised()); - PaintSelMargin(surfaceWindow, rcArea); + if (!bufferedDraw) + surfaceWindow->SetClip(rcArea); + + if (paintState != paintAbandoned) { + PaintSelMargin(surfaceWindow, rcArea); - PRectangle rcRightMargin = rcClient; - rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth; - if (rcArea.Intersects(rcRightMargin)) { - surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back.allocated); + PRectangle rcRightMargin = rcClient; + rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth; + if (rcArea.Intersects(rcRightMargin)) { + surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back); + } } if (paintState == paintAbandoned) { @@ -3266,8 +3504,12 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { } //Platform::DebugPrintf("start display %d, offset = %d\n", pdoc->Length(), xOffset); + // Allow text at start of line to overlap 1 pixel into the margin as this displays + // serifs and italic stems for aliased text. + const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0; + // Do the painting - if (rcArea.right > vs.fixedColumnWidth) { + if (rcArea.right > vs.fixedColumnWidth - leftTextOverlap) { Surface *surface = surfaceWindow; if (bufferedDraw) { @@ -3284,12 +3526,17 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { posCaret = posDrag; int lineCaret = pdoc->LineFromPosition(posCaret.Position()); - // Remove selection margin from drawing area so text will not be drawn - // on it in unbuffered mode. PRectangle rcTextArea = rcClient; rcTextArea.left = vs.fixedColumnWidth; rcTextArea.right -= vs.rightMarginWidth; - surfaceWindow->SetClip(rcTextArea); + + // Remove selection margin from drawing area so text will not be drawn + // on it in unbuffered mode. + if (!bufferedDraw) { + PRectangle rcClipText = rcTextArea; + rcClipText.left -= leftTextOverlap; + surfaceWindow->SetClip(rcClipText); + } // Loop on visible lines //double durLayout = 0.0; @@ -3325,50 +3572,63 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { GetHotSpotRange(ll->hsStart, ll->hsEnd); - PRectangle rcLine = rcClient; + PRectangle rcLine = rcTextArea; rcLine.top = ypos; rcLine.bottom = ypos + vs.lineHeight; + bool bracesIgnoreStyle = false; + if ((vs.braceHighlightIndicatorSet && (bracesMatchStyle == STYLE_BRACELIGHT)) || + (vs.braceBadLightIndicatorSet && (bracesMatchStyle == STYLE_BRACEBAD))) { + bracesIgnoreStyle = true; + } Range rangeLine(pdoc->LineStart(lineDoc), pdoc->LineStart(lineDoc + 1)); // Highlight the current braces if any ll->SetBracesHighlight(rangeLine, braces, static_cast<char>(bracesMatchStyle), - highlightGuideColumn * vs.spaceWidth); + highlightGuideColumn * vs.spaceWidth, bracesIgnoreStyle); + + if (leftTextOverlap && bufferedDraw) { + PRectangle rcSpacer = rcLine; + rcSpacer.right = rcSpacer.left; + rcSpacer.left -= 1; + surface->FillRectangle(rcSpacer, vs.styles[STYLE_DEFAULT].back); + } // Draw the line DrawLine(surface, vs, lineDoc, visibleLine, xStart, rcLine, ll, subLine); //durPaint += et.Duration(true); // Restore the previous styles for the brace highlights in case layout is in cache. - ll->RestoreBracesHighlight(rangeLine, braces); + ll->RestoreBracesHighlight(rangeLine, braces, bracesIgnoreStyle); bool expanded = cs.GetExpanded(lineDoc); - // Paint the line above the fold - if ((expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED)) - || - (!expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) { - if (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELHEADERFLAG) { + const int level = pdoc->GetLevel(lineDoc); + const int levelNext = pdoc->GetLevel(lineDoc + 1); + if ((level & SC_FOLDLEVELHEADERFLAG) && + ((level & SC_FOLDLEVELNUMBERMASK) < (levelNext & SC_FOLDLEVELNUMBERMASK))) { + // Paint the line above the fold + if ((expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_EXPANDED)) + || + (!expanded && (foldFlags & SC_FOLDFLAG_LINEBEFORE_CONTRACTED))) { PRectangle rcFoldLine = rcLine; rcFoldLine.bottom = rcFoldLine.top + 1; - surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated); + surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore); } - } - // Paint the line below the fold - if ((expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED)) - || - (!expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) { - if (pdoc->GetLevel(lineDoc) & SC_FOLDLEVELHEADERFLAG) { + // Paint the line below the fold + if ((expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_EXPANDED)) + || + (!expanded && (foldFlags & SC_FOLDFLAG_LINEAFTER_CONTRACTED))) { PRectangle rcFoldLine = rcLine; rcFoldLine.top = rcFoldLine.bottom - 1; - surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore.allocated); + surface->FillRectangle(rcFoldLine, vs.styles[STYLE_DEFAULT].fore); } } DrawCarets(surface, vs, lineDoc, xStart, rcLine, ll, subLine); if (bufferedDraw) { - Point from(vs.fixedColumnWidth, 0); - PRectangle rcCopyArea(vs.fixedColumnWidth, yposScreen, - rcClient.right, yposScreen + vs.lineHeight); + Point from(vs.fixedColumnWidth-leftTextOverlap, 0); + PRectangle rcCopyArea(vs.fixedColumnWidth-leftTextOverlap, yposScreen, + rcClient.right - vs.rightMarginWidth, yposScreen + vs.lineHeight); surfaceWindow->Copy(rcCopyArea, from, *pixmapLine); } @@ -3393,15 +3653,15 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { // Right column limit indicator PRectangle rcBeyondEOF = rcClient; rcBeyondEOF.left = vs.fixedColumnWidth; - rcBeyondEOF.right = rcBeyondEOF.right; + rcBeyondEOF.right = rcBeyondEOF.right - vs.rightMarginWidth; rcBeyondEOF.top = (cs.LinesDisplayed() - topLine) * vs.lineHeight; if (rcBeyondEOF.top < rcBeyondEOF.bottom) { - surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back.allocated); + surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back); if (vs.edgeState == EDGE_LINE) { int edgeX = theEdge * vs.spaceWidth; rcBeyondEOF.left = edgeX + xStart; rcBeyondEOF.right = rcBeyondEOF.left + 1; - surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour.allocated); + surfaceWindow->FillRectangle(rcBeyondEOF, vs.edgecolour); } } //Platform::DebugPrintf( @@ -3435,10 +3695,10 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { if (!pfr) return 0; - AutoSurface surface(pfr->hdc, this); + AutoSurface surface(pfr->hdc, this, SC_TECHNOLOGY_DEFAULT); if (!surface) return 0; - AutoSurface surfaceMeasure(pfr->hdcTarget, this); + AutoSurface surfaceMeasure(pfr->hdcTarget, this, SC_TECHNOLOGY_DEFAULT); if (!surfaceMeasure) { return 0; } @@ -3447,6 +3707,7 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { posCache.Clear(); ViewStyle vsPrint(vs); + vsPrint.technology = SC_TECHNOLOGY_DEFAULT; // Modify the view style for printing as do not normally want any of the transient features to be printed // Printing supports only the line number margin. @@ -3458,9 +3719,10 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { vsPrint.ms[margin].width = 0; } } - vsPrint.showMarkedLines = false; vsPrint.fixedColumnWidth = 0; vsPrint.zoomLevel = printMagnification; + // Don't show indentation guides + // If this ever gets changed, cached pixmap would need to be recreated if technology != SC_TECHNOLOGY_DEFAULT vsPrint.viewIndentationGuides = ivNone; // Don't show the selection when printing vsPrint.selbackset = false; @@ -3470,25 +3732,32 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { vsPrint.whitespaceBackgroundSet = false; vsPrint.whitespaceForegroundSet = false; vsPrint.showCaretLineBackground = false; + // Don't highlight matching braces using indicators + vsPrint.braceHighlightIndicatorSet = false; + vsPrint.braceBadLightIndicatorSet = false; // Set colours for printing according to users settings - for (size_t sty = 0;sty < vsPrint.stylesSize;sty++) { + for (size_t sty = 0; sty < vsPrint.stylesSize; sty++) { if (printColourMode == SC_PRINT_INVERTLIGHT) { - vsPrint.styles[sty].fore.desired = InvertedLight(vsPrint.styles[sty].fore.desired); - vsPrint.styles[sty].back.desired = InvertedLight(vsPrint.styles[sty].back.desired); + vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore); + vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back); } else if (printColourMode == SC_PRINT_BLACKONWHITE) { - vsPrint.styles[sty].fore.desired = ColourDesired(0, 0, 0); - vsPrint.styles[sty].back.desired = ColourDesired(0xff, 0xff, 0xff); + vsPrint.styles[sty].fore = ColourDesired(0, 0, 0); + vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); } else if (printColourMode == SC_PRINT_COLOURONWHITE) { - vsPrint.styles[sty].back.desired = ColourDesired(0xff, 0xff, 0xff); + vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); } else if (printColourMode == SC_PRINT_COLOURONWHITEDEFAULTBG) { if (sty <= STYLE_DEFAULT) { - vsPrint.styles[sty].back.desired = ColourDesired(0xff, 0xff, 0xff); + vsPrint.styles[sty].back = ColourDesired(0xff, 0xff, 0xff); } } } // White background for the line numbers - vsPrint.styles[STYLE_LINENUMBER].back.desired = ColourDesired(0xff, 0xff, 0xff); + vsPrint.styles[STYLE_LINENUMBER].back = ColourDesired(0xff, 0xff, 0xff); + + // Printing uses different margins, so reset screen margins + vsPrint.leftMarginWidth = 0; + vsPrint.rightMarginWidth = 0; vsPrint.Refresh(*surfaceMeasure); // Determining width must hapen after fonts have been realised in Refresh @@ -3499,9 +3768,6 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { vsPrint.ms[lineNumberIndex].width = lineNumberWidth; vsPrint.Refresh(*surfaceMeasure); // Recalculate fixedColumnWidth } - // Ensure colours are set up - vsPrint.RefreshColourPalette(palette, true); - vsPrint.RefreshColourPalette(palette, false); int linePrintStart = pdoc->LineFromPosition(pfr->chrg.cpMin); int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1; @@ -3527,7 +3793,7 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { int nPrintPos = pfr->chrg.cpMin; int visibleLine = 0; - int widthPrint = pfr->rc.Width() - vsPrint.fixedColumnWidth; + int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth; if (printWrapState == eWrapNone) widthPrint = LineLayout::wrapWidthInfinite; @@ -3581,8 +3847,8 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { surface->FlushCachedState(); surface->DrawTextNoClip(rcNumber, vsPrint.styles[STYLE_LINENUMBER].font, ypos + vsPrint.maxAscent, number, istrlen(number), - vsPrint.styles[STYLE_LINENUMBER].fore.allocated, - vsPrint.styles[STYLE_LINENUMBER].back.allocated); + vsPrint.styles[STYLE_LINENUMBER].fore, + vsPrint.styles[STYLE_LINENUMBER].back); } // Draw the line @@ -3653,7 +3919,7 @@ void Editor::SetScrollBars() { } void Editor::ChangeSize() { - DropGraphics(); + DropGraphics(false); SetScrollBars(); if (wrapState != eWrapNone) { PRectangle rcTextArea = GetClientRectangle(); @@ -3690,42 +3956,59 @@ void Editor::FilterSelections() { } } +static bool cmpSelPtrs(const SelectionRange *a, const SelectionRange *b) { + return *a < *b; +} + // AddCharUTF inserts an array of bytes which may or may not be in UTF-8. void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { FilterSelections(); { UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty() || inOverstrike); - for (size_t r=0; r<sel.Count(); r++) { - if (!RangeContainsProtected(sel.Range(r).Start().Position(), - sel.Range(r).End().Position())) { - int positionInsert = sel.Range(r).Start().Position(); - if (!sel.Range(r).Empty()) { - if (sel.Range(r).Length()) { - pdoc->DeleteChars(positionInsert, sel.Range(r).Length()); - sel.Range(r).ClearVirtualSpace(); + + std::vector<SelectionRange *> selPtrs; + for (size_t r = 0; r < sel.Count(); r++) { + selPtrs.push_back(&sel.Range(r)); + } + std::sort(selPtrs.begin(), selPtrs.end(), cmpSelPtrs); + + for (std::vector<SelectionRange *>::reverse_iterator rit = selPtrs.rbegin(); + rit != selPtrs.rend(); ++rit) { + SelectionRange *currentSel = *rit; + if (!RangeContainsProtected(currentSel->Start().Position(), + currentSel->End().Position())) { + int positionInsert = currentSel->Start().Position(); + if (!currentSel->Empty()) { + if (currentSel->Length()) { + pdoc->DeleteChars(positionInsert, currentSel->Length()); + currentSel->ClearVirtualSpace(); } else { // Range is all virtual so collapse to start of virtual space - sel.Range(r).MinimizeVirtualSpace(); + currentSel->MinimizeVirtualSpace(); } } else if (inOverstrike) { if (positionInsert < pdoc->Length()) { if (!IsEOLChar(pdoc->CharAt(positionInsert))) { pdoc->DelChar(positionInsert); - sel.Range(r).ClearVirtualSpace(); + currentSel->ClearVirtualSpace(); } } } - positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace()); + positionInsert = InsertSpace(positionInsert, currentSel->caret.VirtualSpace()); if (pdoc->InsertString(positionInsert, s, len)) { - sel.Range(r).caret.SetPosition(positionInsert + len); - sel.Range(r).anchor.SetPosition(positionInsert + len); + currentSel->caret.SetPosition(positionInsert + len); + currentSel->anchor.SetPosition(positionInsert + len); } - sel.Range(r).ClearVirtualSpace(); + currentSel->ClearVirtualSpace(); // If in wrap mode rewrap current line so EnsureCaretVisible has accurate information if (wrapState != eWrapNone) { AutoSurface surface(this); if (surface) { - WrapOneLine(surface, pdoc->LineFromPosition(positionInsert)); + if (WrapOneLine(surface, pdoc->LineFromPosition(positionInsert))) { + SetScrollBars(); + SetVerticalScrollPos(); + Redraw(); + } } } } @@ -3739,7 +4022,8 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { EnsureCaretVisible(); // Avoid blinking during rapid typing: ShowCaretAtCurrentPosition(); - if (!caretSticky) { + if ((caretSticky == SC_CARETSTICKY_OFF) || + ((caretSticky == SC_CARETSTICKY_WHITESPACE) && !IsAllSpacesOrTabs(s, len))) { SetLastXChosen(); } @@ -3785,8 +4069,40 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { } } -void Editor::ClearSelection() { - if (!sel.IsRectangular()) +void Editor::InsertPaste(SelectionPosition selStart, const char *text, int len) { + if (multiPasteMode == SC_MULTIPASTE_ONCE) { + selStart = SelectionPosition(InsertSpace(selStart.Position(), selStart.VirtualSpace())); + if (pdoc->InsertString(selStart.Position(), text, len)) { + SetEmptySelection(selStart.Position() + len); + } + } else { + // SC_MULTIPASTE_EACH + for (size_t r=0; r<sel.Count(); r++) { + if (!RangeContainsProtected(sel.Range(r).Start().Position(), + sel.Range(r).End().Position())) { + int positionInsert = sel.Range(r).Start().Position(); + if (!sel.Range(r).Empty()) { + if (sel.Range(r).Length()) { + pdoc->DeleteChars(positionInsert, sel.Range(r).Length()); + sel.Range(r).ClearVirtualSpace(); + } else { + // Range is all virtual so collapse to start of virtual space + sel.Range(r).MinimizeVirtualSpace(); + } + } + positionInsert = InsertSpace(positionInsert, sel.Range(r).caret.VirtualSpace()); + if (pdoc->InsertString(positionInsert, text, len)) { + sel.Range(r).caret.SetPosition(positionInsert + len); + sel.Range(r).anchor.SetPosition(positionInsert + len); + } + sel.Range(r).ClearVirtualSpace(); + } + } + } +} + +void Editor::ClearSelection(bool retainMultipleSelections) { + if (!sel.IsRectangular() && !retainMultipleSelections) FilterSelections(); UndoGroup ug(pdoc); for (size_t r=0; r<sel.Count(); r++) { @@ -3900,9 +4216,15 @@ bool Editor::CanPaste() { } void Editor::Clear() { - UndoGroup ug(pdoc); // If multiple selections, don't delete EOLS if (sel.Empty()) { + bool singleVirtual = false; + if ((sel.Count() == 1) && + !RangeContainsProtected(sel.MainCaret(), sel.MainCaret() + 1) && + sel.RangeMain().Start().VirtualSpace()) { + singleVirtual = true; + } + UndoGroup ug(pdoc, (sel.Count() > 1) || singleVirtual); for (size_t r=0; r<sel.Count(); r++) { if (!RangeContainsProtected(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1)) { if (sel.Range(r).Start().VirtualSpace()) { @@ -3966,7 +4288,7 @@ void Editor::DelCharBack(bool allowLineStartDeletion) { UndoGroup ug(pdoc, (sel.Count() > 1) || !sel.Empty()); if (sel.Empty()) { for (size_t r=0; r<sel.Count(); r++) { - if (!RangeContainsProtected(sel.Range(r).caret.Position(), sel.Range(r).caret.Position() + 1)) { + if (!RangeContainsProtected(sel.Range(r).caret.Position() - 1, sel.Range(r).caret.Position())) { if (sel.Range(r).caret.VirtualSpace()) { sel.Range(r).caret.SetVirtualSpace(sel.Range(r).caret.VirtualSpace() - 1); sel.Range(r).anchor.SetVirtualSpace(sel.Range(r).caret.VirtualSpace()); @@ -4005,6 +4327,10 @@ void Editor::DelCharBack(bool allowLineStartDeletion) { void Editor::NotifyFocus(bool) {} +void Editor::SetCtrlID(int identifier) { + ctrlID = identifier; +} + void Editor::NotifyStyleToNeeded(int endStyleNeeded) { SCNotification scn = {0}; scn.nmhdr.code = SCN_STYLENEEDED; @@ -4012,10 +4338,17 @@ void Editor::NotifyStyleToNeeded(int endStyleNeeded) { NotifyParent(scn); } -void Editor::NotifyStyleNeeded(Document*, void *, int endStyleNeeded) { +void Editor::NotifyStyleNeeded(Document *, void *, int endStyleNeeded) { NotifyStyleToNeeded(endStyleNeeded); } +void Editor::NotifyLexerChanged(Document *, void *) { +} + +void Editor::NotifyErrorOccurred(Document *, void *, int status) { + errorStatus = status; +} + void Editor::NotifyChar(int ch) { SCNotification scn = {0}; scn.nmhdr.code = SCN_CHARADDED; @@ -4067,9 +4400,19 @@ void Editor::NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt) NotifyParent(scn); } +void Editor::NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt) { + SCNotification scn = {0}; + scn.nmhdr.code = SCN_HOTSPOTRELEASECLICK; + scn.position = position; + scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) | + (alt ? SCI_ALT : 0); + NotifyParent(scn); +} + void Editor::NotifyUpdateUI() { SCNotification scn = {0}; scn.nmhdr.code = SCN_UPDATEUI; + scn.updated = needUpdateUI; NotifyParent(scn); } @@ -4095,7 +4438,7 @@ bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) { int marginClicked = -1; int x = 0; for (int margin = 0; margin < ViewStyle::margins; margin++) { - if ((pt.x > x) && (pt.x < x + vs.ms[margin].width)) + if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width)) marginClicked = margin; x += vs.ms[margin].width; } @@ -4137,12 +4480,12 @@ void Editor::NotifyZoom() { } // Notifications from document -void Editor::NotifyModifyAttempt(Document*, void *) { +void Editor::NotifyModifyAttempt(Document *, void *) { //Platform::DebugPrintf("** Modify Attempt\n"); NotifyModifyAttempt(); } -void Editor::NotifySavePoint(Document*, void *, bool atSavePoint) { +void Editor::NotifySavePoint(Document *, void *, bool atSavePoint) { //Platform::DebugPrintf("** Save Point %s\n", atSavePoint ? "On" : "Off"); NotifySavePoint(atSavePoint); } @@ -4150,14 +4493,13 @@ void Editor::NotifySavePoint(Document*, void *, bool atSavePoint) { void Editor::CheckModificationForWrap(DocModification mh) { if (mh.modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) { llc.Invalidate(LineLayout::llCheckTextAndStyle); + int lineDoc = pdoc->LineFromPosition(mh.position); + int lines = Platform::Maximum(0, mh.linesAdded); if (wrapState != eWrapNone) { - int lineDoc = pdoc->LineFromPosition(mh.position); - int lines = Platform::Maximum(0, mh.linesAdded); NeedWrapping(lineDoc, lineDoc + lines + 1); } + RefreshStyleData(); // Fix up annotation heights - int lineDoc = pdoc->LineFromPosition(mh.position); - int lines = Platform::Maximum(0, mh.linesAdded); SetAnnotationHeights(lineDoc, lineDoc + lines + 2); } } @@ -4185,17 +4527,25 @@ static inline int MovePositionForDeletion(int position, int startDeletion, int l } } -void Editor::NotifyModified(Document*, DocModification mh, void *) { - needUpdateUI = true; +void Editor::NotifyModified(Document *, DocModification mh, void *) { + ContainerNeedsUpdate(SC_UPDATE_CONTENT); if (paintState == painting) { CheckForChangeOutsidePaint(Range(mh.position, mh.position + mh.length)); } if (mh.modificationType & SC_MOD_CHANGELINESTATE) { if (paintState == painting) { CheckForChangeOutsidePaint( - Range(pdoc->LineStart(mh.line), pdoc->LineStart(mh.line + 1))); + Range(pdoc->LineStart(mh.line), pdoc->LineStart(mh.line + 1))); + } else { + // Could check that change is before last visible line. + Redraw(); + } + } + if (mh.modificationType & SC_MOD_LEXERSTATE) { + if (paintState == painting) { + CheckForChangeOutsidePaint( + Range(mh.position, mh.position + mh.length)); } else { - // Could check that change is before last visible line. Redraw(); } } @@ -4225,11 +4575,20 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) { braces[0] = MovePositionForDeletion(braces[0], mh.position, mh.length); braces[1] = MovePositionForDeletion(braces[1], mh.position, mh.length); } - if (cs.LinesDisplayed() < cs.LinesInDoc()) { + if ((mh.modificationType & (SC_MOD_BEFOREINSERT | SC_MOD_BEFOREDELETE)) && cs.HiddenLines()) { // Some lines are hidden so may need shown. // TODO: check if the modified area is hidden. if (mh.modificationType & SC_MOD_BEFOREINSERT) { - NotifyNeedShown(mh.position, 0); + int lineOfPos = pdoc->LineFromPosition(mh.position); + bool insertingNewLine = false; + for (int i=0; i < mh.length; i++) { + if ((mh.text[i] == '\n') || (mh.text[i] == '\r')) + insertingNewLine = true; + } + if (insertingNewLine && (mh.position != pdoc->LineStart(lineOfPos))) + NotifyNeedShown(mh.position, pdoc->LineStart(lineOfPos+1) - mh.position); + else + NotifyNeedShown(mh.position, 0); } else if (mh.modificationType & SC_MOD_BEFOREDELETE) { NotifyNeedShown(mh.position, mh.length); } @@ -4248,6 +4607,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) { int lineDoc = pdoc->LineFromPosition(mh.position); if (vs.annotationVisible) { cs.SetHeight(lineDoc, cs.GetHeight(lineDoc) + mh.annotationLinesAdded); + Redraw(); } } CheckModificationForWrap(mh); @@ -4265,12 +4625,14 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) { // TODO: could invalidate from mh.startModification to end of screen //InvalidateRange(mh.position, mh.position + mh.length); if (paintState == notPainting && !CanDeferToLastStep(mh)) { + QueueStyling(pdoc->Length()); Redraw(); } } else { //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this, // mh.position, mh.position + mh.length); if (paintState == notPainting && mh.length && !CanEliminate(mh)) { + QueueStyling(mh.position + mh.length); InvalidateRange(mh.position, mh.position + mh.length); } } @@ -4281,10 +4643,10 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) { } if ((mh.modificationType & SC_MOD_CHANGEMARKER) || (mh.modificationType & SC_MOD_CHANGEMARGIN)) { - if ((paintState == notPainting) || !PaintContainsMargin()) { + if ((!willRedrawAll) && ((paintState == notPainting) || !PaintContainsMargin())) { if (mh.modificationType & SC_MOD_CHANGEFOLD) { // Fold changes can affect the drawing of following lines so redraw whole margin - RedrawSelMargin(); + RedrawSelMargin(highlightDelimiter.isEnabled ? -1 : mh.line-1, true); } else { RedrawSelMargin(mh.line); } @@ -4428,6 +4790,11 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lPar case SCI_PAGEDOWNRECTEXTEND: case SCI_SELECTIONDUPLICATE: case SCI_COPYALLOWLINE: + case SCI_VERTICALCENTRECARET: + case SCI_MOVESELECTEDLINESUP: + case SCI_MOVESELECTEDLINESDOWN: + case SCI_SCROLLTOSTART: + case SCI_SCROLLTOEND: break; // Filter out all others like display changes. Also, newlines are redundant @@ -4447,6 +4814,11 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lPar NotifyParent(scn); } +// Something has changed that the container should know about +void Editor::ContainerNeedsUpdate(int flags) { + needUpdateUI |= flags; +} + /** * Force scroll and keep position relative to top of window. * @@ -4454,51 +4826,79 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lPar * If stuttered = true and already at first/last row, scroll as normal. */ void Editor::PageMove(int direction, Selection::selTypes selt, bool stuttered) { - int topLineNew, newPos; + int topLineNew; + SelectionPosition newPos; - // I consider only the caretYSlop, and ignore the caretYPolicy-- is that a problem? int currentLine = pdoc->LineFromPosition(sel.MainCaret()); int topStutterLine = topLine + caretYSlop; int bottomStutterLine = pdoc->LineFromPosition(PositionFromLocation( - Point(lastXChosen, direction * vs.lineHeight * LinesToScroll()))) + Point(lastXChosen - xOffset, direction * vs.lineHeight * LinesToScroll()))) - caretYSlop - 1; if (stuttered && (direction < 0 && currentLine > topStutterLine)) { topLineNew = topLine; - newPos = PositionFromLocation(Point(lastXChosen, vs.lineHeight * caretYSlop)); + newPos = SPositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * caretYSlop), + false, false, UserVirtualSpace()); } else if (stuttered && (direction > 0 && currentLine < bottomStutterLine)) { topLineNew = topLine; - newPos = PositionFromLocation(Point(lastXChosen, vs.lineHeight * (LinesToScroll() - caretYSlop))); + newPos = SPositionFromLocation(Point(lastXChosen - xOffset, vs.lineHeight * (LinesToScroll() - caretYSlop)), + false, false, UserVirtualSpace()); } else { Point pt = LocationFromPosition(sel.MainCaret()); topLineNew = Platform::Clamp( topLine + direction * LinesToScroll(), 0, MaxScrollPos()); - newPos = PositionFromLocation( - Point(lastXChosen, pt.y + direction * (vs.lineHeight * LinesToScroll()))); + newPos = SPositionFromLocation( + Point(lastXChosen - xOffset, pt.y + direction * (vs.lineHeight * LinesToScroll())), + false, false, UserVirtualSpace()); } if (topLineNew != topLine) { SetTopLine(topLineNew); - MovePositionTo(SelectionPosition(newPos), selt); + MovePositionTo(newPos, selt); Redraw(); SetVerticalScrollPos(); } else { - MovePositionTo(SelectionPosition(newPos), selt); + MovePositionTo(newPos, selt); } } -void Editor::ChangeCaseOfSelection(bool makeUpperCase) { +void Editor::ChangeCaseOfSelection(int caseMapping) { UndoGroup ug(pdoc); for (size_t r=0; r<sel.Count(); r++) { SelectionRange current = sel.Range(r); - pdoc->ChangeCase(Range(current.Start().Position(), current.End().Position()), - makeUpperCase); - // Automatic movement cuts off last character so reset to exactly the same as it was. - sel.Range(r) = current; + SelectionRange currentNoVS = current; + currentNoVS.ClearVirtualSpace(); + char *text = CopyRange(currentNoVS.Start().Position(), currentNoVS.End().Position()); + size_t rangeBytes = currentNoVS.Length(); + if (rangeBytes > 0) { + std::string sText(text, rangeBytes); + + std::string sMapped = CaseMapString(sText, caseMapping); + + if (sMapped != sText) { + size_t firstDifference = 0; + while (sMapped[firstDifference] == sText[firstDifference]) + firstDifference++; + size_t lastDifference = sMapped.size() - 1; + while (sMapped[lastDifference] == sText[lastDifference]) + lastDifference--; + size_t endSame = sMapped.size() - 1 - lastDifference; + pdoc->DeleteChars( + static_cast<int>(currentNoVS.Start().Position() + firstDifference), + static_cast<int>(rangeBytes - firstDifference - endSame)); + pdoc->InsertString( + static_cast<int>(currentNoVS.Start().Position() + firstDifference), + sMapped.c_str() + firstDifference, + static_cast<int>(lastDifference - firstDifference + 1)); + // Automatic movement changes selection so reset to exactly the same as it was. + sel.Range(r) = current; + } + } + delete []text; } } @@ -4528,8 +4928,7 @@ void Editor::Duplicate(bool forLine) { if (sel.Empty()) { forLine = true; } - UndoGroup ug(pdoc, sel.Count() > 1); - SelectionPosition last; + UndoGroup ug(pdoc); const char *eol = ""; int eolLen = 0; if (forLine) { @@ -4569,14 +4968,28 @@ void Editor::CancelModes() { } void Editor::NewLine() { - ClearSelection(); + // Remove non-main ranges + InvalidateSelection(sel.RangeMain(), true); + sel.SetSelection(sel.RangeMain()); + + // Clear main range and insert line end + bool needGroupUndo = !sel.Empty(); + if (needGroupUndo) + pdoc->BeginUndoAction(); + + if (!sel.Empty()) + ClearSelection(); const char *eol = "\n"; if (pdoc->eolMode == SC_EOL_CRLF) { eol = "\r\n"; } else if (pdoc->eolMode == SC_EOL_CR) { eol = "\r"; } // else SC_EOL_LF -> "\n" already set - if (pdoc->InsertCString(sel.MainCaret(), eol)) { + bool inserted = pdoc->InsertCString(sel.MainCaret(), eol); + // Want to end undo group before NotifyChar as applications often modify text here + if (needGroupUndo) + pdoc->EndUndoAction(); + if (inserted) { SetEmptySelection(sel.MainCaret() + istrlen(eol)); while (*eol) { NotifyChar(*eol); @@ -4605,30 +5018,50 @@ void Editor::CursorUpOrDown(int direction, Selection::selTypes selt) { caretToUse = sel.Rectangular().caret; } } + Point pt = LocationFromPosition(caretToUse); - int lineDoc = pdoc->LineFromPosition(caretToUse.Position()); - Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc)); - int subLine = (pt.y - ptStartLine.y) / vs.lineHeight; - int commentLines = vs.annotationVisible ? pdoc->AnnotationLines(lineDoc) : 0; - SelectionPosition posNew = SPositionFromLocation( - Point(lastXChosen, pt.y + direction * vs.lineHeight), false, false, UserVirtualSpace()); - if ((direction > 0) && (subLine >= (cs.GetHeight(lineDoc) - 1 - commentLines))) { - posNew = SPositionFromLocation( - Point(lastXChosen, pt.y + (commentLines + 1) * vs.lineHeight), false, false, UserVirtualSpace()); + int skipLines = 0; + + if (vs.annotationVisible) { + int lineDoc = pdoc->LineFromPosition(caretToUse.Position()); + Point ptStartLine = LocationFromPosition(pdoc->LineStart(lineDoc)); + int subLine = (pt.y - ptStartLine.y) / vs.lineHeight; + + if (direction < 0 && subLine == 0) { + int lineDisplay = cs.DisplayFromDoc(lineDoc); + if (lineDisplay > 0) { + skipLines = pdoc->AnnotationLines(cs.DocFromDisplay(lineDisplay - 1)); + } + } else if (direction > 0 && subLine >= (cs.GetHeight(lineDoc) - 1 - pdoc->AnnotationLines(lineDoc))) { + skipLines = pdoc->AnnotationLines(lineDoc); + } } + + int newY = pt.y + (1 + skipLines) * direction * vs.lineHeight; + SelectionPosition posNew = SPositionFromLocation( + Point(lastXChosen - xOffset, newY), false, false, UserVirtualSpace()); + if (direction < 0) { // Line wrapping may lead to a location on the same line, so // seek back if that is the case. - // There is an equivalent case when moving down which skips - // over a line but as that does not trap the user it is fine. Point ptNew = LocationFromPosition(posNew.Position()); while ((posNew.Position() > 0) && (pt.y == ptNew.y)) { - posNew.Add(- 1); + posNew.Add(-1); + posNew.SetVirtualSpace(0); + ptNew = LocationFromPosition(posNew.Position()); + } + } else if (direction > 0 && posNew.Position() != pdoc->Length()) { + // There is an equivalent case when moving down which skips + // over a line. + Point ptNew = LocationFromPosition(posNew.Position()); + while ((posNew.Position() > caretToUse.Position()) && (ptNew.y > newY)) { + posNew.Add(-1); posNew.SetVirtualSpace(0); ptNew = LocationFromPosition(posNew.Position()); } } - MovePositionTo(posNew, selt); + + MovePositionTo(MovePositionSoVisible(posNew, direction), selt); } void Editor::ParaUpOrDown(int direction, Selection::selTypes selt) { @@ -4933,6 +5366,7 @@ int Editor::KeyCommand(unsigned int iMessage) { inOverstrike = !inOverstrike; DropCaret(); ShowCaretAtCurrentPosition(); + ContainerNeedsUpdate(SC_UPDATE_CONTENT); NotifyUpdateUI(); break; case SCI_CANCEL: // Cancel any modes - handled in subclass @@ -4941,21 +5375,21 @@ int Editor::KeyCommand(unsigned int iMessage) { break; case SCI_DELETEBACK: DelCharBack(true); - if (!caretSticky) { + if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) { SetLastXChosen(); } EnsureCaretVisible(); break; case SCI_DELETEBACKNOTLINE: DelCharBack(false); - if (!caretSticky) { + if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) { SetLastXChosen(); } EnsureCaretVisible(); break; case SCI_TAB: Indent(true); - if (!caretSticky) { + if (caretSticky == SC_CARETSTICKY_OFF) { SetLastXChosen(); } EnsureCaretVisible(); @@ -4963,7 +5397,7 @@ int Editor::KeyCommand(unsigned int iMessage) { break; case SCI_BACKTAB: Indent(false); - if (!caretSticky) { + if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) { SetLastXChosen(); } EnsureCaretVisible(); @@ -5032,6 +5466,7 @@ int Editor::KeyCommand(unsigned int iMessage) { UndoGroup ug(pdoc); sel.RangeMain().caret = SelectionPosition( InsertSpace(sel.RangeMain().caret.Position(), sel.RangeMain().caret.VirtualSpace())); + sel.RangeMain().anchor = sel.RangeMain().caret; int endWord = pdoc->NextWordStart(sel.MainCaret(), 1); pdoc->DeleteChars(sel.MainCaret(), endWord - sel.MainCaret()); } @@ -5092,10 +5527,10 @@ int Editor::KeyCommand(unsigned int iMessage) { Duplicate(false); break; case SCI_LOWERCASE: - ChangeCaseOfSelection(false); + ChangeCaseOfSelection(cmLower); break; case SCI_UPPERCASE: - ChangeCaseOfSelection(true); + ChangeCaseOfSelection(cmUpper); break; case SCI_WORDPARTLEFT: MovePositionTo(MovePositionSoVisible(pdoc->WordPartLeft(sel.MainCaret()), -1)); @@ -5133,6 +5568,12 @@ int Editor::KeyCommand(unsigned int iMessage) { StartEndDisplayLine(sel.MainCaret(), false), 1), Selection::selStream); SetLastXChosen(); break; + case SCI_SCROLLTOSTART: + ScrollTo(0); + break; + case SCI_SCROLLTOEND: + ScrollTo(MaxScrollPos()); + break; } return 0; } @@ -5141,10 +5582,8 @@ int Editor::KeyDefault(int, int) { return 0; } -int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed) { +int Editor::KeyDownWithModifiers(int key, int modifiers, bool *consumed) { DwellEnd(false); - int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) | - (alt ? SCI_ALT : 0); int msg = kmap.Find(key, modifiers); if (msg) { if (consumed) @@ -5157,12 +5596,10 @@ int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed) { } } -void Editor::SetWhitespaceVisible(int view) { - vs.viewWhitespace = static_cast<WhiteSpaceVisibility>(view); -} - -int Editor::GetWhitespaceVisible() { - return vs.viewWhitespace; +int Editor::KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed) { + int modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) | + (alt ? SCI_ALT : 0); + return KeyDownWithModifiers(key, modifiers, consumed); } void Editor::Indent(bool forwards) { @@ -5203,7 +5640,7 @@ void Editor::Indent(bool forwards) { int indentation = pdoc->GetLineIndentation(lineCurrentPos); int indentationStep = pdoc->IndentSize(); pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep); - SetEmptySelection(pdoc->GetLineIndentPosition(lineCurrentPos)); + sel.Range(r) = SelectionRange(pdoc->GetLineIndentPosition(lineCurrentPos)); } else { int newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) * pdoc->tabInChars; @@ -5242,6 +5679,21 @@ void Editor::Indent(bool forwards) { } } +class CaseFolderASCII : public CaseFolderTable { +public: + CaseFolderASCII() { + StandardASCII(); + } + ~CaseFolderASCII() { + } +}; + + +CaseFolder *Editor::CaseFolderForEncoding() { + // Simple default that only maps ASCII upper case to lower case. + return new CaseFolderASCII(); +} + /** * Search of a text in the document, in the given range. * @return The position of the found text, -1 if not found. @@ -5253,13 +5705,15 @@ long Editor::FindText( Sci_TextToFind *ft = reinterpret_cast<Sci_TextToFind *>(lParam); int lengthFound = istrlen(ft->lpstrText); + std::auto_ptr<CaseFolder> pcf(CaseFolderForEncoding()); int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText, (wParam & SCFIND_MATCHCASE) != 0, (wParam & SCFIND_WHOLEWORD) != 0, (wParam & SCFIND_WORDSTART) != 0, (wParam & SCFIND_REGEXP) != 0, wParam, - &lengthFound); + &lengthFound, + pcf.get()); if (pos != -1) { ft->chrgText.cpMin = pos; ft->chrgText.cpMax = pos + lengthFound; @@ -5282,6 +5736,19 @@ void Editor::SearchAnchor() { searchAnchor = SelectionStart().Position(); } +// Simple RAII wrapper for CaseFolder as std::auto_ptr is now deprecated +class ScopedCaseFolder { + CaseFolder *pcf; +public: + ScopedCaseFolder(CaseFolder *pcf_) : pcf(pcf_) { + } + ~ScopedCaseFolder() { + delete pcf; + pcf = 0; + } + CaseFolder *get() const { return pcf; } +}; + /** * Find text from current search anchor: Must call @c SearchAnchor first. * Used for next text and previous text requests. @@ -5296,6 +5763,7 @@ long Editor::SearchText( const char *txt = reinterpret_cast<char *>(lParam); int pos; int lengthFound = istrlen(txt); + ScopedCaseFolder pcf(CaseFolderForEncoding()); if (iMessage == SCI_SEARCHNEXT) { pos = pdoc->FindText(searchAnchor, pdoc->Length(), txt, (wParam & SCFIND_MATCHCASE) != 0, @@ -5303,7 +5771,8 @@ long Editor::SearchText( (wParam & SCFIND_WORDSTART) != 0, (wParam & SCFIND_REGEXP) != 0, wParam, - &lengthFound); + &lengthFound, + pcf.get()); } else { pos = pdoc->FindText(searchAnchor, 0, txt, (wParam & SCFIND_MATCHCASE) != 0, @@ -5311,9 +5780,9 @@ long Editor::SearchText( (wParam & SCFIND_WORDSTART) != 0, (wParam & SCFIND_REGEXP) != 0, wParam, - &lengthFound); + &lengthFound, + pcf.get()); } - if (pos != -1) { SetSelection(pos, pos + lengthFound); } @@ -5321,19 +5790,39 @@ long Editor::SearchText( return pos; } +std::string Editor::CaseMapString(const std::string &s, int caseMapping) { + std::string ret(s); + for (size_t i=0; i<ret.size(); i++) { + switch (caseMapping) { + case cmUpper: + if (ret[i] >= 'a' && ret[i] <= 'z') + ret[i] = static_cast<char>(ret[i] - 'a' + 'A'); + break; + case cmLower: + if (ret[i] >= 'A' && ret[i] <= 'Z') + ret[i] = static_cast<char>(ret[i] - 'A' + 'a'); + break; + } + } + return ret; +} + /** * Search for text in the target range of the document. * @return The position of the found text, -1 if not found. */ long Editor::SearchInTarget(const char *text, int length) { int lengthFound = length; + + ScopedCaseFolder pcf(CaseFolderForEncoding()); int pos = pdoc->FindText(targetStart, targetEnd, text, (searchFlags & SCFIND_MATCHCASE) != 0, (searchFlags & SCFIND_WHOLEWORD) != 0, (searchFlags & SCFIND_WORDSTART) != 0, (searchFlags & SCFIND_REGEXP) != 0, searchFlags, - &lengthFound); + &lengthFound, + pcf.get()); if (pos != -1) { targetStart = pos; targetEnd = pos + lengthFound; @@ -5372,6 +5861,18 @@ char *Editor::CopyRange(int start, int end) { return text; } +std::string Editor::RangeText(int start, int end) const { + if (start < end) { + int len = end - start; + std::string ret(len, '\0'); + for (int i = 0; i < len; i++) { + ret[i] = pdoc->CharAt(start + i); + } + return ret; + } + return std::string(); +} + void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) { if (sel.Empty()) { if (allowLineCopy) { @@ -5380,7 +5881,7 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) { int end = pdoc->LineEnd(currentLine); char *text = CopyRange(start, end); - int textLen = text ? strlen(text) : 0; + size_t textLen = text ? strlen(text) : 0; // include room for \r\n\0 textLen += 3; char *textWithEndl = new char[textLen]; @@ -5391,7 +5892,7 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) { strncat(textWithEndl, "\r", textLen); if (pdoc->eolMode != SC_EOL_CR) strncat(textWithEndl, "\n", textLen); - ss->Set(textWithEndl, strlen(textWithEndl) + 1, + ss->Set(textWithEndl, static_cast<int>(strlen(textWithEndl) + 1), pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, false, true); delete []text; } @@ -5404,12 +5905,12 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) { delimiterLength = 1; } } - int size = sel.Length() + delimiterLength * sel.Count(); + size_t size = sel.Length() + delimiterLength * sel.Count(); char *text = new char[size + 1]; int j = 0; - wxVector<SelectionRange> rangesInOrder = sel.RangesCopy(); + std::vector<SelectionRange> rangesInOrder = sel.RangesCopy(); if (sel.selType == Selection::selRectangle) - wxVectorSort(rangesInOrder); + std::sort(rangesInOrder.begin(), rangesInOrder.end()); for (size_t r=0; r<rangesInOrder.size(); r++) { SelectionRange current = rangesInOrder[r]; for (int i = current.Start().Position(); @@ -5427,7 +5928,7 @@ void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) { } } text[size] = '\0'; - ss->Set(text, size + 1, pdoc->dbcsCodePage, + ss->Set(text, static_cast<int>(size + 1), pdoc->dbcsCodePage, vs.styles[STYLE_DEFAULT].characterSet, sel.IsRectangular(), sel.selType == Selection::selLines); } } @@ -5553,21 +6054,21 @@ bool Editor::PositionInSelection(int pos) { } bool Editor::PointInSelection(Point pt) { - SelectionPosition pos = SPositionFromLocation(pt); - int xPos = XFromPosition(pos); + SelectionPosition pos = SPositionFromLocation(pt, false, true); + Point ptPos = LocationFromPosition(pos); for (size_t r=0; r<sel.Count(); r++) { SelectionRange range = sel.Range(r); if (range.Contains(pos)) { bool hit = true; if (pos == range.Start()) { // see if just before selection - if (pt.x < xPos) { + if (pt.x < ptPos.x) { hit = false; } } if (pos == range.End()) { // see if just after selection - if (pt.x > xPos) { + if (pt.x > ptPos.x) { hit = false; } } @@ -5589,16 +6090,75 @@ bool Editor::PointInSelMargin(Point pt) { } } -void Editor::LineSelection(int lineCurrent_, int lineAnchor_) { - if (lineAnchor_ < lineCurrent_) { - SetSelection(pdoc->LineStart(lineCurrent_ + 1), - pdoc->LineStart(lineAnchor_)); - } else if (lineAnchor_ > lineCurrent_) { - SetSelection(pdoc->LineStart(lineCurrent_), - pdoc->LineStart(lineAnchor_ + 1)); - } else { // Same line, select it - SetSelection(pdoc->LineStart(lineAnchor_ + 1), - pdoc->LineStart(lineAnchor_)); +Window::Cursor Editor::GetMarginCursor(Point pt) { + int x = 0; + for (int margin = 0; margin < ViewStyle::margins; margin++) { + if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width)) + return static_cast<Window::Cursor>(vs.ms[margin].cursor); + x += vs.ms[margin].width; + } + return Window::cursorReverseArrow; +} + +void Editor::TrimAndSetSelection(int currentPos_, int anchor_) { + sel.TrimSelection(SelectionRange(currentPos_, anchor_)); + SetSelection(currentPos_, anchor_); +} + +void Editor::LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine) { + int selCurrentPos, selAnchorPos; + if (wholeLine) { + int lineCurrent_ = pdoc->LineFromPosition(lineCurrentPos_); + int lineAnchor_ = pdoc->LineFromPosition(lineAnchorPos_); + if (lineAnchorPos_ < lineCurrentPos_) { + selCurrentPos = pdoc->LineStart(lineCurrent_ + 1); + selAnchorPos = pdoc->LineStart(lineAnchor_); + } else if (lineAnchorPos_ > lineCurrentPos_) { + selCurrentPos = pdoc->LineStart(lineCurrent_); + selAnchorPos = pdoc->LineStart(lineAnchor_ + 1); + } else { // Same line, select it + selCurrentPos = pdoc->LineStart(lineAnchor_ + 1); + selAnchorPos = pdoc->LineStart(lineAnchor_); + } + } else { + if (lineAnchorPos_ < lineCurrentPos_) { + selCurrentPos = StartEndDisplayLine(lineCurrentPos_, false) + 1; + selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1); + selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true); + } else if (lineAnchorPos_ > lineCurrentPos_) { + selCurrentPos = StartEndDisplayLine(lineCurrentPos_, true); + selAnchorPos = StartEndDisplayLine(lineAnchorPos_, false) + 1; + selAnchorPos = pdoc->MovePositionOutsideChar(selAnchorPos, 1); + } else { // Same line, select it + selCurrentPos = StartEndDisplayLine(lineAnchorPos_, false) + 1; + selCurrentPos = pdoc->MovePositionOutsideChar(selCurrentPos, 1); + selAnchorPos = StartEndDisplayLine(lineAnchorPos_, true); + } + } + TrimAndSetSelection(selCurrentPos, selAnchorPos); +} + +void Editor::WordSelection(int pos) { + if (pos < wordSelectAnchorStartPos) { + // Extend backward to the word containing pos. + // Skip ExtendWordSelect if the line is empty or if pos is after the last character. + // This ensures that a series of empty lines isn't counted as a single "word". + if (!pdoc->IsLineEndPosition(pos)) + pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos + 1, 1), -1); + TrimAndSetSelection(pos, wordSelectAnchorEndPos); + } else if (pos > wordSelectAnchorEndPos) { + // Extend forward to the word containing the character to the left of pos. + // Skip ExtendWordSelect if the line is empty or if pos is the first position on the line. + // This ensures that a series of empty lines isn't counted as a single "word". + if (pos > pdoc->LineStart(pdoc->LineFromPosition(pos))) + pos = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(pos - 1, -1), 1); + TrimAndSetSelection(pos, wordSelectAnchorStartPos); + } else { + // Select only the anchored word + if (pos >= originalAnchorPos) + TrimAndSetSelection(wordSelectAnchorEndPos, wordSelectAnchorStartPos); + else + TrimAndSetSelection(wordSelectAnchorStartPos, wordSelectAnchorEndPos); } } @@ -5613,8 +6173,16 @@ void Editor::DwellEnd(bool mouseMoved) { } } -static bool AllowVirtualSpace(int virtualSpaceOptions, bool rectangular) { - return ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0) +void Editor::MouseLeave() { + SetHotSpotRange(NULL); + if (!HaveMouseCapture()) { + ptMouseLast = Point(-1,-1); + DwellEnd(true); + } +} + +static bool AllowVirtualSpace(int virtualSpaceOptions, bool rectangular) { + return (!rectangular && ((virtualSpaceOptions & SCVS_USERACCESSIBLE) != 0)) || (rectangular && ((virtualSpaceOptions & SCVS_RECTANGULARSELECTION) != 0)); } @@ -5626,45 +6194,86 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b inDragDrop = ddNone; sel.SetMoveExtends(false); - bool processed = NotifyMarginClick(pt, shift, ctrl, alt); - if (processed) + if (NotifyMarginClick(pt, shift, ctrl, alt)) return; NotifyIndicatorClick(true, newPos.Position(), shift, ctrl, alt); bool inSelMargin = PointInSelMargin(pt); - if (shift & !inSelMargin) { - SetSelection(newPos.Position()); + // In margin ctrl+(double)click should always select everything + if (ctrl && inSelMargin) { + SelectAll(); + lastClickTime = curTime; + lastClick = pt; + return; + } + if (shift && !inSelMargin) { + SetSelection(newPos); } if (((curTime - lastClickTime) < Platform::DoubleClickTime()) && Close(pt, lastClick)) { //Platform::DebugPrintf("Double click %d %d = %d\n", curTime, lastClickTime, curTime - lastClickTime); SetMouseCapture(true); - SetEmptySelection(newPos.Position()); + if (!ctrl || !multipleSelection || (selectionType != selChar && selectionType != selWord)) + SetEmptySelection(newPos.Position()); bool doubleClick = false; // Stop mouse button bounce changing selection type if (!Platform::MouseButtonBounce() || curTime != lastClickTime) { - if (selectionType == selChar) { - selectionType = selWord; - doubleClick = true; - } else if (selectionType == selWord) { - selectionType = selLine; + if (inSelMargin) { + // Inside margin selection type should be either selSubLine or selWholeLine. + if (selectionType == selSubLine) { + // If it is selSubLine, we're inside a *double* click and word wrap is enabled, + // so we switch to selWholeLine in order to select whole line. + selectionType = selWholeLine; + } else if (selectionType != selSubLine && selectionType != selWholeLine) { + // If it is neither, reset selection type to line selection. + selectionType = ((wrapState != eWrapNone) && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine; + } } else { - selectionType = selChar; - originalAnchorPos = sel.MainCaret(); + if (selectionType == selChar) { + selectionType = selWord; + doubleClick = true; + } else if (selectionType == selWord) { + // Since we ended up here, we're inside a *triple* click, which should always select + // whole line irregardless of word wrap being enabled or not. + selectionType = selWholeLine; + } else { + selectionType = selChar; + originalAnchorPos = sel.MainCaret(); + } } } if (selectionType == selWord) { - if (sel.MainCaret() >= originalAnchorPos) { // Moved forward - SetSelection(pdoc->ExtendWordSelect(sel.MainCaret(), 1), - pdoc->ExtendWordSelect(originalAnchorPos, -1)); - } else { // Moved backward - SetSelection(pdoc->ExtendWordSelect(sel.MainCaret(), -1), - pdoc->ExtendWordSelect(originalAnchorPos, 1)); - } - } else if (selectionType == selLine) { - lineAnchor = LineFromLocation(pt); - SetSelection(pdoc->LineStart(lineAnchor + 1), pdoc->LineStart(lineAnchor)); + int charPos = originalAnchorPos; + if (sel.MainCaret() == originalAnchorPos) { + charPos = PositionFromLocation(pt, false, true); + charPos = MovePositionOutsideChar(charPos, -1); + } + + int startWord, endWord; + if ((sel.MainCaret() >= originalAnchorPos) && !pdoc->IsLineEndPosition(charPos)) { + startWord = pdoc->ExtendWordSelect(pdoc->MovePositionOutsideChar(charPos + 1, 1), -1); + endWord = pdoc->ExtendWordSelect(charPos, 1); + } else { + // Selecting backwards, or anchor beyond last character on line. In these cases, + // we select the word containing the character to the *left* of the anchor. + if (charPos > pdoc->LineStart(pdoc->LineFromPosition(charPos))) { + startWord = pdoc->ExtendWordSelect(charPos, -1); + endWord = pdoc->ExtendWordSelect(startWord, 1); + } else { + // Anchor at start of line; select nothing to begin with. + startWord = charPos; + endWord = charPos; + } + } + + wordSelectAnchorStartPos = startWord; + wordSelectAnchorEndPos = endWord; + wordSelectInitialCaretPos = sel.MainCaret(); + WordSelection(wordSelectInitialCaretPos); + } else if (selectionType == selSubLine || selectionType == selWholeLine) { + lineAnchorPos = newPos.Position(); + LineSelection(lineAnchorPos, lineAnchorPos, selectionType == selWholeLine); //Platform::DebugPrintf("Triple click: %d - %d\n", anchor, currentPos); } else { SetEmptySelection(sel.MainCaret()); @@ -5678,34 +6287,32 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b } else { // Single click if (inSelMargin) { sel.selType = Selection::selStream; - if (ctrl) { - SelectAll(); - lastClickTime = curTime; - return; - } if (!shift) { - lineAnchor = LineFromLocation(pt); - // Single click in margin: select whole line - LineSelection(lineAnchor, lineAnchor); - SetSelection(pdoc->LineStart(lineAnchor + 1), - pdoc->LineStart(lineAnchor)); + // Single click in margin: select whole line or only subline if word wrap is enabled + lineAnchorPos = newPos.Position(); + selectionType = ((wrapState != eWrapNone) && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine; + LineSelection(lineAnchorPos, lineAnchorPos, selectionType == selWholeLine); } else { // Single shift+click in margin: select from line anchor to clicked line if (sel.MainAnchor() > sel.MainCaret()) - lineAnchor = pdoc->LineFromPosition(sel.MainAnchor() - 1); + lineAnchorPos = sel.MainAnchor() - 1; else - lineAnchor = pdoc->LineFromPosition(sel.MainAnchor()); - int lineStart = LineFromLocation(pt); - LineSelection(lineStart, lineAnchor); - //lineAnchor = lineStart; // Keep the same anchor for ButtonMove + lineAnchorPos = sel.MainAnchor(); + // Reset selection type if there is an empty selection. + // This ensures that we don't end up stuck in previous selection mode, which is no longer valid. + // Otherwise, if there's a non empty selection, reset selection type only if it differs from selSubLine and selWholeLine. + // This ensures that we continue selecting in the same selection mode. + if (sel.Empty() || (selectionType != selSubLine && selectionType != selWholeLine)) + selectionType = ((wrapState != eWrapNone) && (marginOptions & SC_MARGINOPTION_SUBLINESELECT)) ? selSubLine : selWholeLine; + LineSelection(newPos.Position(), lineAnchorPos, selectionType == selWholeLine); } SetDragPosition(SelectionPosition(invalidPosition)); SetMouseCapture(true); - selectionType = selLine; } else { if (PointIsHotspot(pt)) { NotifyHotSpotClicked(newPos.Position(), shift, ctrl, alt); + hotSpotClickPos = PositionFromLocation(pt,true,false); } if (!shift) { if (PointInSelection(pt) && !SelectionEmpty()) @@ -5725,7 +6332,8 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b InvalidateSelection(SelectionRange(newPos), true); if (sel.Count() > 1) Redraw(); - sel.Clear(); + if ((sel.Count() > 1) || (sel.selType != Selection::selStream)) + sel.Clear(); sel.selType = alt ? Selection::selRectangle : Selection::selStream; SetSelection(newPos, newPos); } @@ -5743,7 +6351,8 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b } } lastClickTime = curTime; - lastXChosen = pt.x; + lastClick = pt; + lastXChosen = pt.x + xOffset; ShowCaretAtCurrentPosition(); } @@ -5791,7 +6400,7 @@ void Editor::SetHotSpotRange(Point *pt) { } } -void Editor::GetHotSpotRange(int& hsStart_, int& hsEnd_) { +void Editor::GetHotSpotRange(int &hsStart_, int &hsEnd_) { hsStart_ = hsStart; hsEnd_ = hsEnd; } @@ -5842,7 +6451,7 @@ void Editor::ButtonMove(Point pt) { } } else if (selectionType == selWord) { // Continue selecting by word - if (movePos.Position() == originalAnchorPos) { // Didn't move + if (movePos.Position() == wordSelectInitialCaretPos) { // Didn't move // No need to do anything. Previously this case was lumped // in with "Moved forward", but that can be harmful in this // case: a handler for the NotifyDoubleClick re-adjusts @@ -5852,32 +6461,24 @@ void Editor::ButtonMove(Point pt) { // the ButtonMove() called via Tick() for auto-scrolling // could result in the fancier word selection adjustment // being unmade. - } else if (movePos.Position() > originalAnchorPos) { // Moved forward - SetSelection(pdoc->ExtendWordSelect(movePos.Position(), 1), - pdoc->ExtendWordSelect(originalAnchorPos, -1)); - } else { // Moved backward - SetSelection(pdoc->ExtendWordSelect(movePos.Position(), -1), - pdoc->ExtendWordSelect(originalAnchorPos, 1)); + } else { + wordSelectInitialCaretPos = -1; + WordSelection(movePos.Position()); } } else { // Continue selecting by line - int lineMove = LineFromLocation(pt); - LineSelection(lineMove, lineAnchor); + LineSelection(movePos.Position(), lineAnchorPos, selectionType == selWholeLine); } } // Autoscroll PRectangle rcClient = GetClientRectangle(); + int lineMove = DisplayFromPosition(movePos.Position()); if (pt.y > rcClient.bottom) { - int lineMove = cs.DisplayFromDoc(LineFromLocation(pt)); - if (lineMove < 0) { - lineMove = cs.DisplayFromDoc(pdoc->LinesTotal() - 1); - } ScrollTo(lineMove - LinesOnScreen() + 1); Redraw(); } else if (pt.y < rcClient.top) { - int lineMove = cs.DisplayFromDoc(LineFromLocation(pt)); - ScrollTo(lineMove - 1); + ScrollTo(lineMove); Redraw(); } EnsureCaretVisible(false, false, true); @@ -5885,10 +6486,18 @@ void Editor::ButtonMove(Point pt) { if (hsStart != -1 && !PositionIsHotspot(movePos.Position())) SetHotSpotRange(NULL); + if (hotSpotClickPos != INVALID_POSITION && PositionFromLocation(pt,true,false) != hotSpotClickPos) { + if (inDragDrop == ddNone) { + DisplayCursor(Window::cursorText); + } + hotSpotClickPos = INVALID_POSITION; + } + } else { if (vs.fixedColumnWidth > 0) { // There is a margin if (PointInSelMargin(pt)) { - DisplayCursor(Window::cursorReverseArrow); + DisplayCursor(GetMarginCursor(pt)); + SetHotSpotRange(NULL); return; // No need to test for selection } } @@ -5912,11 +6521,17 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position()); if (inDragDrop == ddInitial) { inDragDrop = ddNone; - SetEmptySelection(newPos.Position()); + SetEmptySelection(newPos); + selectionType = selChar; + originalAnchorPos = sel.MainCaret(); + } + if (hotSpotClickPos != INVALID_POSITION && PointIsHotspot(pt)) { + hotSpotClickPos = INVALID_POSITION; + NotifyHotSpotReleaseClick(newPos.Position(), false, ctrl, false); } if (HaveMouseCapture()) { if (PointInSelMargin(pt)) { - DisplayCursor(Window::cursorReverseArrow); + DisplayCursor(GetMarginCursor(pt)); } else { DisplayCursor(Window::cursorText); SetHotSpotRange(NULL); @@ -5966,7 +6581,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { SetRectangularRange(); lastClickTime = curTime; lastClick = pt; - lastXChosen = pt.x; + lastXChosen = pt.x + xOffset; if (sel.selType == Selection::selStream) { SetLastXChosen(); } @@ -5998,7 +6613,8 @@ void Editor::Tick() { } if ((dwellDelay < SC_TIME_FOREVER) && (ticksToDwell > 0) && - (!HaveMouseCapture())) { + (!HaveMouseCapture()) && + (ptMouseLast.y >= 0)) { ticksToDwell -= timer.tickSize; if (ticksToDwell <= 0) { dwelling = true; @@ -6042,6 +6658,48 @@ void Editor::SetFocusState(bool focusState) { } } +int Editor::PositionAfterArea(PRectangle rcArea) { + // The start of the document line after the display line after the area + // This often means that the line after a modification is restyled which helps + // detect multiline comment additions and heals single line comments + int lineAfter = topLine + (rcArea.bottom - 1) / vs.lineHeight + 1; + if (lineAfter < cs.LinesDisplayed()) + return pdoc->LineStart(cs.DocFromDisplay(lineAfter) + 1); + else + return pdoc->Length(); +} + +// Style to a position within the view. If this causes a change at end of last line then +// affects later lines so style all the viewed text. +void Editor::StyleToPositionInView(Position pos) { + int endWindow = PositionAfterArea(GetClientRectangle()); + if (pos > endWindow) + pos = endWindow; + int styleAtEnd = pdoc->StyleAt(pos-1); + pdoc->EnsureStyledTo(pos); + if ((endWindow > pos) && (styleAtEnd != pdoc->StyleAt(pos-1))) { + // Style at end of line changed so is multi-line change like starting a comment + // so require rest of window to be styled. + pdoc->EnsureStyledTo(endWindow); + } +} + +void Editor::IdleStyling() { + // Style the line after the modification as this allows modifications that change just the + // line of the modification to heal instead of propagating to the rest of the window. + StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(styleNeeded.upTo) + 2)); + + if (needUpdateUI) { + NotifyUpdateUI(); + needUpdateUI = 0; + } + styleNeeded.Reset(); +} + +void Editor::QueueStyling(int upTo) { + styleNeeded.NeedUpTo(upTo); +} + bool Editor::PaintContains(PRectangle rc) { if (rc.Empty()) { return true; @@ -6098,8 +6756,22 @@ void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) { void Editor::SetAnnotationHeights(int start, int end) { if (vs.annotationVisible) { - for (int line=start; line<end; line++) { - cs.SetHeight(line, pdoc->AnnotationLines(line) + 1); + bool changedHeight = false; + for (int line=start; line<end && line<pdoc->LinesTotal(); line++) { + int linesWrapped = 1; + if (wrapState != eWrapNone) { + AutoSurface surface(this); + AutoLineLayout ll(llc, RetrieveLineLayout(line)); + if (surface && ll) { + LayoutLine(line, surface, vs, ll, wrapWidth); + linesWrapped = ll->lines; + } + } + if (cs.SetHeight(line, pdoc->AnnotationLines(line) + linesWrapped)) + changedHeight = true; + } + if (changedHeight) { + Redraw(); } } } @@ -6148,6 +6820,7 @@ void Editor::SetAnnotationVisible(int visible) { } } } + Redraw(); } } @@ -6183,8 +6856,8 @@ void Editor::ToggleContraction(int line) { if (cs.GetExpanded(line)) { int lineMaxSubord = pdoc->GetLastChild(line); - cs.SetExpanded(line, 0); if (lineMaxSubord > line) { + cs.SetExpanded(line, 0); cs.SetVisible(line + 1, lineMaxSubord, false); int lineCurrent = pdoc->LineFromPosition(sel.MainCaret()); @@ -6210,6 +6883,18 @@ void Editor::ToggleContraction(int line) { } } +int Editor::ContractedFoldNext(int lineStart) { + for (int line = lineStart; line<pdoc->LinesTotal();) { + if (!cs.GetExpanded(line) && (pdoc->GetLevel(line) & SC_FOLDLEVELHEADERFLAG)) + return line; + line = cs.ContractedNext(line+1); + if (line < 0) + return -1; + } + + return -1; +} + /** * Recurse up from this line to find any folds that prevent this line from being visible * and unfold them all. @@ -6217,10 +6902,16 @@ void Editor::ToggleContraction(int line) { void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) { // In case in need of wrapping to ensure DisplayFromDoc works. - WrapLines(true, -1); + if (lineDoc >= wrapStart) + WrapLines(true, -1); if (!cs.GetVisible(lineDoc)) { - int lineParent = pdoc->GetFoldParent(lineDoc); + int lookLine = lineDoc; + int lookLineLevel = pdoc->GetLevel(lookLine); + while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) { + lookLineLevel = pdoc->GetLevel(--lookLine); + } + int lineParent = pdoc->GetFoldParent(lookLine); if (lineParent >= 0) { if (lineDoc != lineParent) EnsureLineVisible(lineParent, enforcePolicy); @@ -6255,6 +6946,24 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) { } } +int Editor::GetTag(char *tagValue, int tagNumber) { + const char *text = 0; + int length = 0; + if ((tagNumber >= 1) && (tagNumber <= 9)) { + char name[3] = "\\?"; + name[1] = static_cast<char>(tagNumber + '0'); + length = 2; + text = pdoc->SubstituteByPosition(name, &length); + } + if (tagValue) { + if (text) + memcpy(tagValue, text, length + 1); + else + *tagValue = '\0'; + } + return length; +} + int Editor::ReplaceTarget(bool replacePatterns, const char *text, int length) { UndoGroup ug(pdoc); if (length == -1) @@ -6298,14 +7007,14 @@ int Editor::WrapCount(int line) { void Editor::AddStyledText(char *buffer, int appendLength) { // The buffer consists of alternating character bytes and style bytes - size_t textLength = appendLength / 2; + int textLength = appendLength / 2; char *text = new char[textLength]; - size_t i; - for (i = 0;i < textLength;i++) { + int i; + for (i = 0; i < textLength; i++) { text[i] = buffer[i*2]; } pdoc->InsertString(CurrentPosition(), text, textLength); - for (i = 0;i < textLength;i++) { + for (i = 0; i < textLength; i++) { text[i] = buffer[i*2+1]; } pdoc->StartStyling(CurrentPosition(), static_cast<char>(0xff)); @@ -6326,13 +7035,16 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam vs.EnsureStyle(wParam); switch (iMessage) { case SCI_STYLESETFORE: - vs.styles[wParam].fore.desired = ColourDesired(lParam); + vs.styles[wParam].fore = ColourDesired(lParam); break; case SCI_STYLESETBACK: - vs.styles[wParam].back.desired = ColourDesired(lParam); + vs.styles[wParam].back = ColourDesired(lParam); break; case SCI_STYLESETBOLD: - vs.styles[wParam].bold = lParam != 0; + vs.styles[wParam].weight = lParam != 0 ? SC_WEIGHT_BOLD : SC_WEIGHT_NORMAL; + break; + case SCI_STYLESETWEIGHT: + vs.styles[wParam].weight = lParam; break; case SCI_STYLESETITALIC: vs.styles[wParam].italic = lParam != 0; @@ -6341,6 +7053,9 @@ void Editor::StyleSetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lParam vs.styles[wParam].eolFilled = lParam != 0; break; case SCI_STYLESETSIZE: + vs.styles[wParam].size = lParam * SC_FONT_SIZE_MULTIPLIER; + break; + case SCI_STYLESETSIZEFRACTIONAL: vs.styles[wParam].size = lParam; break; case SCI_STYLESETFONT: @@ -6374,16 +7089,20 @@ sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lPar vs.EnsureStyle(wParam); switch (iMessage) { case SCI_STYLEGETFORE: - return vs.styles[wParam].fore.desired.AsLong(); + return vs.styles[wParam].fore.AsLong(); case SCI_STYLEGETBACK: - return vs.styles[wParam].back.desired.AsLong(); + return vs.styles[wParam].back.AsLong(); case SCI_STYLEGETBOLD: - return vs.styles[wParam].bold ? 1 : 0; + return vs.styles[wParam].weight > SC_WEIGHT_NORMAL; + case SCI_STYLEGETWEIGHT: + return vs.styles[wParam].weight; case SCI_STYLEGETITALIC: return vs.styles[wParam].italic ? 1 : 0; case SCI_STYLEGETEOLFILLED: return vs.styles[wParam].eolFilled ? 1 : 0; case SCI_STYLEGETSIZE: + return vs.styles[wParam].size / SC_FONT_SIZE_MULTIPLIER; + case SCI_STYLEGETSIZEFRACTIONAL: return vs.styles[wParam].size; case SCI_STYLEGETFONT: if (!vs.styles[wParam].fontName) @@ -6408,7 +7127,7 @@ sptr_t Editor::StyleGetMessage(unsigned int iMessage, uptr_t wParam, sptr_t lPar } sptr_t Editor::StringResult(sptr_t lParam, const char *val) { - const int n = strlen(val); + const size_t n = strlen(val); if (lParam != 0) { char *ptr = reinterpret_cast<char *>(lParam); strcpy(ptr, val); @@ -6464,6 +7183,18 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { CopyAllowLine(); break; + case SCI_VERTICALCENTRECARET: + VerticalCentreCaret(); + break; + + case SCI_MOVESELECTEDLINESUP: + MoveSelectedLinesUp(); + break; + + case SCI_MOVESELECTEDLINESDOWN: + MoveSelectedLinesDown(); + break; + case SCI_COPYRANGE: CopyRangeToClipboard(wParam, lParam); break; @@ -6474,7 +7205,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_PASTE: Paste(); - if (!caretSticky) { + if ((caretSticky == SC_CARETSTICKY_OFF) || (caretSticky == SC_CARETSTICKY_WHITESPACE)) { SetLastXChosen(); } EnsureCaretVisible(); @@ -6639,6 +7370,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETSEARCHFLAGS: return searchFlags; + case SCI_GETTAG: + return GetTag(CharPtrFromSPtr(lParam), wParam); + case SCI_POSITIONBEFORE: return pdoc->MovePositionOutsideChar(wParam - 1, -1, true); @@ -6652,6 +7386,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETXOFFSET: xOffset = wParam; + ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); SetHorizontalScrollPos(); Redraw(); break; @@ -6773,6 +7508,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { ClearAll(); return 0; + case SCI_DELETERANGE: + pdoc->DeleteChars(wParam, lParam); + return 0; + case SCI_CLEARDOCUMENTSTYLE: ClearDocumentStyle(); return 0; @@ -6799,6 +7538,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { caret.period = wParam; break; + case SCI_GETWORDCHARS: + return pdoc->GetCharsOfClass(CharClassify::ccWord, reinterpret_cast<unsigned char *>(lParam)); + case SCI_SETWORDCHARS: { pdoc->SetDefaultCharClasses(false); if (lParam == 0) @@ -6807,6 +7549,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { } break; + case SCI_GETWHITESPACECHARS: + return pdoc->GetCharsOfClass(CharClassify::ccSpace, reinterpret_cast<unsigned char *>(lParam)); + case SCI_SETWHITESPACECHARS: { if (lParam == 0) return 0; @@ -6814,6 +7559,16 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { } break; + case SCI_GETPUNCTUATIONCHARS: + return pdoc->GetCharsOfClass(CharClassify::ccPunctuation, reinterpret_cast<unsigned char *>(lParam)); + + case SCI_SETPUNCTUATIONCHARS: { + if (lParam == 0) + return 0; + pdoc->SetCharClasses(reinterpret_cast<unsigned char *>(lParam), CharClassify::ccPunctuation); + } + break; + case SCI_SETCHARSDEFAULT: pdoc->SetDefaultCharClasses(true); break; @@ -6859,14 +7614,18 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_GETSELECTIONSTART: - return Platform::Minimum(sel.MainAnchor(), sel.MainCaret()); + return sel.LimitsForRectangularElseMain().start.Position(); case SCI_SETSELECTIONEND: SetSelection(wParam, Platform::Minimum(sel.MainAnchor(), wParam)); break; case SCI_GETSELECTIONEND: - return Platform::Maximum(sel.MainAnchor(), sel.MainCaret()); + return sel.LimitsForRectangularElseMain().end.Position(); + + case SCI_SETEMPTYSELECTION: + SetEmptySelection(wParam); + break; case SCI_SETPRINTMAGNIFICATION: printMagnification = wParam; @@ -6966,7 +7725,6 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GOTOPOS: SetEmptySelection(wParam); EnsureCaretVisible(); - Redraw(); break; case SCI_GETCURLINE: { @@ -7117,6 +7875,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; } xOffset = 0; + ContainerNeedsUpdate(SC_UPDATE_H_SCROLL); InvalidateStyleRedraw(); ReconfigureScrollBars(); break; @@ -7125,9 +7884,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return wrapState; case SCI_SETWRAPVISUALFLAGS: - wrapVisualFlags = wParam; - InvalidateStyleRedraw(); - ReconfigureScrollBars(); + if (wrapVisualFlags != static_cast<int>(wParam)) { + wrapVisualFlags = wParam; + InvalidateStyleRedraw(); + ReconfigureScrollBars(); + } break; case SCI_GETWRAPVISUALFLAGS: @@ -7142,18 +7903,22 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return wrapVisualFlagsLocation; case SCI_SETWRAPSTARTINDENT: - wrapVisualStartIndent = wParam; - InvalidateStyleRedraw(); - ReconfigureScrollBars(); + if (wrapVisualStartIndent != static_cast<int>(wParam)) { + wrapVisualStartIndent = wParam; + InvalidateStyleRedraw(); + ReconfigureScrollBars(); + } break; case SCI_GETWRAPSTARTINDENT: return wrapVisualStartIndent; case SCI_SETWRAPINDENTMODE: - wrapIndentMode = wParam; - InvalidateStyleRedraw(); - ReconfigureScrollBars(); + if (wrapIndentMode != static_cast<int>(wParam)) { + wrapIndentMode = wParam; + InvalidateStyleRedraw(); + ReconfigureScrollBars(); + } break; case SCI_GETWRAPINDENTMODE: @@ -7220,9 +7985,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return endAtLastLine; case SCI_SETCARETSTICKY: - PLATFORM_ASSERT((wParam == 0) || (wParam == 1)); - if (caretSticky != (wParam != 0)) { - caretSticky = wParam != 0; + PLATFORM_ASSERT(wParam <= SC_CARETSTICKY_WHITESPACE); + if (wParam <= SC_CARETSTICKY_WHITESPACE) { + caretSticky = wParam; } break; @@ -7292,18 +8057,21 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETCODEPAGE: return pdoc->dbcsCodePage; +#ifdef INCLUDE_DEPRECATED_FEATURES case SCI_SETUSEPALETTE: - palette.allowRealization = wParam != 0; InvalidateStyleRedraw(); break; case SCI_GETUSEPALETTE: - return palette.allowRealization; + return 0; +#endif // Marker definition and setting case SCI_MARKERDEFINE: - if (wParam <= MARKER_MAX) + if (wParam <= MARKER_MAX) { vs.markers[wParam].markType = lParam; + vs.CalcLargestMarkerHeight(); + } InvalidateStyleData(); RedrawSelMargin(); break; @@ -7316,13 +8084,23 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_MARKERSETFORE: if (wParam <= MARKER_MAX) - vs.markers[wParam].fore.desired = ColourDesired(lParam); + vs.markers[wParam].fore = ColourDesired(lParam); + InvalidateStyleData(); + RedrawSelMargin(); + break; + case SCI_MARKERSETBACKSELECTED: + if (wParam <= MARKER_MAX) + vs.markers[wParam].backSelected = ColourDesired(lParam); InvalidateStyleData(); RedrawSelMargin(); break; + case SCI_MARKERENABLEHIGHLIGHT: + highlightDelimiter.isEnabled = wParam == 1; + RedrawSelMargin(); + break; case SCI_MARKERSETBACK: if (wParam <= MARKER_MAX) - vs.markers[wParam].back.desired = ColourDesired(lParam); + vs.markers[wParam].back = ColourDesired(lParam); InvalidateStyleData(); RedrawSelMargin(); break; @@ -7351,14 +8129,8 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_MARKERGET: return pdoc->GetMark(wParam); - case SCI_MARKERNEXT: { - int lt = pdoc->LinesTotal(); - for (int iLine = wParam; iLine < lt; iLine++) { - if ((pdoc->GetMark(iLine) & lParam) != 0) - return iLine; - } - } - return -1; + case SCI_MARKERNEXT: + return pdoc->MarkerNext(wParam, lParam); case SCI_MARKERPREVIOUS: { for (int iLine = wParam; iLine >= 0; iLine--) { @@ -7371,6 +8143,24 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_MARKERDEFINEPIXMAP: if (wParam <= MARKER_MAX) { vs.markers[wParam].SetXPM(CharPtrFromSPtr(lParam)); + vs.CalcLargestMarkerHeight(); + }; + InvalidateStyleData(); + RedrawSelMargin(); + break; + + case SCI_RGBAIMAGESETWIDTH: + sizeRGBAImage.x = wParam; + break; + + case SCI_RGBAIMAGESETHEIGHT: + sizeRGBAImage.y = wParam; + break; + + case SCI_MARKERDEFINERGBAIMAGE: + if (wParam <= MARKER_MAX) { + vs.markers[wParam].SetRGBAImage(sizeRGBAImage, reinterpret_cast<unsigned char *>(lParam)); + vs.CalcLargestMarkerHeight(); }; InvalidateStyleData(); RedrawSelMargin(); @@ -7431,6 +8221,17 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { else return 0; + case SCI_SETMARGINCURSORN: + if (ValidMargin(wParam)) + vs.ms[wParam].cursor = lParam; + break; + + case SCI_GETMARGINCURSORN: + if (ValidMargin(wParam)) + return vs.ms[wParam].cursor; + else + return 0; + case SCI_STYLECLEARALL: vs.ClearStyles(); InvalidateStyleRedraw(); @@ -7439,9 +8240,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_STYLESETFORE: case SCI_STYLESETBACK: case SCI_STYLESETBOLD: + case SCI_STYLESETWEIGHT: case SCI_STYLESETITALIC: case SCI_STYLESETEOLFILLED: case SCI_STYLESETSIZE: + case SCI_STYLESETSIZEFRACTIONAL: case SCI_STYLESETFONT: case SCI_STYLESETUNDERLINE: case SCI_STYLESETCASE: @@ -7455,9 +8258,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_STYLEGETFORE: case SCI_STYLEGETBACK: case SCI_STYLEGETBOLD: + case SCI_STYLEGETWEIGHT: case SCI_STYLEGETITALIC: case SCI_STYLEGETEOLFILLED: case SCI_STYLEGETSIZE: + case SCI_STYLEGETSIZEFRACTIONAL: case SCI_STYLEGETFONT: case SCI_STYLEGETUNDERLINE: case SCI_STYLEGETCASE: @@ -7495,9 +8300,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { InvalidateStyleRedraw(); break; case SCI_GETCARETLINEBACK: - return vs.caretLineBackground.desired.AsLong(); + return vs.caretLineBackground.AsLong(); case SCI_SETCARETLINEBACK: - vs.caretLineBackground.desired = wParam; + vs.caretLineBackground = wParam; InvalidateStyleRedraw(); break; case SCI_GETCARETLINEBACKALPHA: @@ -7550,6 +8355,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETLINEVISIBLE: return cs.GetVisible(wParam); + case SCI_GETALLLINESVISIBLE: + return cs.HiddenLines() ? 0 : 1; + case SCI_SETFOLDEXPANDED: if (cs.SetExpanded(wParam, lParam != 0)) { RedrawSelMargin(); @@ -7568,6 +8376,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { ToggleContraction(wParam); break; + case SCI_CONTRACTEDFOLDNEXT: + return ContractedFoldNext(wParam); + case SCI_ENSUREVISIBLE: EnsureLineVisible(wParam, false); break; @@ -7604,15 +8415,15 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETSELFORE: vs.selforeset = wParam != 0; - vs.selforeground.desired = ColourDesired(lParam); - vs.selAdditionalForeground.desired = ColourDesired(lParam); + vs.selforeground = ColourDesired(lParam); + vs.selAdditionalForeground = ColourDesired(lParam); InvalidateStyleRedraw(); break; case SCI_SETSELBACK: vs.selbackset = wParam != 0; - vs.selbackground.desired = ColourDesired(lParam); - vs.selAdditionalBackground.desired = ColourDesired(lParam); + vs.selbackground = ColourDesired(lParam); + vs.selAdditionalBackground = ColourDesired(lParam); InvalidateStyleRedraw(); break; @@ -7635,26 +8446,26 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETWHITESPACEFORE: vs.whitespaceForegroundSet = wParam != 0; - vs.whitespaceForeground.desired = ColourDesired(lParam); + vs.whitespaceForeground = ColourDesired(lParam); InvalidateStyleRedraw(); break; case SCI_SETWHITESPACEBACK: vs.whitespaceBackgroundSet = wParam != 0; - vs.whitespaceBackground.desired = ColourDesired(lParam); + vs.whitespaceBackground = ColourDesired(lParam); InvalidateStyleRedraw(); break; case SCI_SETCARETFORE: - vs.caretcolour.desired = ColourDesired(wParam); + vs.caretcolour = ColourDesired(wParam); InvalidateStyleRedraw(); break; case SCI_GETCARETFORE: - return vs.caretcolour.desired.AsLong(); + return vs.caretcolour.AsLong(); case SCI_SETCARETSTYLE: - if (wParam >= CARETSTYLE_INVISIBLE && wParam <= CARETSTYLE_BLOCK) + if (wParam <= CARETSTYLE_BLOCK) vs.caretStyle = wParam; else /* Default to the line caret */ @@ -7666,7 +8477,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.caretStyle; case SCI_SETCARETWIDTH: - if (wParam <= 0) + if (static_cast<int>(wParam) <= 0) vs.caretWidth = 0; else if (wParam >= 3) vs.caretWidth = 3; @@ -7704,13 +8515,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_INDICSETFORE: if (wParam <= INDIC_MAX) { - vs.indicators[wParam].fore.desired = ColourDesired(lParam); + vs.indicators[wParam].fore = ColourDesired(lParam); InvalidateStyleRedraw(); } break; case SCI_INDICGETFORE: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.desired.AsLong() : 0; + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.AsLong() : 0; case SCI_INDICSETUNDER: if (wParam <= INDIC_MAX) { @@ -7723,7 +8534,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return (wParam <= INDIC_MAX) ? vs.indicators[wParam].under : 0; case SCI_INDICSETALPHA: - if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 100) { + if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) { vs.indicators[wParam].fillAlpha = lParam; InvalidateStyleRedraw(); } @@ -7732,6 +8543,16 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_INDICGETALPHA: return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fillAlpha : 0; + case SCI_INDICSETOUTLINEALPHA: + if (wParam <= INDIC_MAX && lParam >=0 && lParam <= 255) { + vs.indicators[wParam].outlineAlpha = lParam; + InvalidateStyleRedraw(); + } + break; + + case SCI_INDICGETOUTLINEALPHA: + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].outlineAlpha : 0; + case SCI_SETINDICATORCURRENT: pdoc->decorations.SetCurrentIndicator(wParam); break; @@ -7795,6 +8616,8 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_DOCUMENTSTARTEXTEND: case SCI_DOCUMENTEND: case SCI_DOCUMENTENDEXTEND: + case SCI_SCROLLTOSTART: + case SCI_SCROLLTOEND: case SCI_STUTTEREDPAGEUP: case SCI_STUTTEREDPAGEUPEXTEND: @@ -7857,10 +8680,24 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { SetBraceHighlight(static_cast<int>(wParam), lParam, STYLE_BRACELIGHT); break; + case SCI_BRACEHIGHLIGHTINDICATOR: + if (lParam >= 0 && lParam <= INDIC_MAX) { + vs.braceHighlightIndicatorSet = wParam != 0; + vs.braceHighlightIndicator = lParam; + } + break; + case SCI_BRACEBADLIGHT: SetBraceHighlight(static_cast<int>(wParam), -1, STYLE_BRACEBAD); break; + case SCI_BRACEBADLIGHTINDICATOR: + if (lParam >= 0 && lParam <= INDIC_MAX) { + vs.braceBadLightIndicatorSet = wParam != 0; + vs.braceBadLightIndicator = lParam; + } + break; + case SCI_BRACEMATCH: // wParam is position of char to find brace for, // lParam is maximum amount of text to restyle to find it @@ -7900,10 +8737,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { break; case SCI_GETEDGECOLOUR: - return vs.edgecolour.desired.AsLong(); + return vs.edgecolour.AsLong(); case SCI_SETEDGECOLOUR: - vs.edgecolour.desired = ColourDesired(wParam); + vs.edgecolour = ColourDesired(wParam); InvalidateStyleRedraw(); break; @@ -7931,6 +8768,16 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { (reinterpret_cast<Document *>(lParam))->Release(); break; + case SCI_CREATELOADER: { + Document *doc = new Document(); + if (doc) { + doc->AddRef(); + doc->Allocate(wParam); + doc->SetUndoCollection(false); + } + return reinterpret_cast<sptr_t>(static_cast<ILoader *>(doc)); + } + case SCI_SETMODEVENTMASK: modEventMask = wParam; return 0; @@ -8057,33 +8904,33 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETFOLDMARGINCOLOUR: vs.foldmarginColourSet = wParam != 0; - vs.foldmarginColour.desired = ColourDesired(lParam); + vs.foldmarginColour = ColourDesired(lParam); InvalidateStyleRedraw(); break; case SCI_SETFOLDMARGINHICOLOUR: vs.foldmarginHighlightColourSet = wParam != 0; - vs.foldmarginHighlightColour.desired = ColourDesired(lParam); + vs.foldmarginHighlightColour = ColourDesired(lParam); InvalidateStyleRedraw(); break; case SCI_SETHOTSPOTACTIVEFORE: vs.hotspotForegroundSet = wParam != 0; - vs.hotspotForeground.desired = ColourDesired(lParam); + vs.hotspotForeground = ColourDesired(lParam); InvalidateStyleRedraw(); break; case SCI_GETHOTSPOTACTIVEFORE: - return vs.hotspotForeground.desired.AsLong(); + return vs.hotspotForeground.AsLong(); case SCI_SETHOTSPOTACTIVEBACK: vs.hotspotBackgroundSet = wParam != 0; - vs.hotspotBackground.desired = ColourDesired(lParam); + vs.hotspotBackground = ColourDesired(lParam); InvalidateStyleRedraw(); break; case SCI_GETHOTSPOTACTIVEBACK: - return vs.hotspotBackground.desired.AsLong(); + return vs.hotspotBackground.AsLong(); case SCI_SETHOTSPOTACTIVEUNDERLINE: vs.hotspotUnderline = wParam != 0; @@ -8111,6 +8958,12 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETCHARACTERPOINTER: return reinterpret_cast<sptr_t>(pdoc->BufferPointer()); + case SCI_GETRANGEPOINTER: + return reinterpret_cast<sptr_t>(pdoc->RangePointer(wParam, lParam)); + + case SCI_GETGAPPOSITION: + return pdoc->GapPosition(); + case SCI_SETEXTRAASCENT: vs.extraAscent = wParam; InvalidateStyleRedraw(); @@ -8135,6 +8988,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_MARGINGETSTYLEOFFSET: return vs.marginStyleOffset; + case SCI_SETMARGINOPTIONS: + marginOptions = wParam; + break; + + case SCI_GETMARGINOPTIONS: + return marginOptions; + case SCI_MARGINSETTEXT: pdoc->MarginSetText(wParam, CharPtrFromSPtr(lParam)); break; @@ -8259,6 +9119,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETADDITIONALSELECTIONTYPING: return additionalSelectionTyping; + case SCI_SETMULTIPASTE: + multiPasteMode = wParam; + break; + + case SCI_GETMULTIPASTE: + return multiPasteMode; + case SCI_SETADDITIONALCARETSBLINK: additionalCaretsBlink = wParam != 0; InvalidateCaret(); @@ -8404,12 +9271,12 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return virtualSpaceOptions; case SCI_SETADDITIONALSELFORE: - vs.selAdditionalForeground.desired = ColourDesired(wParam); + vs.selAdditionalForeground = ColourDesired(wParam); InvalidateStyleRedraw(); break; case SCI_SETADDITIONALSELBACK: - vs.selAdditionalBackground.desired = ColourDesired(wParam); + vs.selAdditionalBackground = ColourDesired(wParam); InvalidateStyleRedraw(); break; @@ -8422,12 +9289,12 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return vs.selAdditionalAlpha; case SCI_SETADDITIONALCARETFORE: - vs.additionalCaretColour.desired = ColourDesired(wParam); + vs.additionalCaretColour = ColourDesired(wParam); InvalidateStyleRedraw(); break; case SCI_GETADDITIONALCARETFORE: - return vs.additionalCaretColour.desired.AsLong(); + return vs.additionalCaretColour.AsLong(); case SCI_ROTATESELECTION: sel.RotateMain(); @@ -8439,6 +9306,27 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { sel.RangeMain() = SelectionRange(sel.RangeMain().anchor, sel.RangeMain().caret); break; + case SCI_CHANGELEXERSTATE: + pdoc->ChangeLexerState(wParam, lParam); + break; + + case SCI_SETIDENTIFIER: + SetCtrlID(wParam); + break; + + case SCI_GETIDENTIFIER: + return GetCtrlID(); + + case SCI_SETTECHNOLOGY: + // No action by default + break; + + case SCI_GETTECHNOLOGY: + return technology; + + case SCI_COUNTCHARACTERS: + return pdoc->CountCharacters(wParam, lParam); + default: return DefWndProc(iMessage, wParam, lParam); } diff --git a/src/stc/scintilla/src/Editor.h b/src/stc/scintilla/src/Editor.h index 92dcfb14bf..00e4ec3a63 100644 --- a/src/stc/scintilla/src/Editor.h +++ b/src/stc/scintilla/src/Editor.h @@ -2,7 +2,7 @@ /** @file Editor.h ** Defines the main editor class. **/ -// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> +// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. #ifndef EDITOR_H @@ -45,6 +45,26 @@ public: Idler(); }; +/** + * When platform has a way to generate an event before painting, + * accumulate needed styling range in StyleNeeded to avoid unnecessary work. + */ +class StyleNeeded { +public: + bool active; + Position upTo; + + StyleNeeded() : active(false), upTo(0) {} + void Reset() { + active = false; + upTo = 0; + } + void NeedUpTo(Position pos) { + if (upTo < pos) + upTo = pos; + } +}; + /** * Hold a piece of text selected for copying or dragging. * The text is expected to hold a terminating '\0' and this is counted in len. @@ -111,7 +131,8 @@ protected: // ScintillaBase subclass needs access to much of Editor * When a style attribute is changed, this cache is flushed. */ bool stylesValid; ViewStyle vs; - Palette palette; + int technology; + Point sizeRGBAImage; int printMagnification; int printColourMode; @@ -119,6 +140,9 @@ protected: // ScintillaBase subclass needs access to much of Editor int cursorMode; int controlCharSymbol; + // Highlight current folding block + HighlightDelimiter highlightDelimiter; + bool hasFocus; bool hideSelection; bool inOverstrike; @@ -139,9 +163,11 @@ protected: // ScintillaBase subclass needs access to much of Editor int lineWidthMaxSeen; bool verticalScrollBarVisible; bool endAtLastLine; - bool caretSticky; + int caretSticky; + int marginOptions; bool multipleSelection; bool additionalSelectionTyping; + int multiPasteMode; bool additionalCaretsBlink; bool additionalCaretsVisible; @@ -170,15 +196,19 @@ protected: // ScintillaBase subclass needs access to much of Editor int dwellDelay; int ticksToDwell; bool dwelling; - enum { selChar, selWord, selLine } selectionType; + enum { selChar, selWord, selSubLine, selWholeLine } selectionType; Point ptMouseLast; enum { ddNone, ddInitial, ddDragging } inDragDrop; bool dropWentOutside; SelectionPosition posDrag; SelectionPosition posDrop; + int hotSpotClickPos; int lastXChosen; - int lineAnchor; + int lineAnchorPos; int originalAnchorPos; + int wordSelectAnchorStartPos; + int wordSelectAnchorEndPos; + int wordSelectInitialCaretPos; int targetStart; int targetEnd; int searchFlags; @@ -186,7 +216,7 @@ protected: // ScintillaBase subclass needs access to much of Editor int posTopLine; int lengthForEncode; - bool needUpdateUI; + int needUpdateUI; Position braces[2]; int bracesMatchStyle; int highlightGuideColumn; @@ -196,6 +226,8 @@ protected: // ScintillaBase subclass needs access to much of Editor enum { notPainting, painting, paintAbandoned } paintState; PRectangle rcPaint; bool paintingAllText; + bool willRedrawAll; + StyleNeeded styleNeeded; int modEventMask; @@ -232,7 +264,6 @@ protected: // ScintillaBase subclass needs access to much of Editor int wrapVisualFlags; int wrapVisualFlagsLocation; int wrapVisualStartIndent; - int wrapAddIndent; // This will be added to initial indent of line int wrapIndentMode; // SC_WRAPINDENT_FIXED, _SAME, _INDENT bool convertPastes; @@ -246,9 +277,9 @@ protected: // ScintillaBase subclass needs access to much of Editor void InvalidateStyleData(); void InvalidateStyleRedraw(); - virtual void RefreshColourPalette(Palette &pal, bool want); void RefreshStyleData(); - void DropGraphics(); + void DropGraphics(bool freeObjects); + void AllocateGraphics(); virtual PRectangle GetClientRectangle(); PRectangle GetTextRectangle(); @@ -271,7 +302,7 @@ protected: // ScintillaBase subclass needs access to much of Editor bool AbandonPaint(); void RedrawRect(PRectangle rc); void Redraw(); - void RedrawSelMargin(int line=-1); + void RedrawSelMargin(int line=-1, bool allAfter=false); PRectangle RectangleFromRange(int start, int end); void InvalidateRange(int start, int end); @@ -305,8 +336,20 @@ protected: // ScintillaBase subclass needs access to much of Editor void ScrollTo(int line, bool moveThumb=true); virtual void ScrollText(int linesToMove); void HorizontalScrollTo(int xPos); + void VerticalCentreCaret(); + void MoveSelectedLines(int lineDelta); + void MoveSelectedLinesUp(); + void MoveSelectedLinesDown(); void MoveCaretInsideView(bool ensureVisible=true); int DisplayFromPosition(int pos); + + struct XYScrollPosition { + int xOffset; + int topLine; + XYScrollPosition(int xOffset_, int topLine_) : xOffset(xOffset_), topLine(topLine_) {} + }; + XYScrollPosition XYScrollToMakeVisible(const bool useMargin, const bool vert, const bool horiz); + void SetXYScroll(XYScrollPosition newXY); void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true); void ShowCaretAtCurrentPosition(); void DropCaret(); @@ -324,22 +367,24 @@ protected: // ScintillaBase subclass needs access to much of Editor LineLayout *RetrieveLineLayout(int lineNumber); void LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayout *ll, int width=LineLayout::wrapWidthInfinite); - ColourAllocated SelectionBackground(ViewStyle &vsDraw, bool main); - ColourAllocated TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourAllocated background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll); + ColourDesired SelectionBackground(ViewStyle &vsDraw, bool main); + ColourDesired TextBackground(ViewStyle &vsDraw, bool overrideBackground, ColourDesired background, int inSelection, bool inHotspot, int styleMain, int i, LineLayout *ll); void DrawIndentGuide(Surface *surface, int lineVisible, int lineHeight, int start, PRectangle rcSegment, bool highlight); - void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourAllocated wrapColour); + void DrawWrapMarker(Surface *surface, PRectangle rcPlace, bool isEndMarker, ColourDesired wrapColour); void DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, LineLayout *ll, - int line, int lineEnd, int xStart, int subLine, int subLineStart, - bool overrideBackground, ColourAllocated background, - bool drawWrapMark, ColourAllocated wrapColour); + int line, int lineEnd, int xStart, int subLine, XYACCUMULATOR subLineStart, + bool overrideBackground, ColourDesired background, + bool drawWrapMark, ColourDesired wrapColour); + void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, ViewStyle &vsDraw, + int xStart, PRectangle rcLine, LineLayout *ll, int subLine); void DrawIndicators(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout *ll, int subLine, int lineEnd, bool under); void DrawAnnotation(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout *ll, int subLine); void DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVisible, int xStart, PRectangle rcLine, LineLayout *ll, int subLine); - void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, - int xStart, int offset, int posCaret, PRectangle rcCaret, ColourAllocated caretColour); + void DrawBlockCaret(Surface *surface, ViewStyle &vsDraw, LineLayout *ll, int subLine, + int xStart, int offset, int posCaret, PRectangle rcCaret, ColourDesired caretColour); void DrawCarets(Surface *surface, ViewStyle &vsDraw, int line, int xStart, PRectangle rcLine, LineLayout *ll, int subLine); void RefreshPixMaps(Surface *surfaceWindow); @@ -358,7 +403,8 @@ protected: // ScintillaBase subclass needs access to much of Editor int InsertSpace(int position, unsigned int spaces); void AddChar(char ch); virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false); - void ClearSelection(); + void InsertPaste(SelectionPosition selStart, const char *text, int len); + void ClearSelection(bool retainMultipleSelections=false); void ClearAll(); void ClearDocumentStyle(); void Cut(); @@ -377,6 +423,7 @@ protected: // ScintillaBase subclass needs access to much of Editor virtual void NotifyChange() = 0; virtual void NotifyFocus(bool focus); + virtual void SetCtrlID(int identifier); virtual int GetCtrlID() { return ctrlID; } virtual void NotifyParent(SCNotification scn) = 0; virtual void NotifyStyleToNeeded(int endStyleNeeded); @@ -386,6 +433,7 @@ protected: // ScintillaBase subclass needs access to much of Editor virtual void NotifyDoubleClick(Point pt, bool shift, bool ctrl, bool alt); void NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt); void NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt); + void NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt); void NotifyUpdateUI(); void NotifyPainted(); void NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt); @@ -400,10 +448,15 @@ protected: // ScintillaBase subclass needs access to much of Editor void NotifyModified(Document *document, DocModification mh, void *userData); void NotifyDeleted(Document *document, void *userData); void NotifyStyleNeeded(Document *doc, void *userData, int endPos); + void NotifyLexerChanged(Document *doc, void *userData); + void NotifyErrorOccurred(Document *doc, void *userData, int status); void NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam); + void ContainerNeedsUpdate(int flags); void PageMove(int direction, Selection::selTypes sel=Selection::noSel, bool stuttered = false); - void ChangeCaseOfSelection(bool makeUpperCase); + enum { cmSame, cmUpper, cmLower } caseMap; + virtual std::string CaseMapString(const std::string &s, int caseMapping); + void ChangeCaseOfSelection(int caseMapping); void LineTranspose(); void Duplicate(bool forLine); virtual void CancelModes(); @@ -413,13 +466,12 @@ protected: // ScintillaBase subclass needs access to much of Editor int StartEndDisplayLine(int pos, bool start); virtual int KeyCommand(unsigned int iMessage); virtual int KeyDefault(int /* key */, int /*modifiers*/); + int KeyDownWithModifiers(int key, int modifiers, bool *consumed); int KeyDown(int key, bool shift, bool ctrl, bool alt, bool *consumed=0); - int GetWhitespaceVisible(); - void SetWhitespaceVisible(int view); - void Indent(bool forwards); + virtual CaseFolder *CaseFolderForEncoding(); long FindText(uptr_t wParam, sptr_t lParam); void SearchAnchor(); long SearchText(unsigned int iMessage, uptr_t wParam, sptr_t lParam); @@ -428,6 +480,7 @@ protected: // ScintillaBase subclass needs access to much of Editor virtual void CopyToClipboard(const SelectionText &selectedText) = 0; char *CopyRange(int start, int end); + std::string RangeText(int start, int end) const; void CopySelectionRange(SelectionText *ss, bool allowLineCopy=false); void CopyRangeToClipboard(int start, int end); void CopyText(int length, const char *text); @@ -440,8 +493,12 @@ protected: // ScintillaBase subclass needs access to much of Editor bool PositionInSelection(int pos); bool PointInSelection(Point pt); bool PointInSelMargin(Point pt); - void LineSelection(int lineCurrent_, int lineAnchor_); + Window::Cursor GetMarginCursor(Point pt); + void TrimAndSetSelection(int currentPos_, int anchor_); + void LineSelection(int lineCurrentPos_, int lineAnchorPos_, bool wholeLine); + void WordSelection(int pos); void DwellEnd(bool mouseMoved); + void MouseLeave(); virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt); void ButtonMove(Point pt); void ButtonUp(Point pt, unsigned int curTime, bool ctrl); @@ -454,6 +511,11 @@ protected: // ScintillaBase subclass needs access to much of Editor virtual bool HaveMouseCapture() = 0; void SetFocusState(bool focusState); + int PositionAfterArea(PRectangle rcArea); + void StyleToPositionInView(Position pos); + void IdleStyling(); + virtual void QueueStyling(int upTo); + virtual bool PaintContains(PRectangle rc); bool PaintContainsMargin(); void CheckForChangeOutsidePaint(Range r); @@ -461,18 +523,20 @@ protected: // ScintillaBase subclass needs access to much of Editor void SetAnnotationHeights(int start, int end); void SetDocPointer(Document *document); - + void SetAnnotationVisible(int visible); void Expand(int &line, bool doExpand); void ToggleContraction(int line); + int ContractedFoldNext(int lineStart); void EnsureLineVisible(int lineDoc, bool enforcePolicy); + int GetTag(char *tagValue, int tagNumber); int ReplaceTarget(bool replacePatterns, const char *text, int length=-1); bool PositionIsHotspot(int position); bool PointIsHotspot(Point pt); void SetHotSpotRange(Point *pt); - void GetHotSpotRange(int& hsStart, int& hsEnd); + void GetHotSpotRange(int &hsStart, int &hsEnd); int CodePage() const; virtual bool ValidCodePage(int /* codePage */) const { return true; } @@ -507,9 +571,9 @@ class AutoSurface { private: Surface *surf; public: - AutoSurface(Editor *ed) : surf(0) { + AutoSurface(Editor *ed, int technology = -1) : surf(0) { if (ed->wMain.GetID()) { - surf = Surface::Allocate(); + surf = Surface::Allocate(technology != -1 ? technology : ed->technology); if (surf) { surf->Init(ed->wMain.GetID()); surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); @@ -517,9 +581,9 @@ public: } } } - AutoSurface(SurfaceID sid, Editor *ed) : surf(0) { + AutoSurface(SurfaceID sid, Editor *ed, int technology = -1) : surf(0) { if (ed->wMain.GetID()) { - surf = Surface::Allocate(); + surf = Surface::Allocate(technology != -1 ? technology : ed->technology); if (surf) { surf->Init(sid, ed->wMain.GetID()); surf->SetUnicodeMode(SC_CP_UTF8 == ed->CodePage()); diff --git a/src/stc/scintilla/src/ExternalLexer.cxx b/src/stc/scintilla/src/ExternalLexer.cxx index 098df4dd5b..bb4846497e 100644 --- a/src/stc/scintilla/src/ExternalLexer.cxx +++ b/src/stc/scintilla/src/ExternalLexer.cxx @@ -9,18 +9,18 @@ #include <stdio.h> #include <string.h> #include <ctype.h> +#include <assert.h> #include <string> #include "Platform.h" +#include "ILexer.h" #include "Scintilla.h" - #include "SciLexer.h" -#include "PropSet.h" -#include "Accessor.h" -#include "DocumentAccessor.h" -#include "KeyWords.h" + +#include "LexerModule.h" +#include "Catalogue.h" #include "ExternalLexer.h" #ifdef SCI_NAMESPACE @@ -35,77 +35,9 @@ LexerManager *LexerManager::theInstance = NULL; // //------------------------------------------ -char **WordListsToStrings(WordList *val[]) { - int dim = 0; - while (val[dim]) - dim++; - char **wls = new char * [dim + 1]; - for (int i = 0;i < dim;i++) { - std::string words; - words = ""; - for (int n = 0; n < val[i]->len; n++) { - words += val[i]->words[n]; - if (n != val[i]->len - 1) - words += " "; - } - wls[i] = new char[words.length() + 1]; - strcpy(wls[i], words.c_str()); - } - wls[dim] = 0; - return wls; -} - -void DeleteWLStrings(char *strs[]) { - int dim = 0; - while (strs[dim]) { - delete strs[dim]; - dim++; - } - delete [] strs; -} - -void ExternalLexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) const { - if (!fneLexer) - return ; - - char **kwds = WordListsToStrings(keywordlists); - char *ps = styler.GetProperties(); - - // The accessor passed in is always a DocumentAccessor so this cast and the subsequent - // access will work. Can not use the stricter dynamic_cast as that requires RTTI. - DocumentAccessor &da = static_cast<DocumentAccessor &>(styler); - WindowID wID = da.GetWindow(); - - fneLexer(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps); - - delete ps; - DeleteWLStrings(kwds); -} - -void ExternalLexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) const { - if (!fneFolder) - return ; - - char **kwds = WordListsToStrings(keywordlists); - char *ps = styler.GetProperties(); - - // The accessor passed in is always a DocumentAccessor so this cast and the subsequent - // access will work. Can not use the stricter dynamic_cast as that requires RTTI. - DocumentAccessor &da = static_cast<DocumentAccessor &>(styler); - WindowID wID = da.GetWindow(); - - fneFolder(externalLanguage, startPos, lengthDoc, initStyle, kwds, wID, ps); - - delete ps; - DeleteWLStrings(kwds); -} - -void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index) { - fneLexer = fLexer; - fneFolder = fFolder; - externalLanguage = index; +void ExternalLexerModule::SetExternal(GetLexerFactoryFunction fFactory, int index) { + fneFactory = fFactory; + fnFactory = fFactory(index); } //------------------------------------------ @@ -114,7 +46,7 @@ void ExternalLexerModule::SetExternal(ExtLexerFunction fLexer, ExtFoldFunction f // //------------------------------------------ -LexerLibrary::LexerLibrary(const char* ModuleName) { +LexerLibrary::LexerLibrary(const char *ModuleName) { // Initialise some members... first = NULL; last = NULL; @@ -132,8 +64,7 @@ LexerLibrary::LexerLibrary(const char* ModuleName) { // Find functions in the DLL GetLexerNameFn GetLexerName = (GetLexerNameFn)(sptr_t)lib->FindFunction("GetLexerName"); - ExtLexerFunction Lexer = (ExtLexerFunction)(sptr_t)lib->FindFunction("Lex"); - ExtFoldFunction Folder = (ExtFoldFunction)(sptr_t)lib->FindFunction("Fold"); + GetLexerFactoryFunction fnFactory = (GetLexerFactoryFunction)(sptr_t)lib->FindFunction("GetLexerFactory"); // Assign a buffer for the lexer name. char lexname[100]; @@ -144,6 +75,7 @@ LexerLibrary::LexerLibrary(const char* ModuleName) { for (int i = 0; i < nl; i++) { GetLexerName(i, lexname, 100); lex = new ExternalLexerModule(SCLEX_AUTOMATIC, NULL, lexname, NULL); + Catalogue::AddLexerModule(lex); // Create a LexerMinder so we don't leak the ExternalLexerModule... lm = new LexerMinder; @@ -158,8 +90,8 @@ LexerLibrary::LexerLibrary(const char* ModuleName) { } // The external lexer needs to know how to call into its DLL to - // do its lexing and folding, we tell it here. Folder may be null. - lex->SetExternal(Lexer, Folder, i); + // do its lexing and folding, we tell it here. + lex->SetExternal(fnFactory, i); } } } @@ -172,7 +104,6 @@ LexerLibrary::~LexerLibrary() { } void LexerLibrary::Release() { - //TODO maintain a list of lexers created, and delete them! LexerMinder *lm; LexerMinder *lmNext; lm = first; @@ -195,18 +126,15 @@ void LexerLibrary::Release() { /// Return the single LexerManager instance... LexerManager *LexerManager::GetInstance() { - if(!theInstance) + if (!theInstance) theInstance = new LexerManager; return theInstance; } /// Delete any LexerManager instance... -void LexerManager::DeleteInstance() -{ - if(theInstance) { - delete theInstance; - theInstance = NULL; - } +void LexerManager::DeleteInstance() { + delete theInstance; + theInstance = NULL; } /// protected constructor - this is a singleton... @@ -219,13 +147,15 @@ LexerManager::~LexerManager() { Clear(); } -void LexerManager::Load(const char* path) -{ +void LexerManager::Load(const char *path) { LoadLexerLibrary(path); } -void LexerManager::LoadLexerLibrary(const char* module) -{ +void LexerManager::LoadLexerLibrary(const char *module) { + for (LexerLibrary *ll = first; ll; ll= ll->next) { + if (strcmp(ll->m_sModuleName.c_str(), module) == 0) + return; + } LexerLibrary *lib = new LexerLibrary(module); if (NULL != first) { last->next = lib; @@ -236,8 +166,7 @@ void LexerManager::LoadLexerLibrary(const char* module) } } -void LexerManager::Clear() -{ +void LexerManager::Clear() { if (NULL != first) { LexerLibrary *cur = first; LexerLibrary *next; @@ -257,8 +186,7 @@ void LexerManager::Clear() // //------------------------------------------ -LMMinder::~LMMinder() -{ +LMMinder::~LMMinder() { LexerManager::DeleteInstance(); } diff --git a/src/stc/scintilla/src/ExternalLexer.h b/src/stc/scintilla/src/ExternalLexer.h index 29f42ccf74..bf175a6310 100644 --- a/src/stc/scintilla/src/ExternalLexer.h +++ b/src/stc/scintilla/src/ExternalLexer.h @@ -18,36 +18,26 @@ namespace Scintilla { #endif -// External Lexer function definitions... -typedef void (EXT_LEXER_DECL *ExtLexerFunction)(unsigned int lexer, unsigned int startPos, int length, int initStyle, - char *words[], WindowID window, char *props); -typedef void (EXT_LEXER_DECL *ExtFoldFunction)(unsigned int lexer, unsigned int startPos, int length, int initStyle, - char *words[], WindowID window, char *props); -typedef void* (EXT_LEXER_DECL *GetLexerFunction)(unsigned int Index); +typedef void*(EXT_LEXER_DECL *GetLexerFunction)(unsigned int Index); typedef int (EXT_LEXER_DECL *GetLexerCountFn)(); typedef void (EXT_LEXER_DECL *GetLexerNameFn)(unsigned int Index, char *name, int buflength); - -//class DynamicLibrary; +typedef LexerFactoryFunction(EXT_LEXER_DECL *GetLexerFactoryFunction)(unsigned int Index); /// Sub-class of LexerModule to use an external lexer. -class ExternalLexerModule : protected LexerModule { +class ExternalLexerModule : public LexerModule { protected: - ExtLexerFunction fneLexer; - ExtFoldFunction fneFolder; - int externalLanguage; + GetLexerFactoryFunction fneFactory; char name[100]; public: - ExternalLexerModule(int language_, LexerFunction fnLexer_, - const char *languageName_=0, LexerFunction fnFolder_=0) : LexerModule(language_, fnLexer_, 0, fnFolder_){ + ExternalLexerModule(int language_, LexerFunction fnLexer_, + const char *languageName_=0, LexerFunction fnFolder_=0) : + LexerModule(language_, fnLexer_, 0, fnFolder_), + fneFactory(0) { strncpy(name, languageName_, sizeof(name)); name[sizeof(name)-1] = '\0'; languageName = name; - }; - virtual void Lex(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) const; - virtual void Fold(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) const; - virtual void SetExternal(ExtLexerFunction fLexer, ExtFoldFunction fFolder, int index); + } + virtual void SetExternal(GetLexerFactoryFunction fFactory, int index); }; /// LexerMinder points to an ExternalLexerModule - so we don't leak them. @@ -64,10 +54,10 @@ class LexerLibrary { LexerMinder *last; public: - LexerLibrary(const char* ModuleName); + LexerLibrary(const char *ModuleName); ~LexerLibrary(); void Release(); - + LexerLibrary *next; std::string m_sModuleName; }; @@ -76,18 +66,18 @@ public: class LexerManager { public: ~LexerManager(); - + static LexerManager *GetInstance(); static void DeleteInstance(); - - void Load(const char* path); + + void Load(const char *path); void Clear(); private: LexerManager(); static LexerManager *theInstance; - void LoadLexerLibrary(const char* module); + void LoadLexerLibrary(const char *module); LexerLibrary *first; LexerLibrary *last; }; diff --git a/src/stc/scintilla/src/FontQuality.h b/src/stc/scintilla/src/FontQuality.h index 2c8d548a86..45600c35ec 100644 --- a/src/stc/scintilla/src/FontQuality.h +++ b/src/stc/scintilla/src/FontQuality.h @@ -10,3 +10,6 @@ #define SC_EFF_QUALITY_NON_ANTIALIASED 1 #define SC_EFF_QUALITY_ANTIALIASED 2 #define SC_EFF_QUALITY_LCD_OPTIMIZED 3 + +#define SCWIN_TECH_GDI 0 +#define SCWIN_TECH_DIRECTWRITE 1 diff --git a/src/stc/scintilla/src/Indicator.cxx b/src/stc/scintilla/src/Indicator.cxx index da9531224a..9ea4024bbe 100644 --- a/src/stc/scintilla/src/Indicator.cxx +++ b/src/stc/scintilla/src/Indicator.cxx @@ -5,9 +5,13 @@ // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. +#include <vector> +#include <map> + #include "Platform.h" #include "Scintilla.h" +#include "XPM.h" #include "Indicator.h" #ifdef SCI_NAMESPACE @@ -15,7 +19,7 @@ using namespace Scintilla; #endif void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) { - surface->PenColour(fore.allocated); + surface->PenColour(fore); int ymid = (rc.bottom + rc.top) / 2; if (style == INDIC_SQUIGGLE) { surface->MoveTo(rc.left, rc.top); @@ -27,6 +31,17 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r y = 2 - y; } surface->LineTo(rc.right, rc.top + y); // Finish the line + } else if (style == INDIC_SQUIGGLELOW) { + surface->MoveTo(rc.left, rc.top); + int x = rc.left + 3; + int y = 0; + while (x < rc.right) { + surface->LineTo(x-1, rc.top + y); + y = 1 - y; + surface->LineTo(x, rc.top + y); + x += 3; + } + surface->LineTo(rc.right, rc.top + y); // Finish the line } else if (style == INDIC_TT) { surface->MoveTo(rc.left, ymid); int x = rc.left + 5; @@ -67,12 +82,47 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r surface->LineTo(rc.right, rcLine.top+1); surface->LineTo(rc.left, rcLine.top+1); surface->LineTo(rc.left, ymid+1); - } else if (style == INDIC_ROUNDBOX) { + } else if (style == INDIC_ROUNDBOX || style == INDIC_STRAIGHTBOX) { PRectangle rcBox = rcLine; rcBox.top = rcLine.top + 1; rcBox.left = rc.left; rcBox.right = rc.right; - surface->AlphaRectangle(rcBox, 1, fore.allocated, fillAlpha, fore.allocated, 50, 0); + surface->AlphaRectangle(rcBox, (style == INDIC_ROUNDBOX) ? 1 : 0, fore, fillAlpha, fore, outlineAlpha, 0); + } else if (style == INDIC_DOTBOX) { + PRectangle rcBox = rcLine; + rcBox.top = rcLine.top + 1; + rcBox.left = rc.left; + rcBox.right = rc.right; + // Cap width at 4000 to avoid large allocations when mistakes made + int width = Platform::Minimum(rcBox.Width(), 4000); + RGBAImage image(width, rcBox.Height(), 0); + // Draw horizontal lines top and bottom + for (int x=0; x<width; x++) { + for (int y=0; y<rcBox.Height(); y += rcBox.Height()-1) { + image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha); + } + } + // Draw vertical lines left and right + for (int y=1; y<rcBox.Height(); y++) { + for (int x=0; x<width; x += width-1) { + image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha); + } + } + surface->DrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels()); + } else if (style == INDIC_DASH) { + int x = rc.left; + while (x < rc.right) { + surface->MoveTo(x, ymid); + surface->LineTo(Platform::Minimum(x + 4, rc.right), ymid); + x += 7; + } + } else if (style == INDIC_DOTS) { + int x = rc.left; + while (x < rc.right) { + PRectangle rcDot(x, ymid, x+1, ymid+1); + surface->FillRectangle(rcDot, fore); + x += 2; + } } else { // Either INDIC_PLAIN or unknown surface->MoveTo(rc.left, ymid); surface->LineTo(rc.right, ymid); diff --git a/src/stc/scintilla/src/Indicator.h b/src/stc/scintilla/src/Indicator.h index 42b56f07e7..0284a855bc 100644 --- a/src/stc/scintilla/src/Indicator.h +++ b/src/stc/scintilla/src/Indicator.h @@ -18,9 +18,10 @@ class Indicator { public: int style; bool under; - ColourPair fore; + ColourDesired fore; int fillAlpha; - Indicator() : style(INDIC_PLAIN), under(false), fore(ColourDesired(0,0,0)), fillAlpha(30) { + int outlineAlpha; + Indicator() : style(INDIC_PLAIN), under(false), fore(ColourDesired(0,0,0)), fillAlpha(30), outlineAlpha(50) { } void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine); }; diff --git a/src/stc/scintilla/src/KeyMap.cxx b/src/stc/scintilla/src/KeyMap.cxx index c223d5b59a..4d866d195b 100644 --- a/src/stc/scintilla/src/KeyMap.cxx +++ b/src/stc/scintilla/src/KeyMap.cxx @@ -66,14 +66,42 @@ unsigned int KeyMap::Find(int key, int modifiers) { return 0; } +#if PLAT_GTK_MACOSX +#define OS_X_KEYS 1 +#else +#define OS_X_KEYS 0 +#endif + +// Define a modifier that is exactly Ctrl key on all platforms +// Most uses of Ctrl map to Cmd on OS X but some can't so use SCI_[S]CTRL_META +#if OS_X_KEYS +#define SCI_CTRL_META SCI_META +#define SCI_SCTRL_META (SCI_META | SCI_SHIFT) +#else +#define SCI_CTRL_META SCI_CTRL +#define SCI_SCTRL_META (SCI_CTRL | SCI_SHIFT) +#endif + const KeyToCommand KeyMap::MapDefault[] = { + +#if OS_X_KEYS + {SCK_DOWN, SCI_CTRL, SCI_DOCUMENTEND}, + {SCK_DOWN, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND}, + {SCK_UP, SCI_CTRL, SCI_DOCUMENTSTART}, + {SCK_UP, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND}, + {SCK_LEFT, SCI_CTRL, SCI_VCHOME}, + {SCK_LEFT, SCI_CSHIFT, SCI_VCHOMEEXTEND}, + {SCK_RIGHT, SCI_CTRL, SCI_LINEEND}, + {SCK_RIGHT, SCI_CSHIFT, SCI_LINEENDEXTEND}, +#endif + {SCK_DOWN, SCI_NORM, SCI_LINEDOWN}, {SCK_DOWN, SCI_SHIFT, SCI_LINEDOWNEXTEND}, - {SCK_DOWN, SCI_CTRL, SCI_LINESCROLLDOWN}, + {SCK_DOWN, SCI_CTRL_META, SCI_LINESCROLLDOWN}, {SCK_DOWN, SCI_ASHIFT, SCI_LINEDOWNRECTEXTEND}, {SCK_UP, SCI_NORM, SCI_LINEUP}, {SCK_UP, SCI_SHIFT, SCI_LINEUPEXTEND}, - {SCK_UP, SCI_CTRL, SCI_LINESCROLLUP}, + {SCK_UP, SCI_CTRL_META, SCI_LINESCROLLUP}, {SCK_UP, SCI_ASHIFT, SCI_LINEUPRECTEXTEND}, {'[', SCI_CTRL, SCI_PARAUP}, {'[', SCI_CSHIFT, SCI_PARAUPEXTEND}, @@ -81,13 +109,13 @@ const KeyToCommand KeyMap::MapDefault[] = { {']', SCI_CSHIFT, SCI_PARADOWNEXTEND}, {SCK_LEFT, SCI_NORM, SCI_CHARLEFT}, {SCK_LEFT, SCI_SHIFT, SCI_CHARLEFTEXTEND}, - {SCK_LEFT, SCI_CTRL, SCI_WORDLEFT}, - {SCK_LEFT, SCI_CSHIFT, SCI_WORDLEFTEXTEND}, + {SCK_LEFT, SCI_CTRL_META, SCI_WORDLEFT}, + {SCK_LEFT, SCI_SCTRL_META, SCI_WORDLEFTEXTEND}, {SCK_LEFT, SCI_ASHIFT, SCI_CHARLEFTRECTEXTEND}, {SCK_RIGHT, SCI_NORM, SCI_CHARRIGHT}, {SCK_RIGHT, SCI_SHIFT, SCI_CHARRIGHTEXTEND}, - {SCK_RIGHT, SCI_CTRL, SCI_WORDRIGHT}, - {SCK_RIGHT, SCI_CSHIFT, SCI_WORDRIGHTEXTEND}, + {SCK_RIGHT, SCI_CTRL_META, SCI_WORDRIGHT}, + {SCK_RIGHT, SCI_SCTRL_META, SCI_WORDRIGHTEXTEND}, {SCK_RIGHT, SCI_ASHIFT, SCI_CHARRIGHTRECTEXTEND}, {'/', SCI_CTRL, SCI_WORDPARTLEFT}, {'/', SCI_CSHIFT, SCI_WORDPARTLEFTEXTEND}, @@ -98,14 +126,12 @@ const KeyToCommand KeyMap::MapDefault[] = { {SCK_HOME, SCI_CTRL, SCI_DOCUMENTSTART}, {SCK_HOME, SCI_CSHIFT, SCI_DOCUMENTSTARTEXTEND}, {SCK_HOME, SCI_ALT, SCI_HOMEDISPLAY}, -// {SCK_HOME, SCI_ASHIFT, SCI_HOMEDISPLAYEXTEND}, {SCK_HOME, SCI_ASHIFT, SCI_VCHOMERECTEXTEND}, {SCK_END, SCI_NORM, SCI_LINEEND}, {SCK_END, SCI_SHIFT, SCI_LINEENDEXTEND}, {SCK_END, SCI_CTRL, SCI_DOCUMENTEND}, {SCK_END, SCI_CSHIFT, SCI_DOCUMENTENDEXTEND}, {SCK_END, SCI_ALT, SCI_LINEENDDISPLAY}, -// {SCK_END, SCI_ASHIFT, SCI_LINEENDDISPLAYEXTEND}, {SCK_END, SCI_ASHIFT, SCI_LINEENDRECTEXTEND}, {SCK_PRIOR, SCI_NORM, SCI_PAGEUP}, {SCK_PRIOR, SCI_SHIFT, SCI_PAGEUPEXTEND}, @@ -127,7 +153,11 @@ const KeyToCommand KeyMap::MapDefault[] = { {SCK_BACK, SCI_ALT, SCI_UNDO}, {SCK_BACK, SCI_CSHIFT, SCI_DELLINELEFT}, {'Z', SCI_CTRL, SCI_UNDO}, +#if OS_X_KEYS + {'Z', SCI_CSHIFT, SCI_REDO}, +#else {'Y', SCI_CTRL, SCI_REDO}, +#endif {'X', SCI_CTRL, SCI_CUT}, {'C', SCI_CTRL, SCI_COPY}, {'V', SCI_CTRL, SCI_PASTE}, @@ -139,7 +169,6 @@ const KeyToCommand KeyMap::MapDefault[] = { {SCK_ADD, SCI_CTRL, SCI_ZOOMIN}, {SCK_SUBTRACT, SCI_CTRL, SCI_ZOOMOUT}, {SCK_DIVIDE, SCI_CTRL, SCI_SETZOOM}, - //'L', SCI_CTRL, SCI_FORMFEED, {'L', SCI_CTRL, SCI_LINECUT}, {'L', SCI_CSHIFT, SCI_LINEDELETE}, {'T', SCI_CSHIFT, SCI_LINECOPY}, diff --git a/src/stc/scintilla/src/KeyMap.h b/src/stc/scintilla/src/KeyMap.h index fd9005de84..f1235d8457 100644 --- a/src/stc/scintilla/src/KeyMap.h +++ b/src/stc/scintilla/src/KeyMap.h @@ -16,6 +16,7 @@ namespace Scintilla { #define SCI_SHIFT SCMOD_SHIFT #define SCI_CTRL SCMOD_CTRL #define SCI_ALT SCMOD_ALT +#define SCI_META SCMOD_META #define SCI_CSHIFT (SCI_CTRL | SCI_SHIFT) #define SCI_ASHIFT (SCI_ALT | SCI_SHIFT) diff --git a/src/stc/scintilla/src/KeyWords.cxx b/src/stc/scintilla/src/KeyWords.cxx deleted file mode 100644 index 5e4de668d0..0000000000 --- a/src/stc/scintilla/src/KeyWords.cxx +++ /dev/null @@ -1,429 +0,0 @@ -// Scintilla source code edit control -/** @file KeyWords.cxx - ** Colourise for particular languages. - **/ -// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include <stdarg.h> - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -/** - * Creates an array that points into each word in the string and puts \0 terminators - * after each word. - */ -static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = false) { - int prev = '\n'; - int words = 0; - // For rapid determination of whether a character is a separator, build - // a look up table. - bool wordSeparator[256]; - for (int i=0;i<256; i++) { - wordSeparator[i] = false; - } - wordSeparator['\r'] = true; - wordSeparator['\n'] = true; - if (!onlyLineEnds) { - wordSeparator[' '] = true; - wordSeparator['\t'] = true; - } - for (int j = 0; wordlist[j]; j++) { - int curr = static_cast<unsigned char>(wordlist[j]); - if (!wordSeparator[curr] && wordSeparator[prev]) - words++; - prev = curr; - } - char **keywords = new char *[words + 1]; - if (keywords) { - words = 0; - prev = '\0'; - size_t slen = strlen(wordlist); - for (size_t k = 0; k < slen; k++) { - if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) { - if (!prev) { - keywords[words] = &wordlist[k]; - words++; - } - } else { - wordlist[k] = '\0'; - } - prev = wordlist[k]; - } - keywords[words] = &wordlist[slen]; - *len = words; - } else { - *len = 0; - } - return keywords; -} - -void WordList::Clear() { - if (words) { - delete []list; - delete []words; - } - words = 0; - list = 0; - len = 0; - sorted = false; -} - -void WordList::Set(const char *s) { - list = new char[strlen(s) + 1]; - strcpy(list, s); - sorted = false; - words = ArrayFromWordList(list, &len, onlyLineEnds); -} - -extern "C" int cmpString(const void *a1, const void *a2) { - // Can't work out the correct incantation to use modern casts here - return strcmp(*(char**)(a1), *(char**)(a2)); -} - -static void SortWordList(char **words, unsigned int len) { - qsort(reinterpret_cast<void*>(words), len, sizeof(*words), - cmpString); -} - -bool WordList::InList(const char *s) { - if (0 == words) - return false; - if (!sorted) { - sorted = true; - SortWordList(words, len); - for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++) - starts[k] = -1; - for (int l = len - 1; l >= 0; l--) { - unsigned char indexChar = words[l][0]; - starts[indexChar] = l; - } - } - unsigned char firstChar = s[0]; - int j = starts[firstChar]; - if (j >= 0) { - while ((unsigned char)words[j][0] == firstChar) { - if (s[1] == words[j][1]) { - const char *a = words[j] + 1; - const char *b = s + 1; - while (*a && *a == *b) { - a++; - b++; - } - if (!*a && !*b) - return true; - } - j++; - } - } - j = starts['^']; - if (j >= 0) { - while (words[j][0] == '^') { - const char *a = words[j] + 1; - const char *b = s; - while (*a && *a == *b) { - a++; - b++; - } - if (!*a) - return true; - j++; - } - } - return false; -} - -/** similar to InList, but word s can be a substring of keyword. - * eg. the keyword define is defined as def~ine. This means the word must start - * with def to be a keyword, but also defi, defin and define are valid. - * The marker is ~ in this case. - */ -bool WordList::InListAbbreviated(const char *s, const char marker) { - if (0 == words) - return false; - if (!sorted) { - sorted = true; - SortWordList(words, len); - for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++) - starts[k] = -1; - for (int l = len - 1; l >= 0; l--) { - unsigned char indexChar = words[l][0]; - starts[indexChar] = l; - } - } - unsigned char firstChar = s[0]; - int j = starts[firstChar]; - if (j >= 0) { - while (words[j][0] == firstChar) { - bool isSubword = false; - int start = 1; - if (words[j][1] == marker) { - isSubword = true; - start++; - } - if (s[1] == words[j][start]) { - const char *a = words[j] + start; - const char *b = s + 1; - while (*a && *a == *b) { - a++; - if (*a == marker) { - isSubword = true; - a++; - } - b++; - } - if ((!*a || isSubword) && !*b) - return true; - } - j++; - } - } - j = starts['^']; - if (j >= 0) { - while (words[j][0] == '^') { - const char *a = words[j] + 1; - const char *b = s; - while (*a && *a == *b) { - a++; - b++; - } - if (!*a) - return true; - j++; - } - } - return false; -} - -const LexerModule *LexerModule::base = 0; -int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1; - -LexerModule::LexerModule(int language_, - LexerFunction fnLexer_, - const char *languageName_, - LexerFunction fnFolder_, - const char * const wordListDescriptions_[], - int styleBits_) : - language(language_), - fnLexer(fnLexer_), - fnFolder(fnFolder_), - wordListDescriptions(wordListDescriptions_), - styleBits(styleBits_), - languageName(languageName_) { - next = base; - base = this; - if (language == SCLEX_AUTOMATIC) { - language = nextLanguage; - nextLanguage++; - } -} - -int LexerModule::GetNumWordLists() const { - if (wordListDescriptions == NULL) { - return -1; - } else { - int numWordLists = 0; - - while (wordListDescriptions[numWordLists]) { - ++numWordLists; - } - - return numWordLists; - } -} - -const char *LexerModule::GetWordListDescription(int index) const { - static const char *emptyStr = ""; - - PLATFORM_ASSERT(index < GetNumWordLists()); - if (index >= GetNumWordLists()) { - return emptyStr; - } else { - return wordListDescriptions[index]; - } -} - -int LexerModule::GetStyleBitsNeeded() const { - return styleBits; -} - -const LexerModule *LexerModule::Find(int language) { - const LexerModule *lm = base; - while (lm) { - if (lm->language == language) { - return lm; - } - lm = lm->next; - } - return 0; -} - -const LexerModule *LexerModule::Find(const char *languageName) { - if (languageName) { - const LexerModule *lm = base; - while (lm) { - if (lm->languageName && 0 == strcmp(lm->languageName, languageName)) { - return lm; - } - lm = lm->next; - } - } - return 0; -} - -void LexerModule::Lex(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) const { - if (fnLexer) - fnLexer(startPos, lengthDoc, initStyle, keywordlists, styler); -} - -void LexerModule::Fold(unsigned int startPos, int lengthDoc, int initStyle, - WordList *keywordlists[], Accessor &styler) const { - if (fnFolder) { - int lineCurrent = styler.GetLine(startPos); - // Move back one line in case deletion wrecked current line fold state - if (lineCurrent > 0) { - lineCurrent--; - int newStartPos = styler.LineStart(lineCurrent); - lengthDoc += startPos - newStartPos; - startPos = newStartPos; - initStyle = 0; - if (startPos > 0) { - initStyle = styler.StyleAt(startPos - 1); - } - } - fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler); - } -} - -// Alternative historical name for Scintilla_LinkLexers -int wxForceScintillaLexers(void) { - return Scintilla_LinkLexers(); -} - -// To add or remove a lexer, add or remove its file and run LexGen.py. - -// Force a reference to all of the Scintilla lexers so that the linker will -// not remove the code of the lexers. -int Scintilla_LinkLexers() { - static int forcer = 0; - -// Shorten the code that declares a lexer and ensures it is linked in by calling a method. -#define LINK_LEXER(lexer) extern LexerModule lexer; forcer += lexer.GetLanguage(); - -//++Autogenerated -- run src/LexGen.py to regenerate -//**\(\tLINK_LEXER(\*);\n\) - LINK_LEXER(lmAbaqus); - LINK_LEXER(lmAda); - LINK_LEXER(lmAns1); - LINK_LEXER(lmAPDL); - LINK_LEXER(lmAsm); - LINK_LEXER(lmASY); - LINK_LEXER(lmAU3); - LINK_LEXER(lmAVE); - LINK_LEXER(lmBaan); - LINK_LEXER(lmBash); - LINK_LEXER(lmBatch); - LINK_LEXER(lmBlitzBasic); - LINK_LEXER(lmBullant); - LINK_LEXER(lmCaml); - LINK_LEXER(lmClw); - LINK_LEXER(lmClwNoCase); - LINK_LEXER(lmCmake); - LINK_LEXER(lmCOBOL); - LINK_LEXER(lmConf); - LINK_LEXER(lmCPP); - LINK_LEXER(lmCPPNoCase); - LINK_LEXER(lmCsound); - LINK_LEXER(lmCss); - LINK_LEXER(lmD); - LINK_LEXER(lmDiff); - LINK_LEXER(lmEiffel); - LINK_LEXER(lmEiffelkw); - LINK_LEXER(lmErlang); - LINK_LEXER(lmErrorList); - LINK_LEXER(lmESCRIPT); - LINK_LEXER(lmF77); - LINK_LEXER(lmFlagShip); - LINK_LEXER(lmForth); - LINK_LEXER(lmFortran); - LINK_LEXER(lmFreeBasic); - LINK_LEXER(lmGAP); - LINK_LEXER(lmGui4Cli); - LINK_LEXER(lmHaskell); - LINK_LEXER(lmHTML); - LINK_LEXER(lmInno); - LINK_LEXER(lmKix); - LINK_LEXER(lmLatex); - LINK_LEXER(lmLISP); - LINK_LEXER(lmLot); - LINK_LEXER(lmLout); - LINK_LEXER(lmLua); - LINK_LEXER(lmMagikSF); - LINK_LEXER(lmMake); - LINK_LEXER(lmMarkdown); - LINK_LEXER(lmMatlab); - LINK_LEXER(lmMETAPOST); - LINK_LEXER(lmMMIXAL); - LINK_LEXER(lmMSSQL); - LINK_LEXER(lmMySQL); - LINK_LEXER(lmNimrod); - LINK_LEXER(lmNncrontab); - LINK_LEXER(lmNsis); - LINK_LEXER(lmNull); - LINK_LEXER(lmOctave); - LINK_LEXER(lmOpal); - LINK_LEXER(lmPascal); - LINK_LEXER(lmPB); - LINK_LEXER(lmPerl); - LINK_LEXER(lmPHPSCRIPT); - LINK_LEXER(lmPLM); - LINK_LEXER(lmPo); - LINK_LEXER(lmPOV); - LINK_LEXER(lmPowerPro); - LINK_LEXER(lmPowerShell); - LINK_LEXER(lmProgress); - LINK_LEXER(lmProps); - LINK_LEXER(lmPS); - LINK_LEXER(lmPureBasic); - LINK_LEXER(lmPython); - LINK_LEXER(lmR); - LINK_LEXER(lmREBOL); - LINK_LEXER(lmRuby); - LINK_LEXER(lmScriptol); - LINK_LEXER(lmSmalltalk); - LINK_LEXER(lmSML); - LINK_LEXER(lmSorc); - LINK_LEXER(lmSpecman); - LINK_LEXER(lmSpice); - LINK_LEXER(lmSQL); - LINK_LEXER(lmTACL); - LINK_LEXER(lmTADS3); - LINK_LEXER(lmTAL); - LINK_LEXER(lmTCL); - LINK_LEXER(lmTeX); - LINK_LEXER(lmVB); - LINK_LEXER(lmVBScript); - LINK_LEXER(lmVerilog); - LINK_LEXER(lmVHDL); - LINK_LEXER(lmXML); - LINK_LEXER(lmYAML); - -//--Autogenerated -- end of automatically generated section - - return 1; -} diff --git a/src/stc/scintilla/src/LexAsm.cxx b/src/stc/scintilla/src/LexAsm.cxx deleted file mode 100644 index 17c938420a..0000000000 --- a/src/stc/scintilla/src/LexAsm.cxx +++ /dev/null @@ -1,180 +0,0 @@ -// Scintilla source code edit control -/** @file LexAsm.cxx - ** Lexer for Assembler, just for the MASM syntax - ** Written by The Black Horus - ** Enhancements and NASM stuff by Kein-Hong Man, 2003-10 - ** SCE_ASM_COMMENTBLOCK and SCE_ASM_CHARACTER are for future GNU as colouring - **/ -// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include <stdarg.h> - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || - ch == '_' || ch == '?'); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' || - ch == '%' || ch == '@' || ch == '$' || ch == '?'); -} - -static inline bool IsAsmOperator(const int ch) { - if ((ch < 0x80) && (isalnum(ch))) - return false; - // '.' left out as it is used to make up numbers - if (ch == '*' || ch == '/' || ch == '-' || ch == '+' || - ch == '(' || ch == ')' || ch == '=' || ch == '^' || - ch == '[' || ch == ']' || ch == '<' || ch == '&' || - ch == '>' || ch == ',' || ch == '|' || ch == '~' || - ch == '%' || ch == ':') - return true; - return false; -} - -static void ColouriseAsmDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &cpuInstruction = *keywordlists[0]; - WordList &mathInstruction = *keywordlists[1]; - WordList ®isters = *keywordlists[2]; - WordList &directive = *keywordlists[3]; - WordList &directiveOperand = *keywordlists[4]; - WordList &extInstruction = *keywordlists[5]; - - // Do not leak onto next line - if (initStyle == SCE_ASM_STRINGEOL) - initStyle = SCE_ASM_DEFAULT; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) - { - - // Prevent SCE_ASM_STRINGEOL from leaking back to previous line - if (sc.atLineStart && (sc.state == SCE_ASM_STRING)) { - sc.SetState(SCE_ASM_STRING); - } else if (sc.atLineStart && (sc.state == SCE_ASM_CHARACTER)) { - sc.SetState(SCE_ASM_CHARACTER); - } - - // Handle line continuation generically. - if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { - sc.Forward(); - if (sc.ch == '\r' && sc.chNext == '\n') { - sc.Forward(); - } - continue; - } - } - - // Determine if the current state should terminate. - if (sc.state == SCE_ASM_OPERATOR) { - if (!IsAsmOperator(sc.ch)) { - sc.SetState(SCE_ASM_DEFAULT); - } - }else if (sc.state == SCE_ASM_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_IDENTIFIER) { - if (!IsAWordChar(sc.ch) ) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - - if (cpuInstruction.InList(s)) { - sc.ChangeState(SCE_ASM_CPUINSTRUCTION); - } else if (mathInstruction.InList(s)) { - sc.ChangeState(SCE_ASM_MATHINSTRUCTION); - } else if (registers.InList(s)) { - sc.ChangeState(SCE_ASM_REGISTER); - } else if (directive.InList(s)) { - sc.ChangeState(SCE_ASM_DIRECTIVE); - } else if (directiveOperand.InList(s)) { - sc.ChangeState(SCE_ASM_DIRECTIVEOPERAND); - } else if (extInstruction.InList(s)) { - sc.ChangeState(SCE_ASM_EXTINSTRUCTION); - } - sc.SetState(SCE_ASM_DEFAULT); - } - } - else if (sc.state == SCE_ASM_COMMENT ) { - if (sc.atLineEnd) { - sc.SetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_ASM_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_ASM_STRINGEOL); - sc.ForwardSetState(SCE_ASM_DEFAULT); - } - } else if (sc.state == SCE_ASM_CHARACTER) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { - sc.Forward(); - } - } else if (sc.ch == '\'') { - sc.ForwardSetState(SCE_ASM_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_ASM_STRINGEOL); - sc.ForwardSetState(SCE_ASM_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_ASM_DEFAULT) { - if (sc.ch == ';'){ - sc.SetState(SCE_ASM_COMMENT); - } else if (isascii(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && isascii(sc.chNext) && isdigit(sc.chNext)))) { - sc.SetState(SCE_ASM_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_ASM_IDENTIFIER); - } else if (sc.ch == '\"') { - sc.SetState(SCE_ASM_STRING); - } else if (sc.ch == '\'') { - sc.SetState(SCE_ASM_CHARACTER); - } else if (IsAsmOperator(sc.ch)) { - sc.SetState(SCE_ASM_OPERATOR); - } - } - - } - sc.Complete(); -} - -static const char * const asmWordListDesc[] = { - "CPU instructions", - "FPU instructions", - "Registers", - "Directives", - "Directive operands", - "Extended instructions", - 0 -}; - -LexerModule lmAsm(SCLEX_ASM, ColouriseAsmDoc, "asm", 0, asmWordListDesc); - diff --git a/src/stc/scintilla/src/LexFlagship.cxx b/src/stc/scintilla/src/LexFlagship.cxx deleted file mode 100644 index baf2941a84..0000000000 --- a/src/stc/scintilla/src/LexFlagship.cxx +++ /dev/null @@ -1,230 +0,0 @@ -// Scintilla source code edit control -/** @file LexFlagShip.cxx - ** Lexer for FlagShip - ** (Syntactically compatible to other XBase dialects, like dBase, Clipper, Fox etc.) - **/ -// Copyright 2005 by Randy Butler -// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include <stdarg.h> - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static bool IsFlagShipComment(Accessor &styler, int pos, int len) { - return len>0 && styler[pos]=='\''; -} - -static inline bool IsTypeCharacter(int ch) { - return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$'; -} - -// Extended to accept accented characters -static inline bool IsAWordChar(int ch) { - return ch >= 0x80 || - (isalnum(ch) || ch == '.' || ch == '_'); -} - -static inline bool IsAWordStart(int ch) { - return ch >= 0x80 || - (isalnum(ch) || ch == '_'); -} - -static inline bool IsADateCharacter(const int ch) { - return (ch < 0x80) && - (isalnum(ch) || ch == '|' || ch == '-' || ch == '/' || ch == ':' || ch == ' ' || ch == '\t'); -} - - -static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - //bool FSScriptSyntax = true; - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; - - styler.StartAt(startPos); - - int visibleChars = 0; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - if (sc.state == SCE_FS_OPERATOR) { - sc.SetState(SCE_FS_DEFAULT); - } else if (sc.state == SCE_FS_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_FS_KEYWORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_FS_KEYWORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_FS_KEYWORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_FS_KEYWORD4); - }// Else, it is really an identifier... - sc.SetState(SCE_FS_DEFAULT); - } - } else if (sc.state == SCE_FS_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_FS_DEFAULT); - } - } else if (sc.state == SCE_FS_STRING) { - // VB doubles quotes to preserve them, so just end this string - // state now as a following quote will start again - if (sc.ch == '\"') { - if (tolower(sc.chNext) == 'c') { - sc.Forward(); - } - sc.ForwardSetState(SCE_FS_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_FS_STRINGEOL); - sc.ForwardSetState(SCE_FS_DEFAULT); - } - } else if (sc.state == SCE_FS_COMMENT) { - if (sc.Match('*', '/')) { // new code - sc.Forward(); - sc.ForwardSetState(SCE_FS_DEFAULT); - //if (sc.atLineEnd) { // old code - // sc.SetState(SCE_FS_DEFAULT); - } - } else if (sc.state == SCE_FS_COMMENTLINE) { //new code - if (sc.ch == '\r' || sc.ch == '\n') { - sc.SetState(SCE_FS_DEFAULT); - visibleChars = 0; - } - } else if (sc.state == SCE_FS_PREPROCESSOR) { - if (sc.atLineEnd) { - sc.SetState(SCE_FS_DEFAULT); - } - } else if (sc.state == SCE_FS_DATE) { - if (sc.ch == '#' || !IsADateCharacter(sc.chNext)) { - sc.ForwardSetState(SCE_FS_DEFAULT); - } - } - - // Determine if a new state should be entered. - if (sc.state == SCE_FS_DEFAULT) { - if (sc.Match('/', '*')) { // New code - sc.SetState(SCE_FS_COMMENT); - sc.Forward(); // Eat the * so it isn't used for the end of the comment - //if (sc.ch == '\'') { // Old code - // sc.SetState(SCE_FS_COMMENT); // old code - } else if (sc.Match('/', '/')) { // New code - sc.SetState(SCE_FS_COMMENTLINE); - } else if (sc.ch == '\"') { - sc.SetState(SCE_FS_STRING); - } else if (sc.ch == '#' && visibleChars == 0) { - // Preprocessor commands are alone on their line - sc.SetState(SCE_FS_PREPROCESSOR); - } else if (sc.ch == '#') { - int n = 1; - int chSeek = ' '; - while ((n < 100) && (chSeek == ' ' || chSeek == '\t')) { - chSeek = sc.GetRelative(n); - n++; - } - if (IsADigit(chSeek)) { - sc.SetState(SCE_FS_DATE); - } else { - sc.SetState(SCE_FS_OPERATOR); - } - } else if (sc.ch == '&' && tolower(sc.chNext) == 'h') { - sc.SetState(SCE_FS_NUMBER); - } else if (sc.ch == '&' && tolower(sc.chNext) == 'o') { - sc.SetState(SCE_FS_NUMBER); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_FS_NUMBER); - } else if (IsAWordStart(sc.ch) || (sc.ch == '[')) { - sc.SetState(SCE_FS_IDENTIFIER); - } else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) { - sc.SetState(SCE_FS_OPERATOR); - } - } - - if (sc.atLineEnd) { - visibleChars = 0; - } - if (!IsASpace(sc.ch)) { - visibleChars++; - } - } - sc.Complete(); -} - -static void FoldFlagShipDoc(unsigned int startPos, int length, int, - WordList *[], Accessor &styler) { - - int endPos = startPos + length; - - // Backtrack to previous line in case need to fix its fold status - int lineCurrent = styler.GetLine(startPos); - if (startPos > 0) { - if (lineCurrent > 0) { - lineCurrent--; - startPos = styler.LineStart(lineCurrent); - } - } - int spaceFlags = 0; - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsFlagShipComment); - char chNext = styler[startPos]; - for (int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - - if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) { - int lev = indentCurrent; - int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsFlagShipComment); - if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) { - // Only non whitespace lines can be headers - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } else if (indentNext & SC_FOLDLEVELWHITEFLAG) { - // Line after is blank so check the next - maybe should continue further? - int spaceFlags2 = 0; - int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsFlagShipComment); - if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) { - lev |= SC_FOLDLEVELHEADERFLAG; - } - } - } - indentCurrent = indentNext; - styler.SetLevel(lineCurrent, lev); - lineCurrent++; - } - } -} - - -static const char * const FSWordListDesc[] = { - "Keywords", - "functions", - "user2", - "user3", - 0 -}; - -LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc); - - - diff --git a/src/stc/scintilla/src/LexGen.py b/src/stc/scintilla/src/LexGen.py old mode 100644 new mode 100755 index 571332e6e3..d03c4a24a5 --- a/src/stc/scintilla/src/LexGen.py +++ b/src/stc/scintilla/src/LexGen.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python # LexGen.py - implemented 2002 by Neil Hodgson neilh@scintilla.org # Released to the public domain. @@ -164,6 +165,8 @@ def FindModules(lexFile): modules.append(l.split()[1]) return modules +# Properties that start with lexer. or fold. are automatically found but there are some +# older properties that don't follow this pattern so must be explicitly listed. knownIrregularProperties = [ "fold", "styling.within.preprocessor", @@ -181,7 +184,7 @@ def FindProperties(lexFile): properties = {} f = open(lexFile) for l in f.readlines(): - if "GetProperty" in l: + if ("GetProperty" in l or "DefineProperty" in l) and "\"" in l: l = l.strip() if not l.startswith("//"): # Drop comments propertyName = l.split("\"")[1] @@ -205,13 +208,33 @@ def FindPropertyDocumentation(lexFile): # Only allow lower case property names name = propertyName documents[name] = "" + elif "DefineProperty" in l and "\"" in l: + propertyName = l.split("\"")[1] + if propertyName.lower() == propertyName: + # Only allow lower case property names + name = propertyName + documents[name] = "" elif name: if l.startswith("//"): if documents[name]: documents[name] += " " documents[name] += l[2:].strip() + elif l.startswith("\""): + l = l[1:].strip() + if l.endswith(";"): + l = l[:-1].strip() + if l.endswith(")"): + l = l[:-1].strip() + if l.endswith("\""): + l = l[:-1] + # Fix escaped double quotes + l = l.replace("\\\"", "\"") + documents[name] += l else: name = "" + for name in list(documents.keys()): + if documents[name] == "": + del documents[name] return documents def ciCompare(a,b): @@ -219,18 +242,63 @@ def ciCompare(a,b): def ciKey(a): return a.lower() - + def sortListInsensitive(l): try: # Try key function l.sort(key=ciKey) except TypeError: # Earlier version of Python, so use comparison function l.sort(ciCompare) +def UpdateLineInFile(path, linePrefix, lineReplace): + lines = [] + with open(path, "r") as f: + for l in f.readlines(): + l = l.rstrip() + if l.startswith(linePrefix): + lines.append(lineReplace) + else: + lines.append(l) + contents = NATIVE.join(lines) + NATIVE + UpdateFile(path, contents) + +def UpdateVersionNumbers(root): + with open(root + "scintilla/version.txt") as f: + version = f.read() + versionDotted = version[0] + '.' + version[1] + '.' + version[2] + versionCommad = version[0] + ', ' + version[1] + ', ' + version[2] + ', 0' + + UpdateLineInFile(root + "scintilla/win32/ScintRes.rc", "#define VERSION_SCINTILLA", + "#define VERSION_SCINTILLA \"" + versionDotted + "\"") + UpdateLineInFile(root + "scintilla/win32/ScintRes.rc", "#define VERSION_WORDS", + "#define VERSION_WORDS " + versionCommad) + UpdateLineInFile(root + "scintilla/qt/ScintillaEditBase/ScintillaEditBase.pro", + "VERSION =", + "VERSION = " + versionDotted) + UpdateLineInFile(root + "scintilla/qt/ScintillaEdit/ScintillaEdit.pro", + "VERSION =", + "VERSION = " + versionDotted) + UpdateLineInFile(root + "scintilla/doc/ScintillaDownload.html", " Release", + " Release " + versionDotted) + UpdateLineInFile(root + "scintilla/doc/index.html", + ' <font color="#FFCC99" size="3"> Release version', + ' <font color="#FFCC99" size="3"> Release version ' + versionDotted + '<br />') + + if os.path.exists(root + "scite"): + UpdateLineInFile(root + "scite/src/SciTE.h", "#define VERSION_SCITE", + "#define VERSION_SCITE \"" + versionDotted + "\"") + UpdateLineInFile(root + "scite/src/SciTE.h", "#define VERSION_WORDS", + "#define VERSION_WORDS " + versionCommad) + UpdateLineInFile(root + "scite/doc/SciTEDownload.html", " Release", + " Release " + versionDotted) + UpdateLineInFile(root + "scite/doc/SciTE.html", + ' <font color="#FFCC99" size="3"> Release version', + ' <font color="#FFCC99" size="3"> Release version ' + versionDotted + '<br />') + def RegenerateAll(): root="../../" # Find all the lexer source code files - lexFilePaths = glob.glob(root + "scintilla/src/Lex*.cxx") + lexFilePaths = glob.glob(root + "scintilla/lexers/Lex*.cxx") sortListInsensitive(lexFilePaths) lexFiles = [os.path.basename(f)[:-4] for f in lexFilePaths] print(lexFiles) @@ -245,7 +313,6 @@ def RegenerateAll(): for k in documents.keys(): propertyDocuments[k] = documents[k] sortListInsensitive(lexerModules) - del lexerProperties["fold.comment.python"] lexerProperties = list(lexerProperties.keys()) sortListInsensitive(lexerProperties) @@ -255,9 +322,9 @@ def RegenerateAll(): sortListInsensitive(documentProperties) propertiesHTML = [] for k in documentProperties: - propertiesHTML.append("\t<tr>\n\t<td>%s</td>\n\t<td>%s</td>\n\t</tr>" % - (k, propertyDocuments[k])) - + propertiesHTML.append("\t<tr id='property-%s'>\n\t<td>%s</td>\n\t<td>%s</td>\n\t</tr>" % + (k, k, propertyDocuments[k])) + # Find all the SciTE properties files otherProps = ["abbrev.properties", "Embedded.properties", "SciTEGlobal.properties", "SciTE.properties"] if os.path.exists(root + "scite"): @@ -267,22 +334,17 @@ def RegenerateAll(): sortListInsensitive(propFiles) print(propFiles) - Regenerate(root + "scintilla/src/KeyWords.cxx", "//", NATIVE, lexerModules) - Regenerate(root + "scintilla/win32/makefile", "#", NATIVE, lexFiles) + Regenerate(root + "scintilla/src/Catalogue.cxx", "//", NATIVE, lexerModules) Regenerate(root + "scintilla/win32/scintilla.mak", "#", NATIVE, lexFiles) Regenerate(root + "scintilla/win32/scintilla_vc6.mak", "#", NATIVE, lexFiles) - # Use Unix EOLs for gtk Makefiles so they work for Linux users when - # extracted from the Scintilla source ZIP (typically created on - # Windows). - Regenerate(root + "scintilla/gtk/makefile", "#", LF, lexFiles) - Regenerate(root + "scintilla/gtk/scintilla.mak", "#", NATIVE, lexFiles) - Regenerate(root + "scintilla/macosx/makefile", "#", LF, lexFiles) if os.path.exists(root + "scite"): - Regenerate(root + "scite/win32/makefile", "#", NATIVE, lexFiles, propFiles) - Regenerate(root + "scite/win32/scite.mak", "#", NATIVE, lexFiles, propFiles) + Regenerate(root + "scite/win32/makefile", "#", NATIVE, propFiles) + Regenerate(root + "scite/win32/scite.mak", "#", NATIVE, propFiles) Regenerate(root + "scite/src/SciTEProps.cxx", "//", NATIVE, lexerProperties) Regenerate(root + "scite/doc/SciTEDoc.html", "<!--", NATIVE, propertiesHTML) Generate(root + "scite/boundscheck/vcproj.gen", root + "scite/boundscheck/SciTE.vcproj", "#", NATIVE, lexFiles) + UpdateVersionNumbers(root) + RegenerateAll() diff --git a/src/stc/scintilla/src/LexHaskell.cxx b/src/stc/scintilla/src/LexHaskell.cxx deleted file mode 100644 index b528f3f0e3..0000000000 --- a/src/stc/scintilla/src/LexHaskell.cxx +++ /dev/null @@ -1,275 +0,0 @@ -/****************************************************************** - * LexHaskell.cxx - * - * A haskell lexer for the scintilla code control. - * Some stuff "lended" from LexPython.cxx and LexCPP.cxx. - * External lexer stuff inspired from the caml external lexer. - * - * Written by Tobias Engvall - tumm at dtek dot chalmers dot se - * - * - * TODO: - * * Implement a folder :) - * * Nice Character-lexing (stuff inside '\''), LexPython has - * this. - * - * - *****************************************************************/ - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include <stdarg.h> - -#include "Platform.h" - -#include "PropSet.h" -#include "PropSetSimple.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -#ifdef BUILD_AS_EXTERNAL_LEXER - -#include "ExternalLexer.h" -#include "WindowAccessor.h" - -#define BUILD_EXTERNAL_LEXER 0 - -#endif - -// Max level of nested comments -#define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3 - - -enum kwType { kwOther, kwClass, kwData, kwInstance, kwImport, kwModule, kwType}; - -static inline bool IsNewline(const int ch) { - return (ch == '\n' || ch == '\r'); -} - -static inline bool IsWhitespace(const int ch) { - return ( ch == ' ' - || ch == '\t' - || IsNewline(ch) ); -} - -static inline bool IsAWordStart(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''); -} - -static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { - - WordList &keywords = *keywordlists[0]; - - int kwLast = kwOther; - - StyleContext sc(startPos, length, initStyle, styler); - - for (; sc.More(); sc.Forward()) { - - // Check for state end - // Operator - if (sc.state == SCE_HA_OPERATOR) { - kwLast = kwOther; - sc.SetState(SCE_HA_DEFAULT); - } - // String - else if (sc.state == SCE_HA_STRING) { - if (sc.ch == '\"') { - sc.ForwardSetState(SCE_HA_DEFAULT); - } else if (sc.ch == '\\') { - sc.Forward(); - } - } - // Char - else if (sc.state == SCE_HA_CHARACTER) { - if (sc.ch == '\'') { - sc.ForwardSetState(SCE_HA_DEFAULT); - } else if (sc.ch == '\\') { - sc.Forward(); - } - } - // Number - else if (sc.state == SCE_HA_NUMBER) { - if (!IsADigit(sc.ch)) { - sc.SetState(SCE_HA_DEFAULT); - } - } - // Types, constructors, etc. - else if (sc.state == SCE_HA_CAPITAL) { - if (!IsAWordChar(sc.ch) || sc.ch == '.') { - sc.SetState(SCE_HA_DEFAULT); - } - } - // Identifier - else if (sc.state == SCE_HA_IDENTIFIER) { - if (!IsAWordChar(sc.ch)) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - int style = SCE_HA_IDENTIFIER; - if ((kwLast == kwImport) || (strcmp(s,"qualified") == 0) || (strcmp(s,"as") == 0)) { - style = SCE_HA_IMPORT; - } else if (keywords.InList(s)) { - style = SCE_HA_KEYWORD; - } else if (kwLast == kwData) { - style = SCE_HA_DATA; - } else if (kwLast == kwClass) { - style = SCE_HA_CLASS; - } else if (kwLast == kwModule) { - style = SCE_HA_MODULE; - } else if (isupper(s[0])) { - style = SCE_HA_CAPITAL; - } - sc.ChangeState(style); - sc.SetState(SCE_HA_DEFAULT); - if (style == SCE_HA_KEYWORD) { - if (0 == strcmp(s, "class")) - kwLast = kwClass; - else if (0 == strcmp(s, "data")) - kwLast = kwData; - else if (0 == strcmp(s, "instance")) - kwLast = kwInstance; - else if (0 == strcmp(s, "import")) - kwLast = kwImport; - else if (0 == strcmp(s, "module")) - kwLast = kwModule; - else - kwLast = kwOther; - } else if (style == SCE_HA_CLASS || style == SCE_HA_IMPORT || - style == SCE_HA_MODULE || style == SCE_HA_CAPITAL || - style == SCE_HA_DATA || style == SCE_HA_INSTANCE) { - kwLast = kwOther; - } - } - } - // Comments - // Oneliner - else if (sc.state == SCE_HA_COMMENTLINE) { - if (IsNewline(sc.ch)) - sc.SetState(SCE_HA_DEFAULT); - } - // Nested - else if (sc.state >= SCE_HA_COMMENTBLOCK) { - if (sc.Match("{-")) { - if (sc.state < SCE_HA_COMMENTMAX) - sc.SetState(sc.state + 1); - } - else if (sc.Match("-}")) { - sc.Forward(); - if (sc.state == SCE_HA_COMMENTBLOCK) - sc.ForwardSetState(SCE_HA_DEFAULT); - else - sc.ForwardSetState(sc.state - 1); - } - } - // New state? - if (sc.state == SCE_HA_DEFAULT) { - // Digit - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_HA_NUMBER); - if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) { // Match anything starting with "0x" or "0X", too - sc.Forward(1); - } - } - // Comment line - else if (sc.Match("--")) { - sc.SetState(SCE_HA_COMMENTLINE); - // Comment block - } - else if (sc.Match("{-")) { - sc.SetState(SCE_HA_COMMENTBLOCK); - } - // String - else if (sc.Match('\"')) { - sc.SetState(SCE_HA_STRING); - } - // Character - else if (sc.Match('\'')) { - sc.SetState(SCE_HA_CHARACTER); - } - // Stringstart - else if (sc.Match('\"')) { - sc.SetState(SCE_HA_STRING); - } - // Operator - else if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) { - sc.SetState(SCE_HA_OPERATOR); - } - // Keyword - else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_HA_IDENTIFIER); - } - - } - } - sc.Complete(); -} - -// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet. -// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com -#ifdef BUILD_EXTERNAL_LEXER -static const char* LexerName = "haskell"; - -void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle, - char *words[], WindowID window, char *props) -{ - PropSetSimple ps; - ps.SetMultiple(props); - WindowAccessor wa(window, ps); - - int nWL = 0; - for (; words[nWL]; nWL++) ; - WordList** wl = new WordList* [nWL + 1]; - int i = 0; - for (; i<nWL; i++) - { - wl[i] = new WordList(); - wl[i]->Set(words[i]); - } - wl[i] = 0; - - ColorizeHaskellDoc(startPos, length, initStyle, wl, wa); - wa.Flush(); - for (i=nWL-1;i>=0;i--) - delete wl[i]; - delete [] wl; -} - -void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle, - char *words[], WindowID window, char *props) -{ - -} - -int EXT_LEXER_DECL GetLexerCount() -{ - return 1; -} - -void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength) -{ - if (buflength > 0) { - buflength--; - int n = strlen(LexerName); - if (n > buflength) - n = buflength; - memcpy(name, LexerName, n), name[n] = '\0'; - } -} -#endif - -LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell"); - diff --git a/src/stc/scintilla/src/LexSQL.cxx b/src/stc/scintilla/src/LexSQL.cxx deleted file mode 100644 index 7a4335bd2c..0000000000 --- a/src/stc/scintilla/src/LexSQL.cxx +++ /dev/null @@ -1,357 +0,0 @@ -// Scintilla source code edit control -/** @file LexSQL.cxx - ** Lexer for SQL, including PL/SQL and SQL*Plus. - **/ -// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> -#include <stdarg.h> - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "StyleContext.h" -#include "KeyWords.h" -#include "Scintilla.h" -#include "SciLexer.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -static inline bool IsAWordChar(int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '_'); -} - -static inline bool IsAWordStart(int ch) { - return (ch < 0x80) && (isalpha(ch) || ch == '_'); -} - -static inline bool IsADoxygenChar(int ch) { - return (islower(ch) || ch == '$' || ch == '@' || - ch == '\\' || ch == '&' || ch == '<' || - ch == '>' || ch == '#' || ch == '{' || - ch == '}' || ch == '[' || ch == ']'); -} - -static inline bool IsANumberChar(int ch) { - // Not exactly following number definition (several dots are seen as OK, etc.) - // but probably enough in most cases. - return (ch < 0x80) && - (isdigit(ch) || toupper(ch) == 'E' || - ch == '.' || ch == '-' || ch == '+'); -} - -static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { - - WordList &keywords1 = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &kw_pldoc = *keywordlists[2]; - WordList &kw_sqlplus = *keywordlists[3]; - WordList &kw_user1 = *keywordlists[4]; - WordList &kw_user2 = *keywordlists[5]; - WordList &kw_user3 = *keywordlists[6]; - WordList &kw_user4 = *keywordlists[7]; - - StyleContext sc(startPos, length, initStyle, styler); - - // property sql.backslash.escapes - // Enables backslash as an escape character in SQL. - bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0; - - bool sqlBackticksIdentifier = styler.GetPropertyInt("lexer.sql.backticks.identifier", 0) != 0; - int styleBeforeDCKeyword = SCE_SQL_DEFAULT; - for (; sc.More(); sc.Forward()) { - // Determine if the current state should terminate. - switch (sc.state) { - case SCE_SQL_OPERATOR: - sc.SetState(SCE_SQL_DEFAULT); - break; - case SCE_SQL_NUMBER: - // We stop the number definition on non-numerical non-dot non-eE non-sign char - if (!IsANumberChar(sc.ch)) { - sc.SetState(SCE_SQL_DEFAULT); - } - break; - case SCE_SQL_IDENTIFIER: - if (!IsAWordChar(sc.ch)) { - int nextState = SCE_SQL_DEFAULT; - char s[1000]; - sc.GetCurrentLowered(s, sizeof(s)); - if (keywords1.InList(s)) { - sc.ChangeState(SCE_SQL_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_SQL_WORD2); - } else if (kw_sqlplus.InListAbbreviated(s, '~')) { - sc.ChangeState(SCE_SQL_SQLPLUS); - if (strncmp(s, "rem", 3) == 0) { - nextState = SCE_SQL_SQLPLUS_COMMENT; - } else if (strncmp(s, "pro", 3) == 0) { - nextState = SCE_SQL_SQLPLUS_PROMPT; - } - } else if (kw_user1.InList(s)) { - sc.ChangeState(SCE_SQL_USER1); - } else if (kw_user2.InList(s)) { - sc.ChangeState(SCE_SQL_USER2); - } else if (kw_user3.InList(s)) { - sc.ChangeState(SCE_SQL_USER3); - } else if (kw_user4.InList(s)) { - sc.ChangeState(SCE_SQL_USER4); - } - sc.SetState(nextState); - } - break; - case SCE_SQL_QUOTEDIDENTIFIER: - if (sc.ch == 0x60) { - if (sc.chNext == 0x60) { - sc.Forward(); // Ignore it - } else { - sc.ForwardSetState(SCE_SQL_DEFAULT); - } - } - break; - case SCE_SQL_COMMENT: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_SQL_DEFAULT); - } - break; - case SCE_SQL_COMMENTDOC: - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_SQL_DEFAULT); - } else if (sc.ch == '@' || sc.ch == '\\') { // Doxygen support - // Verify that we have the conditions to mark a comment-doc-keyword - if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) { - styleBeforeDCKeyword = SCE_SQL_COMMENTDOC; - sc.SetState(SCE_SQL_COMMENTDOCKEYWORD); - } - } - break; - case SCE_SQL_COMMENTLINE: - case SCE_SQL_COMMENTLINEDOC: - case SCE_SQL_SQLPLUS_COMMENT: - case SCE_SQL_SQLPLUS_PROMPT: - if (sc.atLineStart) { - sc.SetState(SCE_SQL_DEFAULT); - } - break; - case SCE_SQL_COMMENTDOCKEYWORD: - if ((styleBeforeDCKeyword == SCE_SQL_COMMENTDOC) && sc.Match('*', '/')) { - sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR); - sc.Forward(); - sc.ForwardSetState(SCE_SQL_DEFAULT); - } else if (!IsADoxygenChar(sc.ch)) { - char s[100]; - sc.GetCurrentLowered(s, sizeof(s)); - if (!isspace(sc.ch) || !kw_pldoc.InList(s + 1)) { - sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR); - } - sc.SetState(styleBeforeDCKeyword); - } - break; - case SCE_SQL_CHARACTER: - if (sqlBackslashEscapes && sc.ch == '\\') { - sc.Forward(); - } else if (sc.ch == '\'') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_SQL_DEFAULT); - } - } - break; - case SCE_SQL_STRING: - if (sc.ch == '\\') { - // Escape sequence - sc.Forward(); - } else if (sc.ch == '\"') { - if (sc.chNext == '\"') { - sc.Forward(); - } else { - sc.ForwardSetState(SCE_SQL_DEFAULT); - } - } - break; - } - - // Determine if a new state should be entered. - if (sc.state == SCE_SQL_DEFAULT) { - if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_SQL_NUMBER); - } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_SQL_IDENTIFIER); - } else if (sc.ch == 0x60 && sqlBackticksIdentifier) { - sc.SetState(SCE_SQL_QUOTEDIDENTIFIER); - } else if (sc.Match('/', '*')) { - if (sc.Match("/**") || sc.Match("/*!")) { // Support of Doxygen doc. style - sc.SetState(SCE_SQL_COMMENTDOC); - } else { - sc.SetState(SCE_SQL_COMMENT); - } - sc.Forward(); // Eat the * so it isn't used for the end of the comment - } else if (sc.Match('-', '-')) { - // MySQL requires a space or control char after -- - // http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html - // Perhaps we should enforce that with proper property: -//~ } else if (sc.Match("-- ")) { - sc.SetState(SCE_SQL_COMMENTLINE); - } else if (sc.ch == '#') { - sc.SetState(SCE_SQL_COMMENTLINEDOC); - } else if (sc.ch == '\'') { - sc.SetState(SCE_SQL_CHARACTER); - } else if (sc.ch == '\"') { - sc.SetState(SCE_SQL_STRING); - } else if (isoperator(static_cast<char>(sc.ch))) { - sc.SetState(SCE_SQL_OPERATOR); - } - } - } - sc.Complete(); -} - -static bool IsStreamCommentStyle(int style) { - return style == SCE_SQL_COMMENT || - style == SCE_SQL_COMMENTDOC || - style == SCE_SQL_COMMENTDOCKEYWORD || - style == SCE_SQL_COMMENTDOCKEYWORDERROR; -} - -// Store both the current line's fold level and the next lines in the -// level store to make it easy to pick up with each increment. -static void FoldSQLDoc(unsigned int startPos, int length, int initStyle, - WordList *[], Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldOnlyBegin = styler.GetPropertyInt("fold.sql.only.begin", 0) != 0; - - // property fold.sql.exists - // Enables "EXISTS" to end a fold as is started by "IF" in "DROP TABLE IF EXISTS". - bool foldSqlExists = styler.GetPropertyInt("fold.sql.exists", 1) != 0; - - unsigned int endPos = startPos + length; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelCurrent = SC_FOLDLEVELBASE; - if (lineCurrent > 0) { - levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16; - } - int levelNext = levelCurrent; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int style = initStyle; - bool endFound = false; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int stylePrev = style; - style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { - if (!IsStreamCommentStyle(stylePrev)) { - levelNext++; - } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { - // Comments don't end at end of line and the next character may be unstyled. - levelNext--; - } - } - if (foldComment && (style == SCE_SQL_COMMENTLINE)) { - // MySQL needs -- comments to be followed by space or control char - if ((ch == '-') && (chNext == '-')) { - char chNext2 = styler.SafeGetCharAt(i + 2); - char chNext3 = styler.SafeGetCharAt(i + 3); - if (chNext2 == '{' || chNext3 == '{') { - levelNext++; - } else if (chNext2 == '}' || chNext3 == '}') { - levelNext--; - } - } - } - if (style == SCE_SQL_OPERATOR) { - if (ch == '(') { - levelNext++; - } else if (ch == ')') { - levelNext--; - } - } - // If new keyword (cannot trigger on elseif or nullif, does less tests) - if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) { - const int MAX_KW_LEN = 6; // Maximum length of folding keywords - char s[MAX_KW_LEN + 2]; - unsigned int j = 0; - for (; j < MAX_KW_LEN + 1; j++) { - if (!iswordchar(styler[i + j])) { - break; - } - s[j] = static_cast<char>(tolower(styler[i + j])); - } - if (j == MAX_KW_LEN + 1) { - // Keyword too long, don't test it - s[0] = '\0'; - } else { - s[j] = '\0'; - } - if ((!foldOnlyBegin) && (strcmp(s, "if") == 0 || strcmp(s, "loop") == 0)) { - if (endFound) { - // ignore - endFound = false; - } else { - levelNext++; - } - } else if (strcmp(s, "begin") == 0) { - levelNext++; - } else if ((strcmp(s, "end") == 0) || -// // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS - (foldSqlExists && (strcmp(s, "exists") == 0)) || -// // SQL Anywhere permits IF ... ELSE ... ENDIF -// // will only be active if "endif" appears in the -// // keyword list. - (strcmp(s, "endif") == 0)) { - endFound = true; - levelNext--; - if (levelNext < SC_FOLDLEVELBASE) { - levelNext = SC_FOLDLEVELBASE; - } - } - } - if (atEOL) { - int levelUse = levelCurrent; - int lev = levelUse | levelNext << 16; - if (visibleChars == 0 && foldCompact) - lev |= SC_FOLDLEVELWHITEFLAG; - if (levelUse < levelNext) - lev |= SC_FOLDLEVELHEADERFLAG; - if (lev != styler.LevelAt(lineCurrent)) { - styler.SetLevel(lineCurrent, lev); - } - lineCurrent++; - levelCurrent = levelNext; - visibleChars = 0; - endFound = false; - } - if (!isspacechar(ch)) { - visibleChars++; - } - } -} - -static const char * const sqlWordListDesc[] = { - "Keywords", - "Database Objects", - "PLDoc", - "SQL*Plus", - "User Keywords 1", - "User Keywords 2", - "User Keywords 3", - "User Keywords 4", - 0 -}; - -LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", FoldSQLDoc, sqlWordListDesc); diff --git a/src/stc/scintilla/src/LineMarker.cxx b/src/stc/scintilla/src/LineMarker.cxx index 0bfd479384..99e83265e4 100644 --- a/src/stc/scintilla/src/LineMarker.cxx +++ b/src/stc/scintilla/src/LineMarker.cxx @@ -2,11 +2,14 @@ /** @file LineMarker.cxx ** Defines the look of a line marker in the margin . **/ -// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> +// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. #include <string.h> +#include <vector> +#include <map> + #include "Platform.h" #include "Scintilla.h" @@ -17,27 +20,25 @@ using namespace Scintilla; #endif -void LineMarker::RefreshColourPalette(Palette &pal, bool want) { - pal.WantFind(fore, want); - pal.WantFind(back, want); - if (pxpm) { - pxpm->RefreshColourPalette(pal, want); - } -} - void LineMarker::SetXPM(const char *textForm) { delete pxpm; pxpm = new XPM(textForm); markType = SC_MARK_PIXMAP; } -void LineMarker::SetXPM(const char * const *linesForm) { +void LineMarker::SetXPM(const char *const *linesForm) { delete pxpm; pxpm = new XPM(linesForm); markType = SC_MARK_PIXMAP; } -static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) { +void LineMarker::SetRGBAImage(Point sizeRGBAImage, const unsigned char *pixelsRGBAImage) { + delete image; + image = new RGBAImage(sizeRGBAImage.x, sizeRGBAImage.y, pixelsRGBAImage); + markType = SC_MARK_RGBAIMAGE; +} + +static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) { PRectangle rc; rc.left = centreX - armSize; rc.top = centreY - armSize; @@ -46,7 +47,7 @@ static void DrawBox(Surface *surface, int centreX, int centreY, int armSize, Col surface->RectangleDraw(rc, back, fore); } -static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore, ColourAllocated back) { +static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore, ColourDesired back) { PRectangle rcCircle; rcCircle.left = centreX - armSize; rcCircle.top = centreY - armSize; @@ -55,23 +56,56 @@ static void DrawCircle(Surface *surface, int centreX, int centreY, int armSize, surface->Ellipse(rcCircle, back, fore); } -static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) { +static void DrawPlus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) { PRectangle rcV(centreX, centreY - armSize + 2, centreX + 1, centreY + armSize - 2 + 1); surface->FillRectangle(rcV, fore); PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1); surface->FillRectangle(rcH, fore); } -static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourAllocated fore) { +static void DrawMinus(Surface *surface, int centreX, int centreY, int armSize, ColourDesired fore) { PRectangle rcH(centreX - armSize + 2, centreY, centreX + armSize - 2 + 1, centreY+1); surface->FillRectangle(rcH, fore); } -void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter) { +void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharacter, typeOfFold tFold, int marginStyle) { + ColourDesired head = back; + ColourDesired body = back; + ColourDesired tail = back; + + switch (tFold) { + case LineMarker::head : + case LineMarker::headWithTail : + head = backSelected; + tail = backSelected; + break; + case LineMarker::body : + head = backSelected; + body = backSelected; + break; + case LineMarker::tail : + body = backSelected; + tail = backSelected; + break; + default : + // LineMarker::undefined + break; + } + if ((markType == SC_MARK_PIXMAP) && (pxpm)) { pxpm->Draw(surface, rcWhole); return; } + if ((markType == SC_MARK_RGBAIMAGE) && (image)) { + // Make rectangle just large enough to fit image centred on centre of rcWhole + PRectangle rcImage; + rcImage.top = static_cast<int>(((rcWhole.top + rcWhole.bottom) - image->GetHeight()) / 2); + rcImage.bottom = rcImage.top + image->GetHeight(); + rcImage.left = static_cast<int>(((rcWhole.left + rcWhole.right) - image->GetWidth()) / 2); + rcImage.right = rcImage.left + image->GetWidth(); + surface->DrawRGBAImage(rcImage, image->GetWidth(), image->GetHeight(), image->Pixels()); + return; + } // Restrict most shapes a bit PRectangle rc = rcWhole; rc.top++; @@ -84,22 +118,22 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac int dimOn4 = minDim / 4; int blobSize = dimOn2-1; int armSize = dimOn2-2; - if (rc.Width() > (rc.Height() * 2)) { - // Wide column is line number so move to left to try to avoid overlapping number + if (marginStyle == SC_MARGIN_NUMBER || marginStyle == SC_MARGIN_TEXT || marginStyle == SC_MARGIN_RTEXT) { + // On textual margins move marker to the left to try to avoid overlapping the text centreX = rc.left + dimOn2 + 1; } if (markType == SC_MARK_ROUNDRECT) { PRectangle rcRounded = rc; rcRounded.left = rc.left + 1; rcRounded.right = rc.right - 1; - surface->RoundedRectangle(rcRounded, fore.allocated, back.allocated); + surface->RoundedRectangle(rcRounded, fore, back); } else if (markType == SC_MARK_CIRCLE) { PRectangle rcCircle; rcCircle.left = centreX - dimOn2; rcCircle.top = centreY - dimOn2; rcCircle.right = centreX + dimOn2; rcCircle.bottom = centreY + dimOn2; - surface->Ellipse(rcCircle, fore.allocated, back.allocated); + surface->Ellipse(rcCircle, fore, back); } else if (markType == SC_MARK_ARROW) { Point pts[] = { Point(centreX - dimOn4, centreY - dimOn2), @@ -107,7 +141,7 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac Point(centreX + dimOn2 - dimOn4, centreY), }; surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), - fore.allocated, back.allocated); + fore, back); } else if (markType == SC_MARK_ARROWDOWN) { Point pts[] = { @@ -116,7 +150,7 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac Point(centreX, centreY + dimOn2 - dimOn4), }; surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), - fore.allocated, back.allocated); + fore, back); } else if (markType == SC_MARK_PLUS) { Point pts[] = { @@ -134,7 +168,7 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac Point(centreX - armSize, centreY + 1), }; surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), - fore.allocated, back.allocated); + fore, back); } else if (markType == SC_MARK_MINUS) { Point pts[] = { @@ -144,7 +178,7 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac Point(centreX - armSize, centreY + 1), }; surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), - fore.allocated, back.allocated); + fore, back); } else if (markType == SC_MARK_SMALLRECT) { PRectangle rcSmall; @@ -152,134 +186,173 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac rcSmall.top = rc.top + 2; rcSmall.right = rc.right - 1; rcSmall.bottom = rc.bottom - 2; - surface->RectangleDraw(rcSmall, fore.allocated, back.allocated); + surface->RectangleDraw(rcSmall, fore, back); - } else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND || + } else if (markType == SC_MARK_EMPTY || markType == SC_MARK_BACKGROUND || markType == SC_MARK_UNDERLINE || markType == SC_MARK_AVAILABLE) { // An invisible marker so don't draw anything } else if (markType == SC_MARK_VLINE) { - surface->PenColour(back.allocated); + surface->PenColour(body); surface->MoveTo(centreX, rcWhole.top); surface->LineTo(centreX, rcWhole.bottom); } else if (markType == SC_MARK_LCORNER) { - surface->PenColour(back.allocated); + surface->PenColour(tail); surface->MoveTo(centreX, rcWhole.top); - surface->LineTo(centreX, rc.top + dimOn2); - surface->LineTo(rc.right - 2, rc.top + dimOn2); + surface->LineTo(centreX, centreY); + surface->LineTo(rc.right - 1, centreY); } else if (markType == SC_MARK_TCORNER) { - surface->PenColour(back.allocated); + surface->PenColour(tail); + surface->MoveTo(centreX, centreY); + surface->LineTo(rc.right - 1, centreY); + + surface->PenColour(body); surface->MoveTo(centreX, rcWhole.top); + surface->LineTo(centreX, centreY + 1); + + surface->PenColour(head); surface->LineTo(centreX, rcWhole.bottom); - surface->MoveTo(centreX, rc.top + dimOn2); - surface->LineTo(rc.right - 2, rc.top + dimOn2); } else if (markType == SC_MARK_LCORNERCURVE) { - surface->PenColour(back.allocated); + surface->PenColour(tail); surface->MoveTo(centreX, rcWhole.top); - surface->LineTo(centreX, rc.top + dimOn2-3); - surface->LineTo(centreX+3, rc.top + dimOn2); - surface->LineTo(rc.right - 1, rc.top + dimOn2); + surface->LineTo(centreX, centreY-3); + surface->LineTo(centreX+3, centreY); + surface->LineTo(rc.right - 1, centreY); } else if (markType == SC_MARK_TCORNERCURVE) { - surface->PenColour(back.allocated); + surface->PenColour(tail); + surface->MoveTo(centreX, centreY-3); + surface->LineTo(centreX+3, centreY); + surface->LineTo(rc.right - 1, centreY); + + surface->PenColour(body); surface->MoveTo(centreX, rcWhole.top); - surface->LineTo(centreX, rcWhole.bottom); + surface->LineTo(centreX, centreY-2); - surface->MoveTo(centreX, rc.top + dimOn2-3); - surface->LineTo(centreX+3, rc.top + dimOn2); - surface->LineTo(rc.right - 1, rc.top + dimOn2); + surface->PenColour(head); + surface->LineTo(centreX, rcWhole.bottom); } else if (markType == SC_MARK_BOXPLUS) { - surface->PenColour(back.allocated); - DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated); - DrawPlus(surface, centreX, centreY, blobSize, back.allocated); + DrawBox(surface, centreX, centreY, blobSize, fore, head); + DrawPlus(surface, centreX, centreY, blobSize, tail); } else if (markType == SC_MARK_BOXPLUSCONNECTED) { - surface->PenColour(back.allocated); - DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated); - DrawPlus(surface, centreX, centreY, blobSize, back.allocated); - + if (tFold == LineMarker::headWithTail) + surface->PenColour(tail); + else + surface->PenColour(body); surface->MoveTo(centreX, centreY + blobSize); surface->LineTo(centreX, rcWhole.bottom); + surface->PenColour(body); surface->MoveTo(centreX, rcWhole.top); surface->LineTo(centreX, centreY - blobSize); + DrawBox(surface, centreX, centreY, blobSize, fore, head); + DrawPlus(surface, centreX, centreY, blobSize, tail); + + if (tFold == LineMarker::body) { + surface->PenColour(tail); + surface->MoveTo(centreX + 1, centreY + blobSize); + surface->LineTo(centreX + blobSize + 1, centreY + blobSize); + + surface->MoveTo(centreX + blobSize, centreY + blobSize); + surface->LineTo(centreX + blobSize, centreY - blobSize); + + surface->MoveTo(centreX + 1, centreY - blobSize); + surface->LineTo(centreX + blobSize + 1, centreY - blobSize); + } } else if (markType == SC_MARK_BOXMINUS) { - surface->PenColour(back.allocated); - DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated); - DrawMinus(surface, centreX, centreY, blobSize, back.allocated); + DrawBox(surface, centreX, centreY, blobSize, fore, head); + DrawMinus(surface, centreX, centreY, blobSize, tail); + surface->PenColour(head); surface->MoveTo(centreX, centreY + blobSize); surface->LineTo(centreX, rcWhole.bottom); } else if (markType == SC_MARK_BOXMINUSCONNECTED) { - surface->PenColour(back.allocated); - DrawBox(surface, centreX, centreY, blobSize, fore.allocated, back.allocated); - DrawMinus(surface, centreX, centreY, blobSize, back.allocated); + DrawBox(surface, centreX, centreY, blobSize, fore, head); + DrawMinus(surface, centreX, centreY, blobSize, tail); + surface->PenColour(head); surface->MoveTo(centreX, centreY + blobSize); surface->LineTo(centreX, rcWhole.bottom); + surface->PenColour(body); surface->MoveTo(centreX, rcWhole.top); surface->LineTo(centreX, centreY - blobSize); + if (tFold == LineMarker::body) { + surface->PenColour(tail); + surface->MoveTo(centreX + 1, centreY + blobSize); + surface->LineTo(centreX + blobSize + 1, centreY + blobSize); + + surface->MoveTo(centreX + blobSize, centreY + blobSize); + surface->LineTo(centreX + blobSize, centreY - blobSize); + + surface->MoveTo(centreX + 1, centreY - blobSize); + surface->LineTo(centreX + blobSize + 1, centreY - blobSize); + } } else if (markType == SC_MARK_CIRCLEPLUS) { - DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated); - surface->PenColour(back.allocated); - DrawPlus(surface, centreX, centreY, blobSize, back.allocated); + DrawCircle(surface, centreX, centreY, blobSize, fore, head); + DrawPlus(surface, centreX, centreY, blobSize, tail); } else if (markType == SC_MARK_CIRCLEPLUSCONNECTED) { - DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated); - surface->PenColour(back.allocated); - DrawPlus(surface, centreX, centreY, blobSize, back.allocated); - + if (tFold == LineMarker::headWithTail) + surface->PenColour(tail); + else + surface->PenColour(body); surface->MoveTo(centreX, centreY + blobSize); surface->LineTo(centreX, rcWhole.bottom); + surface->PenColour(body); surface->MoveTo(centreX, rcWhole.top); surface->LineTo(centreX, centreY - blobSize); + DrawCircle(surface, centreX, centreY, blobSize, fore, head); + DrawPlus(surface, centreX, centreY, blobSize, tail); + } else if (markType == SC_MARK_CIRCLEMINUS) { - DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated); - surface->PenColour(back.allocated); - DrawMinus(surface, centreX, centreY, blobSize, back.allocated); + DrawCircle(surface, centreX, centreY, blobSize, fore, head); + DrawMinus(surface, centreX, centreY, blobSize, tail); + surface->PenColour(head); surface->MoveTo(centreX, centreY + blobSize); surface->LineTo(centreX, rcWhole.bottom); } else if (markType == SC_MARK_CIRCLEMINUSCONNECTED) { - DrawCircle(surface, centreX, centreY, blobSize, fore.allocated, back.allocated); - surface->PenColour(back.allocated); - DrawMinus(surface, centreX, centreY, blobSize, back.allocated); + DrawCircle(surface, centreX, centreY, blobSize, fore, head); + DrawMinus(surface, centreX, centreY, blobSize, tail); + surface->PenColour(head); surface->MoveTo(centreX, centreY + blobSize); surface->LineTo(centreX, rcWhole.bottom); + surface->PenColour(body); surface->MoveTo(centreX, rcWhole.top); surface->LineTo(centreX, centreY - blobSize); } else if (markType >= SC_MARK_CHARACTER) { char character[1]; character[0] = static_cast<char>(markType - SC_MARK_CHARACTER); - int width = surface->WidthText(fontForCharacter, character, 1); + XYPOSITION width = surface->WidthText(fontForCharacter, character, 1); rc.left += (rc.Width() - width) / 2; rc.right = rc.left + width; surface->DrawTextClipped(rc, fontForCharacter, rc.bottom - 2, - character, 1, fore.allocated, back.allocated); + character, 1, fore, back); } else if (markType == SC_MARK_DOTDOTDOT) { int right = centreX - 6; for (int b=0; b<3; b++) { PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom-2); - surface->FillRectangle(rcBlob, fore.allocated); + surface->FillRectangle(rcBlob, fore); right += 5; } } else if (markType == SC_MARK_ARROWS) { - surface->PenColour(fore.allocated); + surface->PenColour(fore); int right = centreX - 2; for (int b=0; b<3; b++) { surface->MoveTo(right - 4, centreY - 4); @@ -299,12 +372,12 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac Point(centreX, centreY + dimOn2), }; surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]), - fore.allocated, back.allocated); + fore, back); } else if (markType == SC_MARK_LEFTRECT) { PRectangle rcLeft = rcWhole; rcLeft.right = rcLeft.left + 4; - surface->FillRectangle(rcLeft, back.allocated); + surface->FillRectangle(rcLeft, back); } else { // SC_MARK_FULLRECT - surface->FillRectangle(rcWhole, back.allocated); + surface->FillRectangle(rcWhole, back); } } diff --git a/src/stc/scintilla/src/LineMarker.h b/src/stc/scintilla/src/LineMarker.h index 3cb4139f08..5c73a62178 100644 --- a/src/stc/scintilla/src/LineMarker.h +++ b/src/stc/scintilla/src/LineMarker.h @@ -2,7 +2,7 @@ /** @file LineMarker.h ** Defines the look of a line marker in the margin . **/ -// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org> +// Copyright 1998-2011 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. #ifndef LINEMARKER_H @@ -12,47 +12,62 @@ namespace Scintilla { #endif + /** */ class LineMarker { public: + enum typeOfFold { undefined, head, body, tail, headWithTail }; + int markType; - ColourPair fore; - ColourPair back; + ColourDesired fore; + ColourDesired back; + ColourDesired backSelected; int alpha; XPM *pxpm; + RGBAImage *image; LineMarker() { markType = SC_MARK_CIRCLE; fore = ColourDesired(0,0,0); back = ColourDesired(0xff,0xff,0xff); + backSelected = ColourDesired(0xff,0x00,0x00); alpha = SC_ALPHA_NOALPHA; pxpm = NULL; + image = NULL; } LineMarker(const LineMarker &) { - // Defined to avoid pxpm being blindly copied, not as real copy constructor + // Defined to avoid pxpm being blindly copied, not as a complete copy constructor markType = SC_MARK_CIRCLE; fore = ColourDesired(0,0,0); back = ColourDesired(0xff,0xff,0xff); + backSelected = ColourDesired(0xff,0x00,0x00); alpha = SC_ALPHA_NOALPHA; pxpm = NULL; + image = NULL; } ~LineMarker() { delete pxpm; + delete image; } - LineMarker &operator=(const LineMarker &) { - // Defined to avoid pxpm being blindly copied, not as real assignment operator - markType = SC_MARK_CIRCLE; - fore = ColourDesired(0,0,0); - back = ColourDesired(0xff,0xff,0xff); - alpha = SC_ALPHA_NOALPHA; - delete pxpm; - pxpm = NULL; + LineMarker &operator=(const LineMarker &other) { + // Defined to avoid pxpm being blindly copied, not as a complete assignment operator + if (this != &other) { + markType = SC_MARK_CIRCLE; + fore = ColourDesired(0,0,0); + back = ColourDesired(0xff,0xff,0xff); + backSelected = ColourDesired(0xff,0x00,0x00); + alpha = SC_ALPHA_NOALPHA; + delete pxpm; + pxpm = NULL; + delete image; + image = NULL; + } return *this; } - void RefreshColourPalette(Palette &pal, bool want); void SetXPM(const char *textForm); - void SetXPM(const char * const *linesForm); - void Draw(Surface *surface, PRectangle &rc, Font &fontForCharacter); + void SetXPM(const char *const *linesForm); + void SetRGBAImage(Point sizeRGBAImage, const unsigned char *pixelsRGBAImage); + void Draw(Surface *surface, PRectangle &rc, Font &fontForCharacter, typeOfFold tFold, int marginStyle); }; #ifdef SCI_NAMESPACE diff --git a/src/stc/scintilla/src/Partitioning.h b/src/stc/scintilla/src/Partitioning.h index 225e350e03..07f3c5d7b0 100644 --- a/src/stc/scintilla/src/Partitioning.h +++ b/src/stc/scintilla/src/Partitioning.h @@ -8,7 +8,7 @@ #ifndef PARTITIONING_H #define PARTITIONING_H -/// A split vector of integers with a method for adding a value to all elements +/// A split vector of integers with a method for adding a value to all elements /// in a range. /// Used by the Partitioning class. @@ -42,6 +42,10 @@ public: /// Divide an interval into multiple partitions. /// Useful for breaking a document down into sections such as lines. +/// A 0 length interval has a single 0 length partition, numbered 0 +/// If interval not 0 length then each partition non-zero length +/// When needed, positions after the interval are considered part of the last partition +/// but the end of the last partition can be found with PositionFromPartition(last+1). class Partitioning { private: @@ -153,6 +157,7 @@ public: return pos; } + /// Return value in range [0 .. Partitions() - 1] even for arguments outside interval int PartitionFromPosition(int pos) const { if (body->Length() <= 1) return 0; diff --git a/src/stc/scintilla/src/PerLine.cxx b/src/stc/scintilla/src/PerLine.cxx index 3e02d65fa1..a903d6f5fd 100644 --- a/src/stc/scintilla/src/PerLine.cxx +++ b/src/stc/scintilla/src/PerLine.cxx @@ -99,7 +99,7 @@ void MarkerHandleSet::RemoveHandle(int handle) { } } -bool MarkerHandleSet::RemoveNumber(int markerNum) { +bool MarkerHandleSet::RemoveNumber(int markerNum, bool all) { bool performedDeletion = false; MarkerHandleNumber **pmhn = &root; while (*pmhn) { @@ -108,6 +108,8 @@ bool MarkerHandleSet::RemoveNumber(int markerNum) { *pmhn = mhn->next; delete mhn; performedDeletion = true; + if (!all) + break; } else { pmhn = &((*pmhn)->next); } @@ -182,6 +184,19 @@ int LineMarkers::MarkValue(int line) { return 0; } +int LineMarkers::MarkerNext(int lineStart, int mask) const { + if (lineStart < 0) + lineStart = 0; + int length = markers.Length(); + for (int iLine = lineStart; iLine < length; iLine++) { + MarkerHandleSet *onLine = markers[iLine]; + if (onLine && ((onLine->MarkValue() & mask) != 0)) + //if ((pdoc->GetMark(iLine) & lParam) != 0) + return iLine; + } + return -1; +} + int LineMarkers::AddMark(int line, int markerNum, int lines) { handleCurrent++; if (!markers.Length()) { @@ -202,22 +217,22 @@ int LineMarkers::AddMark(int line, int markerNum, int lines) { return handleCurrent; } -void LineMarkers::DeleteMark(int line, int markerNum, bool all) { +bool LineMarkers::DeleteMark(int line, int markerNum, bool all) { + bool someChanges = false; if (markers.Length() && (line >= 0) && (line < markers.Length()) && markers[line]) { if (markerNum == -1) { + someChanges = true; delete markers[line]; markers[line] = NULL; } else { - bool performedDeletion = markers[line]->RemoveNumber(markerNum); - while (all && performedDeletion) { - performedDeletion = markers[line]->RemoveNumber(markerNum); - } + someChanges = markers[line]->RemoveNumber(markerNum, all); if (markers[line]->Length() == 0) { delete markers[line]; markers[line] = NULL; } } } + return someChanges; } void LineMarkers::DeleteMarkFromHandle(int markerHandle) { @@ -240,10 +255,7 @@ void LineLevels::Init() { void LineLevels::InsertLine(int line) { if (levels.Length()) { - int level = SC_FOLDLEVELBASE; - if ((line > 0) && (line < levels.Length())) { - level = levels[line-1] & ~SC_FOLDLEVELWHITEFLAG; - } + int level = (line < levels.Length()) ? levels[line] : SC_FOLDLEVELBASE; levels.InsertValue(line, 1, level); } } @@ -301,7 +313,8 @@ void LineState::Init() { void LineState::InsertLine(int line) { if (lineStates.Length()) { lineStates.EnsureLength(line); - lineStates.Insert(line, 0); + int val = (line < lineStates.Length()) ? lineStates[line] : 0; + lineStates.Insert(line, val); } } @@ -319,6 +332,8 @@ int LineState::SetLineState(int line, int state) { } int LineState::GetLineState(int line) { + if (line < 0) + return 0; lineStates.EnsureLength(line + 1); return lineStates[line]; } @@ -379,28 +394,28 @@ bool LineAnnotation::AnySet() const { } bool LineAnnotation::MultipleStyles(int line) const { - if (annotations.Length() && (line < annotations.Length()) && annotations[line]) + if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) return reinterpret_cast<AnnotationHeader *>(annotations[line])->style == IndividualStyles; else return 0; } int LineAnnotation::Style(int line) { - if (annotations.Length() && (line < annotations.Length()) && annotations[line]) + if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) return reinterpret_cast<AnnotationHeader *>(annotations[line])->style; else return 0; } const char *LineAnnotation::Text(int line) const { - if (annotations.Length() && (line < annotations.Length()) && annotations[line]) + if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) return annotations[line]+sizeof(AnnotationHeader); else return 0; } const unsigned char *LineAnnotation::Styles(int line) const { - if (annotations.Length() && (line < annotations.Length()) && annotations[line] && MultipleStyles(line)) + if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line] && MultipleStyles(line)) return reinterpret_cast<unsigned char *>(annotations[line] + sizeof(AnnotationHeader) + Length(line)); else return 0; @@ -414,20 +429,20 @@ static char *AllocateAnnotation(int length, int style) { } void LineAnnotation::SetText(int line, const char *text) { - if (text) { + if (text && (line >= 0)) { annotations.EnsureLength(line+1); int style = Style(line); if (annotations[line]) { delete []annotations[line]; } - annotations[line] = AllocateAnnotation(strlen(text), style); - AnnotationHeader *pah = reinterpret_cast<AnnotationHeader*>(annotations[line]); + annotations[line] = AllocateAnnotation(static_cast<int>(strlen(text)), style); + AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]); pah->style = static_cast<short>(style); - pah->length = strlen(text); + pah->length = static_cast<int>(strlen(text)); pah->lines = static_cast<short>(NumberLines(text)); memcpy(annotations[line]+sizeof(AnnotationHeader), text, pah->length); } else { - if (annotations.Length() && (line < annotations.Length()) && annotations[line]) { + if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) { delete []annotations[line]; annotations[line] = 0; } @@ -451,35 +466,37 @@ void LineAnnotation::SetStyle(int line, int style) { } void LineAnnotation::SetStyles(int line, const unsigned char *styles) { - annotations.EnsureLength(line+1); - if (!annotations[line]) { - annotations[line] = AllocateAnnotation(0, IndividualStyles); - } else { - AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line]); - if (pahSource->style != IndividualStyles) { - char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles); - AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation); - pahAlloc->length = pahSource->length; - pahAlloc->lines = pahSource->lines; - memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length); - delete []annotations[line]; - annotations[line] = allocation; + if (line >= 0) { + annotations.EnsureLength(line+1); + if (!annotations[line]) { + annotations[line] = AllocateAnnotation(0, IndividualStyles); + } else { + AnnotationHeader *pahSource = reinterpret_cast<AnnotationHeader *>(annotations[line]); + if (pahSource->style != IndividualStyles) { + char *allocation = AllocateAnnotation(pahSource->length, IndividualStyles); + AnnotationHeader *pahAlloc = reinterpret_cast<AnnotationHeader *>(allocation); + pahAlloc->length = pahSource->length; + pahAlloc->lines = pahSource->lines; + memcpy(allocation + sizeof(AnnotationHeader), annotations[line] + sizeof(AnnotationHeader), pahSource->length); + delete []annotations[line]; + annotations[line] = allocation; + } } + AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]); + pah->style = IndividualStyles; + memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length); } - AnnotationHeader *pah = reinterpret_cast<AnnotationHeader *>(annotations[line]); - pah->style = IndividualStyles; - memcpy(annotations[line] + sizeof(AnnotationHeader) + pah->length, styles, pah->length); } int LineAnnotation::Length(int line) const { - if (annotations.Length() && (line < annotations.Length()) && annotations[line]) + if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) return reinterpret_cast<AnnotationHeader *>(annotations[line])->length; else return 0; } int LineAnnotation::Lines(int line) const { - if (annotations.Length() && (line < annotations.Length()) && annotations[line]) + if (annotations.Length() && (line >= 0) && (line < annotations.Length()) && annotations[line]) return reinterpret_cast<AnnotationHeader *>(annotations[line])->lines; else return 0; diff --git a/src/stc/scintilla/src/PerLine.h b/src/stc/scintilla/src/PerLine.h index ab34c46fe4..50ce1e551f 100644 --- a/src/stc/scintilla/src/PerLine.h +++ b/src/stc/scintilla/src/PerLine.h @@ -11,7 +11,7 @@ #ifdef SCI_NAMESPACE namespace Scintilla { #endif - + /** * This holds the marker identifier and the marker type to display. * MarkerHandleNumbers are members of lists. @@ -37,7 +37,7 @@ public: bool Contains(int handle) const; bool InsertHandle(int handle, int markerNum); void RemoveHandle(int handle); - bool RemoveNumber(int markerNum); + bool RemoveNumber(int markerNum, bool all); void CombineWith(MarkerHandleSet *other); }; @@ -54,9 +54,10 @@ public: virtual void RemoveLine(int line); int MarkValue(int line); + int MarkerNext(int lineStart, int mask) const; int AddMark(int line, int marker, int lines); void MergeMarkers(int pos); - void DeleteMark(int line, int markerNum, bool all); + bool DeleteMark(int line, int markerNum, bool all); void DeleteMarkFromHandle(int markerHandle); int LineFromHandle(int markerHandle); }; diff --git a/src/stc/scintilla/src/PositionCache.cxx b/src/stc/scintilla/src/PositionCache.cxx index 1d0bef93c5..759558e739 100644 --- a/src/stc/scintilla/src/PositionCache.cxx +++ b/src/stc/scintilla/src/PositionCache.cxx @@ -10,6 +10,10 @@ #include <stdio.h> #include <ctype.h> +#include <string> +#include <vector> +#include <map> + #include "Platform.h" #include "Scintilla.h" @@ -27,6 +31,7 @@ #include "ViewStyle.h" #include "CharClassify.h" #include "Decoration.h" +#include "ILexer.h" #include "Document.h" #include "Selection.h" #include "PositionCache.h" @@ -64,6 +69,8 @@ LineLayout::LineLayout(int maxLineLength_) : widthLine(wrapWidthInfinite), lines(1), wrapIndent(0) { + bracePreviousStyles[0] = 0; + bracePreviousStyles[1] = 0; Resize(maxLineLength_); } @@ -79,7 +86,7 @@ void LineLayout::Resize(int maxLineLength_) { indicators = new char[maxLineLength_ + 1]; // Extra position allocated as sometimes the Windows // GetTextExtentExPoint API writes an extra element. - positions = new int[maxLineLength_ + 1 + 1]; + positions = new XYPOSITION[maxLineLength_ + 1 + 1]; maxLineLength = maxLineLength_; } } @@ -145,15 +152,15 @@ void LineLayout::SetLineStart(int line, int start) { } void LineLayout::SetBracesHighlight(Range rangeLine, Position braces[], - char bracesMatchStyle, int xHighlight) { - if (rangeLine.ContainsCharacter(braces[0])) { + char bracesMatchStyle, int xHighlight, bool ignoreStyle) { + if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) { int braceOffset = braces[0] - rangeLine.start; if (braceOffset < numCharsInLine) { bracePreviousStyles[0] = styles[braceOffset]; styles[braceOffset] = bracesMatchStyle; } } - if (rangeLine.ContainsCharacter(braces[1])) { + if (!ignoreStyle && rangeLine.ContainsCharacter(braces[1])) { int braceOffset = braces[1] - rangeLine.start; if (braceOffset < numCharsInLine) { bracePreviousStyles[1] = styles[braceOffset]; @@ -166,14 +173,14 @@ void LineLayout::SetBracesHighlight(Range rangeLine, Position braces[], } } -void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[]) { - if (rangeLine.ContainsCharacter(braces[0])) { +void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[], bool ignoreStyle) { + if (!ignoreStyle && rangeLine.ContainsCharacter(braces[0])) { int braceOffset = braces[0] - rangeLine.start; if (braceOffset < numCharsInLine) { styles[braceOffset] = bracePreviousStyles[0]; } } - if (rangeLine.ContainsCharacter(braces[1])) { + if (!ignoreStyle && rangeLine.ContainsCharacter(braces[1])) { int braceOffset = braces[1] - rangeLine.start; if (braceOffset < numCharsInLine) { styles[braceOffset] = bracePreviousStyles[1]; @@ -182,10 +189,10 @@ void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[]) { xHighlightGuide = 0; } -int LineLayout::FindBefore(int x, int lower, int upper) const { +int LineLayout::FindBefore(XYPOSITION x, int lower, int upper) const { do { int middle = (upper + lower + 1) / 2; // Round high - int posMiddle = positions[middle]; + XYPOSITION posMiddle = positions[middle]; if (x < posMiddle) { upper = middle - 1; } else { @@ -359,7 +366,8 @@ void BreakFinder::Insert(int val) { for (unsigned int j = 0; j<saeLen; j++) { if (val == selAndEdge[j]) { return; - } if (val < selAndEdge[j]) { + } + if (val < selAndEdge[j]) { for (unsigned int k = saeLen; k>j; k--) { selAndEdge[k] = selAndEdge[k-1]; } @@ -384,18 +392,19 @@ static int NextBadU(const char *s, int p, int len, int &trailBytes) { return -1; } -BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, bool utf8_, int xStart, bool breakForSelection) : +BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, + int xStart, bool breakForSelection, Document *pdoc_) : ll(ll_), lineStart(lineStart_), lineEnd(lineEnd_), posLineStart(posLineStart_), - utf8(utf8_), nextBreak(lineStart_), saeSize(0), saeLen(0), saeCurrentPos(0), saeNext(0), - subBreak(-1) { + subBreak(-1), + pdoc(pdoc_) { saeSize = 8; selAndEdge = new int[saeSize]; for (unsigned int j=0; j < saeSize; j++) { @@ -428,7 +437,7 @@ BreakFinder::BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posL Insert(ll->edgeColumn - 1); Insert(lineEnd - 1); - if (utf8) { + if (pdoc && (SC_CP_UTF8 == pdoc->dbcsCodePage)) { int trailBytes=0; for (int pos = -1;;) { pos = NextBadU(ll->chars, pos, lineEnd, trailBytes); @@ -445,14 +454,10 @@ BreakFinder::~BreakFinder() { delete []selAndEdge; } -int BreakFinder::First() { +int BreakFinder::First() const { return nextBreak; } -static bool IsTrailByte(int ch) { - return (ch >= 0x80) && (ch < (0x80 + 0x40)); -} - int BreakFinder::Next() { if (subBreak == -1) { int prev = nextBreak; @@ -483,34 +488,7 @@ int BreakFinder::Next() { subBreak = -1; return nextBreak; } else { - int lastGoodBreak = -1; - int lastOKBreak = -1; - int lastUTF8Break = -1; - int j; - for (j = subBreak + 1; j <= nextBreak; j++) { - if (IsSpaceOrTab(ll->chars[j - 1]) && !IsSpaceOrTab(ll->chars[j])) { - lastGoodBreak = j; - } - if (static_cast<unsigned char>(ll->chars[j]) < 'A') { - lastOKBreak = j; - } - if (utf8 && !IsTrailByte(static_cast<unsigned char>(ll->chars[j]))) { - lastUTF8Break = j; - } - if (((j - subBreak) >= lengthEachSubdivision) && - ((lastGoodBreak >= 0) || (lastOKBreak >= 0) || (lastUTF8Break >= 0))) { - break; - } - } - if (lastGoodBreak >= 0) { - subBreak = lastGoodBreak; - } else if (lastOKBreak >= 0) { - subBreak = lastOKBreak; - } else if (lastUTF8Break >= 0) { - subBreak = lastUTF8Break; - } else { - subBreak = nextBreak; - } + subBreak += pdoc->SafeSegment(ll->chars + subBreak, nextBreak-subBreak, lengthEachSubdivision); if (subBreak >= nextBreak) { subBreak = -1; return nextBreak; @@ -525,15 +503,15 @@ PositionCacheEntry::PositionCacheEntry() : } void PositionCacheEntry::Set(unsigned int styleNumber_, const char *s_, - unsigned int len_, int *positions_, unsigned int clock_) { + unsigned int len_, XYPOSITION *positions_, unsigned int clock_) { Clear(); styleNumber = styleNumber_; len = len_; clock = clock_; if (s_ && positions_) { - positions = new short[len + (len + 1) / 2]; - for (unsigned int i=0;i<len;i++) { - positions[i] = static_cast<short>(positions_[i]); + positions = new XYPOSITION[len + (len + 1) / 2]; + for (unsigned int i=0; i<len; i++) { + positions[i] = static_cast<XYPOSITION>(positions_[i]); } memcpy(reinterpret_cast<char *>(positions + len), s_, len); } @@ -552,10 +530,10 @@ void PositionCacheEntry::Clear() { } bool PositionCacheEntry::Retrieve(unsigned int styleNumber_, const char *s_, - unsigned int len_, int *positions_) const { + unsigned int len_, XYPOSITION *positions_) const { if ((styleNumber == styleNumber_) && (len == len_) && (memcmp(reinterpret_cast<char *>(positions + len), s_, len)== 0)) { - for (unsigned int i=0;i<len;i++) { + for (unsigned int i=0; i<len; i++) { positions_[i] = positions[i]; } return true; @@ -564,20 +542,20 @@ bool PositionCacheEntry::Retrieve(unsigned int styleNumber_, const char *s_, } } -int PositionCacheEntry::Hash(unsigned int styleNumber, const char *s, unsigned int len) { +int PositionCacheEntry::Hash(unsigned int styleNumber_, const char *s, unsigned int len_) { unsigned int ret = s[0] << 7; - for (unsigned int i=0; i<len; i++) { + for (unsigned int i=0; i<len_; i++) { ret *= 1000003; ret ^= s[i]; } ret *= 1000003; - ret ^= len; + ret ^= len_; ret *= 1000003; - ret ^= styleNumber; + ret ^= styleNumber_; return ret; } -bool PositionCacheEntry::NewerThan(const PositionCacheEntry &other) { +bool PositionCacheEntry::NewerThan(const PositionCacheEntry &other) const { return clock > other.clock; } @@ -601,7 +579,7 @@ PositionCache::~PositionCache() { void PositionCache::Clear() { if (!allClear) { - for (size_t i=0;i<size;i++) { + for (size_t i=0; i<size; i++) { pces[i].Clear(); } } @@ -617,7 +595,8 @@ void PositionCache::SetSize(size_t size_) { } void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber, - const char *s, unsigned int len, int *positions) { + const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc) { + allClear = false; int probe = -1; if ((size > 0) && (len < 30)) { @@ -626,11 +605,11 @@ void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned // Two way associative: try two probe positions. int hashValue = PositionCacheEntry::Hash(styleNumber, s, len); - probe = hashValue % size; + probe = static_cast<int>(hashValue % size); if (pces[probe].Retrieve(styleNumber, s, len, positions)) { return; } - int probe2 = (hashValue * 37) % size; + int probe2 = static_cast<int>((hashValue * 37) % size); if (pces[probe2].Retrieve(styleNumber, s, len, positions)) { return; } @@ -639,13 +618,28 @@ void PositionCache::MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned probe = probe2; } } - surface->MeasureWidths(vstyle.styles[styleNumber].font, s, len, positions); + if (len > BreakFinder::lengthStartSubdivision) { + // Break up into segments + unsigned int startSegment = 0; + XYPOSITION xStartSegment = 0; + while (startSegment < len) { + unsigned int lenSegment = pdoc->SafeSegment(s + startSegment, len - startSegment, BreakFinder::lengthEachSubdivision); + surface->MeasureWidths(vstyle.styles[styleNumber].font, s + startSegment, lenSegment, positions + startSegment); + for (unsigned int inSeg = 0; inSeg < lenSegment; inSeg++) { + positions[startSegment + inSeg] += xStartSegment; + } + xStartSegment = positions[startSegment + lenSegment - 1]; + startSegment += lenSegment; + } + } else { + surface->MeasureWidths(vstyle.styles[styleNumber].font, s, len, positions); + } if (probe >= 0) { clock++; if (clock > 60000) { // Since there are only 16 bits for the clock, wrap it round and // reset all cache entries so none get stuck with a high clock. - for (size_t i=0;i<size;i++) { + for (size_t i=0; i<size; i++) { pces[i].ResetClock(); } clock = 2; diff --git a/src/stc/scintilla/src/PositionCache.h b/src/stc/scintilla/src/PositionCache.h index e99ae58707..08ecee10a6 100644 --- a/src/stc/scintilla/src/PositionCache.h +++ b/src/stc/scintilla/src/PositionCache.h @@ -41,7 +41,7 @@ public: unsigned char *styles; int styleBitsSet; char *indicators; - int *positions; + XYPOSITION *positions; char bracePreviousStyles[2]; // Hotspot support @@ -51,7 +51,7 @@ public: // Wrapped line support int widthLine; int lines; - int wrapIndent; // In pixels + XYPOSITION wrapIndent; // In pixels LineLayout(int maxLineLength_); virtual ~LineLayout(); @@ -63,9 +63,9 @@ public: bool InLine(int offset, int line) const; void SetLineStart(int line, int start); void SetBracesHighlight(Range rangeLine, Position braces[], - char bracesMatchStyle, int xHighlight); - void RestoreBracesHighlight(Range rangeLine, Position braces[]); - int FindBefore(int x, int lower, int upper) const; + char bracesMatchStyle, int xHighlight, bool ignoreStyle); + void RestoreBracesHighlight(Range rangeLine, Position braces[], bool ignoreStyle); + int FindBefore(XYPOSITION x, int lower, int upper) const; int EndLineStyle() const; }; @@ -93,7 +93,7 @@ public: }; void Invalidate(LineLayout::validLevel validity_); void SetLevel(int level_); - int GetLevel() { return level; } + int GetLevel() const { return level; } LineLayout *Retrieve(int lineNumber, int lineCaret, int maxChars, int styleClock_, int linesOnScreen, int linesInDoc); void Dispose(LineLayout *ll); @@ -103,30 +103,24 @@ class PositionCacheEntry { unsigned int styleNumber:8; unsigned int len:8; unsigned int clock:16; - short *positions; + XYPOSITION *positions; public: PositionCacheEntry(); ~PositionCacheEntry(); - void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, int *positions_, unsigned int clock); + void Set(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_, unsigned int clock); void Clear(); - bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, int *positions_) const; - static int Hash(unsigned int styleNumber, const char *s, unsigned int len); - bool NewerThan(const PositionCacheEntry &other); + bool Retrieve(unsigned int styleNumber_, const char *s_, unsigned int len_, XYPOSITION *positions_) const; + static int Hash(unsigned int styleNumber_, const char *s, unsigned int len); + bool NewerThan(const PositionCacheEntry &other) const; void ResetClock(); }; // Class to break a line of text into shorter runs at sensible places. class BreakFinder { - // If a whole run is longer than lengthStartSubdivision then subdivide - // into smaller runs at spaces or punctuation. - enum { lengthStartSubdivision = 300 }; - // Try to make each subdivided run lengthEachSubdivision or shorter. - enum { lengthEachSubdivision = 100 }; LineLayout *ll; int lineStart; int lineEnd; int posLineStart; - bool utf8; int nextBreak; int *selAndEdge; unsigned int saeSize; @@ -134,11 +128,18 @@ class BreakFinder { unsigned int saeCurrentPos; int saeNext; int subBreak; + Document *pdoc; void Insert(int val); public: - BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, bool utf8_, int xStart, bool breakForSelection); + // If a whole run is longer than lengthStartSubdivision then subdivide + // into smaller runs at spaces or punctuation. + enum { lengthStartSubdivision = 300 }; + // Try to make each subdivided run lengthEachSubdivision or shorter. + enum { lengthEachSubdivision = 100 }; + BreakFinder(LineLayout *ll_, int lineStart_, int lineEnd_, int posLineStart_, + int xStart, bool breakForSelection, Document *pdoc_); ~BreakFinder(); - int First(); + int First() const; int Next(); }; @@ -152,9 +153,9 @@ public: ~PositionCache(); void Clear(); void SetSize(size_t size_); - int GetSize() { return size; } + size_t GetSize() const { return size; } void MeasureWidths(Surface *surface, ViewStyle &vstyle, unsigned int styleNumber, - const char *s, unsigned int len, int *positions); + const char *s, unsigned int len, XYPOSITION *positions, Document *pdoc); }; inline bool IsSpaceOrTab(int ch) { diff --git a/src/stc/scintilla/src/RESearch.cxx b/src/stc/scintilla/src/RESearch.cxx index 0c400450eb..ffcc58d365 100644 --- a/src/stc/scintilla/src/RESearch.cxx +++ b/src/stc/scintilla/src/RESearch.cxx @@ -17,6 +17,7 @@ * Put all global/static variables into an object so this code can be * used from multiple threads, etc. * Some extensions by Philippe Lhoste PhiLho(a)GMX.net + * '?' extensions by Michael Mullin masmullin@gmail.com * * These routines are the PUBLIC DOMAIN equivalents of regex * routines as found in 4.nBSD UN*X, with minor extensions. @@ -53,7 +54,7 @@ * Regular Expressions: * * [1] char matches itself, unless it is a special - * character (metachar): . \ [ ] * + ^ $ + * character (metachar): . \ [ ] * + ? ^ $ * and ( ) if posix option. * * [2] . matches any character. @@ -65,12 +66,12 @@ * regex searches are made line per line * (stripped of end-of-line chars). * - if not in posix mode, when followed by a - * left or right round bracket (see [7]); - * - when followed by a digit 1 to 9 (see [8]); + * left or right round bracket (see [8]); + * - when followed by a digit 1 to 9 (see [9]); * - when followed by a left or right angle bracket - * (see [9]); - * - when followed by d, D, s, S, w or W (see [10]); - * - when followed by x and two hexa digits (see [11]. + * (see [10]); + * - when followed by d, D, s, S, w or W (see [11]); + * - when followed by x and two hexa digits (see [12]. * Backslash is used as an escape character for all * other meta-characters, and itself. * @@ -101,23 +102,28 @@ * [a-zA-Z] any alpha * * [5] * any regular expression form [1] to [4] - * (except [7], [8] and [9] forms of [3]), + * (except [8], [9] and [10] forms of [3]), * followed by closure char (*) * matches zero or more matches of that form. * * [6] + same as [5], except it matches one or more. - * Both [5] and [6] are greedy (they match as much as possible). * - * [7] a regular expression in the form [1] to [12], enclosed + * [5-6] Both [5] and [6] are greedy (they match as much as possible). + * Unless they are followed by the 'lazy' quantifier (?) + * In which case both [5] and [6] try to match as little as possible + * + * [7] ? same as [5] except it matches zero or one. + * + * [8] a regular expression in the form [1] to [13], enclosed * as \(form\) (or (form) with posix flag) matches what * form matches. The enclosure creates a set of tags, - * used for [8] and for pattern substitution. + * used for [9] and for pattern substitution. * The tagged forms are numbered starting from 1. * - * [8] a \ followed by a digit 1 to 9 matches whatever a - * previously tagged regular expression ([7]) matched. + * [9] a \ followed by a digit 1 to 9 matches whatever a + * previously tagged regular expression ([8]) matched. * - * [9] \< a regular expression starting with a \< construct + * [10] \< a regular expression starting with a \< construct * \> and/or ending with a \> construct, restricts the * pattern matching to the beginning of a word, and/or * the end of a word. A word is defined to be a character @@ -126,7 +132,7 @@ * by user setting. The word must also be preceded and/or * followed by any character outside those mentioned. * - * [10] \l a backslash followed by d, D, s, S, w or W, + * [11] \l a backslash followed by d, D, s, S, w or W, * becomes a character class (both inside and * outside sets []). * d: decimal digits @@ -136,16 +142,16 @@ * w: alphanumeric & underscore (changed by user setting) * W: any char except alphanumeric & underscore (see above) * - * [11] \xHH a backslash followed by x and two hexa digits, + * [12] \xHH a backslash followed by x and two hexa digits, * becomes the character whose Ascii code is equal * to these digits. If not followed by two digits, * it is 'x' char itself. * - * [12] a composite regular expression xy where x and y - * are in the form [1] to [11] matches the longest + * [13] a composite regular expression xy where x and y + * are in the form [1] to [12] matches the longest * match of x followed by a match for y. * - * [13] ^ a regular expression starting with a ^ character + * [14] ^ a regular expression starting with a ^ character * $ and/or ending with a $ character, restricts the * pattern matching to the beginning of the line, * or the end of line. [anchors] Elsewhere in the @@ -226,6 +232,8 @@ using namespace Scintilla; #define EOW 9 #define REF 10 #define CLO 11 +#define CLQ 12 /* 0 to 1 closure */ +#define LCLO 13 /* lazy closure */ #define END 0 @@ -248,6 +256,7 @@ const char bitarr[] = { 1, 2, 4, 8, 16, 32, 64, '\200' }; */ RESearch::RESearch(CharClassify *charClassTable) { + failure = 0; charClass = charClassTable; Init(); } @@ -312,7 +321,7 @@ void RESearch::ChSetWithCase(unsigned char c, bool caseSensitive) { } } -const unsigned char escapeValue(unsigned char ch) { +unsigned char escapeValue(unsigned char ch) { switch (ch) { case 'a': return '\a'; case 'b': return '\b'; @@ -355,8 +364,8 @@ static int GetHexaChar(unsigned char hd1, unsigned char hd2) { * or -1 for a char class. In this case, bittab is changed. */ int RESearch::GetBackslashExpression( - const char *pattern, - int &incr) { + const char *pattern, + int &incr) { // Since error reporting is primitive and messages are not used anyway, // I choose to interpret unexpected syntax in a logical way instead // of reporting errors. Otherwise, we can stick on, eg., PCRE behavior. @@ -521,7 +530,7 @@ const char *RESearch::Compile(const char *pattern, int length, bool caseSensitiv if (*(p+1) != ']') { c1 = prevChar + 1; i++; - c2 = *++p; + c2 = static_cast<unsigned char>(*++p); if (c2 == '\\') { if (!*(p+1)) // End of RE return badpat("Missing ]"); @@ -576,7 +585,7 @@ const char *RESearch::Compile(const char *pattern, int length, bool caseSensitiv prevChar = -1; } } else { - prevChar = *p; + prevChar = static_cast<unsigned char>(*p); ChSetWithCase(*p, caseSensitive); } i++; @@ -592,10 +601,11 @@ const char *RESearch::Compile(const char *pattern, int length, bool caseSensitiv case '*': /* match 0 or more... */ case '+': /* match 1 or more... */ + case '?': if (p == pattern) return badpat("Empty closure"); lp = sp; /* previous opcode */ - if (*lp == CLO) /* equivalence... */ + if (*lp == CLO || *lp == LCLO) /* equivalence... */ break; switch (*lp) { @@ -617,9 +627,13 @@ const char *RESearch::Compile(const char *pattern, int length, bool caseSensitiv *mp++ = END; *mp++ = END; sp = mp; + while (--mp > lp) *mp = mp[-1]; - *mp = CLO; + if (*p == '?') *mp = CLQ; + else if (*(p+1) == '?') *mp = LCLO; + else *mp = CLO; + mp = sp; break; @@ -844,6 +858,7 @@ int RESearch::PMatch(CharacterIndexer &ci, int lp, int endp, char *ap) { int bp; /* beginning of subpat... */ int ep; /* ending of subpat... */ int are; /* to save the line ptr. */ + int llp; /* lazy lp for LCLO */ while ((op = *ap++) != END) switch (op) { @@ -873,12 +888,12 @@ int RESearch::PMatch(CharacterIndexer &ci, int lp, int endp, char *ap) { return NOTFOUND; break; case BOT: - bopat[*ap++] = lp; + bopat[static_cast<int>(*ap++)] = lp; break; case EOT: - eopat[*ap++] = lp; + eopat[static_cast<int>(*ap++)] = lp; break; - case BOW: + case BOW: if ((lp!=bol && iswordc(ci.CharAt(lp-1))) || !iswordc(ci.CharAt(lp))) return NOTFOUND; break; @@ -894,18 +909,27 @@ int RESearch::PMatch(CharacterIndexer &ci, int lp, int endp, char *ap) { if (ci.CharAt(bp++) != ci.CharAt(lp++)) return NOTFOUND; break; + case LCLO: + case CLQ: case CLO: are = lp; switch (*ap) { case ANY: - while (lp < endp) + if (op == CLO || op == LCLO) + while (lp < endp) + lp++; + else if (lp < endp) lp++; + n = ANYSKIP; break; case CHR: c = *(ap+1); - while ((lp < endp) && (c == ci.CharAt(lp))) + if (op == CLO || op == LCLO) + while ((lp < endp) && (c == ci.CharAt(lp))) + lp++; + else if ((lp < endp) && (c == ci.CharAt(lp))) lp++; n = CHRSKIP; break; @@ -919,15 +943,23 @@ int RESearch::PMatch(CharacterIndexer &ci, int lp, int endp, char *ap) { //re_fail("closure: bad nfa.", *ap); return NOTFOUND; } - ap += n; - while (lp >= are) { - if ((e = PMatch(ci, lp, endp, ap)) != NOTFOUND) - return e; - --lp; + llp = lp; + e = NOTFOUND; + while (llp >= are) { + int q; + if ((q = PMatch(ci, llp, endp, ap)) != NOTFOUND) { + e = q; + lp = llp; + if (op != LCLO) return e; + } + if (*ap == END) return e; + --llp; } - return NOTFOUND; + if (*ap == EOT) + PMatch(ci, lp, endp, ap); + return e; default: //re_fail("RESearch::Execute: bad nfa.", static_cast<char>(op)); return NOTFOUND; diff --git a/src/stc/scintilla/src/RunStyles.cxx b/src/stc/scintilla/src/RunStyles.cxx index ae32c7380d..643d2fb2d1 100644 --- a/src/stc/scintilla/src/RunStyles.cxx +++ b/src/stc/scintilla/src/RunStyles.cxx @@ -21,7 +21,7 @@ using namespace Scintilla; #endif // Find the first run at a position -int RunStyles::RunFromPosition(int position) { +int RunStyles::RunFromPosition(int position) const { int run = starts->PartitionFromPosition(position); // Go to first element with this position while ((run > 0) && (position == starts->PositionFromPartition(run-1))) { @@ -147,8 +147,12 @@ bool RunStyles::FillRange(int &position, int value, int &fillLength) { runEnd = RunFromPosition(end); RemoveRunIfSameAsPrevious(runEnd); RemoveRunIfSameAsPrevious(runStart); + runEnd = RunFromPosition(end); + RemoveRunIfEmpty(runEnd); + return true; + } else { + return false; } - return true; } void RunStyles::SetValueAt(int position, int value) { @@ -214,3 +218,33 @@ void RunStyles::DeleteRange(int position, int deleteLength) { } } +int RunStyles::Runs() const { + return starts->Partitions(); +} + +bool RunStyles::AllSame() const { + for (int run = 1; run < starts->Partitions(); run++) { + if (styles->ValueAt(run) != styles->ValueAt(run - 1)) + return false; + } + return true; +} + +bool RunStyles::AllSameAs(int value) const { + return AllSame() && (styles->ValueAt(0) == value); +} + +int RunStyles::Find(int value, int start) const { + if (start < Length()) { + int run = start ? RunFromPosition(start) : 0; + if (styles->ValueAt(run) == value) + return start; + run++; + while (run < starts->Partitions()) { + if (styles->ValueAt(run) == value) + return starts->PositionFromPartition(run); + run++; + } + } + return -1; +} diff --git a/src/stc/scintilla/src/RunStyles.h b/src/stc/scintilla/src/RunStyles.h index 0a333ca2aa..a3efd93c94 100644 --- a/src/stc/scintilla/src/RunStyles.h +++ b/src/stc/scintilla/src/RunStyles.h @@ -15,10 +15,10 @@ namespace Scintilla { #endif class RunStyles { -public: +private: Partitioning *starts; SplitVector<int> *styles; - int RunFromPosition(int position); + int RunFromPosition(int position) const; int SplitRun(int position); void RemoveRun(int run); void RemoveRunIfEmpty(int run); @@ -37,6 +37,10 @@ public: void InsertSpace(int position, int insertLength); void DeleteAll(); void DeleteRange(int position, int deleteLength); + int Runs() const; + bool AllSame() const; + bool AllSameAs(int value) const; + int Find(int value, int start) const; }; #ifdef SCI_NAMESPACE diff --git a/src/stc/scintilla/src/SVector.h b/src/stc/scintilla/src/SVector.h index 7b929190d5..12a7d5d401 100644 --- a/src/stc/scintilla/src/SVector.h +++ b/src/stc/scintilla/src/SVector.h @@ -19,19 +19,19 @@ namespace Scintilla { */ class SVector { enum { allocSize = 4000 }; - + int *v; ///< The vector unsigned int size; ///< Number of elements allocated unsigned int len; ///< Number of elements used in vector - + /** Internally allocate more elements than the user wants * to avoid thrashing the memory allocator. */ void SizeTo(int newSize) { if (newSize < allocSize) newSize += allocSize; - else + else newSize = (newSize * 3) / 2; - int* newv = new int[newSize]; + int *newv = new int[newSize]; size = newSize; unsigned int i=0; for (; i<len; i++) { @@ -43,7 +43,7 @@ class SVector { delete []v; v = newv; } - + public: SVector() { v = 0; @@ -60,7 +60,7 @@ public: size = 0; if (other.Length() > 0) { SizeTo(other.Length()); - for (int i=0;i<other.Length();i++) + for (int i=0; i<other.Length(); i++) v[i] = other.v[i]; len = other.Length(); } @@ -74,7 +74,7 @@ public: size = 0; if (other.Length() > 0) { SizeTo(other.Length()); - for (int i=0;i<other.Length();i++) + for (int i=0; i<other.Length(); i++) v[i] = other.v[i]; len = other.Length(); } diff --git a/src/stc/scintilla/src/ScintillaBase.cxx b/src/stc/scintilla/src/ScintillaBase.cxx index cae6cff15c..cc3992f8f9 100644 --- a/src/stc/scintilla/src/ScintillaBase.cxx +++ b/src/stc/scintilla/src/ScintillaBase.cxx @@ -9,17 +9,22 @@ #include <string.h> #include <stdio.h> #include <ctype.h> +#include <assert.h> + +#include <string> +#include <vector> +#include <map> #include "Platform.h" +#include "ILexer.h" #include "Scintilla.h" -#include "PropSet.h" + #include "PropSetSimple.h" #ifdef SCI_LEXER #include "SciLexer.h" -#include "Accessor.h" -#include "DocumentAccessor.h" -#include "KeyWords.h" +#include "LexerModule.h" +#include "Catalogue.h" #endif #include "SplitVector.h" #include "Partitioning.h" @@ -50,21 +55,9 @@ ScintillaBase::ScintillaBase() { displayPopupMenu = true; listType = 0; maxListWidth = 0; -#ifdef SCI_LEXER - lexLanguage = SCLEX_CONTAINER; - performingStyle = false; - lexCurrent = 0; - for (int wl = 0;wl < numWordLists;wl++) - keyWordLists[wl] = new WordList; - keyWordLists[numWordLists] = 0; -#endif } ScintillaBase::~ScintillaBase() { -#ifdef SCI_LEXER - for (int wl = 0;wl < numWordLists;wl++) - delete keyWordLists[wl]; -#endif } void ScintillaBase::Finalise() { @@ -72,11 +65,6 @@ void ScintillaBase::Finalise() { popup.Destroy(); } -void ScintillaBase::RefreshColourPalette(Palette &pal, bool want) { - Editor::RefreshColourPalette(pal, want); - ct.RefreshColourPalette(pal, want); -} - void ScintillaBase::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { bool isFillUp = ac.Active() && ac.IsFillUpChar(*s); if (!isFillUp) { @@ -143,16 +131,16 @@ int ScintillaBase::KeyCommand(unsigned int iMessage) { AutoCompleteMove(1); return 0; case SCI_LINEUP: - AutoCompleteMove( -1); + AutoCompleteMove(-1); return 0; case SCI_PAGEDOWN: - AutoCompleteMove(5); + AutoCompleteMove(ac.lb->GetVisibleRows()); return 0; case SCI_PAGEUP: - AutoCompleteMove( -5); + AutoCompleteMove(-ac.lb->GetVisibleRows()); return 0; case SCI_VCHOME: - AutoCompleteMove( -5000); + AutoCompleteMove(-5000); return 0; case SCI_LINEEND: AutoCompleteMove(5000); @@ -200,8 +188,8 @@ int ScintillaBase::KeyCommand(unsigned int iMessage) { return Editor::KeyCommand(iMessage); } -void ScintillaBase::AutoCompleteDoubleClick(void* p) { - ScintillaBase* sci = reinterpret_cast<ScintillaBase*>(p); +void ScintillaBase::AutoCompleteDoubleClick(void *p) { + ScintillaBase *sci = reinterpret_cast<ScintillaBase *>(p); sci->AutoCompleteCompleted(); } @@ -212,7 +200,8 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { if (ac.chooseSingle && (listType == 0)) { if (list && !strchr(list, ac.GetSeparator())) { const char *typeSep = strchr(list, ac.GetTypesep()); - size_t lenInsert = (typeSep) ? (typeSep-list) : strlen(list); + int lenInsert = typeSep ? + static_cast<int>(typeSep-list) : static_cast<int>(strlen(list)); if (ac.ignoreCase) { SetEmptySelection(sel.MainCaret() - lenEntered); pdoc->DeleteChars(sel.MainCaret(), lenEntered); @@ -224,11 +213,12 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { pdoc->InsertString(sel.MainCaret(), list + lenEntered, lenInsert - lenEntered); SetEmptySelection(sel.MainCaret() + lenInsert - lenEntered); } + ac.Cancel(); return; } } ac.Start(wMain, idAutoComplete, sel.MainCaret(), PointMainCaret(), - lenEntered, vs.lineHeight, IsUnicodeMode()); + lenEntered, vs.lineHeight, IsUnicodeMode(), technology); PRectangle rcClient = GetClientRectangle(); Point pt = LocationFromPosition(sel.MainCaret() - lenEntered); @@ -304,13 +294,8 @@ void ScintillaBase::AutoCompleteMove(int delta) { } void ScintillaBase::AutoCompleteMoveToCurrentWord() { - char wordCurrent[1000]; - int i; - int startWord = ac.posStart - ac.startLen; - for (i = startWord; i < sel.MainCaret() && i - startWord < 1000; i++) - wordCurrent[i - startWord] = pdoc->CharAt(i); - wordCurrent[Platform::Minimum(i - startWord, 999)] = '\0'; - ac.Select(wordCurrent); + std::string wordCurrent = RangeText(ac.posStart - ac.startLen, sel.MainCaret()); + ac.Select(wordCurrent.c_str()); } void ScintillaBase::AutoCompleteCharacterAdded(char ch) { @@ -339,15 +324,12 @@ void ScintillaBase::AutoCompleteCharacterDeleted() { } void ScintillaBase::AutoCompleteCompleted() { - int item = ac.lb->GetSelection(); - char selected[1000]; - selected[0] = '\0'; - if (item != -1) { - ac.lb->GetValue(item, selected, sizeof(selected)); - } else { + int item = ac.GetSelection(); + if (item == -1) { AutoCompleteCancel(); return; } + const std::string selected = ac.GetValue(item); ac.Show(false); @@ -357,8 +339,9 @@ void ScintillaBase::AutoCompleteCompleted() { scn.wParam = listType; scn.listType = listType; Position firstPos = ac.posStart - ac.startLen; + scn.position = firstPos; scn.lParam = firstPos; - scn.text = selected; + scn.text = selected.c_str(); NotifyParent(scn); if (!ac.Active()) @@ -379,27 +362,26 @@ void ScintillaBase::AutoCompleteCompleted() { } SetEmptySelection(ac.posStart); if (item != -1) { - pdoc->InsertCString(firstPos, selected); - SetEmptySelection(firstPos + static_cast<int>(strlen(selected))); + pdoc->InsertCString(firstPos, selected.c_str()); + SetEmptySelection(firstPos + static_cast<int>(selected.length())); } + SetLastXChosen(); } int ScintillaBase::AutoCompleteGetCurrent() { if (!ac.Active()) return -1; - return ac.lb->GetSelection(); + return ac.GetSelection(); } int ScintillaBase::AutoCompleteGetCurrentText(char *buffer) { if (ac.Active()) { - int item = ac.lb->GetSelection(); - char selected[1000]; - selected[0] = '\0'; + int item = ac.GetSelection(); if (item != -1) { - ac.lb->GetValue(item, selected, sizeof(selected)); + const std::string selected = ac.GetValue(item); if (buffer != NULL) - strcpy(buffer, selected); - return strlen(selected); + strcpy(buffer, selected.c_str()); + return static_cast<int>(selected.length()); } } if (buffer != NULL) @@ -409,7 +391,6 @@ int ScintillaBase::AutoCompleteGetCurrentText(char *buffer) { void ScintillaBase::CallTipShow(Point pt, const char *defn) { ac.Cancel(); - pt.y += vs.lineHeight; // If container knows about STYLE_CALLTIP then use it in place of the // STYLE_DEFAULT for the face name, size and character set. Also use it // for the foreground and background colour. @@ -418,17 +399,25 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) { ct.SetForeBack(vs.styles[STYLE_CALLTIP].fore, vs.styles[STYLE_CALLTIP].back); } PRectangle rc = ct.CallTipStart(sel.MainCaret(), pt, + vs.lineHeight, defn, vs.styles[ctStyle].fontName, vs.styles[ctStyle].sizeZoomed, CodePage(), vs.styles[ctStyle].characterSet, + vs.technology, wMain); // If the call-tip window would be out of the client - // space, adjust so it displays above the text. + // space PRectangle rcClient = GetClientRectangle(); + int offset = vs.lineHeight + rc.Height(); + // adjust so it displays below the text. + if (rc.top < rcClient.top) { + rc.top += offset; + rc.bottom += offset; + } + // adjust so it displays above the text. if (rc.bottom > rcClient.bottom) { - int offset = vs.lineHeight + rc.Height(); rc.top -= offset; rc.bottom -= offset; } @@ -474,76 +463,194 @@ void ScintillaBase::ButtonDown(Point pt, unsigned int curTime, bool shift, bool } #ifdef SCI_LEXER -void ScintillaBase::SetLexer(uptr_t wParam) { - lexLanguage = wParam; - lexCurrent = LexerModule::Find(lexLanguage); - if (!lexCurrent) - lexCurrent = LexerModule::Find(SCLEX_NULL); - int bits = lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5; - vs.EnsureStyle((1 << bits) - 1); + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +class LexState : public LexInterface { + const LexerModule *lexCurrent; + void SetLexerModule(const LexerModule *lex); + PropSetSimple props; +public: + int lexLanguage; + + LexState(Document *pdoc_); + virtual ~LexState(); + void SetLexer(uptr_t wParam); + void SetLexerLanguage(const char *languageName); + const char *DescribeWordListSets(); + void SetWordList(int n, const char *wl); + int GetStyleBitsNeeded() const; + const char *GetName() const; + void *PrivateCall(int operation, void *pointer); + const char *PropertyNames(); + int PropertyType(const char *name); + const char *DescribeProperty(const char *name); + void PropSet(const char *key, const char *val); + const char *PropGet(const char *key) const; + int PropGetInt(const char *key, int defaultValue=0) const; + int PropGetExpanded(const char *key, char *result) const; +}; + +#ifdef SCI_NAMESPACE } +#endif -void ScintillaBase::SetLexerLanguage(const char *languageName) { +LexState::LexState(Document *pdoc_) : LexInterface(pdoc_) { + lexCurrent = 0; + performingStyle = false; lexLanguage = SCLEX_CONTAINER; - lexCurrent = LexerModule::Find(languageName); - if (!lexCurrent) - lexCurrent = LexerModule::Find(SCLEX_NULL); - if (lexCurrent) - lexLanguage = lexCurrent->GetLanguage(); - int bits = lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5; - vs.EnsureStyle((1 << bits) - 1); } -void ScintillaBase::Colourise(int start, int end) { - if (!performingStyle) { - // Protect against reentrance, which may occur, for example, when - // fold points are discovered while performing styling and the folding - // code looks for child lines which may trigger styling. - performingStyle = true; +LexState::~LexState() { + if (instance) { + instance->Release(); + instance = 0; + } +} + +LexState *ScintillaBase::DocumentLexState() { + if (!pdoc->pli) { + pdoc->pli = new LexState(pdoc); + } + return static_cast<LexState *>(pdoc->pli); +} - int lengthDoc = pdoc->Length(); - if (end == -1) - end = lengthDoc; - int len = end - start; +void LexState::SetLexerModule(const LexerModule *lex) { + if (lex != lexCurrent) { + if (instance) { + instance->Release(); + instance = 0; + } + lexCurrent = lex; + if (lexCurrent) + instance = lexCurrent->Create(); + pdoc->LexerChanged(); + } +} - PLATFORM_ASSERT(len >= 0); - PLATFORM_ASSERT(start + len <= lengthDoc); +void LexState::SetLexer(uptr_t wParam) { + lexLanguage = wParam; + if (lexLanguage == SCLEX_CONTAINER) { + SetLexerModule(0); + } else { + const LexerModule *lex = Catalogue::Find(lexLanguage); + if (!lex) + lex = Catalogue::Find(SCLEX_NULL); + SetLexerModule(lex); + } +} - //WindowAccessor styler(wMain.GetID(), props); - DocumentAccessor styler(pdoc, props, wMain.GetID()); +void LexState::SetLexerLanguage(const char *languageName) { + const LexerModule *lex = Catalogue::Find(languageName); + if (!lex) + lex = Catalogue::Find(SCLEX_NULL); + if (lex) + lexLanguage = lex->GetLanguage(); + SetLexerModule(lex); +} - int styleStart = 0; - if (start > 0) - styleStart = styler.StyleAt(start - 1) & pdoc->stylingBitsMask; - styler.SetCodePage(pdoc->dbcsCodePage); +const char *LexState::DescribeWordListSets() { + if (instance) { + return instance->DescribeWordListSets(); + } else { + return 0; + } +} - if (lexCurrent && (len > 0)) { // Should always succeed as null lexer should always be available - lexCurrent->Lex(start, len, styleStart, keyWordLists, styler); - styler.Flush(); - if (styler.GetPropertyInt("fold")) { - lexCurrent->Fold(start, len, styleStart, keyWordLists, styler); - styler.Flush(); - } +void LexState::SetWordList(int n, const char *wl) { + if (instance) { + int firstModification = instance->WordListSet(n, wl); + if (firstModification >= 0) { + pdoc->ModifiedAt(firstModification); } + } +} - performingStyle = false; +int LexState::GetStyleBitsNeeded() const { + return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5; +} + +const char *LexState::GetName() const { + return lexCurrent ? lexCurrent->languageName : ""; +} + +void *LexState::PrivateCall(int operation, void *pointer) { + if (pdoc && instance) { + return instance->PrivateCall(operation, pointer); + } else { + return 0; + } +} + +const char *LexState::PropertyNames() { + if (instance) { + return instance->PropertyNames(); + } else { + return 0; + } +} + +int LexState::PropertyType(const char *name) { + if (instance) { + return instance->PropertyType(name); + } else { + return SC_TYPE_BOOLEAN; + } +} + +const char *LexState::DescribeProperty(const char *name) { + if (instance) { + return instance->DescribeProperty(name); + } else { + return 0; + } +} + +void LexState::PropSet(const char *key, const char *val) { + props.Set(key, val); + if (instance) { + int firstModification = instance->PropertySet(key, val); + if (firstModification >= 0) { + pdoc->ModifiedAt(firstModification); + } } } + +const char *LexState::PropGet(const char *key) const { + return props.Get(key); +} + +int LexState::PropGetInt(const char *key, int defaultValue) const { + return props.GetInt(key, defaultValue); +} + +int LexState::PropGetExpanded(const char *key, char *result) const { + return props.GetExpanded(key, result); +} + #endif void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) { #ifdef SCI_LEXER - if (lexLanguage != SCLEX_CONTAINER) { - int endStyled = WndProc(SCI_GETENDSTYLED, 0, 0); - int lineEndStyled = WndProc(SCI_LINEFROMPOSITION, endStyled, 0); - endStyled = WndProc(SCI_POSITIONFROMLINE, lineEndStyled, 0); - Colourise(endStyled, endStyleNeeded); + if (DocumentLexState()->lexLanguage != SCLEX_CONTAINER) { + int lineEndStyled = pdoc->LineFromPosition(pdoc->GetEndStyled()); + int endStyled = pdoc->LineStart(lineEndStyled); + DocumentLexState()->Colourise(endStyled, endStyleNeeded); return; } #endif Editor::NotifyStyleToNeeded(endStyleNeeded); } +void ScintillaBase::NotifyLexerChanged(Document *, void *) { +#ifdef SCI_LEXER + int bits = DocumentLexState()->GetStyleBitsNeeded(); + vs.EnsureStyle((1 << bits) - 1); +#endif +} + sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { switch (iMessage) { case SCI_AUTOCSHOW: @@ -611,6 +718,13 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara case SCI_AUTOCGETIGNORECASE: return ac.ignoreCase; + case SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR: + ac.ignoreCaseBehaviour = wParam; + break; + + case SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR: + return ac.ignoreCaseBehaviour; + case SCI_USERLISTSHOW: listType = wParam; AutoCompleteStart(0, reinterpret_cast<const char *>(lParam)); @@ -648,6 +762,10 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara ac.lb->RegisterImage(wParam, reinterpret_cast<const char *>(lParam)); break; + case SCI_REGISTERRGBAIMAGE: + ac.lb->RegisterRGBAImage(wParam, sizeRGBAImage.x, sizeRGBAImage.y, reinterpret_cast<unsigned char *>(lParam)); + break; + case SCI_CLEARREGISTEREDIMAGES: ac.lb->ClearRegisteredImages(); break; @@ -700,67 +818,77 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara InvalidateStyleRedraw(); break; + case SCI_CALLTIPSETPOSITION: + ct.SetPosition(wParam != 0); + InvalidateStyleRedraw(); + break; + case SCI_USEPOPUP: displayPopupMenu = wParam != 0; break; #ifdef SCI_LEXER case SCI_SETLEXER: - SetLexer(wParam); - lexLanguage = wParam; + DocumentLexState()->SetLexer(wParam); break; case SCI_GETLEXER: - return lexLanguage; + return DocumentLexState()->lexLanguage; case SCI_COLOURISE: - if (lexLanguage == SCLEX_CONTAINER) { + if (DocumentLexState()->lexLanguage == SCLEX_CONTAINER) { pdoc->ModifiedAt(wParam); NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam); } else { - Colourise(wParam, lParam); + DocumentLexState()->Colourise(wParam, lParam); } Redraw(); break; case SCI_SETPROPERTY: - props.Set(reinterpret_cast<const char *>(wParam), + DocumentLexState()->PropSet(reinterpret_cast<const char *>(wParam), reinterpret_cast<const char *>(lParam)); break; case SCI_GETPROPERTY: - return StringResult(lParam, props.Get(reinterpret_cast<const char *>(wParam))); - - case SCI_GETPROPERTYEXPANDED: { - char *val = props.Expanded(reinterpret_cast<const char *>(wParam)); - const int n = strlen(val); - if (lParam != 0) { - char *ptr = reinterpret_cast<char *>(lParam); - strcpy(ptr, val); - } - delete []val; - return n; // Not including NUL - } + return StringResult(lParam, DocumentLexState()->PropGet(reinterpret_cast<const char *>(wParam))); + + case SCI_GETPROPERTYEXPANDED: + return DocumentLexState()->PropGetExpanded(reinterpret_cast<const char *>(wParam), + reinterpret_cast<char *>(lParam)); case SCI_GETPROPERTYINT: - return props.GetInt(reinterpret_cast<const char *>(wParam), lParam); + return DocumentLexState()->PropGetInt(reinterpret_cast<const char *>(wParam), lParam); case SCI_SETKEYWORDS: - if (wParam < numWordLists) { - keyWordLists[wParam]->Clear(); - keyWordLists[wParam]->Set(reinterpret_cast<const char *>(lParam)); - } + DocumentLexState()->SetWordList(wParam, reinterpret_cast<const char *>(lParam)); break; case SCI_SETLEXERLANGUAGE: - SetLexerLanguage(reinterpret_cast<const char *>(lParam)); + DocumentLexState()->SetLexerLanguage(reinterpret_cast<const char *>(lParam)); break; case SCI_GETLEXERLANGUAGE: - return StringResult(lParam, lexCurrent ? lexCurrent->languageName : ""); + return StringResult(lParam, DocumentLexState()->GetName()); + + case SCI_PRIVATELEXERCALL: + return reinterpret_cast<sptr_t>( + DocumentLexState()->PrivateCall(wParam, reinterpret_cast<void *>(lParam))); case SCI_GETSTYLEBITSNEEDED: - return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5; + return DocumentLexState()->GetStyleBitsNeeded(); + + case SCI_PROPERTYNAMES: + return StringResult(lParam, DocumentLexState()->PropertyNames()); + + case SCI_PROPERTYTYPE: + return DocumentLexState()->PropertyType(reinterpret_cast<const char *>(wParam)); + + case SCI_DESCRIBEPROPERTY: + return StringResult(lParam, DocumentLexState()->DescribeProperty(reinterpret_cast<const char *>(wParam))); + + case SCI_DESCRIBEKEYWORDSETS: + return StringResult(lParam, DocumentLexState()->DescribeWordListSets()); #endif diff --git a/src/stc/scintilla/src/ScintillaBase.h b/src/stc/scintilla/src/ScintillaBase.h index f1fdc5dfdb..e143f027d3 100644 --- a/src/stc/scintilla/src/ScintillaBase.h +++ b/src/stc/scintilla/src/ScintillaBase.h @@ -12,6 +12,10 @@ namespace Scintilla { #endif +#ifdef SCI_LEXER +class LexState; +#endif + /** */ class ScintillaBase : public Editor { @@ -44,12 +48,7 @@ protected: int maxListWidth; /// Maximum width of list, in average character widths #ifdef SCI_LEXER - bool performingStyle; ///< Prevent reentrance - int lexLanguage; - const LexerModule *lexCurrent; - PropSetSimple props; - enum {numWordLists=KEYWORDSET_MAX+1}; - WordList *keyWordLists[numWordLists+1]; + LexState *DocumentLexState(); void SetLexer(uptr_t wParam); void SetLexerLanguage(const char *languageName); void Colourise(int start, int end); @@ -60,8 +59,6 @@ protected: virtual void Initialise() = 0; virtual void Finalise() = 0; - virtual void RefreshColourPalette(Palette &pal, bool want); - virtual void AddCharUTF(char *s, unsigned int len, bool treatAsDBCS=false); void Command(int cmdId); virtual void CancelModes(); @@ -76,7 +73,7 @@ protected: void AutoCompleteCharacterDeleted(); void AutoCompleteCompleted(); void AutoCompleteMoveToCurrentWord(); - static void AutoCompleteDoubleClick(void* p); + static void AutoCompleteDoubleClick(void *p); void CallTipClick(); void CallTipShow(Point pt, const char *defn); @@ -87,7 +84,9 @@ protected: virtual void ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, bool alt); - virtual void NotifyStyleToNeeded(int endStyleNeeded); + void NotifyStyleToNeeded(int endStyleNeeded); + void NotifyLexerChanged(Document *doc, void *userData); + public: // Public so scintilla_send_message can use it virtual sptr_t WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam); diff --git a/src/stc/scintilla/src/Selection.cxx b/src/stc/scintilla/src/Selection.cxx index 2cdbe60f2e..305d7219fb 100644 --- a/src/stc/scintilla/src/Selection.cxx +++ b/src/stc/scintilla/src/Selection.cxx @@ -20,6 +20,9 @@ using namespace Scintilla; #endif void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int length) { + if (position == startChange) { + virtualSpace = 0; + } if (insertion) { if (position > startChange) { position += length; @@ -31,6 +34,7 @@ void SelectionPosition::MoveForInsertDelete(bool insertion, int startChange, int position -= length; } else { position = startChange; + virtualSpace = 0; } } } @@ -127,7 +131,7 @@ bool SelectionRange::Trim(SelectionRange range) { } else if (start <= startRange) { // Trim end end = startRange; - } else { // + } else { // PLATFORM_ASSERT(end >= endRange); // Trim start start = endRange; @@ -267,7 +271,7 @@ void Selection::TrimSelection(SelectionRange range) { for (size_t i=0; i<ranges.size();) { if ((i != mainRange) && (ranges[i].Trim(range))) { // Trimmed to empty so remove - for (size_t j=i;j<ranges.size()-1;j++) { + for (size_t j=i; j<ranges.size()-1; j++) { ranges[j] = ranges[j+1]; if (j == mainRange-1) mainRange--; @@ -291,6 +295,11 @@ void Selection::AddSelection(SelectionRange range) { mainRange = ranges.size() - 1; } +void Selection::AddSelectionWithoutTrim(SelectionRange range) { + ranges.push_back(range); + mainRange = ranges.size() - 1; +} + void Selection::TentativeSelection(SelectionRange range) { if (!tentativeMain) { rangesSaved = ranges; diff --git a/src/stc/scintilla/src/Selection.h b/src/stc/scintilla/src/Selection.h index 75c56bad43..d7c7d79ad2 100644 --- a/src/stc/scintilla/src/Selection.h +++ b/src/stc/scintilla/src/Selection.h @@ -57,10 +57,10 @@ public: }; // Ordered range to make drawing simpler -struct SelectionSegment { +struct SelectionSegment { SelectionPosition start; SelectionPosition end; - SelectionSegment() { + SelectionSegment() : start(), end() { } SelectionSegment(SelectionPosition a, SelectionPosition b) { if (a < b) { @@ -86,7 +86,7 @@ struct SelectionRange { SelectionPosition caret; SelectionPosition anchor; - SelectionRange() { + SelectionRange() : caret(), anchor() { } SelectionRange(SelectionPosition single) : caret(single), anchor(single) { } @@ -130,12 +130,9 @@ struct SelectionRange { void MinimizeVirtualSpace(); }; - -#include "wx/vector.h" - class Selection { - wxVector<SelectionRange> ranges; - wxVector<SelectionRange> rangesSaved; + std::vector<SelectionRange> ranges; + std::vector<SelectionRange> rangesSaved; SelectionRange rangeRectangular; size_t mainRange; bool moveExtends; @@ -151,7 +148,7 @@ public: int MainAnchor() const; SelectionRange &Rectangular(); SelectionSegment Limits() const; - // This is for when you want to move the caret in response to a + // This is for when you want to move the caret in response to a // user direction command - for rectangular selections, use the range // that covers all selected text otherwise return the main selection. SelectionSegment LimitsForRectangularElseMain() const; @@ -169,6 +166,7 @@ public: void TrimSelection(SelectionRange range); void SetSelection(SelectionRange range); void AddSelection(SelectionRange range); + void AddSelectionWithoutTrim(SelectionRange range); void TentativeSelection(SelectionRange range); void CommitTentative(); int CharacterInSelection(int posCharacter) const; @@ -178,7 +176,7 @@ public: void RemoveDuplicates(); void RotateMain(); bool Tentative() const { return tentativeMain; } - wxVector<SelectionRange> RangesCopy() const { + std::vector<SelectionRange> RangesCopy() const { return ranges; } }; diff --git a/src/stc/scintilla/src/SplitVector.h b/src/stc/scintilla/src/SplitVector.h index af4e890e3a..0ccf6c9f48 100644 --- a/src/stc/scintilla/src/SplitVector.h +++ b/src/stc/scintilla/src/SplitVector.h @@ -1,6 +1,6 @@ // Scintilla source code edit control /** @file SplitVector.h - ** Main data structure for holding arrays that handle insertions + ** Main data structure for holding arrays that handle insertions ** and deletions efficiently. **/ // Copyright 1998-2007 by Neil Hodgson <neilh@scintilla.org> @@ -97,7 +97,7 @@ public: /// Retrieve the character at a particular position. /// Retrieving positions outside the range of the buffer returns 0. - /// The assertions here are disabled since calling code can be + /// The assertions here are disabled since calling code can be /// simpler if out of range access works and returns 0. T ValueAt(int position) const { if (position < part1Length) { @@ -135,7 +135,7 @@ public: } } - T& operator[](int position) const { + T &operator[](int position) const { PLATFORM_ASSERT(position >= 0 && position < lengthBody); if (position < part1Length) { return body[position]; @@ -182,14 +182,14 @@ public: } } - /// Ensure at least length elements allocated, + /// Ensure at least length elements allocated, /// appending zero valued elements if needed. void EnsureLength(int wantedLength) { if (Length() < wantedLength) { InsertValue(Length(), wantedLength - Length(), 0); } } - + /// Insert text into the buffer from an array. void InsertFromArray(int positionToInsert, const T s[], int positionFrom, int insertLength) { PLATFORM_ASSERT((positionToInsert >= 0) && (positionToInsert <= lengthBody)); @@ -238,12 +238,47 @@ public: DeleteRange(0, lengthBody); } - T* BufferPointer() { + // Retrieve a range of elements into an array + void GetRange(T *buffer, int position, int retrieveLength) const { + // Split into up to 2 ranges, before and after the split then use memcpy on each. + int range1Length = 0; + if (position < part1Length) { + int part1AfterPosition = part1Length - position; + range1Length = retrieveLength; + if (range1Length > part1AfterPosition) + range1Length = part1AfterPosition; + } + memcpy(buffer, body + position, range1Length * sizeof(T)); + buffer += range1Length; + position = position + range1Length + gapLength; + int range2Length = retrieveLength - range1Length; + memcpy(buffer, body + position, range2Length * sizeof(T)); + } + + T *BufferPointer() { RoomFor(1); GapTo(lengthBody); body[lengthBody] = 0; return body; } + + T *RangePointer(int position, int rangeLength) { + if (position < part1Length) { + if ((position + rangeLength) > part1Length) { + // Range overlaps gap, so move gap to start of range. + GapTo(position); + return body + position + gapLength; + } else { + return body + position ; + } + } else { + return body + position + gapLength; + } + } + + int GapPosition() const { + return part1Length; + } }; #endif diff --git a/src/stc/scintilla/src/Style.cxx b/src/stc/scintilla/src/Style.cxx index 4314dec0ac..375738c679 100644 --- a/src/stc/scintilla/src/Style.cxx +++ b/src/stc/scintilla/src/Style.cxx @@ -16,21 +16,56 @@ using namespace Scintilla; #endif -Style::Style() { - aliasOfDefaultFont = true; +FontAlias::FontAlias() { +} + +FontAlias::~FontAlias() { + SetID(0); + // ~Font will not release the actual font resource sine it is now 0 +} + +void FontAlias::MakeAlias(Font &fontOrigin) { + SetID(fontOrigin.GetID()); +} + +void FontAlias::ClearFont() { + SetID(0); +} + +bool FontSpecification::EqualTo(const FontSpecification &other) const { + return weight == other.weight && + italic == other.italic && + size == other.size && + characterSet == other.characterSet && + fontName == other.fontName; +} + +FontMeasurements::FontMeasurements() { + Clear(); +} + +void FontMeasurements::Clear() { + ascent = 1; + descent = 1; + aveCharWidth = 1; + spaceWidth = 1; + sizeZoomed = 2; +} + +Style::Style() : FontSpecification() { Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff), - Platform::DefaultFontSize(), 0, SC_CHARSET_DEFAULT, - false, false, false, false, caseMixed, true, true, false); + Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, 0, SC_CHARSET_DEFAULT, + SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false); } -Style::Style(const Style &source) { +Style::Style(const Style &source) : FontSpecification(), FontMeasurements() { Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff), 0, 0, 0, - false, false, false, false, caseMixed, true, true, false); - fore.desired = source.fore.desired; - back.desired = source.back.desired; + SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false); + fore = source.fore; + back = source.back; characterSet = source.characterSet; - bold = source.bold; + weight = source.weight; italic = source.italic; size = source.size; eolFilled = source.eolFilled; @@ -42,11 +77,6 @@ Style::Style(const Style &source) { } Style::~Style() { - if (aliasOfDefaultFont) - font.SetID(0); - else - font.Release(); - aliasOfDefaultFont = false; } Style &Style::operator=(const Style &source) { @@ -54,11 +84,11 @@ Style &Style::operator=(const Style &source) { return * this; Clear(ColourDesired(0, 0, 0), ColourDesired(0xff, 0xff, 0xff), 0, 0, SC_CHARSET_DEFAULT, - false, false, false, false, caseMixed, true, true, false); - fore.desired = source.fore.desired; - back.desired = source.back.desired; + SC_WEIGHT_NORMAL, false, false, false, caseMixed, true, true, false); + fore = source.fore; + back = source.back; characterSet = source.characterSet; - bold = source.bold; + weight = source.weight; italic = source.italic; size = source.size; eolFilled = source.eolFilled; @@ -70,14 +100,14 @@ Style &Style::operator=(const Style &source) { } void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_, - const char *fontName_, int characterSet_, - bool bold_, bool italic_, bool eolFilled_, - bool underline_, ecaseForced caseForce_, - bool visible_, bool changeable_, bool hotspot_) { - fore.desired = fore_; - back.desired = back_; + const char *fontName_, int characterSet_, + int weight_, bool italic_, bool eolFilled_, + bool underline_, ecaseForced caseForce_, + bool visible_, bool changeable_, bool hotspot_) { + fore = fore_; + back = back_; characterSet = characterSet_; - bold = bold_; + weight = weight_; italic = italic_; size = size_; fontName = fontName_; @@ -87,72 +117,31 @@ void Style::Clear(ColourDesired fore_, ColourDesired back_, int size_, visible = visible_; changeable = changeable_; hotspot = hotspot_; - if (aliasOfDefaultFont) - font.SetID(0); - else - font.Release(); - aliasOfDefaultFont = false; + font.ClearFont(); + FontMeasurements::Clear(); } void Style::ClearTo(const Style &source) { Clear( - source.fore.desired, - source.back.desired, - source.size, - source.fontName, - source.characterSet, - source.bold, - source.italic, - source.eolFilled, - source.underline, - source.caseForce, - source.visible, - source.changeable, - source.hotspot); -} - -bool Style::EquivalentFontTo(const Style *other) const { - if (bold != other->bold || - italic != other->italic || - size != other->size || - characterSet != other->characterSet) - return false; - if (fontName == other->fontName) - return true; - if (!fontName) - return false; - if (!other->fontName) - return false; - return strcmp(fontName, other->fontName) == 0; + source.fore, + source.back, + source.size, + source.fontName, + source.characterSet, + source.weight, + source.italic, + source.eolFilled, + source.underline, + source.caseForce, + source.visible, + source.changeable, + source.hotspot); } -void Style::Realise(Surface &surface, int zoomLevel, Style *defaultStyle, int extraFontFlag) { - sizeZoomed = size + zoomLevel; - if (sizeZoomed <= 2) // Hangs if sizeZoomed <= 1 - sizeZoomed = 2; - - if (aliasOfDefaultFont) - font.SetID(0); - else - font.Release(); - int deviceHeight = surface.DeviceHeightFont(sizeZoomed); - aliasOfDefaultFont = defaultStyle && - (EquivalentFontTo(defaultStyle) || !fontName); - if (aliasOfDefaultFont) { - font.SetID(defaultStyle->font.GetID()); - } else if (fontName) { - font.Create(fontName, characterSet, deviceHeight, bold, italic, extraFontFlag); - } else { - font.SetID(0); - } - - ascent = surface.Ascent(font); - descent = surface.Descent(font); - // Probably more typographically correct to include leading - // but that means more complex drawing as leading must be erased - //lineHeight = surface.ExternalLeading() + surface.Height(); - externalLeading = surface.ExternalLeading(font); - lineHeight = surface.Height(font); - aveCharWidth = surface.AverageCharWidth(font); - spaceWidth = surface.WidthChar(font, ' '); +void Style::Copy(Font &font_, const FontMeasurements &fm_) { + font.MakeAlias(font_); +#if PLAT_WX + font.SetAscent(fm_.ascent); +#endif + (FontMeasurements &)(*this) = fm_; } diff --git a/src/stc/scintilla/src/Style.h b/src/stc/scintilla/src/Style.h index 0be3d4f07a..85663acf23 100644 --- a/src/stc/scintilla/src/Style.h +++ b/src/stc/scintilla/src/Style.h @@ -12,18 +12,52 @@ namespace Scintilla { #endif -/** - */ -class Style { -public: - ColourPair fore; - ColourPair back; - bool aliasOfDefaultFont; - bool bold; +struct FontSpecification { + const char *fontName; + int weight; bool italic; int size; - const char *fontName; int characterSet; + int extraFontFlag; + FontSpecification() : + fontName(0), + weight(SC_WEIGHT_NORMAL), + italic(false), + size(10 * SC_FONT_SIZE_MULTIPLIER), + characterSet(0), + extraFontFlag(0) { + } + bool EqualTo(const FontSpecification &other) const; +}; + +// Just like Font but only has a copy of the FontID so should not delete it +class FontAlias : public Font { + // Private so FontAlias objects can not be copied + FontAlias(const FontAlias &); + FontAlias &operator=(const FontAlias &); +public: + FontAlias(); + virtual ~FontAlias(); + void MakeAlias(Font &fontOrigin); + void ClearFont(); +}; + +struct FontMeasurements { + unsigned int ascent; + unsigned int descent; + XYPOSITION aveCharWidth; + XYPOSITION spaceWidth; + int sizeZoomed; + FontMeasurements(); + void Clear(); +}; + +/** + */ +class Style : public FontSpecification, public FontMeasurements { +public: + ColourDesired fore; + ColourDesired back; bool eolFilled; bool underline; enum ecaseForced {caseMixed, caseUpper, caseLower}; @@ -32,14 +66,7 @@ public: bool changeable; bool hotspot; - Font font; - int sizeZoomed; - unsigned int lineHeight; - unsigned int ascent; - unsigned int descent; - unsigned int externalLeading; - unsigned int aveCharWidth; - unsigned int spaceWidth; + FontAlias font; Style(); Style(const Style &source); @@ -48,13 +75,12 @@ public: void Clear(ColourDesired fore_, ColourDesired back_, int size_, const char *fontName_, int characterSet_, - bool bold_, bool italic_, bool eolFilled_, + int weight_, bool italic_, bool eolFilled_, bool underline_, ecaseForced caseForce_, bool visible_, bool changeable_, bool hotspot_); void ClearTo(const Style &source); - bool EquivalentFontTo(const Style *other) const; - void Realise(Surface &surface, int zoomLevel, Style *defaultStyle = 0, int extraFontFlag = 0); - bool IsProtected() const { return !(changeable && visible);}; + void Copy(Font &font_, const FontMeasurements &fm_); + bool IsProtected() const { return !(changeable && visible);} }; #ifdef SCI_NAMESPACE diff --git a/src/stc/scintilla/src/UniConversion.cxx b/src/stc/scintilla/src/UniConversion.cxx index 7dbe9e23de..ffe67f75c4 100644 --- a/src/stc/scintilla/src/UniConversion.cxx +++ b/src/stc/scintilla/src/UniConversion.cxx @@ -1,6 +1,6 @@ // Scintilla source code edit control /** @file UniConversion.cxx - ** Functions to handle UFT-8 and UCS-2 strings. + ** Functions to handle UTF-8 and UTF-16 strings. **/ // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. @@ -61,10 +61,22 @@ void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned putf[len] = '\0'; } +unsigned int UTF8CharLength(unsigned char ch) { + if (ch < 0x80) { + return 1; + } else if (ch < 0x80 + 0x40 + 0x20) { + return 2; + } else if (ch < 0x80 + 0x40 + 0x20 + 0x10) { + return 3; + } else { + return 4; + } +} + unsigned int UTF16Length(const char *s, unsigned int len) { unsigned int ulen = 0; unsigned int charLen; - for (unsigned int i=0;i<len;) { + for (unsigned int i=0; i<len;) { unsigned char ch = static_cast<unsigned char>(s[i]); if (ch < 0x80) { charLen = 1; @@ -117,3 +129,120 @@ unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsig } return ui; } + +int UTF8BytesOfLead[256]; +static bool initialisedBytesOfLead = false; + +static int BytesFromLead(int leadByte) { + if (leadByte < 0xC2) { + // Single byte or invalid + return 1; + } else if (leadByte < 0xE0) { + return 2; + } else if (leadByte < 0xF0) { + return 3; + } else if (leadByte < 0xF5) { + return 4; + } else { + // Characters longer than 4 bytes not possible in current UTF-8 + return 1; + } +} + +void UTF8BytesOfLeadInitialise() { + if (!initialisedBytesOfLead) { + for (int i=0;i<256;i++) { + UTF8BytesOfLead[i] = BytesFromLead(i); + } + initialisedBytesOfLead = true; + } +} + +// Return both the width of the first character in the string and a status +// saying whether it is valid or invalid. +// Most invalid sequences return a width of 1 so are treated as isolated bytes but +// the non-characters *FFFE, *FFFF and FDD0 .. FDEF return 3 or 4 as they can be +// reasonably treated as code points in some circumstances. They will, however, +// not have associated glyphs. +int UTF8Classify(const unsigned char *us, int len) { + // For the rules: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8 + if (*us < 0x80) { + // Single bytes easy + return 1; + } else if (*us > 0xf4) { + // Characters longer than 4 bytes not possible in current UTF-8 + return UTF8MaskInvalid | 1; + } else if (*us >= 0xf0) { + // 4 bytes + if (len < 4) + return UTF8MaskInvalid | 1; + if (UTF8IsTrailByte(us[1]) && UTF8IsTrailByte(us[2]) && UTF8IsTrailByte(us[3])) { + if (((us[1] & 0xf) == 0xf) && (us[2] == 0xbf) && ((us[3] == 0xbe) || (us[3] == 0xbf))) { + // *FFFE or *FFFF non-character + return UTF8MaskInvalid | 4; + } + if (*us == 0xf4) { + // Check if encoding a value beyond the last Unicode character 10FFFF + if (us[1] > 0x8f) { + return UTF8MaskInvalid | 1; + } else if (us[1] == 0x8f) { + if (us[2] > 0xbf) { + return UTF8MaskInvalid | 1; + } else if (us[2] == 0xbf) { + if (us[3] > 0xbf) { + return UTF8MaskInvalid | 1; + } + } + } + } else if ((*us == 0xf0) && ((us[1] & 0xf0) == 0x80)) { + // Overlong + return UTF8MaskInvalid | 1; + } + return 4; + } else { + return UTF8MaskInvalid | 1; + } + } else if (*us >= 0xe0) { + // 3 bytes + if (len < 3) + return UTF8MaskInvalid | 1; + if (UTF8IsTrailByte(us[1]) && UTF8IsTrailByte(us[2])) { + if ((*us == 0xe0) && ((us[1] & 0xe0) == 0x80)) { + // Overlong + return UTF8MaskInvalid | 1; + } + if ((*us == 0xed) && ((us[1] & 0xe0) == 0xa0)) { + // Surrogate + return UTF8MaskInvalid | 1; + } + if ((*us == 0xef) && (us[1] == 0xbf) && (us[2] == 0xbe)) { + // U+FFFE non-character - 3 bytes long + return UTF8MaskInvalid | 3; + } + if ((*us == 0xef) && (us[1] == 0xbf) && (us[2] == 0xbf)) { + // U+FFFF non-character - 3 bytes long + return UTF8MaskInvalid | 3; + } + if ((*us == 0xef) && (us[1] == 0xb7) && (((us[2] & 0xf0) == 0x90) || ((us[2] & 0xf0) == 0xa0))) { + // U+FDD0 .. U+FDEF + return UTF8MaskInvalid | 3; + } + return 3; + } else { + return UTF8MaskInvalid | 1; + } + } else if (*us >= 0xc2) { + // 2 bytes + if (len < 2) + return UTF8MaskInvalid | 1; + if (UTF8IsTrailByte(us[1])) { + return 2; + } else { + return UTF8MaskInvalid | 1; + } + } else { + // 0xc0 .. 0xc1 is overlong encoding + // 0x80 .. 0xbf is trail byte + return UTF8MaskInvalid | 1; + } +} diff --git a/src/stc/scintilla/src/UniConversion.h b/src/stc/scintilla/src/UniConversion.h index fd420a6884..704f162393 100644 --- a/src/stc/scintilla/src/UniConversion.h +++ b/src/stc/scintilla/src/UniConversion.h @@ -1,12 +1,28 @@ // Scintilla source code edit control /** @file UniConversion.h - ** Functions to handle UFT-8 and UCS-2 strings. + ** Functions to handle UTF-8 and UTF-16 strings. **/ // Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> // The License.txt file describes the conditions under which this software may be distributed. +const int UTF8MaxBytes = 4; + unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen); void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len); +unsigned int UTF8CharLength(unsigned char ch); unsigned int UTF16Length(const char *s, unsigned int len); unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen); +extern int UTF8BytesOfLead[256]; +void UTF8BytesOfLeadInitialise(); + +inline bool UTF8IsTrailByte(int ch) { + return (ch >= 0x80) && (ch < 0xc0); +} + +inline bool UTF8IsAscii(int ch) { + return ch < 0x80; +} + +enum { UTF8MaskWidth=0x7, UTF8MaskInvalid=0x8 }; +int UTF8Classify(const unsigned char *us, int len); diff --git a/src/stc/scintilla/src/ViewStyle.cxx b/src/stc/scintilla/src/ViewStyle.cxx index 8e9c4a4634..a4894ef58b 100644 --- a/src/stc/scintilla/src/ViewStyle.cxx +++ b/src/stc/scintilla/src/ViewStyle.cxx @@ -7,6 +7,9 @@ #include <string.h> +#include <vector> +#include <map> + #include "Platform.h" #include "Scintilla.h" @@ -24,7 +27,7 @@ using namespace Scintilla; #endif MarginStyle::MarginStyle() : - style(SC_MARGIN_SYMBOL), width(0), mask(0), sensitive(false) { + style(SC_MARGIN_SYMBOL), width(0), mask(0), sensitive(false), cursor(SC_CURSORREVERSEARROW) { } // A list of the fontnames - avoids wasting space in each style @@ -41,7 +44,7 @@ FontNames::~FontNames() { } void FontNames::Clear() { - for (int i=0;i<max;i++) { + for (int i=0; i<max; i++) { delete []names[i]; } max = 0; @@ -50,7 +53,7 @@ void FontNames::Clear() { const char *FontNames::Save(const char *name) { if (!name) return 0; - for (int i=0;i<max;i++) { + for (int i=0; i<max; i++) { if (strcmp(names[i], name) == 0) { return names[i]; } @@ -59,7 +62,7 @@ const char *FontNames::Save(const char *name) { // Grow array int sizeNew = size * 2; char **namesNew = new char *[sizeNew]; - for (int j=0;j<max;j++) { + for (int j=0; j<max; j++) { namesNew[j] = names[j]; } delete []names; @@ -72,69 +75,124 @@ const char *FontNames::Save(const char *name) { return names[max-1]; } +FontRealised::FontRealised(const FontSpecification &fs) { + frNext = NULL; + (FontSpecification &)(*this) = fs; +} + +FontRealised::~FontRealised() { + font.Release(); + delete frNext; + frNext = 0; +} + +void FontRealised::Realise(Surface &surface, int zoomLevel, int technology) { + PLATFORM_ASSERT(fontName); + sizeZoomed = size + zoomLevel * SC_FONT_SIZE_MULTIPLIER; + if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1 + sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER; + + float deviceHeight = surface.DeviceHeightFont(sizeZoomed); + FontParameters fp(fontName, deviceHeight / SC_FONT_SIZE_MULTIPLIER, weight, italic, extraFontFlag, technology, characterSet); + font.Create(fp); + + ascent = surface.Ascent(font); + descent = surface.Descent(font); + aveCharWidth = surface.AverageCharWidth(font); + spaceWidth = surface.WidthChar(font, ' '); + if (frNext) { + frNext->Realise(surface, zoomLevel, technology); + } +} + +FontRealised *FontRealised::Find(const FontSpecification &fs) { + if (!fs.fontName) + return this; + FontRealised *fr = this; + while (fr) { + if (fr->EqualTo(fs)) + return fr; + fr = fr->frNext; + } + return 0; +} + +void FontRealised::FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent) { + FontRealised *fr = this; + while (fr) { + if (maxAscent < fr->ascent) + maxAscent = fr->ascent; + if (maxDescent < fr->descent) + maxDescent = fr->descent; + fr = fr->frNext; + } +} + ViewStyle::ViewStyle() { Init(); } ViewStyle::ViewStyle(const ViewStyle &source) { + frFirst = NULL; Init(source.stylesSize); - for (unsigned int sty=0;sty<source.stylesSize;sty++) { + for (unsigned int sty=0; sty<source.stylesSize; sty++) { styles[sty] = source.styles[sty]; // Can't just copy fontname as its lifetime is relative to its owning ViewStyle styles[sty].fontName = fontNames.Save(source.styles[sty].fontName); } - for (int mrk=0;mrk<=MARKER_MAX;mrk++) { + for (int mrk=0; mrk<=MARKER_MAX; mrk++) { markers[mrk] = source.markers[mrk]; } - for (int ind=0;ind<=INDIC_MAX;ind++) { + CalcLargestMarkerHeight(); + for (int ind=0; ind<=INDIC_MAX; ind++) { indicators[ind] = source.indicators[ind]; } selforeset = source.selforeset; - selforeground.desired = source.selforeground.desired; - selAdditionalForeground.desired = source.selAdditionalForeground.desired; + selforeground = source.selforeground; + selAdditionalForeground = source.selAdditionalForeground; selbackset = source.selbackset; - selbackground.desired = source.selbackground.desired; - selAdditionalBackground.desired = source.selAdditionalBackground.desired; - selbackground2.desired = source.selbackground2.desired; + selbackground = source.selbackground; + selAdditionalBackground = source.selAdditionalBackground; + selbackground2 = source.selbackground2; selAlpha = source.selAlpha; selAdditionalAlpha = source.selAdditionalAlpha; selEOLFilled = source.selEOLFilled; foldmarginColourSet = source.foldmarginColourSet; - foldmarginColour.desired = source.foldmarginColour.desired; + foldmarginColour = source.foldmarginColour; foldmarginHighlightColourSet = source.foldmarginHighlightColourSet; - foldmarginHighlightColour.desired = source.foldmarginHighlightColour.desired; + foldmarginHighlightColour = source.foldmarginHighlightColour; hotspotForegroundSet = source.hotspotForegroundSet; - hotspotForeground.desired = source.hotspotForeground.desired; + hotspotForeground = source.hotspotForeground; hotspotBackgroundSet = source.hotspotBackgroundSet; - hotspotBackground.desired = source.hotspotBackground.desired; + hotspotBackground = source.hotspotBackground; hotspotUnderline = source.hotspotUnderline; hotspotSingleLine = source.hotspotSingleLine; whitespaceForegroundSet = source.whitespaceForegroundSet; - whitespaceForeground.desired = source.whitespaceForeground.desired; + whitespaceForeground = source.whitespaceForeground; whitespaceBackgroundSet = source.whitespaceBackgroundSet; - whitespaceBackground.desired = source.whitespaceBackground.desired; - selbar.desired = source.selbar.desired; - selbarlight.desired = source.selbarlight.desired; - caretcolour.desired = source.caretcolour.desired; - additionalCaretColour.desired = source.additionalCaretColour.desired; + whitespaceBackground = source.whitespaceBackground; + selbar = source.selbar; + selbarlight = source.selbarlight; + caretcolour = source.caretcolour; + additionalCaretColour = source.additionalCaretColour; showCaretLineBackground = source.showCaretLineBackground; - caretLineBackground.desired = source.caretLineBackground.desired; + caretLineBackground = source.caretLineBackground; caretLineAlpha = source.caretLineAlpha; - edgecolour.desired = source.edgecolour.desired; + edgecolour = source.edgecolour; edgeState = source.edgeState; caretStyle = source.caretStyle; caretWidth = source.caretWidth; someStylesProtected = false; + someStylesForceCase = false; leftMarginWidth = source.leftMarginWidth; rightMarginWidth = source.rightMarginWidth; - for (int i=0;i < margins; i++) { + for (int i=0; i < margins; i++) { ms[i] = source.ms[i]; } - symbolMargin = source.symbolMargin; maskInLine = source.maskInLine; fixedColumnWidth = source.fixedColumnWidth; zoomLevel = source.zoomLevel; @@ -142,27 +200,36 @@ ViewStyle::ViewStyle(const ViewStyle &source) { whitespaceSize = source.whitespaceSize; viewIndentationGuides = source.viewIndentationGuides; viewEOL = source.viewEOL; - showMarkedLines = source.showMarkedLines; extraFontFlag = source.extraFontFlag; extraAscent = source.extraAscent; extraDescent = source.extraDescent; marginStyleOffset = source.marginStyleOffset; annotationVisible = source.annotationVisible; annotationStyleOffset = source.annotationStyleOffset; + braceHighlightIndicatorSet = source.braceHighlightIndicatorSet; + braceHighlightIndicator = source.braceHighlightIndicator; + braceBadLightIndicatorSet = source.braceBadLightIndicatorSet; + braceBadLightIndicator = source.braceBadLightIndicator; } ViewStyle::~ViewStyle() { delete []styles; styles = NULL; + delete frFirst; + frFirst = NULL; } void ViewStyle::Init(size_t stylesSize_) { + frFirst = NULL; stylesSize = 0; styles = NULL; AllocStyles(stylesSize_); fontNames.Clear(); ResetDefaultStyle(); + // There are no image markers by default, so no need for calling CalcLargestMarkerHeight() + largestMarkerHeight = 0; + indicators[0].style = INDIC_SQUIGGLE; indicators[0].under = false; indicators[0].fore = ColourDesired(0, 0x7f, 0); @@ -173,6 +240,7 @@ void ViewStyle::Init(size_t stylesSize_) { indicators[2].under = false; indicators[2].fore = ColourDesired(0xff, 0, 0); + technology = SC_TECHNOLOGY_DEFAULT; lineHeight = 1; maxAscent = 1; maxDescent = 1; @@ -180,44 +248,45 @@ void ViewStyle::Init(size_t stylesSize_) { spaceWidth = 8; selforeset = false; - selforeground.desired = ColourDesired(0xff, 0, 0); - selAdditionalForeground.desired = ColourDesired(0xff, 0, 0); + selforeground = ColourDesired(0xff, 0, 0); + selAdditionalForeground = ColourDesired(0xff, 0, 0); selbackset = true; - selbackground.desired = ColourDesired(0xc0, 0xc0, 0xc0); - selAdditionalBackground.desired = ColourDesired(0xd7, 0xd7, 0xd7); - selbackground2.desired = ColourDesired(0xb0, 0xb0, 0xb0); + selbackground = ColourDesired(0xc0, 0xc0, 0xc0); + selAdditionalBackground = ColourDesired(0xd7, 0xd7, 0xd7); + selbackground2 = ColourDesired(0xb0, 0xb0, 0xb0); selAlpha = SC_ALPHA_NOALPHA; selAdditionalAlpha = SC_ALPHA_NOALPHA; selEOLFilled = false; foldmarginColourSet = false; - foldmarginColour.desired = ColourDesired(0xff, 0, 0); + foldmarginColour = ColourDesired(0xff, 0, 0); foldmarginHighlightColourSet = false; - foldmarginHighlightColour.desired = ColourDesired(0xc0, 0xc0, 0xc0); + foldmarginHighlightColour = ColourDesired(0xc0, 0xc0, 0xc0); whitespaceForegroundSet = false; - whitespaceForeground.desired = ColourDesired(0, 0, 0); + whitespaceForeground = ColourDesired(0, 0, 0); whitespaceBackgroundSet = false; - whitespaceBackground.desired = ColourDesired(0xff, 0xff, 0xff); - selbar.desired = Platform::Chrome(); - selbarlight.desired = Platform::ChromeHighlight(); - styles[STYLE_LINENUMBER].fore.desired = ColourDesired(0, 0, 0); - styles[STYLE_LINENUMBER].back.desired = Platform::Chrome(); - caretcolour.desired = ColourDesired(0, 0, 0); - additionalCaretColour.desired = ColourDesired(0x7f, 0x7f, 0x7f); + whitespaceBackground = ColourDesired(0xff, 0xff, 0xff); + selbar = Platform::Chrome(); + selbarlight = Platform::ChromeHighlight(); + styles[STYLE_LINENUMBER].fore = ColourDesired(0, 0, 0); + styles[STYLE_LINENUMBER].back = Platform::Chrome(); + caretcolour = ColourDesired(0, 0, 0); + additionalCaretColour = ColourDesired(0x7f, 0x7f, 0x7f); showCaretLineBackground = false; - caretLineBackground.desired = ColourDesired(0xff, 0xff, 0); + caretLineBackground = ColourDesired(0xff, 0xff, 0); caretLineAlpha = SC_ALPHA_NOALPHA; - edgecolour.desired = ColourDesired(0xc0, 0xc0, 0xc0); + edgecolour = ColourDesired(0xc0, 0xc0, 0xc0); edgeState = EDGE_NONE; caretStyle = CARETSTYLE_LINE; caretWidth = 1; someStylesProtected = false; + someStylesForceCase = false; hotspotForegroundSet = false; - hotspotForeground.desired = ColourDesired(0, 0, 0xff); + hotspotForeground = ColourDesired(0, 0, 0xff); hotspotBackgroundSet = false; - hotspotBackground.desired = ColourDesired(0xff, 0xff, 0xff); + hotspotBackground = ColourDesired(0xff, 0xff, 0xff); hotspotUnderline = true; hotspotSingleLine = true; @@ -233,11 +302,9 @@ void ViewStyle::Init(size_t stylesSize_) { ms[2].width = 0; ms[2].mask = 0; fixedColumnWidth = leftMarginWidth; - symbolMargin = false; maskInLine = 0xffffffff; for (int margin=0; margin < margins; margin++) { fixedColumnWidth += ms[margin].width; - symbolMargin = symbolMargin || (ms[margin].style != SC_MARGIN_NUMBER); if (ms[margin].width > 0) maskInLine &= ~ms[margin].mask; } @@ -246,80 +313,78 @@ void ViewStyle::Init(size_t stylesSize_) { whitespaceSize = 1; viewIndentationGuides = ivNone; viewEOL = false; - showMarkedLines = true; extraFontFlag = 0; extraAscent = 0; extraDescent = 0; marginStyleOffset = 0; annotationVisible = ANNOTATION_HIDDEN; annotationStyleOffset = 0; + braceHighlightIndicatorSet = false; + braceHighlightIndicator = 0; + braceBadLightIndicatorSet = false; + braceBadLightIndicator = 0; } -void ViewStyle::RefreshColourPalette(Palette &pal, bool want) { - unsigned int i; - for (i=0;i<stylesSize;i++) { - pal.WantFind(styles[i].fore, want); - pal.WantFind(styles[i].back, want); - } - for (i=0;i<(sizeof(indicators)/sizeof(indicators[0]));i++) { - pal.WantFind(indicators[i].fore, want); - } - for (i=0;i<(sizeof(markers)/sizeof(markers[0]));i++) { - markers[i].RefreshColourPalette(pal, want); +void ViewStyle::CreateFont(const FontSpecification &fs) { + if (fs.fontName) { + for (FontRealised *cur=frFirst; cur; cur=cur->frNext) { + if (cur->EqualTo(fs)) + return; + if (!cur->frNext) { + cur->frNext = new FontRealised(fs); + return; + } + } + frFirst = new FontRealised(fs); } - pal.WantFind(selforeground, want); - pal.WantFind(selAdditionalForeground, want); - pal.WantFind(selbackground, want); - pal.WantFind(selAdditionalBackground, want); - pal.WantFind(selbackground2, want); - - pal.WantFind(foldmarginColour, want); - pal.WantFind(foldmarginHighlightColour, want); - - pal.WantFind(whitespaceForeground, want); - pal.WantFind(whitespaceBackground, want); - pal.WantFind(selbar, want); - pal.WantFind(selbarlight, want); - pal.WantFind(caretcolour, want); - pal.WantFind(additionalCaretColour, want); - pal.WantFind(caretLineBackground, want); - pal.WantFind(edgecolour, want); - pal.WantFind(hotspotForeground, want); - pal.WantFind(hotspotBackground, want); } void ViewStyle::Refresh(Surface &surface) { - selbar.desired = Platform::Chrome(); - selbarlight.desired = Platform::ChromeHighlight(); - styles[STYLE_DEFAULT].Realise(surface, zoomLevel, NULL, extraFontFlag); - maxAscent = styles[STYLE_DEFAULT].ascent; - maxDescent = styles[STYLE_DEFAULT].descent; - someStylesProtected = false; + delete frFirst; + frFirst = NULL; + selbar = Platform::Chrome(); + selbarlight = Platform::ChromeHighlight(); + for (unsigned int i=0; i<stylesSize; i++) { - if (i != STYLE_DEFAULT) { - styles[i].Realise(surface, zoomLevel, &styles[STYLE_DEFAULT], extraFontFlag); - if (maxAscent < styles[i].ascent) - maxAscent = styles[i].ascent; - if (maxDescent < styles[i].descent) - maxDescent = styles[i].descent; - } - if (styles[i].IsProtected()) { - someStylesProtected = true; - } + styles[i].extraFontFlag = extraFontFlag; } + + CreateFont(styles[STYLE_DEFAULT]); + for (unsigned int j=0; j<stylesSize; j++) { + CreateFont(styles[j]); + } + + frFirst->Realise(surface, zoomLevel, technology); + + for (unsigned int k=0; k<stylesSize; k++) { + FontRealised *fr = frFirst->Find(styles[k]); + styles[k].Copy(fr->font, *fr); + } + maxAscent = 1; + maxDescent = 1; + frFirst->FindMaxAscentDescent(maxAscent, maxDescent); maxAscent += extraAscent; maxDescent += extraDescent; - lineHeight = maxAscent + maxDescent; + + someStylesProtected = false; + someStylesForceCase = false; + for (unsigned int l=0; l<stylesSize; l++) { + if (styles[l].IsProtected()) { + someStylesProtected = true; + } + if (styles[l].caseForce != Style::caseMixed) { + someStylesForceCase = true; + } + } + aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth; spaceWidth = styles[STYLE_DEFAULT].spaceWidth; fixedColumnWidth = leftMarginWidth; - symbolMargin = false; maskInLine = 0xffffffff; for (int margin=0; margin < margins; margin++) { fixedColumnWidth += ms[margin].width; - symbolMargin = symbolMargin || (ms[margin].style != SC_MARGIN_NUMBER); if (ms[margin].width > 0) maskInLine &= ~ms[margin].mask; } @@ -355,10 +420,10 @@ void ViewStyle::EnsureStyle(size_t index) { void ViewStyle::ResetDefaultStyle() { styles[STYLE_DEFAULT].Clear(ColourDesired(0,0,0), - ColourDesired(0xff,0xff,0xff), - Platform::DefaultFontSize(), fontNames.Save(Platform::DefaultFont()), - SC_CHARSET_DEFAULT, - false, false, false, false, Style::caseMixed, true, true, false); + ColourDesired(0xff,0xff,0xff), + Platform::DefaultFontSize() * SC_FONT_SIZE_MULTIPLIER, fontNames.Save(Platform::DefaultFont()), + SC_CHARSET_DEFAULT, + SC_WEIGHT_NORMAL, false, false, false, Style::caseMixed, true, true, false); } void ViewStyle::ClearStyles() { @@ -368,11 +433,11 @@ void ViewStyle::ClearStyles() { styles[i].ClearTo(styles[STYLE_DEFAULT]); } } - styles[STYLE_LINENUMBER].back.desired = Platform::Chrome(); + styles[STYLE_LINENUMBER].back = Platform::Chrome(); // Set call tip fore/back to match the values previously set for call tips - styles[STYLE_CALLTIP].back.desired = ColourDesired(0xff, 0xff, 0xff); - styles[STYLE_CALLTIP].fore.desired = ColourDesired(0x80, 0x80, 0x80); + styles[STYLE_CALLTIP].back = ColourDesired(0xff, 0xff, 0xff); + styles[STYLE_CALLTIP].fore = ColourDesired(0x80, 0x80, 0x80); } void ViewStyle::SetStyleFontName(int styleIndex, const char *name) { @@ -387,3 +452,19 @@ bool ViewStyle::ValidStyle(size_t styleIndex) const { return styleIndex < stylesSize; } +void ViewStyle::CalcLargestMarkerHeight() { + largestMarkerHeight = 0; + for (int m = 0; m <= MARKER_MAX; ++m) { + switch (markers[m].markType) { + case SC_MARK_PIXMAP: + if (markers[m].pxpm->GetHeight() > largestMarkerHeight) + largestMarkerHeight = markers[m].pxpm->GetHeight(); + break; + case SC_MARK_RGBAIMAGE: + if (markers[m].image->GetHeight() > largestMarkerHeight) + largestMarkerHeight = markers[m].image->GetHeight(); + break; + } + } +} + diff --git a/src/stc/scintilla/src/ViewStyle.h b/src/stc/scintilla/src/ViewStyle.h index 22e365b02d..292ed01ec6 100644 --- a/src/stc/scintilla/src/ViewStyle.h +++ b/src/stc/scintilla/src/ViewStyle.h @@ -20,6 +20,7 @@ public: int width; int mask; bool sensitive; + int cursor; MarginStyle(); }; @@ -38,6 +39,20 @@ public: const char *Save(const char *name); }; +class FontRealised : public FontSpecification, public FontMeasurements { + // Private so FontRealised objects can not be copied + FontRealised(const FontRealised &); + FontRealised &operator=(const FontRealised &); +public: + Font font; + FontRealised *frNext; + FontRealised(const FontSpecification &fs); + virtual ~FontRealised(); + void Realise(Surface &surface, int zoomLevel, int technology); + FontRealised *Find(const FontSpecification &fs); + void FindMaxAscentDescent(unsigned int &maxAscent, unsigned int &maxDescent); +}; + enum IndentView {ivNone, ivReal, ivLookForward, ivLookBoth}; enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterIndent=2}; @@ -47,46 +62,48 @@ enum WhiteSpaceVisibility {wsInvisible=0, wsVisibleAlways=1, wsVisibleAfterInden class ViewStyle { public: FontNames fontNames; + FontRealised *frFirst; size_t stylesSize; Style *styles; LineMarker markers[MARKER_MAX + 1]; + int largestMarkerHeight; Indicator indicators[INDIC_MAX + 1]; + int technology; int lineHeight; unsigned int maxAscent; unsigned int maxDescent; - unsigned int aveCharWidth; - unsigned int spaceWidth; + XYPOSITION aveCharWidth; + XYPOSITION spaceWidth; bool selforeset; - ColourPair selforeground; - ColourPair selAdditionalForeground; + ColourDesired selforeground; + ColourDesired selAdditionalForeground; bool selbackset; - ColourPair selbackground; - ColourPair selAdditionalBackground; - ColourPair selbackground2; + ColourDesired selbackground; + ColourDesired selAdditionalBackground; + ColourDesired selbackground2; int selAlpha; int selAdditionalAlpha; bool selEOLFilled; bool whitespaceForegroundSet; - ColourPair whitespaceForeground; + ColourDesired whitespaceForeground; bool whitespaceBackgroundSet; - ColourPair whitespaceBackground; - ColourPair selbar; - ColourPair selbarlight; + ColourDesired whitespaceBackground; + ColourDesired selbar; + ColourDesired selbarlight; bool foldmarginColourSet; - ColourPair foldmarginColour; + ColourDesired foldmarginColour; bool foldmarginHighlightColourSet; - ColourPair foldmarginHighlightColour; + ColourDesired foldmarginHighlightColour; bool hotspotForegroundSet; - ColourPair hotspotForeground; + ColourDesired hotspotForeground; bool hotspotBackgroundSet; - ColourPair hotspotBackground; + ColourDesired hotspotBackground; bool hotspotUnderline; bool hotspotSingleLine; /// Margins are ordered: Line Numbers, Selection Margin, Spacing Margin enum { margins=5 }; int leftMarginWidth; ///< Spacing margin on left of text - int rightMarginWidth; ///< Spacing margin on left of text - bool symbolMargin; + int rightMarginWidth; ///< Spacing margin on right of text int maskInLine; ///< Mask for markers to be put into text because there is nowhere for them to go in margin MarginStyle ms[margins]; int fixedColumnWidth; @@ -95,29 +112,33 @@ public: int whitespaceSize; IndentView viewIndentationGuides; bool viewEOL; - bool showMarkedLines; - ColourPair caretcolour; - ColourPair additionalCaretColour; + ColourDesired caretcolour; + ColourDesired additionalCaretColour; bool showCaretLineBackground; - ColourPair caretLineBackground; + ColourDesired caretLineBackground; int caretLineAlpha; - ColourPair edgecolour; + ColourDesired edgecolour; int edgeState; int caretStyle; int caretWidth; bool someStylesProtected; + bool someStylesForceCase; int extraFontFlag; int extraAscent; int extraDescent; int marginStyleOffset; int annotationVisible; int annotationStyleOffset; + bool braceHighlightIndicatorSet; + int braceHighlightIndicator; + bool braceBadLightIndicatorSet; + int braceBadLightIndicator; ViewStyle(); ViewStyle(const ViewStyle &source); ~ViewStyle(); void Init(size_t stylesSize_=64); - void RefreshColourPalette(Palette &pal, bool want); + void CreateFont(const FontSpecification &fs); void Refresh(Surface &surface); void AllocStyles(size_t sizeNew); void EnsureStyle(size_t index); @@ -126,6 +147,7 @@ public: void SetStyleFontName(int styleIndex, const char *name); bool ProtectionActive() const; bool ValidStyle(size_t styleIndex) const; + void CalcLargestMarkerHeight(); }; #ifdef SCI_NAMESPACE diff --git a/src/stc/scintilla/src/WindowAccessor.cxx b/src/stc/scintilla/src/WindowAccessor.cxx deleted file mode 100644 index 9de106fb78..0000000000 --- a/src/stc/scintilla/src/WindowAccessor.cxx +++ /dev/null @@ -1,191 +0,0 @@ -// Scintilla source code edit control -/** @file WindowAccessor.cxx - ** Rapid easy access to contents of a Scintilla. - **/ -// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> -// The License.txt file describes the conditions under which this software may be distributed. - -#include <stdlib.h> -#include <string.h> -#include <ctype.h> -#include <stdio.h> - -#include "Platform.h" - -#include "PropSet.h" -#include "Accessor.h" -#include "WindowAccessor.h" -#include "Scintilla.h" - -#ifdef SCI_NAMESPACE -using namespace Scintilla; -#endif - -WindowAccessor::~WindowAccessor() { -} - -bool WindowAccessor::InternalIsLeadByte(char ch) { - if (SC_CP_UTF8 == codePage) - // For lexing, all characters >= 0x80 are treated the - // same so none is considered a lead byte. - return false; - else - return Platform::IsDBCSLeadByte(codePage, ch); -} - -void WindowAccessor::Fill(int position) { - if (lenDoc == -1) - lenDoc = Platform::SendScintilla(id, SCI_GETTEXTLENGTH, 0, 0); - startPos = position - slopSize; - if (startPos + bufferSize > lenDoc) - startPos = lenDoc - bufferSize; - if (startPos < 0) - startPos = 0; - endPos = startPos + bufferSize; - if (endPos > lenDoc) - endPos = lenDoc; - - Sci_TextRange tr = {{startPos, endPos}, buf}; - Platform::SendScintillaPointer(id, SCI_GETTEXTRANGE, 0, &tr); -} - -bool WindowAccessor::Match(int pos, const char *s) { - for (int i=0; *s; i++) { - if (*s != SafeGetCharAt(pos+i)) - return false; - s++; - } - return true; -} - -char WindowAccessor::StyleAt(int position) { - return static_cast<char>(Platform::SendScintilla( - id, SCI_GETSTYLEAT, position, 0)); -} - -int WindowAccessor::GetLine(int position) { - return Platform::SendScintilla(id, SCI_LINEFROMPOSITION, position, 0); -} - -int WindowAccessor::LineStart(int line) { - return Platform::SendScintilla(id, SCI_POSITIONFROMLINE, line, 0); -} - -int WindowAccessor::LevelAt(int line) { - return Platform::SendScintilla(id, SCI_GETFOLDLEVEL, line, 0); -} - -int WindowAccessor::Length() { - if (lenDoc == -1) - lenDoc = Platform::SendScintilla(id, SCI_GETTEXTLENGTH, 0, 0); - return lenDoc; -} - -int WindowAccessor::GetLineState(int line) { - return Platform::SendScintilla(id, SCI_GETLINESTATE, line); -} - -int WindowAccessor::SetLineState(int line, int state) { - return Platform::SendScintilla(id, SCI_SETLINESTATE, line, state); -} - -void WindowAccessor::StartAt(unsigned int start, char chMask) { - Platform::SendScintilla(id, SCI_STARTSTYLING, start, chMask); -} - -void WindowAccessor::StartSegment(unsigned int pos) { - startSeg = pos; -} - -void WindowAccessor::ColourTo(unsigned int pos, int chAttr) { - // Only perform styling if non empty range - if (pos != startSeg - 1) { - if (pos < startSeg) { - Platform::DebugPrintf("Bad colour positions %d - %d\n", startSeg, pos); - } - - if (validLen + (pos - startSeg + 1) >= bufferSize) - Flush(); - if (validLen + (pos - startSeg + 1) >= bufferSize) { - // Too big for buffer so send directly - Platform::SendScintilla(id, SCI_SETSTYLING, pos - startSeg + 1, chAttr); - } else { - if (chAttr != chWhile) - chFlags = 0; - chAttr |= chFlags; - for (unsigned int i = startSeg; i <= pos; i++) { - styleBuf[validLen++] = static_cast<char>(chAttr); - } - } - } - startSeg = pos+1; -} - -void WindowAccessor::SetLevel(int line, int level) { - Platform::SendScintilla(id, SCI_SETFOLDLEVEL, line, level); -} - -void WindowAccessor::Flush() { - startPos = extremePosition; - lenDoc = -1; - if (validLen > 0) { - Platform::SendScintillaPointer(id, SCI_SETSTYLINGEX, validLen, - styleBuf); - validLen = 0; - } -} - -int WindowAccessor::IndentAmount(int line, int *flags, PFNIsCommentLeader pfnIsCommentLeader) { - int end = Length(); - int spaceFlags = 0; - - // Determines the indentation level of the current line and also checks for consistent - // indentation compared to the previous line. - // Indentation is judged consistent when the indentation whitespace of each line lines - // the same or the indentation of one line is a prefix of the other. - - int pos = LineStart(line); - char ch = (*this)[pos]; - int indent = 0; - bool inPrevPrefix = line > 0; - int posPrev = inPrevPrefix ? LineStart(line-1) : 0; - while ((ch == ' ' || ch == '\t') && (pos < end)) { - if (inPrevPrefix) { - char chPrev = (*this)[posPrev++]; - if (chPrev == ' ' || chPrev == '\t') { - if (chPrev != ch) - spaceFlags |= wsInconsistent; - } else { - inPrevPrefix = false; - } - } - if (ch == ' ') { - spaceFlags |= wsSpace; - indent++; - } else { // Tab - spaceFlags |= wsTab; - if (spaceFlags & wsSpace) - spaceFlags |= wsSpaceTab; - indent = (indent / 8 + 1) * 8; - } - ch = (*this)[++pos]; - } - - *flags = spaceFlags; - indent += SC_FOLDLEVELBASE; - // if completely empty line or the start of a comment... - if (isspace(ch) || (pfnIsCommentLeader && (*pfnIsCommentLeader)(*this, pos, end-pos)) ) - return indent | SC_FOLDLEVELWHITEFLAG; - else - return indent; -} - -void WindowAccessor::IndicatorFill(int start, int end, int indicator, int value) { - Platform::SendScintilla(id, SCI_SETINDICATORCURRENT, indicator); - if (value) { - Platform::SendScintilla(id, SCI_SETINDICATORVALUE, value); - Platform::SendScintilla(id, SCI_INDICATORFILLRANGE, start, end - start); - } else { - Platform::SendScintilla(id, SCI_INDICATORCLEARRANGE, start, end - start); - } -} diff --git a/src/stc/scintilla/src/XPM.cxx b/src/stc/scintilla/src/XPM.cxx index 7fc05bb9b4..aeb94a9c62 100644 --- a/src/stc/scintilla/src/XPM.cxx +++ b/src/stc/scintilla/src/XPM.cxx @@ -8,6 +8,9 @@ #include <string.h> #include <stdlib.h> +#include <vector> +#include <map> + #include "Platform.h" #include "XPM.h" @@ -38,16 +41,12 @@ static size_t MeasureLength(const char *s) { return i; } -ColourAllocated XPM::ColourFromCode(int ch) { - return colourCodeTable[ch]->allocated; -#ifdef SLOW - for (int i=0; i<nColours; i++) { - if (codes[i] == ch) { - return colours[i].allocated; - } - } - return colours[0].allocated; -#endif +ColourDesired XPM::ColourDesiredFromCode(int ch) const { + return *colourCodeTable[ch]; +} + +ColourDesired XPM::ColourFromCode(int ch) const { + return *colourCodeTable[ch]; } void XPM::FillRun(Surface *surface, int code, int startX, int y, int x) { @@ -62,7 +61,7 @@ XPM::XPM(const char *textForm) : Init(textForm); } -XPM::XPM(const char * const *linesForm) : +XPM::XPM(const char *const *linesForm) : data(0), codes(0), colours(0), lines(0) { Init(linesForm); } @@ -88,7 +87,7 @@ void XPM::Init(const char *textForm) { } } -void XPM::Init(const char * const *linesForm) { +void XPM::Init(const char *const *linesForm) { Clear(); height = 1; width = 1; @@ -113,7 +112,7 @@ void XPM::Init(const char * const *linesForm) { return; } codes = new char[nColours]; - colours = new ColourPair[nColours]; + colours = new ColourDesired[nColours]; int strings = 1+height+nColours; lines = new char *[strings]; @@ -140,9 +139,9 @@ void XPM::Init(const char * const *linesForm) { codes[c] = colourDef[0]; colourDef += 4; if (*colourDef == '#') { - colours[c].desired.Set(colourDef); + colours[c].Set(colourDef); } else { - colours[c].desired = ColourDesired(0xff, 0xff, 0xff); + colours[c] = ColourDesired(0xff, 0xff, 0xff); codeTransparent = codes[c]; } colourCodeTable[static_cast<unsigned char>(codes[c])] = &(colours[c]); @@ -160,24 +159,6 @@ void XPM::Clear() { lines = 0; } -void XPM::RefreshColourPalette(Palette &pal, bool want) { - if (!data || !codes || !colours || !lines) { - return; - } - for (int i=0; i<nColours; i++) { - pal.WantFind(colours[i], want); - } -} - -void XPM::CopyDesiredColours() { - if (!data || !codes || !colours || !lines) { - return; - } - for (int i=0; i<nColours; i++) { - colours[i].Copy(); - } -} - void XPM::Draw(Surface *surface, PRectangle &rc) { if (!data || !codes || !colours || !lines) { return; @@ -185,7 +166,7 @@ void XPM::Draw(Surface *surface, PRectangle &rc) { // Centre the pixmap int startY = rc.top + (rc.Height() - height) / 2; int startX = rc.left + (rc.Width() - width) / 2; - for (int y=0;y<height;y++) { + for (int y=0; y<height; y++) { int prevCode = 0; int xStartRun = 0; for (int x=0; x<width; x++) { @@ -200,6 +181,21 @@ void XPM::Draw(Surface *surface, PRectangle &rc) { } } +void XPM::PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const { + if (!data || !codes || !colours || !lines || (x<0) || (x >= width) || (y<0) || (y >= height)) { + colour = 0; + transparent = true; + return; + } + int code = lines[y+nColours+1][x]; + transparent = code == codeTransparent; + if (transparent) { + colour = 0; + } else { + colour = ColourDesiredFromCode(code).AsLong(); + } +} + const char **XPM::LinesFormFromTextForm(const char *textForm) { // Build the lines form out of the text form const char **linesForm = 0; @@ -261,16 +257,15 @@ void XPMSet::Clear() { width = -1; } -void XPMSet::Add(int id, const char *textForm) { +void XPMSet::Add(int ident, const char *textForm) { // Invalidate cached dimensions height = -1; width = -1; // Replace if this id already present for (int i = 0; i < len; i++) { - if (set[i]->GetId() == id) { + if (set[i]->GetId() == ident) { set[i]->Init(textForm); - set[i]->CopyDesiredColours(); return; } } @@ -278,8 +273,7 @@ void XPMSet::Add(int id, const char *textForm) { // Not present, so add to end XPM *pxpm = new XPM(textForm); if (pxpm) { - pxpm->SetId(id); - pxpm->CopyDesiredColours(); + pxpm->SetId(ident); if (len == maximum) { maximum += 64; XPM **setNew = new XPM *[maximum]; @@ -294,9 +288,9 @@ void XPMSet::Add(int id, const char *textForm) { } } -XPM *XPMSet::Get(int id) { +XPM *XPMSet::Get(int ident) { for (int i = 0; i < len; i++) { - if (set[i]->GetId() == id) { + if (set[i]->GetId() == ident) { return set[i]; } } @@ -324,3 +318,110 @@ int XPMSet::GetWidth() { } return (width > 0) ? width : 0; } + +RGBAImage::RGBAImage(int width_, int height_, const unsigned char *pixels_) : + height(height_), width(width_) { + if (pixels_) { + pixelBytes.assign(pixels_, pixels_ + CountBytes()); + } else { + pixelBytes.resize(CountBytes()); + } +} + +RGBAImage::RGBAImage(const XPM &xpm) { + height = xpm.GetHeight(); + width = xpm.GetWidth(); + pixelBytes.resize(CountBytes()); + for (int y=0; y<height; y++) { + for (int x=0; x<width; x++) { + ColourDesired colour; + bool transparent = false; + xpm.PixelAt(x, y, colour, transparent); + SetPixel(x, y, colour, transparent ? 0 : 255); + } + } +} + +RGBAImage::~RGBAImage() { +} + +int RGBAImage::CountBytes() const { + return width * height * 4; +} + +const unsigned char *RGBAImage::Pixels() const { + return &pixelBytes[0]; +} + +void RGBAImage::SetPixel(int x, int y, ColourDesired colour, int alpha) { + unsigned char *pixel = &pixelBytes[0] + (y*width+x) * 4; + // RGBA + pixel[0] = colour.GetRed(); + pixel[1] = colour.GetGreen(); + pixel[2] = colour.GetBlue(); + pixel[3] = alpha; +} + +RGBAImageSet::RGBAImageSet() : height(-1), width(-1){ +} + +RGBAImageSet::~RGBAImageSet() { + Clear(); +} + +/// Remove all images. +void RGBAImageSet::Clear() { + for (ImageMap::iterator it=images.begin(); it != images.end(); ++it) { + delete it->second; + it->second = 0; + } + images.clear(); + height = -1; + width = -1; +} + +/// Add an image. +void RGBAImageSet::Add(int ident, RGBAImage *image) { + ImageMap::iterator it=images.find(ident); + if (it == images.end()) { + images[ident] = image; + } else { + delete it->second; + it->second = image; + } + height = -1; + width = -1; +} + +/// Get image by id. +RGBAImage *RGBAImageSet::Get(int ident) { + ImageMap::iterator it = images.find(ident); + if (it != images.end()) { + return it->second; + } + return NULL; +} + +/// Give the largest height of the set. +int RGBAImageSet::GetHeight() const { + if (height < 0) { + for (ImageMap::const_iterator it=images.begin(); it != images.end(); ++it) { + if (height < it->second->GetHeight()) { + height = it->second->GetHeight(); + } + } + } + return (height > 0) ? height : 0; +} + +/// Give the largest width of the set. +int RGBAImageSet::GetWidth() const { + if (width < 0) { + for (ImageMap::const_iterator it=images.begin(); it != images.end(); ++it) { + if (width < it->second->GetWidth()) { + width = it->second->GetWidth(); + } + } + } + return (width > 0) ? width : 0; +} diff --git a/src/stc/scintilla/src/XPM.h b/src/stc/scintilla/src/XPM.h index 07cb5802bd..77ab0806e3 100644 --- a/src/stc/scintilla/src/XPM.h +++ b/src/stc/scintilla/src/XPM.h @@ -23,29 +23,27 @@ class XPM { char *data; char codeTransparent; char *codes; - ColourPair *colours; - ColourAllocated ColourFromCode(int ch); + ColourDesired *colours; + ColourDesired ColourDesiredFromCode(int ch) const; + ColourDesired ColourFromCode(int ch) const; void FillRun(Surface *surface, int code, int startX, int y, int x); char **lines; - ColourPair *colourCodeTable[256]; + ColourDesired *colourCodeTable[256]; public: XPM(const char *textForm); - XPM(const char * const *linesForm); + XPM(const char *const *linesForm); ~XPM(); void Init(const char *textForm); - void Init(const char * const *linesForm); + void Init(const char *const *linesForm); void Clear(); - /// Similar to same named method in ViewStyle: - void RefreshColourPalette(Palette &pal, bool want); - /// No palette used, so just copy the desired colours to the allocated colours - void CopyDesiredColours(); /// Decompose image into runs and use FillRectangle for each run void Draw(Surface *surface, PRectangle &rc); char **InLinesForm() { return lines; } void SetId(int pid_) { pid = pid_; } - int GetId() { return pid; } - int GetHeight() { return height; } - int GetWidth() { return width; } + int GetId() const { return pid; } + int GetHeight() const { return height; } + int GetWidth() const { return width; } + void PixelAt(int x, int y, ColourDesired &colour, bool &transparent) const; static const char **LinesFormFromTextForm(const char *textForm); }; @@ -64,15 +62,59 @@ public: /// Remove all XPMs. void Clear(); /// Add a XPM. - void Add(int id, const char *textForm); + void Add(int ident, const char *textForm); /// Get XPM by id. - XPM *Get(int id); + XPM *Get(int ident); /// Give the largest height of the set. int GetHeight(); /// Give the largest width of the set. int GetWidth(); }; +/** + * An translucent image stoed as a sequence of RGBA bytes. + */ +class RGBAImage { + // Private so RGBAImage objects can not be copied + RGBAImage(const RGBAImage &); + RGBAImage &operator=(const RGBAImage &); + int height; + int width; + std::vector<unsigned char> pixelBytes; +public: + RGBAImage(int width_, int height_, const unsigned char *pixels_); + RGBAImage(const XPM &xpm); + virtual ~RGBAImage(); + int GetHeight() const { return height; } + int GetWidth() const { return width; } + int CountBytes() const; + const unsigned char *Pixels() const; + void SetPixel(int x, int y, ColourDesired colour, int alpha=0xff); +}; + +/** + * A collection of RGBAImage pixmaps indexed by integer id. + */ +class RGBAImageSet { + typedef std::map<int, RGBAImage*> ImageMap; + ImageMap images; + mutable int height; ///< Memorize largest height of the set. + mutable int width; ///< Memorize largest width of the set. +public: + RGBAImageSet(); + ~RGBAImageSet(); + /// Remove all images. + void Clear(); + /// Add an image. + void Add(int ident, RGBAImage *image); + /// Get image by id. + RGBAImage *Get(int ident); + /// Give the largest height of the set. + int GetHeight() const; + /// Give the largest width of the set. + int GetWidth() const; +}; + #ifdef SCI_NAMESPACE } #endif diff --git a/src/stc/scintilla/src/descrip.mms b/src/stc/scintilla/src/descrip.mms deleted file mode 100644 index c56963e73d..0000000000 --- a/src/stc/scintilla/src/descrip.mms +++ /dev/null @@ -1,236 +0,0 @@ -#***************************************************************************** -# * -# Make file for VMS * -# Author : J.Jansen (joukj@hrem.nano.tudelft.nl) * -# Date : 27 September 2011 * -# * -#***************************************************************************** - -.first - define wx [----.include.wx] - -.suffixes : .cpp - -.ifdef __WXMOTIF__ -CXX_DEFINE = /define=(__WX__=1,__WXMOTIF__=1,__USE_STD_IOSTREAM=1)/name=(as_is,short)\ - /assume=(nostdnew,noglobal_array_new)/include=([],[-.src],[-.include]) -CC_DEFINE = /define=(__WX__=1,__WXMOTIF__=1)/name=(as_is,short)\ - /include=([],[-.src],[-.include]) -.else -.ifdef __WXGTK__ -CXX_DEFINE = /define=(__WX__=1,__WXGTK__=1,__USE_STD_IOSTREAM=1)/float=ieee/name=(as_is,short)/ieee=denorm\ - /assume=(nostdnew,noglobal_array_new)/include=([],[-.src],[-.include]) -CC_DEFINE = /define=(__WX__=1,__WXGTK__=1)/float=ieee/name=(as_is,short)/ieee=denorm\ - /include=([],[-.src],[-.include]) -.else -.ifdef __WXGTK2__ -CXX_DEFINE = /define=(__WX__=1,__WXGTK__=1,VMS_GTK2=1,__USE_STD_IOSTREAM=1)/float=ieee/name=(as_is,short)/ieee=denorm\ - /assume=(nostdnew,noglobal_array_new)/include=([],[-.src],[-.include]) -CC_DEFINE = /define=(__WX__=1,__WXGTK__=1,VMS_GTK2=1)/float=ieee/name=(as_is,short)\ - /ieee=denorm/include=([],[-.src],[-.include]) -.else -.ifdef __WXX11__ -CXX_DEFINE = /define=(__WX__=1,__WXX11__=1,__WXUNIVERSAL__==1,__USE_STD_IOSTREAM=1)/float=ieee\ - /name=(as_is,short)/assume=(nostdnew,noglobal_array_new)\ - /include=([],[-.src],[-.include]) -CC_DEFINE = /define=(__WX__=1,__WXX11__=1,__WXUNIVERSAL__==1)/float=ieee\ - /name=(as_is,short)/include=([],[-.src],[-.include]) -.else -CXX_DEFINE = -CC_DEFINE = -.endif -.endif -.endif -.endif - -.cxx.obj : - cxx $(CXXFLAGS)$(CXX_DEFINE) $(MMS$TARGET_NAME).cxx -.cpp.obj : - cxx $(CXXFLAGS)$(CXX_DEFINE) $(MMS$TARGET_NAME).cpp -.c.obj : - cc $(CFLAGS)$(CC_DEFINE) $(MMS$TARGET_NAME).c - -OBJECTS=AutoComplete.obj,CallTip.obj,CellBuffer.obj,CharClassify.obj,\ - ContractionState.obj,Decoration.obj,Document.obj,DocumentAccessor.obj,\ - Editor.obj,ExternalLexer.obj,Indicator.obj,KeyMap.obj,KeyWords.obj,\ - LexAbaqus.obj,LexAda.obj,LexAPDL.obj,LexAsm.obj,LexAsn1.obj,\ - LexASY.obj,LexAU3.obj,LexAVE.obj,LexBaan.obj,LexBash.obj,LexBasic.obj,\ - LexBullant.obj,LexCaml.obj,LexCLW.obj,LexCmake.obj,LexConf.obj,\ - LexCPP.obj,LexCrontab.obj,LexCsound.obj,LexCSS.obj,LexD.obj,\ - LexEiffel.obj,LexErlang.obj,LexEScript.obj,LexFlagship.obj,\ - LexForth.obj,LexFortran.obj,LexGAP.obj,LexGui4Cli.obj,LexHaskell.obj - -OBJECTS1=LexHTML.obj,LexInno.obj,LexKix.obj,LexLisp.obj,LexLout.obj,LexLua.obj,\ - LexMatlab.obj,LexMetapost.obj,LexMMIXAL.obj,LexMPT.obj,LexMSSQL.obj,\ - LexNsis.obj,LexOpal.obj,LexOthers.obj,LexPascal.obj,LexPB.obj,\ - LexPerl.obj,LexPLM.obj,LexPOV.obj,LexProgress.obj,LexPS.obj,\ - LexPython.obj,LexR.obj,LexRebol.obj,LexRuby.obj,LexScriptol.obj,\ - LexSmalltalk.obj,LexSpecman.obj,LexSpice.obj,LexSQL.obj,LexTADS3.obj,\ - LexTCL.obj,LexTeX.obj,LexVB.obj,LexVerilog.obj,LexVHDL.obj,\ - LexYAML.obj,LineMarker.obj,PositionCache.obj,PropSet.obj,RESearch.obj,\ - RunStyles.obj,ScintillaBase.obj,Style.obj,StyleContext.obj,\ - UniConversion.obj,ViewStyle.obj,WindowAccessor.obj,XPM.obj,\ - PerLine.obj,Selection.obj,LexPowerPro.obj,LexCOBOL.obj,\ - LexMagik.obj,LexMarkdown.obj,LexMySQL.obj,LexNimrod.obj,\ - LexPowerShell.obj,LexSML.obj,LexSorcus.obj,LexTACL.obj,LexTAL.obj - -SOURCES=AutoComplete.cxx,CallTip.cxx,CellBuffer.cxx,CharClassify.cxx,\ - ContractionState.cxx,Decoration.cxx,Document.cxx,DocumentAccessor.cxx,\ - Editor.cxx,ExternalLexer.cxx,Indicator.cxx,KeyMap.cxx,KeyWords.cxx,\ - LexAbaqus.cxx,LexAda.cxx,LexAPDL.cxx,LexAsm.cxx,LexAsn1.cxx,\ - LexASY.cxx,LexAU3.cxx,LexAVE.cxx,LexBaan.cxx,LexBash.cxx,LexBasic.cxx,\ - LexBullant.cxx,LexCaml.cxx,LexCLW.cxx,LexCmake.cxx,LexConf.cxx,\ - LexCPP.cxx,LexCrontab.cxx,LexCsound.cxx,LexCSS.cxx,LexD.cxx,\ - LexEiffel.cxx,LexErlang.cxx,LexEScript.cxx,LexFlagship.cxx,\ - LexForth.cxx,LexFortran.cxx,LexGAP.cxx,LexGui4Cli.cxx,LexHaskell.cxx,\ - LexHTML.cxx,LexInno.cxx,LexKix.cxx,LexLisp.cxx,LexLout.cxx,LexLua.cxx,\ - LexMatlab.cxx,LexMetapost.cxx,LexMMIXAL.cxx,LexMPT.cxx,LexMSSQL.cxx,\ - LexNsis.cxx,LexOpal.cxx,LexOthers.cxx,LexPascal.cxx,LexPB.cxx,\ - LexPerl.cxx,LexPLM.cxx,LexPOV.cxx,LexProgress.cxx,LexPS.cxx,\ - LexPython.cxx,LexR.cxx,LexRebol.cxx,LexRuby.cxx,LexScriptol.cxx,\ - LexSmalltalk.cxx,LexSpecman.cxx,LexSpice.cxx,LexSQL.cxx,LexTADS3.cxx,\ - LexTCL.cxx,LexTeX.cxx,LexVB.cxx,LexVerilog.cxx,LexVHDL.cxx,\ - LexYAML.cxx,LineMarker.cxx,PositionCache.cxx,PropSet.cxx,RESearch.cxx,\ - RunStyles.cxx,ScintillaBase.cxx,Style.cxx,StyleContext.cxx,\ - UniConversion.cxx,ViewStyle.cxx,WindowAccessor.cxx,XPM.cxx,\ - PerLine.cxx,Selection.cxx,LexPowerPro.cxx,LexCOBOL.cxx,\ - LexMagik.cxx,LexMarkdown.cxx,LexMySQL.cxx,LexNimrod.cxx,\ - LexPowerShell.cxx,LexSML.cxx,LexSorcus.cxx,LexTACL.cxx,LexTAL.cxx - -all : $(SOURCES) - $(MMS)$(MMSQUALIFIERS) $(OBJECTS) - $(MMS)$(MMSQUALIFIERS) $(OBJECTS1) -.ifdef __WXMOTIF__ - library [----.lib]libwx_motif.olb $(OBJECTS) - library [----.lib]libwx_motif.olb $(OBJECTS1) - If f$getsyi("HW_MODEL") .le. 2048 then library [----.lib]libwx_motif.olb [.CXX_REPOSITORY]*.obj -.else -.ifdef __WXGTK__ - library [----.lib]libwx_gtk.olb $(OBJECTS) - library [----.lib]libwx_gtk.olb $(OBJECTS1) - If f$getsyi("HW_MODEL") .le. 2048 then library [----.lib]libwx_gtk.olb [.CXX_REPOSITORY]*.obj -.else -.ifdef __WXGTK2__ - library [----.lib]libwx_gtk2.olb $(OBJECTS) - library [----.lib]libwx_gtk2.olb $(OBJECTS1) - If f$getsyi("HW_MODEL") .le. 2048 then library [----.lib]libwx_gtk2.olb [.CXX_REPOSITORY]*.obj -.else -.ifdef __WXX11__ - library [----.lib]libwx_x11_univ.olb $(OBJECTS) - library [----.lib]libwx_x11_univ.olb $(OBJECTS1) - If f$getsyi("HW_MODEL") .le. 2048 then library [----.lib]libwx_x11_univ.olb [.CXX_REPOSITORY]*.obj -.endif -.endif -.endif -.endif - -$(OBJECTS) : [----.include.wx]setup.h -$(OBJECTS1) : [----.include.wx]setup.h - -AutoComplete.obj : AutoComplete.cxx -CallTip.obj : CallTip.cxx -CellBuffer.obj : CellBuffer.cxx -CharClassify.obj : CharClassify.cxx -ContractionState.obj : ContractionState.cxx -Decoration.obj : Decoration.cxx -Document.obj : Document.cxx -DocumentAccessor.obj : DocumentAccessor.cxx -Editor.obj : Editor.cxx - cxx $(CXXFLAGS)$(CXX_DEFINE)/nowarn Editor.cxx -ExternalLexer.obj : ExternalLexer.cxx -Indicator.obj : Indicator.cxx -KeyMap.obj : KeyMap.cxx -KeyWords.obj : KeyWords.cxx -LexAbaqus.obj : LexAbaqus.cxx -LexAda.obj : LexAda.cxx -LexAPDL.obj : LexAPDL.cxx -LexAsm.obj : LexAsm.cxx -LexAsn1.obj : LexAsn1.cxx -LexASY.obj : LexASY.cxx -LexAU3.obj : LexAU3.cxx -LexAVE.obj : LexAVE.cxx -LexBaan.obj : LexBaan.cxx -LexBash.obj : LexBash.cxx -LexBasic.obj : LexBasic.cxx -LexBullant.obj : LexBullant.cxx -LexCaml.obj : LexCaml.cxx -LexCLW.obj : LexCLW.cxx -LexCmake.obj : LexCmake.cxx -LexConf.obj : LexConf.cxx -LexCPP.obj : LexCPP.cxx -LexCrontab.obj : LexCrontab.cxx -LexCsound.obj : LexCsound.cxx -LexCSS.obj : LexCSS.cxx -LexD.obj : LexD.cxx - cxx $(CXXFLAGS)$(CXX_DEFINE)/nowarn LexD.cxx -LexEiffel.obj : LexEiffel.cxx -LexErlang.obj : LexErlang.cxx -LexEScript.obj : LexEScript.cxx -LexFlagship.obj : LexFlagship.cxx -LexForth.obj : LexForth.cxx -LexFortran.obj : LexFortran.cxx -LexGAP.obj : LexGAP.cxx -LexGui4Cli.obj : LexGui4Cli.cxx -LexHaskell.obj : LexHaskell.cxx -LexHTML.obj : LexHTML.cxx -LexInno.obj : LexInno.cxx -LexKix.obj : LexKix.cxx -LexLisp.obj : LexLisp.cxx -LexLout.obj : LexLout.cxx -LexLua.obj : LexLua.cxx -LexMatlab.obj : LexMatlab.cxx -LexMetapost.obj : LexMetapost.cxx -LexMMIXAL.obj : LexMMIXAL.cxx -LexMPT.obj : LexMPT.cxx -LexMSSQL.obj : LexMSSQL.cxx -LexNsis.obj : LexNsis.cxx -LexOpal.obj : LexOpal.cxx -LexOthers.obj : LexOthers.cxx -LexPascal.obj : LexPascal.cxx -LexPB.obj : LexPB.cxx -LexPerl.obj : LexPerl.cxx -LexPLM.obj : LexPLM.cxx -LexPOV.obj : LexPOV.cxx -LexProgress.obj : LexProgress.cxx -LexPS.obj : LexPS.cxx -LexPython.obj : LexPython.cxx -LexR.obj : LexR.cxx -LexRebol.obj : LexRebol.cxx -LexRuby.obj : LexRuby.cxx -LexScriptol.obj : LexScriptol.cxx -LexSmalltalk.obj : LexSmalltalk.cxx -LexSpecman.obj : LexSpecman.cxx -LexSpice.obj : LexSpice.cxx -LexSQL.obj : LexSQL.cxx -LexTADS3.obj : LexTADS3.cxx -LexTCL.obj : LexTCL.cxx -LexTeX.obj : LexTeX.cxx -LexVB.obj : LexVB.cxx -LexVerilog.obj : LexVerilog.cxx -LexVHDL.obj : LexVHDL.cxx -LexYAML.obj : LexYAML.cxx -LineMarker.obj : LineMarker.cxx -PositionCache.obj : PositionCache.cxx -PropSet.obj : PropSet.cxx -RESearch.obj : RESearch.cxx -RunStyles.obj : RunStyles.cxx -ScintillaBase.obj : ScintillaBase.cxx -Style.obj : Style.cxx -StyleContext.obj : StyleContext.cxx -UniConversion.obj : UniConversion.cxx -ViewStyle.obj : ViewStyle.cxx -WindowAccessor.obj : WindowAccessor.cxx -XPM.obj : XPM.cxx -PerLine.obj : PerLine.cxx -Selection.obj : Selection.cxx -LexPowerPro.obj : LexPowerPro.cxx -LexCOBOL.obj : LexCOBOL.cxx -LexMagik.obj : LexMagik.cxx -LexMarkdown.obj : LexMarkdown.cxx -LexMySQL.obj : LexMySQL.cxx -LexNimrod.obj : LexNimrod.cxx -LexPowerShell.obj : LexPowerShell.cxx -LexSML.obj : LexSML.cxx -LexSorcus.obj : LexSorcus.cxx -LexTACL.obj : LexTACL.cxx -LexTAL.obj : LexTAL.cxx -- 2.45.2