From 28e80e5b58170b9211168b9c631ddab69fd2b101 Mon Sep 17 00:00:00 2001 From: ARATA Mizuki Date: Sat, 25 Apr 2015 23:49:22 +0900 Subject: [PATCH] Update Scintilla from 3.5.2 to 3.5.5 --- Makefile.in | 4 + build/bakefiles/scintilla.bkl | 1 + build/msw/makefile.bcc | 4 + build/msw/makefile.gcc | 4 + build/msw/makefile.vc | 4 + build/msw/wx_vc7_wxscintilla.vcproj | 3 + build/msw/wx_vc8_wxscintilla.vcproj | 4 + build/msw/wx_vc9_wxscintilla.vcproj | 4 + include/wx/stc/stc.h | 72 +- interface/wx/stc/stc.h | 92 +- src/stc/gen_iface.py | 22 + src/stc/scintilla/README.txt | 2 +- src/stc/scintilla/include/Platform.h | 7 +- src/stc/scintilla/include/SciLexer.h | 27 + src/stc/scintilla/include/Scintilla.h | 18 +- src/stc/scintilla/include/Scintilla.iface | 106 ++- src/stc/scintilla/lexers/LexBash.cxx | 14 +- src/stc/scintilla/lexers/LexCPP.cxx | 13 +- src/stc/scintilla/lexers/LexHex.cxx | 1045 +++++++++++++++++++++ src/stc/scintilla/lexers/LexRuby.cxx | 807 ++++++++-------- src/stc/scintilla/lexers/LexRust.cxx | 4 +- src/stc/scintilla/lexers/LexSQL.cxx | 59 +- src/stc/scintilla/lexers/LexTCL.cxx | 365 ++++--- src/stc/scintilla/lexers/LexVHDL.cxx | 17 +- src/stc/scintilla/lexers/LexVerilog.cxx | 1000 +++++++++++++++++--- src/stc/scintilla/lexlib/LexAccessor.h | 3 + src/stc/scintilla/lexlib/SubStyles.h | 3 +- src/stc/scintilla/lexlib/WordList.cxx | 2 + src/stc/scintilla/src/AutoComplete.cxx | 4 +- src/stc/scintilla/src/Catalogue.cxx | 3 + src/stc/scintilla/src/CellBuffer.cxx | 5 + src/stc/scintilla/src/Document.cxx | 63 +- src/stc/scintilla/src/Document.h | 2 + src/stc/scintilla/src/EditModel.cxx | 1 + src/stc/scintilla/src/EditModel.h | 1 + src/stc/scintilla/src/EditView.cxx | 63 +- src/stc/scintilla/src/EditView.h | 1 + src/stc/scintilla/src/Editor.cxx | 191 ++-- src/stc/scintilla/src/Editor.h | 3 + src/stc/scintilla/src/Indicator.cxx | 69 +- src/stc/scintilla/src/Indicator.h | 34 +- src/stc/scintilla/src/MarginView.cxx | 18 +- src/stc/scintilla/src/PositionCache.cxx | 14 +- src/stc/scintilla/src/PositionCache.h | 2 +- src/stc/scintilla/src/RESearch.cxx | 4 +- src/stc/scintilla/src/ScintillaBase.cxx | 26 +- src/stc/scintilla/src/UniConversion.cxx | 22 +- src/stc/scintilla/src/UniConversion.h | 10 +- src/stc/scintilla/src/ViewStyle.cxx | 16 + src/stc/scintilla/src/ViewStyle.h | 2 + src/stc/stc.cpp | 76 +- src/stc/stc.cpp.in | 2 +- 52 files changed, 3372 insertions(+), 966 deletions(-) create mode 100644 src/stc/scintilla/lexers/LexHex.cxx diff --git a/Makefile.in b/Makefile.in index 0322d80ad1..947dd80d4c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -261,6 +261,7 @@ WXSCINTILLA_OBJECTS = \ wxscintilla_LexGAP.o \ wxscintilla_LexGui4Cli.o \ wxscintilla_LexHaskell.o \ + wxscintilla_LexHex.o \ wxscintilla_LexHTML.o \ wxscintilla_LexInno.o \ wxscintilla_LexKix.o \ @@ -17140,6 +17141,9 @@ wxscintilla_LexGui4Cli.o: $(srcdir)/src/stc/scintilla/lexers/LexGui4Cli.cxx wxscintilla_LexHaskell.o: $(srcdir)/src/stc/scintilla/lexers/LexHaskell.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexHaskell.cxx +wxscintilla_LexHex.o: $(srcdir)/src/stc/scintilla/lexers/LexHex.cxx + $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexHex.cxx + wxscintilla_LexHTML.o: $(srcdir)/src/stc/scintilla/lexers/LexHTML.cxx $(CXXC) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(srcdir)/src/stc/scintilla/lexers/LexHTML.cxx diff --git a/build/bakefiles/scintilla.bkl b/build/bakefiles/scintilla.bkl index 37065e76f6..06d41a15b1 100644 --- a/build/bakefiles/scintilla.bkl +++ b/build/bakefiles/scintilla.bkl @@ -94,6 +94,7 @@ src/stc/scintilla/lexers/LexGAP.cxx src/stc/scintilla/lexers/LexGui4Cli.cxx src/stc/scintilla/lexers/LexHaskell.cxx + src/stc/scintilla/lexers/LexHex.cxx src/stc/scintilla/lexers/LexHTML.cxx src/stc/scintilla/lexers/LexInno.cxx src/stc/scintilla/lexers/LexKix.cxx diff --git a/build/msw/makefile.bcc b/build/msw/makefile.bcc index 7ac4fe1644..aab7be56ea 100644 --- a/build/msw/makefile.bcc +++ b/build/msw/makefile.bcc @@ -242,6 +242,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexGAP.obj \ $(OBJS)\wxscintilla_LexGui4Cli.obj \ $(OBJS)\wxscintilla_LexHaskell.obj \ + $(OBJS)\wxscintilla_LexHex.obj \ $(OBJS)\wxscintilla_LexHTML.obj \ $(OBJS)\wxscintilla_LexInno.obj \ $(OBJS)\wxscintilla_LexKix.obj \ @@ -6022,6 +6023,9 @@ $(OBJS)\wxscintilla_LexGui4Cli.obj: ..\..\src\stc\scintilla\lexers\LexGui4Cli.cx $(OBJS)\wxscintilla_LexHaskell.obj: ..\..\src\stc\scintilla\lexers\LexHaskell.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHaskell.cxx +$(OBJS)\wxscintilla_LexHex.obj: ..\..\src\stc\scintilla\lexers\LexHex.cxx + $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHex.cxx + $(OBJS)\wxscintilla_LexHTML.obj: ..\..\src\stc\scintilla\lexers\LexHTML.cxx $(CXX) -q -c -P -o$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHTML.cxx diff --git a/build/msw/makefile.gcc b/build/msw/makefile.gcc index d0d1a013c8..e9a450f975 100644 --- a/build/msw/makefile.gcc +++ b/build/msw/makefile.gcc @@ -230,6 +230,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexGAP.o \ $(OBJS)\wxscintilla_LexGui4Cli.o \ $(OBJS)\wxscintilla_LexHaskell.o \ + $(OBJS)\wxscintilla_LexHex.o \ $(OBJS)\wxscintilla_LexHTML.o \ $(OBJS)\wxscintilla_LexInno.o \ $(OBJS)\wxscintilla_LexKix.o \ @@ -6197,6 +6198,9 @@ $(OBJS)\wxscintilla_LexGui4Cli.o: ../../src/stc/scintilla/lexers/LexGui4Cli.cxx $(OBJS)\wxscintilla_LexHaskell.o: ../../src/stc/scintilla/lexers/LexHaskell.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< +$(OBJS)\wxscintilla_LexHex.o: ../../src/stc/scintilla/lexers/LexHex.cxx + $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< + $(OBJS)\wxscintilla_LexHTML.o: ../../src/stc/scintilla/lexers/LexHTML.cxx $(CXX) -c -o $@ $(WXSCINTILLA_CXXFLAGS) $(CPPDEPS) $< diff --git a/build/msw/makefile.vc b/build/msw/makefile.vc index fe5f95662b..85e140a1fe 100644 --- a/build/msw/makefile.vc +++ b/build/msw/makefile.vc @@ -253,6 +253,7 @@ WXSCINTILLA_OBJECTS = \ $(OBJS)\wxscintilla_LexGAP.obj \ $(OBJS)\wxscintilla_LexGui4Cli.obj \ $(OBJS)\wxscintilla_LexHaskell.obj \ + $(OBJS)\wxscintilla_LexHex.obj \ $(OBJS)\wxscintilla_LexHTML.obj \ $(OBJS)\wxscintilla_LexInno.obj \ $(OBJS)\wxscintilla_LexKix.obj \ @@ -6714,6 +6715,9 @@ $(OBJS)\wxscintilla_LexGui4Cli.obj: ..\..\src\stc\scintilla\lexers\LexGui4Cli.cx $(OBJS)\wxscintilla_LexHaskell.obj: ..\..\src\stc\scintilla\lexers\LexHaskell.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHaskell.cxx +$(OBJS)\wxscintilla_LexHex.obj: ..\..\src\stc\scintilla\lexers\LexHex.cxx + $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHex.cxx + $(OBJS)\wxscintilla_LexHTML.obj: ..\..\src\stc\scintilla\lexers\LexHTML.cxx $(CXX) /c /nologo /TP /Fo$@ $(WXSCINTILLA_CXXFLAGS) ..\..\src\stc\scintilla\lexers\LexHTML.cxx diff --git a/build/msw/wx_vc7_wxscintilla.vcproj b/build/msw/wx_vc7_wxscintilla.vcproj index 90af102689..a9bd1621bd 100644 --- a/build/msw/wx_vc7_wxscintilla.vcproj +++ b/build/msw/wx_vc7_wxscintilla.vcproj @@ -421,6 +421,9 @@ + + diff --git a/build/msw/wx_vc8_wxscintilla.vcproj b/build/msw/wx_vc8_wxscintilla.vcproj index 418e0fe9c9..c5888d7105 100644 --- a/build/msw/wx_vc8_wxscintilla.vcproj +++ b/build/msw/wx_vc8_wxscintilla.vcproj @@ -910,6 +910,10 @@ RelativePath="..\..\src\stc\scintilla\lexers\LexHaskell.cxx" > + + diff --git a/build/msw/wx_vc9_wxscintilla.vcproj b/build/msw/wx_vc9_wxscintilla.vcproj index 479161d738..61b58586ce 100644 --- a/build/msw/wx_vc9_wxscintilla.vcproj +++ b/build/msw/wx_vc9_wxscintilla.vcproj @@ -906,6 +906,10 @@ RelativePath="..\..\src\stc\scintilla\lexers\LexHaskell.cxx" > + + diff --git a/include/wx/stc/stc.h b/include/wx/stc/stc.h index 381596251d..abc8de19bc 100644 --- a/include/wx/stc/stc.h +++ b/include/wx/stc/stc.h @@ -192,6 +192,9 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_INDIC_DOTBOX 12 #define wxSTC_INDIC_SQUIGGLEPIXMAP 13 #define wxSTC_INDIC_COMPOSITIONTHICK 14 +#define wxSTC_INDIC_COMPOSITIONTHIN 15 +#define wxSTC_INDIC_FULLBOX 16 +#define wxSTC_INDIC_TEXTFORE 17 #define wxSTC_INDIC_IME 32 #define wxSTC_INDIC_IME_MAX 35 #define wxSTC_INDIC_MAX 35 @@ -200,6 +203,9 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_INDIC1_MASK 0x40 #define wxSTC_INDIC2_MASK 0x80 #define wxSTC_INDICS_MASK 0xE0 +#define wxSTC_INDICVALUEBIT 0x1000000 +#define wxSTC_INDICVALUEMASK 0xFFFFFF +#define wxSTC_INDICFLAG_VALUEFORE 1 #define wxSTC_IV_NONE 0 #define wxSTC_IV_REAL 1 #define wxSTC_IV_LOOKFORWARD 2 @@ -539,6 +545,9 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_LEX_DMIS 114 #define wxSTC_LEX_REGISTRY 115 #define wxSTC_LEX_BIBTEX 116 +#define wxSTC_LEX_SREC 117 +#define wxSTC_LEX_IHEX 118 +#define wxSTC_LEX_TEHEX 119 /// When a lexer specifies its language as SCLEX_AUTOMATIC it receives a /// value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -1422,6 +1431,11 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_V_IDENTIFIER 11 #define wxSTC_V_STRINGEOL 12 #define wxSTC_V_USER 19 +#define wxSTC_V_COMMENT_WORD 20 +#define wxSTC_V_INPUT 21 +#define wxSTC_V_OUTPUT 22 +#define wxSTC_V_INOUT 23 +#define wxSTC_V_PORT_CONNECT 24 /// Lexical states for SCLEX_KIX #define wxSTC_KIX_DEFAULT 0 @@ -2366,6 +2380,27 @@ class WXDLLIMPEXP_FWD_CORE wxScrollBar; #define wxSTC_BIBTEX_VALUE 5 #define wxSTC_BIBTEX_COMMENT 6 +/// Lexical state for SCLEX_SREC +#define wxSTC_HEX_DEFAULT 0 +#define wxSTC_HEX_RECSTART 1 +#define wxSTC_HEX_RECTYPE 2 +#define wxSTC_HEX_RECTYPE_UNKNOWN 3 +#define wxSTC_HEX_BYTECOUNT 4 +#define wxSTC_HEX_BYTECOUNT_WRONG 5 +#define wxSTC_HEX_NOADDRESS 6 +#define wxSTC_HEX_DATAADDRESS 7 +#define wxSTC_HEX_RECCOUNT 8 +#define wxSTC_HEX_STARTADDRESS 9 +#define wxSTC_HEX_ADDRESSFIELD_UNKNOWN 10 +#define wxSTC_HEX_EXTENDEDADDRESS 11 +#define wxSTC_HEX_DATA_ODD 12 +#define wxSTC_HEX_DATA_EVEN 13 +#define wxSTC_HEX_DATA_UNKNOWN 14 +#define wxSTC_HEX_DATA_EMPTY 15 +#define wxSTC_HEX_CHECKSUM 16 +#define wxSTC_HEX_CHECKSUM_WRONG 17 +#define wxSTC_HEX_GARBAGE 18 + //}}} //---------------------------------------------------------------------- @@ -2813,6 +2848,7 @@ public: // Retrieve the text of the line containing the caret. // Returns the index of the caret on the line. + // Result is NUL-terminated. #ifdef SWIG wxString GetCurLine(int* OUTPUT); #else @@ -3108,6 +3144,24 @@ public: // Retrieve whether indicator drawn under or over text. bool IndicatorGetUnder(int indic) const; + // Set a hover indicator to plain, squiggle or TT. + void IndicatorSetHoverStyle(int indic, int style); + + // Retrieve the hover style of an indicator. + int IndicatorGetHoverStyle(int indic) const; + + // Set the foreground hover colour of an indicator. + void IndicatorSetHoverForeground(int indic, const wxColour& fore); + + // Retrieve the foreground hover colour of an indicator. + wxColour IndicatorGetHoverForeground(int indic) const; + + // Set the attributes of an indicator. + void IndicatorSetFlags(int indic, int flags); + + // Retrieve the attributes of an indicator. + int IndicatorGetFlags(int indic) const; + // Set the foreground colour of all whitespace and whether to use this setting. void SetWhitespaceForeground(bool useSetting, const wxColour& fore); @@ -3466,6 +3520,12 @@ public: // Get the position that ends the target. int GetTargetEnd() const; + // Sets both the start and end of the target in one call. + void SetTargetRange(int start, int end); + + // Retrieve the text in the target. + wxString GetTargetText() const; + // Replace the target text with the argument text. // Text is counted so it can contain NULs. // Returns the length of the replacement text. @@ -3719,6 +3779,7 @@ public: int GetMultiPaste() const; // Retrieve the value of a tag from a regular expression search. + // Result is NUL-terminated. wxString GetTag(int tagNumber) const; // Make the target range start and end be the same as the selection range start and end. @@ -4322,12 +4383,6 @@ public: // the range of a call to GetRangePointer. int GetGapPosition() const; - // Always interpret keyboard input as Unicode - void SetKeysUnicode(bool keysUnicode); - - // Are keys always interpreted as Unicode? - bool GetKeysUnicode() const; - // Set the alpha fill colour of the given indicator. void IndicatorSetAlpha(int indicator, int alpha); @@ -4637,6 +4692,7 @@ public: void SetRepresentation(const wxString& encodedCharacter, const wxString& representation); // Set the way a character is drawn. + // Result is NUL-terminated. wxString GetRepresentation(const wxString& encodedCharacter) const; // Remove a character representation. @@ -4684,15 +4740,18 @@ public: void* PrivateLexerCall(int operation, void* pointer); // Retrieve a '\n' separated list of properties understood by the current lexer. + // Result is NUL-terminated. wxString PropertyNames() const; // Retrieve the type of a property. int PropertyType(const wxString& name); // Describe a property. + // Result is NUL-terminated. wxString DescribeProperty(const wxString& name) const; // Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer. + // Result is NUL-terminated. wxString DescribeKeyWordSets() const; // Bit set of LineEndType enumertion for which line ends beyond the standard @@ -4725,6 +4784,7 @@ public: int DistanceToSecondaryStyles() const; // Get the set of base styles that can be extended with sub styles + // Result is NUL-terminated. wxString GetSubStyleBases() const; //}}} diff --git a/interface/wx/stc/stc.h b/interface/wx/stc/stc.h index 80f4a21676..62ed006e2a 100644 --- a/interface/wx/stc/stc.h +++ b/interface/wx/stc/stc.h @@ -148,6 +148,9 @@ #define wxSTC_INDIC_DOTBOX 12 #define wxSTC_INDIC_SQUIGGLEPIXMAP 13 #define wxSTC_INDIC_COMPOSITIONTHICK 14 +#define wxSTC_INDIC_COMPOSITIONTHIN 15 +#define wxSTC_INDIC_FULLBOX 16 +#define wxSTC_INDIC_TEXTFORE 17 #define wxSTC_INDIC_IME 32 #define wxSTC_INDIC_IME_MAX 35 #define wxSTC_INDIC_MAX 35 @@ -156,6 +159,9 @@ #define wxSTC_INDIC1_MASK 0x40 #define wxSTC_INDIC2_MASK 0x80 #define wxSTC_INDICS_MASK 0xE0 +#define wxSTC_INDICVALUEBIT 0x1000000 +#define wxSTC_INDICVALUEMASK 0xFFFFFF +#define wxSTC_INDICFLAG_VALUEFORE 1 #define wxSTC_IV_NONE 0 #define wxSTC_IV_REAL 1 #define wxSTC_IV_LOOKFORWARD 2 @@ -495,6 +501,9 @@ #define wxSTC_LEX_DMIS 114 #define wxSTC_LEX_REGISTRY 115 #define wxSTC_LEX_BIBTEX 116 +#define wxSTC_LEX_SREC 117 +#define wxSTC_LEX_IHEX 118 +#define wxSTC_LEX_TEHEX 119 /// When a lexer specifies its language as SCLEX_AUTOMATIC it receives a /// value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -1378,6 +1387,11 @@ #define wxSTC_V_IDENTIFIER 11 #define wxSTC_V_STRINGEOL 12 #define wxSTC_V_USER 19 +#define wxSTC_V_COMMENT_WORD 20 +#define wxSTC_V_INPUT 21 +#define wxSTC_V_OUTPUT 22 +#define wxSTC_V_INOUT 23 +#define wxSTC_V_PORT_CONNECT 24 /// Lexical states for SCLEX_KIX #define wxSTC_KIX_DEFAULT 0 @@ -2322,6 +2336,27 @@ #define wxSTC_BIBTEX_VALUE 5 #define wxSTC_BIBTEX_COMMENT 6 +/// Lexical state for SCLEX_SREC +#define wxSTC_HEX_DEFAULT 0 +#define wxSTC_HEX_RECSTART 1 +#define wxSTC_HEX_RECTYPE 2 +#define wxSTC_HEX_RECTYPE_UNKNOWN 3 +#define wxSTC_HEX_BYTECOUNT 4 +#define wxSTC_HEX_BYTECOUNT_WRONG 5 +#define wxSTC_HEX_NOADDRESS 6 +#define wxSTC_HEX_DATAADDRESS 7 +#define wxSTC_HEX_RECCOUNT 8 +#define wxSTC_HEX_STARTADDRESS 9 +#define wxSTC_HEX_ADDRESSFIELD_UNKNOWN 10 +#define wxSTC_HEX_EXTENDEDADDRESS 11 +#define wxSTC_HEX_DATA_ODD 12 +#define wxSTC_HEX_DATA_EVEN 13 +#define wxSTC_HEX_DATA_UNKNOWN 14 +#define wxSTC_HEX_DATA_EMPTY 15 +#define wxSTC_HEX_CHECKSUM 16 +#define wxSTC_HEX_CHECKSUM_WRONG 17 +#define wxSTC_HEX_GARBAGE 18 + //}}} // Commands that can be bound to keystrokes {{{ @@ -2906,6 +2941,7 @@ public: /** Retrieve the text of the line containing the caret. Returns the index of the caret on the line. + Result is NUL-terminated. */ wxString GetCurLine(int* linePos=NULL); @@ -3384,6 +3420,36 @@ public: */ bool IndicatorGetUnder(int indic) const; + /** + Set a hover indicator to plain, squiggle or TT. + */ + void IndicatorSetHoverStyle(int indic, int style); + + /** + Retrieve the hover style of an indicator. + */ + int IndicatorGetHoverStyle(int indic) const; + + /** + Set the foreground hover colour of an indicator. + */ + void IndicatorSetHoverForeground(int indic, const wxColour& fore); + + /** + Retrieve the foreground hover colour of an indicator. + */ + wxColour IndicatorGetHoverForeground(int indic) const; + + /** + Set the attributes of an indicator. + */ + void IndicatorSetFlags(int indic, int flags); + + /** + Retrieve the attributes of an indicator. + */ + int IndicatorGetFlags(int indic) const; + /** Set the foreground colour of all whitespace and whether to use this setting. */ @@ -3964,6 +4030,16 @@ public: */ int GetTargetEnd() const; + /** + Sets both the start and end of the target in one call. + */ + void SetTargetRange(int start, int end); + + /** + Retrieve the text in the target. + */ + wxString GetTargetText() const; + /** Replace the target text with the argument text. Text is counted so it can contain NULs. @@ -4372,6 +4448,7 @@ public: /** Retrieve the value of a tag from a regular expression search. + Result is NUL-terminated. */ wxString GetTag(int tagNumber) const; @@ -5346,16 +5423,6 @@ public: */ int GetGapPosition() const; - /** - Always interpret keyboard input as Unicode - */ - void SetKeysUnicode(bool keysUnicode); - - /** - Are keys always interpreted as Unicode? - */ - bool GetKeysUnicode() const; - /** Set the alpha fill colour of the given indicator. */ @@ -5852,6 +5919,7 @@ public: /** Set the way a character is drawn. + Result is NUL-terminated. */ wxString GetRepresentation(const wxString& encodedCharacter) const; @@ -5929,6 +5997,7 @@ public: /** Retrieve a '\n' separated list of properties understood by the current lexer. + Result is NUL-terminated. */ wxString PropertyNames() const; @@ -5939,11 +6008,13 @@ public: /** Describe a property. + Result is NUL-terminated. */ wxString DescribeProperty(const wxString& name) const; /** Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer. + Result is NUL-terminated. */ wxString DescribeKeyWordSets() const; @@ -5996,6 +6067,7 @@ public: /** Get the set of base styles that can be extended with sub styles + Result is NUL-terminated. */ wxString GetSubStyleBases() const; diff --git a/src/stc/gen_iface.py b/src/stc/gen_iface.py index 730dd23116..19b2875fb8 100755 --- a/src/stc/gen_iface.py +++ b/src/stc/gen_iface.py @@ -371,6 +371,12 @@ methodOverrideMap = { 'IndicGetFore' : ('IndicatorGetForeground', 0, 0, 0), 'IndicSetUnder': ('IndicatorSetUnder', 0, 0, 0), 'IndicGetUnder': ('IndicatorGetUnder', 0, 0, 0), + 'IndicSetHoverStyle': ('IndicatorSetHoverStyle', 0, 0, 0), + 'IndicGetHoverStyle': ('IndicatorGetHoverStyle', 0, 0, 0), + 'IndicSetHoverFore': ('IndicatorSetHoverForeground', 0, 0, 0), + 'IndicGetHoverFore': ('IndicatorGetHoverForeground', 0, 0, 0), + 'IndicSetFlags': ('IndicatorSetFlags', 0, 0, 0), + 'IndicGetFlags': ('IndicatorGetFlags', 0, 0, 0), 'SetWhitespaceFore' : ('SetWhitespaceForeground', 0, 0, 0), 'SetWhitespaceBack' : ('SetWhitespaceBackground', 0, 0, 0), @@ -588,6 +594,22 @@ methodOverrideMap = { 'GetDirectFunction' : (None, 0, 0, 0), 'GetDirectPointer' : (None, 0, 0, 0), + 'GetTargetText' : + (0, + 'wxString %s() const;', + + '''wxString %s() const { + int startPos = GetTargetStart(); + int endPos = GetTargetEnd(); + wxMemoryBuffer mbuf(endPos-startPos+1); // leave room for the null... + char* buf = (char*)mbuf.GetWriteBuf(endPos-startPos+1); + SendMsg(%s, 0, (sptr_t)buf); + mbuf.UngetWriteBuf(endPos-startPos); + mbuf.AppendByte(0); + return stc2wx(buf);''', + + 0), + 'CallTipPosStart' : ('CallTipPosAtStart', 0, 0, 0), 'CallTipSetPosStart': ('CallTipSetPosAtStart', 0, 0, 0), 'CallTipSetHlt' : ('CallTipSetHighlight', 0, 0, 0), diff --git a/src/stc/scintilla/README.txt b/src/stc/scintilla/README.txt index 94198e0a47..9bedc7a813 100644 --- a/src/stc/scintilla/README.txt +++ b/src/stc/scintilla/README.txt @@ -3,7 +3,7 @@ directories from the Scintilla source distribution. All other code needed to implement Scintilla on top of wxWidgets is located in the directory above this one. -The current version of the Scintilla code is 3.5.2 +The current version of the Scintilla code is 3.5.5 These are the basic steps needed to update the version of Scintilla used by wxSTC. diff --git a/src/stc/scintilla/include/Platform.h b/src/stc/scintilla/include/Platform.h index 7c6875e12e..4ef7e2aab2 100644 --- a/src/stc/scintilla/include/Platform.h +++ b/src/stc/scintilla/include/Platform.h @@ -144,6 +144,11 @@ public: return (pt.x >= left) && (pt.x <= right) && (pt.y >= top) && (pt.y <= bottom); } + bool ContainsWholePixel(Point pt) const { + // Does the rectangle contain all of the pixel to left/below the point + return (pt.x >= left) && ((pt.x+1) <= right) && + (pt.y >= top) && ((pt.y+1) <= bottom); + } bool Contains(PRectangle rc) const { return (rc.left >= left) && (rc.right <= right) && (rc.top >= top) && (rc.bottom <= bottom); @@ -266,7 +271,6 @@ struct FontParameters { class Font { protected: FontID fid; - // Private so Font objects can not be copied Font(const Font &); Font &operator=(const Font &); @@ -280,7 +284,6 @@ public: FontID GetID() { return fid; } // Alias another font - caller guarantees not to Release void SetID(FontID fid_) { fid = fid_; } - friend class Surface; friend class SurfaceImpl; }; diff --git a/src/stc/scintilla/include/SciLexer.h b/src/stc/scintilla/include/SciLexer.h index dc75a98b6a..034060a4bb 100644 --- a/src/stc/scintilla/include/SciLexer.h +++ b/src/stc/scintilla/include/SciLexer.h @@ -129,6 +129,9 @@ #define SCLEX_DMIS 114 #define SCLEX_REGISTRY 115 #define SCLEX_BIBTEX 116 +#define SCLEX_SREC 117 +#define SCLEX_IHEX 118 +#define SCLEX_TEHEX 119 #define SCLEX_AUTOMATIC 1000 #define SCE_P_DEFAULT 0 #define SCE_P_COMMENTLINE 1 @@ -898,6 +901,11 @@ #define SCE_V_IDENTIFIER 11 #define SCE_V_STRINGEOL 12 #define SCE_V_USER 19 +#define SCE_V_COMMENT_WORD 20 +#define SCE_V_INPUT 21 +#define SCE_V_OUTPUT 22 +#define SCE_V_INOUT 23 +#define SCE_V_PORT_CONNECT 24 #define SCE_KIX_DEFAULT 0 #define SCE_KIX_COMMENT 1 #define SCE_KIX_STRING1 2 @@ -1741,6 +1749,25 @@ #define SCE_BIBTEX_PARAMETER 4 #define SCE_BIBTEX_VALUE 5 #define SCE_BIBTEX_COMMENT 6 +#define SCE_HEX_DEFAULT 0 +#define SCE_HEX_RECSTART 1 +#define SCE_HEX_RECTYPE 2 +#define SCE_HEX_RECTYPE_UNKNOWN 3 +#define SCE_HEX_BYTECOUNT 4 +#define SCE_HEX_BYTECOUNT_WRONG 5 +#define SCE_HEX_NOADDRESS 6 +#define SCE_HEX_DATAADDRESS 7 +#define SCE_HEX_RECCOUNT 8 +#define SCE_HEX_STARTADDRESS 9 +#define SCE_HEX_ADDRESSFIELD_UNKNOWN 10 +#define SCE_HEX_EXTENDEDADDRESS 11 +#define SCE_HEX_DATA_ODD 12 +#define SCE_HEX_DATA_EVEN 13 +#define SCE_HEX_DATA_UNKNOWN 14 +#define SCE_HEX_DATA_EMPTY 15 +#define SCE_HEX_CHECKSUM 16 +#define SCE_HEX_CHECKSUM_WRONG 17 +#define SCE_HEX_GARBAGE 18 /* --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 6fc75c3696..3cc7dd1bf7 100644 --- a/src/stc/scintilla/include/Scintilla.h +++ b/src/stc/scintilla/include/Scintilla.h @@ -285,6 +285,9 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define INDIC_DOTBOX 12 #define INDIC_SQUIGGLEPIXMAP 13 #define INDIC_COMPOSITIONTHICK 14 +#define INDIC_COMPOSITIONTHIN 15 +#define INDIC_FULLBOX 16 +#define INDIC_TEXTFORE 17 #define INDIC_IME 32 #define INDIC_IME_MAX 35 #define INDIC_MAX 35 @@ -299,6 +302,15 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SCI_INDICGETFORE 2083 #define SCI_INDICSETUNDER 2510 #define SCI_INDICGETUNDER 2511 +#define SCI_INDICSETHOVERSTYLE 2680 +#define SCI_INDICGETHOVERSTYLE 2681 +#define SCI_INDICSETHOVERFORE 2682 +#define SCI_INDICGETHOVERFORE 2683 +#define SC_INDICVALUEBIT 0x1000000 +#define SC_INDICVALUEMASK 0xFFFFFF +#define SC_INDICFLAG_VALUEFORE 1 +#define SCI_INDICSETFLAGS 2684 +#define SCI_INDICGETFLAGS 2685 #define SCI_SETWHITESPACEFORE 2084 #define SCI_SETWHITESPACEBACK 2085 #define SCI_SETWHITESPACESIZE 2086 @@ -431,6 +443,8 @@ inline int isascii(int c) { return !(c & ~0x7F); } #define SCI_GETTARGETSTART 2191 #define SCI_SETTARGETEND 2192 #define SCI_GETTARGETEND 2193 +#define SCI_SETTARGETRANGE 2686 +#define SCI_GETTARGETTEXT 2687 #define SCI_REPLACETARGET 2194 #define SCI_REPLACETARGETRE 2195 #define SCI_SEARCHINTARGET 2197 @@ -794,8 +808,6 @@ inline int isascii(int c) { return !(c & ~0x7F); } #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 @@ -1154,6 +1166,8 @@ struct SCNotification { #define SC_CP_DBCS 1 #define SCI_SETUSEPALETTE 2039 #define SCI_GETUSEPALETTE 2139 +#define SCI_SETKEYSUNICODE 2521 +#define SCI_GETKEYSUNICODE 2522 #endif diff --git a/src/stc/scintilla/include/Scintilla.iface b/src/stc/scintilla/include/Scintilla.iface index ca54c65ee8..6432d37aa8 100644 --- a/src/stc/scintilla/include/Scintilla.iface +++ b/src/stc/scintilla/include/Scintilla.iface @@ -72,11 +72,11 @@ ## Line numbers and positions start at 0. ## String arguments may contain NUL ('\0') characters where the calls provide a length -## argument and retrieve NUL characters. All retrieved strings except for those retrieved -## by GetLine also have a NUL appended but client code should calculate the size that -## will be returned rather than relying upon the NUL whenever possible. Allow for the -## extra NUL character when allocating buffers. The size to allocate for a stringresult -## can be determined by calling with a NULL (0) pointer. +## argument and retrieve NUL characters. APIs marked as NUL-terminated also have a +## NUL appended but client code should calculate the size that will be returned rather +## than relying upon the NUL whenever possible. Allow for the extra NUL character when +## allocating buffers. The size to allocate for a stringresult (not including NUL) can be +## determined by calling with a NULL (0) pointer. cat Basics @@ -186,6 +186,7 @@ set void SetAnchor=2026(position posAnchor,) # Retrieve the text of the line containing the caret. # Returns the index of the caret on the line. +# Result is NUL-terminated. fun int GetCurLine=2027(int length, stringresult text) # Retrieve the position of the last correctly styled character. @@ -479,6 +480,7 @@ get int StyleGetSize=2485(int style,) # Get the font of a style. # Returns the length of the fontName +# Result is NUL-terminated. get int StyleGetFont=2486(int style, stringresult fontName) # Get is a style to have its end of line filled or not. @@ -578,7 +580,7 @@ set void SetCaretPeriod=2076(int periodMilliseconds,) 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 +# Returns the number of characters get int GetWordChars=2646(, stringresult characters) # Start a sequence of actions that is undone and redone as a unit. @@ -605,6 +607,9 @@ val INDIC_SQUIGGLELOW=11 val INDIC_DOTBOX=12 val INDIC_SQUIGGLEPIXMAP=13 val INDIC_COMPOSITIONTHICK=14 +val INDIC_COMPOSITIONTHIN=15 +val INDIC_FULLBOX=16 +val INDIC_TEXTFORE=17 val INDIC_IME=32 val INDIC_IME_MAX=35 val INDIC_MAX=35 @@ -632,6 +637,30 @@ set void IndicSetUnder=2510(int indic, bool under) # Retrieve whether indicator drawn under or over text. get bool IndicGetUnder=2511(int indic,) +# Set a hover indicator to plain, squiggle or TT. +set void IndicSetHoverStyle=2680(int indic, int style) + +# Retrieve the hover style of an indicator. +get int IndicGetHoverStyle=2681(int indic,) + +# Set the foreground hover colour of an indicator. +set void IndicSetHoverFore=2682(int indic, colour fore) + +# Retrieve the foreground hover colour of an indicator. +get colour IndicGetHoverFore=2683(int indic,) + +val SC_INDICVALUEBIT=0x1000000 +val SC_INDICVALUEMASK=0xFFFFFF + +enu IndicFlag=SC_INDICFLAG_ +val SC_INDICFLAG_VALUEFORE=1 + +# Set the attributes of an indicator. +set void IndicSetFlags=2684(int indic, int flags) + +# Retrieve the attributes of an indicator. +get int IndicGetFlags=2685(int indic,) + # Set the foreground colour of all whitespace and whether to use this setting. fun void SetWhitespaceFore=2084(bool useSetting, colour fore) @@ -924,6 +953,7 @@ fun void SetSel=2160(position start, position end) # Retrieve the selected text. # Return the length of the text. +# Result is NUL-terminated. fun int GetSelText=2161(, stringresult text) # Retrieve a range of text. @@ -994,6 +1024,7 @@ fun void SetText=2181(, string text) # Retrieve all the text in the document. # Returns number of characters retrieved. +# Result is NUL-terminated. fun int GetText=2182(int length, stringresult text) # Retrieve the number of characters in the document. @@ -1032,6 +1063,12 @@ set void SetTargetEnd=2192(position pos,) # Get the position that ends the target. get position GetTargetEnd=2193(,) +# Sets both the start and end of the target in one call. +fun void SetTargetRange=2686(position start, position end) + +# Retrieve the text in the target. +get int GetTargetText=2687(, stringresult characters) + # Replace the target text with the argument text. # Text is counted so it can contain NULs. # Returns the length of the replacement text. @@ -1363,6 +1400,7 @@ set void SetMultiPaste=2614(int multiPaste,) get int GetMultiPaste=2615(,) # Retrieve the value of a tag from a regular expression search. +# Result is NUL-terminated. 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. @@ -1910,6 +1948,7 @@ get int AutoCGetCurrent=2445(,) # Get currently selected item text in the auto-completion list # Returns the length of the item text +# Result is NUL-terminated. get int AutoCGetCurrentText=2610(, stringresult s) enu CaseInsensitiveBehaviour=SC_CASEINSENSITIVEBEHAVIOUR_ @@ -2059,12 +2098,6 @@ get int GetRangePointer=2643(int position, int rangeLength) # the range of a call to GetRangePointer. get position GetGapPosition=2644(,) -# Always interpret keyboard input as Unicode -set void SetKeysUnicode=2521(bool keysUnicode,) - -# Are keys always interpreted as Unicode? -get bool GetKeysUnicode=2522(,) - # Set the alpha fill colour of the given indicator. set void IndicSetAlpha=2523(int indicator, int alpha) @@ -2419,6 +2452,7 @@ get int GetLineEndTypesActive=2658(,) set void SetRepresentation=2665(string encodedCharacter, string representation) # Set the way a character is drawn. +# Result is NUL-terminated. get int GetRepresentation=2666(string encodedCharacter, stringresult representation) # Remove a character representation. @@ -2455,10 +2489,12 @@ set void SetLexerLanguage=4006(, string language) fun void LoadLexerLibrary=4007(, string path) # Retrieve a "property" value previously set with SetProperty. +# Result is NUL-terminated. get int GetProperty=4008(string key, stringresult buf) # Retrieve a "property" value previously set with SetProperty, # with "$()" variable replacement on returned buffer. +# Result is NUL-terminated. get int GetPropertyExpanded=4009(string key, stringresult buf) # Retrieve a "property" value previously set with SetProperty, @@ -2470,12 +2506,14 @@ get int GetStyleBitsNeeded=4011(,) # Retrieve the name of the lexer. # Return the length of the text. +# Result is NUL-terminated. 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. +# Result is NUL-terminated. fun int PropertyNames=4014(, stringresult names) enu TypeProperty=SC_TYPE_ @@ -2487,9 +2525,11 @@ val SC_TYPE_STRING=2 fun int PropertyType=4015(string name,) # Describe a property. +# Result is NUL-terminated. fun int DescribeProperty=4016(string name, stringresult description) # Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer. +# Result is NUL-terminated. fun int DescribeKeyWordSets=4017(, stringresult descriptions) # Bit set of LineEndType enumertion for which line ends beyond the standard @@ -2522,6 +2562,7 @@ set void SetIdentifiers=4024(int style, string identifiers) get int DistanceToSecondaryStyles=4025(,) # Get the set of base styles that can be extended with sub styles +# Result is NUL-terminated. get int GetSubStyleBases=4026(, stringresult styles) # Notifications @@ -2719,6 +2760,9 @@ val SCLEX_AS=113 val SCLEX_DMIS=114 val SCLEX_REGISTRY=115 val SCLEX_BIBTEX=116 +val SCLEX_SREC=117 +val SCLEX_IHEX=118 +val SCLEX_TEHEX=119 # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a # value assigned in sequence from SCLEX_AUTOMATIC+1. @@ -3599,6 +3643,11 @@ val SCE_V_OPERATOR=10 val SCE_V_IDENTIFIER=11 val SCE_V_STRINGEOL=12 val SCE_V_USER=19 +val SCE_V_COMMENT_WORD=20 +val SCE_V_INPUT=21 +val SCE_V_OUTPUT=22 +val SCE_V_INOUT=23 +val SCE_V_PORT_CONNECT=24 # Lexical states for SCLEX_KIX lex Kix=SCLEX_KIX SCE_KIX_ val SCE_KIX_DEFAULT=0 @@ -4542,6 +4591,31 @@ val SCE_BIBTEX_KEY=3 val SCE_BIBTEX_PARAMETER=4 val SCE_BIBTEX_VALUE=5 val SCE_BIBTEX_COMMENT=6 +# Lexical state for SCLEX_SREC +lex Srec=SCLEX_SREC SCE_HEX_ +val SCE_HEX_DEFAULT=0 +val SCE_HEX_RECSTART=1 +val SCE_HEX_RECTYPE=2 +val SCE_HEX_RECTYPE_UNKNOWN=3 +val SCE_HEX_BYTECOUNT=4 +val SCE_HEX_BYTECOUNT_WRONG=5 +val SCE_HEX_NOADDRESS=6 +val SCE_HEX_DATAADDRESS=7 +val SCE_HEX_RECCOUNT=8 +val SCE_HEX_STARTADDRESS=9 +val SCE_HEX_ADDRESSFIELD_UNKNOWN=10 +val SCE_HEX_EXTENDEDADDRESS=11 +val SCE_HEX_DATA_ODD=12 +val SCE_HEX_DATA_EVEN=13 +val SCE_HEX_DATA_UNKNOWN=14 +val SCE_HEX_DATA_EMPTY=15 +val SCE_HEX_CHECKSUM=16 +val SCE_HEX_CHECKSUM_WRONG=17 +val SCE_HEX_GARBAGE=18 +# Lexical state for SCLEX_IHEX (shared with Srec) +lex IHex=SCLEX_IHEX SCE_HEX_ +# Lexical state for SCLEX_TEHEX (shared with Srec) +lex TEHex=SCLEX_TEHEX SCE_HEX_ # Events @@ -4594,3 +4668,11 @@ 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,) + +# Deprecated in 3.5.5 + +# Always interpret keyboard input as Unicode +set void SetKeysUnicode=2521(bool keysUnicode,) + +# Are keys always interpreted as Unicode? +get bool GetKeysUnicode=2522(,) diff --git a/src/stc/scintilla/lexers/LexBash.cxx b/src/stc/scintilla/lexers/LexBash.cxx index 3ebba8911c..a5f0f6e695 100644 --- a/src/stc/scintilla/lexers/LexBash.cxx +++ b/src/stc/scintilla/lexers/LexBash.cxx @@ -419,8 +419,6 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, sc.Forward(); HereDoc.Quoted = true; HereDoc.State = 1; - } else if (!HereDoc.Indent && sc.chNext == '-') { // <<- indent case - HereDoc.Indent = true; } else if (setHereDoc.Contains(sc.chNext)) { // an unquoted here-doc delimiter, no special handling // TODO check what exactly bash considers part of the delim @@ -469,7 +467,7 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, if (sc.atLineStart) { sc.SetState(SCE_SH_HERE_Q); int prefixws = 0; - while (IsASpace(sc.ch) && !sc.atLineEnd) { // whitespace prefix + while (sc.ch == '\t' && !sc.atLineEnd) { // tabulation prefix sc.Forward(); prefixws++; } @@ -481,7 +479,8 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, char s[HERE_DELIM_MAX]; sc.GetCurrent(s, sizeof(s)); if (sc.LengthCurrent() == 0) { // '' or "" delimiters - if (prefixws == 0 && HereDoc.Quoted && HereDoc.DelimiterLength == 0) + if ((prefixws == 0 || HereDoc.Indent) && + HereDoc.Quoted && HereDoc.DelimiterLength == 0) sc.SetState(SCE_SH_DEFAULT); break; } @@ -672,7 +671,12 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle, } else if (sc.Match('<', '<')) { sc.SetState(SCE_SH_HERE_DELIM); HereDoc.State = 0; - HereDoc.Indent = false; + if (sc.GetRelative(2) == '-') { // <<- indent case + HereDoc.Indent = true; + sc.Forward(); + } else { + HereDoc.Indent = false; + } } else if (sc.ch == '-' && // one-char file test operators setSingleCharOp.Contains(sc.chNext) && !setWord.Contains(sc.GetRelative(2)) && diff --git a/src/stc/scintilla/lexers/LexCPP.cxx b/src/stc/scintilla/lexers/LexCPP.cxx index 5485bf228a..ab982bb4bb 100644 --- a/src/stc/scintilla/lexers/LexCPP.cxx +++ b/src/stc/scintilla/lexers/LexCPP.cxx @@ -306,6 +306,7 @@ struct OptionsCPP { bool identifiersAllowDollars; bool trackPreprocessor; bool updatePreprocessor; + bool verbatimStringsAllowEscapes; bool triplequotedStrings; bool hashquotedStrings; bool backQuotedStrings; @@ -326,6 +327,7 @@ struct OptionsCPP { identifiersAllowDollars = true; trackPreprocessor = true; updatePreprocessor = true; + verbatimStringsAllowEscapes = false; triplequotedStrings = false; hashquotedStrings = false; backQuotedStrings = false; @@ -370,6 +372,9 @@ struct OptionSetCPP : public OptionSet { DefineProperty("lexer.cpp.update.preprocessor", &OptionsCPP::updatePreprocessor, "Set to 1 to update preprocessor definitions when #define found."); + DefineProperty("lexer.cpp.verbatim.strings.allow.escapes", &OptionsCPP::verbatimStringsAllowEscapes, + "Set to 1 to allow verbatim strings to contain escape sequences."); + DefineProperty("lexer.cpp.triplequoted.strings", &OptionsCPP::triplequotedStrings, "Set to 1 to enable highlighting of triple-quoted strings."); @@ -1036,7 +1041,9 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } break; case SCE_C_VERBATIM: - if (sc.ch == '\"') { + if (options.verbatimStringsAllowEscapes && (sc.ch == '\\')) { + sc.Forward(); // Skip all characters after the backslash + } else if (sc.ch == '\"') { if (sc.chNext == '\"') { sc.Forward(); } else { @@ -1344,14 +1351,14 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, } } if (options.foldSyntaxBased && (style == SCE_C_OPERATOR)) { - if (ch == '{') { + if (ch == '{' || ch == '[') { // Measure the minimum before a '{' to allow // folding on "} else {" if (levelMinCurrent > levelNext) { levelMinCurrent = levelNext; } levelNext++; - } else if (ch == '}') { + } else if (ch == '}' || ch == ']') { levelNext--; } } diff --git a/src/stc/scintilla/lexers/LexHex.cxx b/src/stc/scintilla/lexers/LexHex.cxx new file mode 100644 index 0000000000..fe972ffe82 --- /dev/null +++ b/src/stc/scintilla/lexers/LexHex.cxx @@ -0,0 +1,1045 @@ +// Scintilla source code edit control +/** @file LexHex.cxx + ** Lexers for Motorola S-Record, Intel HEX and Tektronix extended HEX. + ** + ** Written by Markus Heidelberg + **/ +// Copyright 1998-2001 by Neil Hodgson +// The License.txt file describes the conditions under which this software may be distributed. + +/* + * Motorola S-Record + * =============================== + * + * Each record (line) is built as follows: + * + * field digits states + * + * +----------+ + * | start | 1 ('S') SCE_HEX_RECSTART + * +----------+ + * | type | 1 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN) + * +----------+ + * | count | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG + * +----------+ + * | address | 4/6/8 SCE_HEX_NOADDRESS, SCE_HEX_DATAADDRESS, SCE_HEX_RECCOUNT, SCE_HEX_STARTADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN) + * +----------+ + * | data | 0..504/502/500 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN, SCE_HEX_DATA_EMPTY, (SCE_HEX_DATA_UNKNOWN) + * +----------+ + * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG + * +----------+ + * + * + * Intel HEX + * =============================== + * + * Each record (line) is built as follows: + * + * field digits states + * + * +----------+ + * | start | 1 (':') SCE_HEX_RECSTART + * +----------+ + * | count | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG + * +----------+ + * | address | 4 SCE_HEX_NOADDRESS, SCE_HEX_DATAADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN) + * +----------+ + * | type | 2 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN) + * +----------+ + * | data | 0..510 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN, SCE_HEX_DATA_EMPTY, SCE_HEX_EXTENDEDADDRESS, SCE_HEX_STARTADDRESS, (SCE_HEX_DATA_UNKNOWN) + * +----------+ + * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG + * +----------+ + * + * + * Folding: + * + * Data records (type 0x00), which follow an extended address record (type + * 0x02 or 0x04), can be folded. The extended address record is the fold + * point at fold level 0, the corresponding data records are set to level 1. + * + * Any record, which is not a data record, sets the fold level back to 0. + * Any line, which is not a record (blank lines and lines starting with a + * character other than ':'), leaves the fold level unchanged. + * + * + * Tektronix extended HEX + * =============================== + * + * Each record (line) is built as follows: + * + * field digits states + * + * +----------+ + * | start | 1 ('%') SCE_HEX_RECSTART + * +----------+ + * | length | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG + * +----------+ + * | type | 1 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN) + * +----------+ + * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG + * +----------+ + * | address | 9 SCE_HEX_DATAADDRESS, SCE_HEX_STARTADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN) + * +----------+ + * | data | 0..241 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN + * +----------+ + * + * + * General notes for all lexers + * =============================== + * + * - Depending on where the helper functions are invoked, some of them have to + * read beyond the current position. In case of malformed data (record too + * short), it has to be ensured that this either does not have bad influence + * or will be captured deliberately. + * + * - States in parentheses in the upper format descriptions indicate that they + * should not appear in a valid hex file. + * + * - State SCE_HEX_GARBAGE means garbage data after the intended end of the + * record, the line is too long then. This state is used in all lexers. + */ + +#include +#include +#include +#include +#include +#include + +#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 + +// prototypes for general helper functions +static inline bool IsNewline(const int ch); +static int GetHexaNibble(char hd); +static int GetHexaChar(char hd1, char hd2); +static int GetHexaChar(unsigned int pos, Accessor &styler); +static bool ForwardWithinLine(StyleContext &sc, int nb = 1); +static bool PosInSameRecord(unsigned int pos1, unsigned int pos2, Accessor &styler); +static int CountByteCount(unsigned int startPos, int uncountedDigits, Accessor &styler); +static int CalcChecksum(unsigned int startPos, int cnt, bool twosCompl, Accessor &styler); + +// prototypes for file format specific helper functions +static unsigned int GetSrecRecStartPosition(unsigned int pos, Accessor &styler); +static int GetSrecByteCount(unsigned int recStartPos, Accessor &styler); +static int CountSrecByteCount(unsigned int recStartPos, Accessor &styler); +static int GetSrecAddressFieldSize(unsigned int recStartPos, Accessor &styler); +static int GetSrecAddressFieldType(unsigned int recStartPos, Accessor &styler); +static int GetSrecDataFieldType(unsigned int recStartPos, Accessor &styler); +static int GetSrecRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler); +static int GetSrecChecksum(unsigned int recStartPos, Accessor &styler); +static int CalcSrecChecksum(unsigned int recStartPos, Accessor &styler); + +static unsigned int GetIHexRecStartPosition(unsigned int pos, Accessor &styler); +static int GetIHexByteCount(unsigned int recStartPos, Accessor &styler); +static int CountIHexByteCount(unsigned int recStartPos, Accessor &styler); +static int GetIHexAddressFieldType(unsigned int recStartPos, Accessor &styler); +static int GetIHexDataFieldType(unsigned int recStartPos, Accessor &styler); +static int GetIHexRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler); +static int GetIHexChecksum(unsigned int recStartPos, Accessor &styler); +static int CalcIHexChecksum(unsigned int recStartPos, Accessor &styler); + +static int GetTEHexDigitCount(unsigned int recStartPos, Accessor &styler); +static int CountTEHexDigitCount(unsigned int recStartPos, Accessor &styler); +static int GetTEHexAddressFieldType(unsigned int recStartPos, Accessor &styler); +static int GetTEHexChecksum(unsigned int recStartPos, Accessor &styler); +static int CalcTEHexChecksum(unsigned int recStartPos, Accessor &styler); + +static inline bool IsNewline(const int ch) +{ + return (ch == '\n' || ch == '\r'); +} + +static int GetHexaNibble(char hd) +{ + int hexValue = 0; + + if (hd >= '0' && hd <= '9') { + hexValue += hd - '0'; + } else if (hd >= 'A' && hd <= 'F') { + hexValue += hd - 'A' + 10; + } else if (hd >= 'a' && hd <= 'f') { + hexValue += hd - 'a' + 10; + } else { + return -1; + } + + return hexValue; +} + +static int GetHexaChar(char hd1, char hd2) +{ + int hexValue = 0; + + if (hd1 >= '0' && hd1 <= '9') { + hexValue += 16 * (hd1 - '0'); + } else if (hd1 >= 'A' && hd1 <= 'F') { + hexValue += 16 * (hd1 - 'A' + 10); + } else if (hd1 >= 'a' && hd1 <= 'f') { + hexValue += 16 * (hd1 - 'a' + 10); + } else { + return -1; + } + + if (hd2 >= '0' && hd2 <= '9') { + hexValue += hd2 - '0'; + } else if (hd2 >= 'A' && hd2 <= 'F') { + hexValue += hd2 - 'A' + 10; + } else if (hd2 >= 'a' && hd2 <= 'f') { + hexValue += hd2 - 'a' + 10; + } else { + return -1; + } + + return hexValue; +} + +static int GetHexaChar(unsigned int pos, Accessor &styler) +{ + char highNibble, lowNibble; + + highNibble = styler.SafeGetCharAt(pos); + lowNibble = styler.SafeGetCharAt(pos + 1); + + return GetHexaChar(highNibble, lowNibble); +} + +// Forward characters, but abort (and return false) if hitting the line +// end. Return true if forwarding within the line was possible. +// Avoids influence on highlighting of the subsequent line if the current line +// is malformed (too short). +static bool ForwardWithinLine(StyleContext &sc, int nb) +{ + for (int i = 0; i < nb; i++) { + if (sc.atLineEnd) { + // line is too short + sc.SetState(SCE_HEX_DEFAULT); + sc.Forward(); + return false; + } else { + sc.Forward(); + } + } + + return true; +} + +// Checks whether the given positions are in the same record. +static bool PosInSameRecord(unsigned int pos1, unsigned int pos2, Accessor &styler) +{ + return styler.GetLine(pos1) == styler.GetLine(pos2); +} + +// Count the number of digit pairs from till end of record, ignoring +// digits. +// If the record is too short, a negative count may be returned. +static int CountByteCount(unsigned int startPos, int uncountedDigits, Accessor &styler) +{ + int cnt; + unsigned int pos; + + pos = startPos; + + while (!IsNewline(styler.SafeGetCharAt(pos, '\n'))) { + pos++; + } + + // number of digits in this line minus number of digits of uncounted fields + cnt = static_cast(pos - startPos) - uncountedDigits; + + // Prepare round up if odd (digit pair incomplete), this way the byte + // count is considered to be valid if the checksum is incomplete. + if (cnt >= 0) { + cnt++; + } + + // digit pairs + cnt /= 2; + + return cnt; +} + +// Calculate the checksum of the record. +// is the position of the first character of the starting digit +// pair, is the number of digit pairs. +static int CalcChecksum(unsigned int startPos, int cnt, bool twosCompl, Accessor &styler) +{ + int cs = 0; + + for (unsigned int pos = startPos; pos < startPos + cnt; pos += 2) { + int val = GetHexaChar(pos, styler); + + if (val < 0) { + return val; + } + + // overflow does not matter + cs += val; + } + + if (twosCompl) { + // low byte of two's complement + return -cs & 0xFF; + } else { + // low byte of one's complement + return ~cs & 0xFF; + } +} + +// Get the position of the record "start" field (first character in line) in +// the record around position . +static unsigned int GetSrecRecStartPosition(unsigned int pos, Accessor &styler) +{ + while (styler.SafeGetCharAt(pos) != 'S') { + pos--; + } + + return pos; +} + +// Get the value of the "byte count" field, it counts the number of bytes in +// the subsequent fields ("address", "data" and "checksum" fields). +static int GetSrecByteCount(unsigned int recStartPos, Accessor &styler) +{ + int val; + + val = GetHexaChar(recStartPos + 2, styler); + if (val < 0) { + val = 0; + } + + return val; +} + +// Count the number of digit pairs for the "address", "data" and "checksum" +// fields in this record. Has to be equal to the "byte count" field value. +// If the record is too short, a negative count may be returned. +static int CountSrecByteCount(unsigned int recStartPos, Accessor &styler) +{ + return CountByteCount(recStartPos, 4, styler); +} + +// Get the size of the "address" field. +static int GetSrecAddressFieldSize(unsigned int recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '0': + case '1': + case '5': + case '9': + return 2; // 16 bit + + case '2': + case '6': + case '8': + return 3; // 24 bit + + case '3': + case '7': + return 4; // 32 bit + + default: + return 0; + } +} + +// Get the type of the "address" field content. +static int GetSrecAddressFieldType(unsigned int recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '0': + return SCE_HEX_NOADDRESS; + + case '1': + case '2': + case '3': + return SCE_HEX_DATAADDRESS; + + case '5': + case '6': + return SCE_HEX_RECCOUNT; + + case '7': + case '8': + case '9': + return SCE_HEX_STARTADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } +} + +// Get the type of the "data" field content. +static int GetSrecDataFieldType(unsigned int recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '0': + case '1': + case '2': + case '3': + return SCE_HEX_DATA_ODD; + + case '5': + case '6': + case '7': + case '8': + case '9': + return SCE_HEX_DATA_EMPTY; + + default: // handle possible format extension in the future + return SCE_HEX_DATA_UNKNOWN; + } +} + +// Get the required size of the "data" field. Useless for block header and +// ordinary data records (type S0, S1, S2, S3), return the value calculated +// from the "byte count" and "address field" size in this case. +static int GetSrecRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 1)) { + case '5': + case '6': + case '7': + case '8': + case '9': + return 0; + + default: + return GetSrecByteCount(recStartPos, styler) + - GetSrecAddressFieldSize(recStartPos, styler) + - 1; // -1 for checksum field + } +} + +// Get the value of the "checksum" field. +static int GetSrecChecksum(unsigned int recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetSrecByteCount(recStartPos, styler); + + return GetHexaChar(recStartPos + 2 + byteCount * 2, styler); +} + +// Calculate the checksum of the record. +static int CalcSrecChecksum(unsigned int recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetSrecByteCount(recStartPos, styler); + + // sum over "byte count", "address" and "data" fields (6..510 digits) + return CalcChecksum(recStartPos + 2, byteCount * 2, false, styler); +} + +// Get the position of the record "start" field (first character in line) in +// the record around position . +static unsigned int GetIHexRecStartPosition(unsigned int pos, Accessor &styler) +{ + while (styler.SafeGetCharAt(pos) != ':') { + pos--; + } + + return pos; +} + +// Get the value of the "byte count" field, it counts the number of bytes in +// the "data" field. +static int GetIHexByteCount(unsigned int recStartPos, Accessor &styler) +{ + int val; + + val = GetHexaChar(recStartPos + 1, styler); + if (val < 0) { + val = 0; + } + + return val; +} + +// Count the number of digit pairs for the "data" field in this record. Has to +// be equal to the "byte count" field value. +// If the record is too short, a negative count may be returned. +static int CountIHexByteCount(unsigned int recStartPos, Accessor &styler) +{ + return CountByteCount(recStartPos, 11, styler); +} + +// Get the type of the "address" field content. +static int GetIHexAddressFieldType(unsigned int recStartPos, Accessor &styler) +{ + if (!PosInSameRecord(recStartPos, recStartPos + 7, styler)) { + // malformed (record too short) + // type cannot be determined + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } + + switch (GetHexaChar(recStartPos + 7, styler)) { + case 0x00: + return SCE_HEX_DATAADDRESS; + + case 0x01: + case 0x02: + case 0x03: + case 0x04: + case 0x05: + return SCE_HEX_NOADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } +} + +// Get the type of the "data" field content. +static int GetIHexDataFieldType(unsigned int recStartPos, Accessor &styler) +{ + switch (GetHexaChar(recStartPos + 7, styler)) { + case 0x00: + return SCE_HEX_DATA_ODD; + + case 0x01: + return SCE_HEX_DATA_EMPTY; + + case 0x02: + case 0x04: + return SCE_HEX_EXTENDEDADDRESS; + + case 0x03: + case 0x05: + return SCE_HEX_STARTADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_DATA_UNKNOWN; + } +} + +// Get the required size of the "data" field. Useless for an ordinary data +// record (type 00), return the "byte count" in this case. +static int GetIHexRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler) +{ + switch (GetHexaChar(recStartPos + 7, styler)) { + case 0x01: + return 0; + + case 0x02: + case 0x04: + return 2; + + case 0x03: + case 0x05: + return 4; + + default: + return GetIHexByteCount(recStartPos, styler); + } +} + +// Get the value of the "checksum" field. +static int GetIHexChecksum(unsigned int recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetIHexByteCount(recStartPos, styler); + + return GetHexaChar(recStartPos + 9 + byteCount * 2, styler); +} + +// Calculate the checksum of the record. +static int CalcIHexChecksum(unsigned int recStartPos, Accessor &styler) +{ + int byteCount; + + byteCount = GetIHexByteCount(recStartPos, styler); + + // sum over "byte count", "address", "type" and "data" fields (8..518 digits) + return CalcChecksum(recStartPos + 1, 8 + byteCount * 2, true, styler); +} + + +// Get the value of the "record length" field, it counts the number of digits in +// the record excluding the percent. +static int GetTEHexDigitCount(unsigned int recStartPos, Accessor &styler) +{ + int val = GetHexaChar(recStartPos + 1, styler); + if (val < 0) + val = 0; + + return val; +} + +// Count the number of digits in this record. Has to +// be equal to the "record length" field value. +static int CountTEHexDigitCount(unsigned int recStartPos, Accessor &styler) +{ + unsigned int pos; + + pos = recStartPos+1; + + while (!IsNewline(styler.SafeGetCharAt(pos, '\n'))) { + pos++; + } + + return static_cast(pos - (recStartPos+1)); +} + +// Get the type of the "address" field content. +static int GetTEHexAddressFieldType(unsigned int recStartPos, Accessor &styler) +{ + switch (styler.SafeGetCharAt(recStartPos + 3)) { + case '6': + return SCE_HEX_DATAADDRESS; + + case '8': + return SCE_HEX_STARTADDRESS; + + default: // handle possible format extension in the future + return SCE_HEX_ADDRESSFIELD_UNKNOWN; + } +} + +// Get the value of the "checksum" field. +static int GetTEHexChecksum(unsigned int recStartPos, Accessor &styler) +{ + return GetHexaChar(recStartPos+4, styler); +} + +// Calculate the checksum of the record (excluding the checksum field). +static int CalcTEHexChecksum(unsigned int recStartPos, Accessor &styler) +{ + unsigned int pos = recStartPos +1; + unsigned int length = GetTEHexDigitCount(recStartPos, styler); + + int cs = GetHexaNibble(styler.SafeGetCharAt(pos++));//length + cs += GetHexaNibble(styler.SafeGetCharAt(pos++));//length + + cs += GetHexaNibble(styler.SafeGetCharAt(pos++));//type + + pos += 2;// jump over CS field + + for (; pos <= recStartPos + length; ++pos) { + int val = GetHexaNibble(styler.SafeGetCharAt(pos)); + + if (val < 0) { + return val; + } + + // overflow does not matter + cs += val; + } + + // low byte + return cs & 0xFF; + +} + +static void ColouriseSrecDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + unsigned int recStartPos; + int byteCount, reqByteCount, addrFieldSize, addrFieldType, dataFieldSize, dataFieldType; + int cs1, cs2; + + switch (sc.state) { + case SCE_HEX_DEFAULT: + if (sc.atLineStart && sc.Match('S')) { + sc.SetState(SCE_HEX_RECSTART); + } + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECSTART: + recStartPos = sc.currentPos - 1; + addrFieldType = GetSrecAddressFieldType(recStartPos, styler); + + if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) { + sc.SetState(SCE_HEX_RECTYPE_UNKNOWN); + } else { + sc.SetState(SCE_HEX_RECTYPE); + } + + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECTYPE: + case SCE_HEX_RECTYPE_UNKNOWN: + recStartPos = sc.currentPos - 2; + byteCount = GetSrecByteCount(recStartPos, styler); + reqByteCount = GetSrecAddressFieldSize(recStartPos, styler) + + GetSrecRequiredDataFieldSize(recStartPos, styler) + + 1; // +1 for checksum field + + if (byteCount == CountSrecByteCount(recStartPos, styler) + && byteCount == reqByteCount) { + sc.SetState(SCE_HEX_BYTECOUNT); + } else { + sc.SetState(SCE_HEX_BYTECOUNT_WRONG); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_BYTECOUNT: + case SCE_HEX_BYTECOUNT_WRONG: + recStartPos = sc.currentPos - 4; + addrFieldSize = GetSrecAddressFieldSize(recStartPos, styler); + addrFieldType = GetSrecAddressFieldType(recStartPos, styler); + + sc.SetState(addrFieldType); + ForwardWithinLine(sc, addrFieldSize * 2); + break; + + case SCE_HEX_NOADDRESS: + case SCE_HEX_DATAADDRESS: + case SCE_HEX_RECCOUNT: + case SCE_HEX_STARTADDRESS: + case SCE_HEX_ADDRESSFIELD_UNKNOWN: + recStartPos = GetSrecRecStartPosition(sc.currentPos, styler); + dataFieldType = GetSrecDataFieldType(recStartPos, styler); + + // Using the required size here if possible has the effect that the + // checksum is highlighted at a fixed position after this field for + // specific record types, independent on the "byte count" value. + dataFieldSize = GetSrecRequiredDataFieldSize(recStartPos, styler); + + sc.SetState(dataFieldType); + + if (dataFieldType == SCE_HEX_DATA_ODD) { + for (int i = 0; i < dataFieldSize * 2; i++) { + if ((i & 0x3) == 0) { + sc.SetState(SCE_HEX_DATA_ODD); + } else if ((i & 0x3) == 2) { + sc.SetState(SCE_HEX_DATA_EVEN); + } + + if (!ForwardWithinLine(sc)) { + break; + } + } + } else { + ForwardWithinLine(sc, dataFieldSize * 2); + } + break; + + case SCE_HEX_DATA_ODD: + case SCE_HEX_DATA_EVEN: + case SCE_HEX_DATA_EMPTY: + case SCE_HEX_DATA_UNKNOWN: + recStartPos = GetSrecRecStartPosition(sc.currentPos, styler); + cs1 = CalcSrecChecksum(recStartPos, styler); + cs2 = GetSrecChecksum(recStartPos, styler); + + if (cs1 != cs2 || cs1 < 0 || cs2 < 0) { + sc.SetState(SCE_HEX_CHECKSUM_WRONG); + } else { + sc.SetState(SCE_HEX_CHECKSUM); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_CHECKSUM: + case SCE_HEX_CHECKSUM_WRONG: + case SCE_HEX_GARBAGE: + // record finished or line too long + sc.SetState(SCE_HEX_GARBAGE); + ForwardWithinLine(sc); + break; + + default: + // prevent endless loop in faulty state + sc.SetState(SCE_HEX_DEFAULT); + break; + } + } + sc.Complete(); +} + +static void ColouriseIHexDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + unsigned int recStartPos; + int byteCount, addrFieldType, dataFieldSize, dataFieldType; + int cs1, cs2; + + switch (sc.state) { + case SCE_HEX_DEFAULT: + if (sc.atLineStart && sc.Match(':')) { + sc.SetState(SCE_HEX_RECSTART); + } + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECSTART: + recStartPos = sc.currentPos - 1; + byteCount = GetIHexByteCount(recStartPos, styler); + dataFieldSize = GetIHexRequiredDataFieldSize(recStartPos, styler); + + if (byteCount == CountIHexByteCount(recStartPos, styler) + && byteCount == dataFieldSize) { + sc.SetState(SCE_HEX_BYTECOUNT); + } else { + sc.SetState(SCE_HEX_BYTECOUNT_WRONG); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_BYTECOUNT: + case SCE_HEX_BYTECOUNT_WRONG: + recStartPos = sc.currentPos - 3; + addrFieldType = GetIHexAddressFieldType(recStartPos, styler); + + sc.SetState(addrFieldType); + ForwardWithinLine(sc, 4); + break; + + case SCE_HEX_NOADDRESS: + case SCE_HEX_DATAADDRESS: + case SCE_HEX_ADDRESSFIELD_UNKNOWN: + recStartPos = sc.currentPos - 7; + addrFieldType = GetIHexAddressFieldType(recStartPos, styler); + + if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) { + sc.SetState(SCE_HEX_RECTYPE_UNKNOWN); + } else { + sc.SetState(SCE_HEX_RECTYPE); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_RECTYPE: + case SCE_HEX_RECTYPE_UNKNOWN: + recStartPos = sc.currentPos - 9; + dataFieldType = GetIHexDataFieldType(recStartPos, styler); + + // Using the required size here if possible has the effect that the + // checksum is highlighted at a fixed position after this field for + // specific record types, independent on the "byte count" value. + dataFieldSize = GetIHexRequiredDataFieldSize(recStartPos, styler); + + sc.SetState(dataFieldType); + + if (dataFieldType == SCE_HEX_DATA_ODD) { + for (int i = 0; i < dataFieldSize * 2; i++) { + if ((i & 0x3) == 0) { + sc.SetState(SCE_HEX_DATA_ODD); + } else if ((i & 0x3) == 2) { + sc.SetState(SCE_HEX_DATA_EVEN); + } + + if (!ForwardWithinLine(sc)) { + break; + } + } + } else { + ForwardWithinLine(sc, dataFieldSize * 2); + } + break; + + case SCE_HEX_DATA_ODD: + case SCE_HEX_DATA_EVEN: + case SCE_HEX_DATA_EMPTY: + case SCE_HEX_EXTENDEDADDRESS: + case SCE_HEX_STARTADDRESS: + case SCE_HEX_DATA_UNKNOWN: + recStartPos = GetIHexRecStartPosition(sc.currentPos, styler); + cs1 = CalcIHexChecksum(recStartPos, styler); + cs2 = GetIHexChecksum(recStartPos, styler); + + if (cs1 != cs2 || cs1 < 0 || cs2 < 0) { + sc.SetState(SCE_HEX_CHECKSUM_WRONG); + } else { + sc.SetState(SCE_HEX_CHECKSUM); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_CHECKSUM: + case SCE_HEX_CHECKSUM_WRONG: + case SCE_HEX_GARBAGE: + // record finished or line too long + sc.SetState(SCE_HEX_GARBAGE); + ForwardWithinLine(sc); + break; + + default: + // prevent endless loop in faulty state + sc.SetState(SCE_HEX_DEFAULT); + break; + } + } + sc.Complete(); +} + +static void FoldIHexDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) +{ + unsigned int endPos = startPos + length; + + int lineCurrent = styler.GetLine(startPos); + int levelCurrent = SC_FOLDLEVELBASE; + if (lineCurrent > 0) + levelCurrent = styler.LevelAt(lineCurrent - 1); + + unsigned int lineStartNext = styler.LineStart(lineCurrent + 1); + int levelNext = SC_FOLDLEVELBASE; // default if no specific line found + + for (unsigned int i = startPos; i < endPos; i++) { + bool atEOL = i == (lineStartNext - 1); + int style = styler.StyleAt(i); + + // search for specific lines + if (style == SCE_HEX_EXTENDEDADDRESS) { + // extended addres record + levelNext = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG; + } else if (style == SCE_HEX_DATAADDRESS + || (style == SCE_HEX_DEFAULT + && i == (unsigned int)styler.LineStart(lineCurrent))) { + // data record or no record start code at all + if (levelCurrent & SC_FOLDLEVELHEADERFLAG) { + levelNext = SC_FOLDLEVELBASE + 1; + } else { + // continue level 0 or 1, no fold point + levelNext = levelCurrent; + } + } + + if (atEOL || (i == endPos - 1)) { + styler.SetLevel(lineCurrent, levelNext); + + lineCurrent++; + lineStartNext = styler.LineStart(lineCurrent + 1); + levelCurrent = levelNext; + levelNext = SC_FOLDLEVELBASE; + } + } +} + +static void ColouriseTEHexDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler) +{ + StyleContext sc(startPos, length, initStyle, styler); + + while (sc.More()) { + unsigned int recStartPos; + int digitCount, addrFieldType; + int cs1, cs2; + + switch (sc.state) { + case SCE_HEX_DEFAULT: + if (sc.atLineStart && sc.Match('%')) { + sc.SetState(SCE_HEX_RECSTART); + } + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECSTART: + + recStartPos = sc.currentPos - 1; + + if (GetTEHexDigitCount(recStartPos, styler) == CountTEHexDigitCount(recStartPos, styler)) { + sc.SetState(SCE_HEX_BYTECOUNT); + } else { + sc.SetState(SCE_HEX_BYTECOUNT_WRONG); + } + + ForwardWithinLine(sc, 2); + break; + + case SCE_HEX_BYTECOUNT: + case SCE_HEX_BYTECOUNT_WRONG: + recStartPos = sc.currentPos - 3; + addrFieldType = GetTEHexAddressFieldType(recStartPos, styler); + + if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) { + sc.SetState(SCE_HEX_RECTYPE_UNKNOWN); + } else { + sc.SetState(SCE_HEX_RECTYPE); + } + + ForwardWithinLine(sc); + break; + + case SCE_HEX_RECTYPE: + case SCE_HEX_RECTYPE_UNKNOWN: + recStartPos = sc.currentPos - 4; + cs1 = CalcTEHexChecksum(recStartPos, styler); + cs2 = GetTEHexChecksum(recStartPos, styler); + + if (cs1 != cs2 || cs1 < 0 || cs2 < 0) { + sc.SetState(SCE_HEX_CHECKSUM_WRONG); + } else { + sc.SetState(SCE_HEX_CHECKSUM); + } + + ForwardWithinLine(sc, 2); + break; + + + case SCE_HEX_CHECKSUM: + case SCE_HEX_CHECKSUM_WRONG: + recStartPos = sc.currentPos - 6; + addrFieldType = GetTEHexAddressFieldType(recStartPos, styler); + + sc.SetState(addrFieldType); + ForwardWithinLine(sc, 9); + break; + + case SCE_HEX_DATAADDRESS: + case SCE_HEX_STARTADDRESS: + case SCE_HEX_ADDRESSFIELD_UNKNOWN: + recStartPos = sc.currentPos - 15; + digitCount = GetTEHexDigitCount(recStartPos, styler) - 14; + + sc.SetState(SCE_HEX_DATA_ODD); + + for (int i = 0; i < digitCount; i++) { + if ((i & 0x3) == 0) { + sc.SetState(SCE_HEX_DATA_ODD); + } else if ((i & 0x3) == 2) { + sc.SetState(SCE_HEX_DATA_EVEN); + } + + if (!ForwardWithinLine(sc)) { + break; + } + } + break; + + case SCE_HEX_DATA_ODD: + case SCE_HEX_DATA_EVEN: + case SCE_HEX_GARBAGE: + // record finished or line too long + sc.SetState(SCE_HEX_GARBAGE); + ForwardWithinLine(sc); + break; + + default: + // prevent endless loop in faulty state + sc.SetState(SCE_HEX_DEFAULT); + break; + } + } + sc.Complete(); +} + +LexerModule lmSrec(SCLEX_SREC, ColouriseSrecDoc, "srec", 0, NULL); +LexerModule lmIHex(SCLEX_IHEX, ColouriseIHexDoc, "ihex", FoldIHexDoc, NULL); +LexerModule lmTEHex(SCLEX_TEHEX, ColouriseTEHexDoc, "tehex", 0, NULL); diff --git a/src/stc/scintilla/lexers/LexRuby.cxx b/src/stc/scintilla/lexers/LexRuby.cxx index d4c3fad25d..9529ac24e9 100644 --- a/src/stc/scintilla/lexers/LexRuby.cxx +++ b/src/stc/scintilla/lexers/LexRuby.cxx @@ -29,7 +29,7 @@ using namespace Scintilla; //XXX Identical to Perl, put in common area static inline bool isEOLChar(char ch) { - return (ch == '\r') || (ch == '\n'); + return (ch == '\r') || (ch == '\n'); } #define isSafeASCII(ch) ((unsigned int)(ch) <= 127) @@ -60,7 +60,7 @@ static inline bool isSafeWordcharOrHigh(char ch) { } static bool inline iswhitespace(char ch) { - return ch == ' ' || ch == '\t'; + return ch == ' ' || ch == '\t'; } #define MAX_KEYWORD_LENGTH 200 @@ -74,20 +74,20 @@ static bool followsDot(unsigned int pos, Accessor &styler) { int style = actual_style(styler.StyleAt(pos)); char ch; switch (style) { - case SCE_RB_DEFAULT: - ch = styler[pos]; - if (ch == ' ' || ch == '\t') { - //continue - } else { - return false; - } - break; - - case SCE_RB_OPERATOR: - return styler[pos] == '.'; - - default: + case SCE_RB_DEFAULT: + ch = styler[pos]; + if (ch == ' ' || ch == '\t') { + //continue + } else { return false; + } + break; + + case SCE_RB_OPERATOR: + return styler[pos] == '.'; + + default: + return false; } } return false; @@ -102,26 +102,26 @@ static bool keywordIsModifier(const char *word, Accessor &styler); static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) { - char s[MAX_KEYWORD_LENGTH]; + char s[MAX_KEYWORD_LENGTH]; unsigned int i, j; - unsigned int lim = end - start + 1; // num chars to copy - if (lim >= MAX_KEYWORD_LENGTH) { - lim = MAX_KEYWORD_LENGTH - 1; - } - for (i = start, j = 0; j < lim; i++, j++) { - s[j] = styler[i]; - } + unsigned int lim = end - start + 1; // num chars to copy + if (lim >= MAX_KEYWORD_LENGTH) { + lim = MAX_KEYWORD_LENGTH - 1; + } + for (i = start, j = 0; j < lim; i++, j++) { + s[j] = styler[i]; + } s[j] = '\0'; - int chAttr; - if (0 == strcmp(prevWord, "class")) - chAttr = SCE_RB_CLASSNAME; - else if (0 == strcmp(prevWord, "module")) - chAttr = SCE_RB_MODULE_NAME; - else if (0 == strcmp(prevWord, "def")) - chAttr = SCE_RB_DEFNAME; + int chAttr; + if (0 == strcmp(prevWord, "class")) + chAttr = SCE_RB_CLASSNAME; + else if (0 == strcmp(prevWord, "module")) + chAttr = SCE_RB_MODULE_NAME; + else if (0 == strcmp(prevWord, "def")) + chAttr = SCE_RB_DEFNAME; else if (keywords.InList(s) && ((start == 0) || !followsDot(start - 1, styler))) { if (keywordIsAmbiguous(s) - && keywordIsModifier(s, start, styler)) { + && keywordIsModifier(s, start, styler)) { // Demoted keywords are colored as keywords, // but do not affect changes in indentation. @@ -136,37 +136,37 @@ static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywor } else { chAttr = SCE_RB_WORD; } - } else + } else chAttr = SCE_RB_IDENTIFIER; - styler.ColourTo(end, chAttr); - if (chAttr == SCE_RB_WORD) { - strcpy(prevWord, s); - } else { - prevWord[0] = 0; - } + styler.ColourTo(end, chAttr); + if (chAttr == SCE_RB_WORD) { + strcpy(prevWord, s); + } else { + prevWord[0] = 0; + } return chAttr; } //XXX Identical to Perl, put in common area static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) { - if ((pos + static_cast(strlen(val))) >= lengthDoc) { - return false; - } - while (*val) { - if (*val != styler[pos++]) { - return false; - } - val++; - } - return true; + if ((pos + static_cast(strlen(val))) >= lengthDoc) { + return false; + } + while (*val) { + if (*val != styler[pos++]) { + return false; + } + val++; + } + return true; } // Do Ruby better -- find the end of the line, work back, // and then check for leading white space // Precondition: the here-doc target can be indented -static bool lookingAtHereDocDelim(Accessor &styler, +static bool lookingAtHereDocDelim(Accessor &styler, int pos, int lengthDoc, const char *HereDocDelim) @@ -187,15 +187,15 @@ static bool lookingAtHereDocDelim(Accessor &styler, //XXX Identical to Perl, put in common area static char opposite(char ch) { - if (ch == '(') - return ')'; - if (ch == '[') - return ']'; - if (ch == '{') - return '}'; - if (ch == '<') - return '>'; - return ch; + if (ch == '(') + return ')'; + if (ch == '[') + return ']'; + if (ch == '{') + return '}'; + if (ch == '<') + return '>'; + return ch; } // Null transitions when we see we've reached the end @@ -216,7 +216,7 @@ static void advance_char(int &i, char &ch, char &chNext, char &chNext2) { } // precondition: startPos points to one after the EOL char -static bool currLineContainsHereDelims(int& startPos, +static bool currLineContainsHereDelims(int &startPos, Accessor &styler) { if (startPos <= 1) return false; @@ -249,7 +249,7 @@ static bool currLineContainsHereDelims(int& startPos, // to be hoisted out of the function. class QuoteCls { - public: +public: int Count; char Up; char Down; @@ -266,19 +266,19 @@ class QuoteCls { Up = u; Down = opposite(Up); } - QuoteCls(const QuoteCls& q) { + QuoteCls(const QuoteCls &q) { // copy constructor -- use this for copying in Count = q.Count; Up = q.Up; Down = q.Down; } - QuoteCls& operator=(const QuoteCls& q) { // assignment constructor + QuoteCls &operator=(const QuoteCls &q) { // assignment constructor if (this != &q) { Count = q.Count; Up = q.Up; Down = q.Down; } - return *this; + return *this; } }; @@ -287,11 +287,11 @@ class QuoteCls { static void enterInnerExpression(int *p_inner_string_types, int *p_inner_expn_brace_counts, QuoteCls *p_inner_quotes, - int& inner_string_count, - int& state, - int& brace_counts, + int &inner_string_count, + int &state, + int &brace_counts, QuoteCls curr_quote - ) { + ) { p_inner_string_types[inner_string_count] = state; state = SCE_RB_DEFAULT; p_inner_expn_brace_counts[inner_string_count] = brace_counts; @@ -301,13 +301,13 @@ static void enterInnerExpression(int *p_inner_string_types, } static void exitInnerExpression(int *p_inner_string_types, - int *p_inner_expn_brace_counts, - QuoteCls *p_inner_quotes, - int& inner_string_count, - int& state, - int& brace_counts, - QuoteCls& curr_quote - ) { + int *p_inner_expn_brace_counts, + QuoteCls *p_inner_quotes, + int &inner_string_count, + int &state, + int &brace_counts, + QuoteCls &curr_quote + ) { --inner_string_count; state = p_inner_string_types[inner_string_count]; brace_counts = p_inner_expn_brace_counts[inner_string_count]; @@ -316,28 +316,28 @@ static void exitInnerExpression(int *p_inner_string_types, static bool isEmptyLine(int pos, Accessor &styler) { - int spaceFlags = 0; - int lineCurrent = styler.GetLine(pos); - int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); + int spaceFlags = 0; + int lineCurrent = styler.GetLine(pos); + int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL); return (indentCurrent & SC_FOLDLEVELWHITEFLAG) != 0; } static bool RE_CanFollowKeyword(const char *keyword) { if (!strcmp(keyword, "and") - || !strcmp(keyword, "begin") - || !strcmp(keyword, "break") - || !strcmp(keyword, "case") - || !strcmp(keyword, "do") - || !strcmp(keyword, "else") - || !strcmp(keyword, "elsif") - || !strcmp(keyword, "if") - || !strcmp(keyword, "next") - || !strcmp(keyword, "return") - || !strcmp(keyword, "when") - || !strcmp(keyword, "unless") - || !strcmp(keyword, "until") - || !strcmp(keyword, "not") - || !strcmp(keyword, "or")) { + || !strcmp(keyword, "begin") + || !strcmp(keyword, "break") + || !strcmp(keyword, "case") + || !strcmp(keyword, "do") + || !strcmp(keyword, "else") + || !strcmp(keyword, "elsif") + || !strcmp(keyword, "if") + || !strcmp(keyword, "next") + || !strcmp(keyword, "return") + || !strcmp(keyword, "when") + || !strcmp(keyword, "unless") + || !strcmp(keyword, "until") + || !strcmp(keyword, "not") + || !strcmp(keyword, "or")) { return true; } return false; @@ -347,8 +347,8 @@ static bool RE_CanFollowKeyword(const char *keyword) { // Don't look at styles in case we're looking forward static int skipWhitespace(int startPos, - int endPos, - Accessor &styler) { + int endPos, + Accessor &styler) { for (int i = startPos; i < endPos; i++) { if (!iswhitespace(styler[i])) { return i; @@ -378,8 +378,8 @@ static bool sureThisIsHeredoc(int iPrev, int firstWordPosn = skipWhitespace(lineStartPosn, iPrev, styler); if (firstWordPosn >= iPrev) { // Have something like {^ <<} - //XXX Look at the first previous non-comment non-white line - // to establish the context. Not too likely though. + //XXX Look at the first previous non-comment non-white line + // to establish the context. Not too likely though. return true; } else { switch (prevStyle = styler.StyleAt(firstWordPosn)) { @@ -395,7 +395,7 @@ static bool sureThisIsHeredoc(int iPrev, char *dst = prevWord; for (;;) { if (firstWordEndPosn >= iPrev || - styler.StyleAt(firstWordEndPosn) != prevStyle) { + styler.StyleAt(firstWordEndPosn) != prevStyle) { *dst = 0; break; } @@ -404,8 +404,8 @@ static bool sureThisIsHeredoc(int iPrev, } //XXX Write a style-aware thing to regex scintilla buffer objects if (!strcmp(prevWord, "undef") - || !strcmp(prevWord, "def") - || !strcmp(prevWord, "alias")) { + || !strcmp(prevWord, "def") + || !strcmp(prevWord, "alias")) { // These keywords are what we were looking for return false; } @@ -424,8 +424,8 @@ static bool haveTargetMatch(int currPos, } int i, j; for (i = targetStartPos, j = currPos; - i < targetEndPos && j < lengthDoc; - i++, j++) { + i < targetEndPos && j < lengthDoc; + i++, j++) { if (styler[i] != styler[j]) { return false; } @@ -450,7 +450,7 @@ static bool haveTargetMatch(int currPos, static bool sureThisIsNotHeredoc(int lt2StartPos, Accessor &styler) { int prevStyle; - // Use full document, not just part we're styling + // Use full document, not just part we're styling int lengthDoc = styler.Length(); int lineStart = styler.GetLine(lt2StartPos); int lineStartPosn = styler.LineStart(lineStart); @@ -466,8 +466,8 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, prevStyle = styler.StyleAt(firstWordPosn); // If we have '<<' following a keyword, it's not a heredoc if (prevStyle != SCE_RB_IDENTIFIER - && prevStyle != SCE_RB_INSTANCE_VAR - && prevStyle != SCE_RB_CLASS_VAR) { + && prevStyle != SCE_RB_INSTANCE_VAR + && prevStyle != SCE_RB_CLASS_VAR) { return definitely_not_a_here_doc; } int newStyle = prevStyle; @@ -508,7 +508,7 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, return definitely_not_a_here_doc; } // OK, now 'j' will point to the current spot moving ahead - int j = firstWordPosn + 1; + int j = firstWordPosn + 1; if (styler.StyleAt(j) != SCE_RB_OPERATOR || styler[j] != '<') { // This shouldn't happen return definitely_not_a_here_doc; @@ -560,10 +560,10 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, // don't handle arbitrary expressions yet target_end = j; - if (target_quote) { - // Now we can move to the character after the string delimiter. - j += 1; - } + if (target_quote) { + // Now we can move to the character after the string delimiter. + j += 1; + } j = skipWhitespace(j, lengthDoc, styler); if (j >= lengthDoc) { return definitely_not_a_here_doc; @@ -604,7 +604,7 @@ static bool sureThisIsNotHeredoc(int lt2StartPos, // move to the start of the first line that is not in a // multi-line construct -static void synchronizeDocStart(unsigned int& startPos, +static void synchronizeDocStart(unsigned int &startPos, int &length, int &initStyle, Accessor &styler, @@ -613,11 +613,11 @@ static void synchronizeDocStart(unsigned int& startPos, styler.Flush(); int style = actual_style(styler.StyleAt(startPos)); switch (style) { - case SCE_RB_STDIN: - case SCE_RB_STDOUT: - case SCE_RB_STDERR: - // Don't do anything else with these. - return; + case SCE_RB_STDIN: + case SCE_RB_STDOUT: + case SCE_RB_STDERR: + // Don't do anything else with these. + return; } int pos = startPos; @@ -655,66 +655,67 @@ static void synchronizeDocStart(unsigned int& startPos, } static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, - WordList *keywordlists[], Accessor &styler) { + WordList *keywordlists[], Accessor &styler) { - // 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 + // 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]; + WordList &keywords = *keywordlists[0]; - class HereDocCls { - public: - int State; + class HereDocCls { + public: + int State; // States // 0: '<<' encountered - // 1: collect the delimiter + // 1: collect the delimiter // 1b: text between the end of the delimiter and the EOL - // 2: here doc text (lines after the delimiter) - char Quote; // the char after '<<' - bool Quoted; // true if Quote in ('\'','"','`') - int DelimiterLength; // strlen(Delimiter) - char Delimiter[256]; // the Delimiter, limit of 256: from Perl + // 2: here doc text (lines after the delimiter) + char Quote; // the char after '<<' + bool Quoted; // true if Quote in ('\'','"','`') + int DelimiterLength; // strlen(Delimiter) + char Delimiter[256]; // the Delimiter, limit of 256: from Perl bool CanBeIndented; - HereDocCls() { - State = 0; - DelimiterLength = 0; - Delimiter[0] = '\0'; + HereDocCls() { + State = 0; + DelimiterLength = 0; + Delimiter[0] = '\0'; CanBeIndented = false; - } - }; - HereDocCls HereDoc; + } + }; + HereDocCls HereDoc; - QuoteCls Quote; + QuoteCls Quote; int numDots = 0; // For numbers -- - // Don't start lexing in the middle of a num + // Don't start lexing in the middle of a num synchronizeDocStart(startPos, length, initStyle, styler, // ref args false); - bool preferRE = true; + bool preferRE = true; int state = initStyle; - int lengthDoc = startPos + length; + int lengthDoc = startPos + length; - char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero - prevWord[0] = '\0'; - if (length == 0) - return; + char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero + prevWord[0] = '\0'; + if (length == 0) + return; - char chPrev = styler.SafeGetCharAt(startPos - 1); - char chNext = styler.SafeGetCharAt(startPos); - bool is_real_number = true; // Differentiate between constants and ?-sequences. - styler.StartAt(startPos); - styler.StartSegment(startPos); + char chPrev = styler.SafeGetCharAt(startPos - 1); + char chNext = styler.SafeGetCharAt(startPos); + bool is_real_number = true; // Differentiate between constants and ?-sequences. + styler.StartAt(startPos); + styler.StartSegment(startPos); static int q_states[] = {SCE_RB_STRING_Q, SCE_RB_STRING_QQ, SCE_RB_STRING_QR, SCE_RB_STRING_QW, SCE_RB_STRING_QW, - SCE_RB_STRING_QX}; - static const char* q_chars = "qQrwWx"; + SCE_RB_STRING_QX + }; + static const char *q_chars = "qQrwWx"; // In most cases a value of 2 should be ample for the code in the // Ruby library, and the code the user is likely to enter. @@ -743,113 +744,113 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, int brace_counts = 0; // Number of #{ ... } things within an expression int i; - for (i = 0; i < INNER_STRINGS_MAX_COUNT; i++) { + for (i = 0; i < INNER_STRINGS_MAX_COUNT; i++) { inner_string_types[i] = 0; inner_expn_brace_counts[i] = 0; } - for (i = startPos; i < lengthDoc; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - char chNext2 = styler.SafeGetCharAt(i + 2); + for (i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + char chNext2 = styler.SafeGetCharAt(i + 2); if (styler.IsLeadByte(ch)) { - chNext = chNext2; - chPrev = ' '; - i += 1; - continue; - } + chNext = chNext2; + chPrev = ' '; + 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 #if 0 - if (ch == '\r' && chNext == '\n') { - continue; + if (ch == '\r' && chNext == '\n') { + continue; } #endif if (HereDoc.State == 1 && isEOLChar(ch)) { - // Begin of here-doc (the line after the here-doc delimiter): - HereDoc.State = 2; - styler.ColourTo(i-1, state); + // Begin of here-doc (the line after the here-doc delimiter): + HereDoc.State = 2; + styler.ColourTo(i-1, state); // Don't check for a missing quote, just jump into // the here-doc state state = SCE_RB_HERE_Q; } // Regular transitions - if (state == SCE_RB_DEFAULT) { + if (state == SCE_RB_DEFAULT) { if (isSafeDigit(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_RB_NUMBER; + styler.ColourTo(i - 1, state); + state = SCE_RB_NUMBER; is_real_number = true; numDots = 0; } else if (isHighBitChar(ch) || iswordstart(ch)) { - styler.ColourTo(i - 1, state); - state = SCE_RB_WORD; - } else if (ch == '#') { - styler.ColourTo(i - 1, state); - state = SCE_RB_COMMENTLINE; - } else if (ch == '=') { - // =begin indicates the start of a comment (doc) block + styler.ColourTo(i - 1, state); + state = SCE_RB_WORD; + } else if (ch == '#') { + styler.ColourTo(i - 1, state); + state = SCE_RB_COMMENTLINE; + } else if (ch == '=') { + // =begin indicates the start of a comment (doc) block 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))) { + && 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))) { styler.ColourTo(i - 1, state); state = SCE_RB_POD; - } else { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_RB_OPERATOR); - preferRE = true; - } - } else if (ch == '"') { - styler.ColourTo(i - 1, state); - state = SCE_RB_STRING; - Quote.New(); - Quote.Open(ch); - } else if (ch == '\'') { + } else { + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_RB_OPERATOR); + preferRE = true; + } + } else if (ch == '"') { + styler.ColourTo(i - 1, state); + state = SCE_RB_STRING; + Quote.New(); + Quote.Open(ch); + } else if (ch == '\'') { styler.ColourTo(i - 1, state); state = SCE_RB_CHARACTER; Quote.New(); Quote.Open(ch); - } else if (ch == '`') { - styler.ColourTo(i - 1, state); - state = SCE_RB_BACKTICKS; - Quote.New(); - Quote.Open(ch); - } else if (ch == '@') { + } else if (ch == '`') { + styler.ColourTo(i - 1, state); + state = SCE_RB_BACKTICKS; + Quote.New(); + Quote.Open(ch); + } else if (ch == '@') { // Instance or class var - styler.ColourTo(i - 1, state); + styler.ColourTo(i - 1, state); if (chNext == '@') { state = SCE_RB_CLASS_VAR; advance_char(i, ch, chNext, chNext2); // pass by ref } else { state = SCE_RB_INSTANCE_VAR; } - } else if (ch == '$') { + } else if (ch == '$') { // Check for a builtin global - styler.ColourTo(i - 1, state); + styler.ColourTo(i - 1, state); // Recognize it bit by bit state = SCE_RB_GLOBAL; } else if (ch == '/' && preferRE) { // Ambigous operator - styler.ColourTo(i - 1, state); - state = SCE_RB_REGEX; + styler.ColourTo(i - 1, state); + state = SCE_RB_REGEX; Quote.New(); Quote.Open(ch); - } else if (ch == '<' && chNext == '<' && chNext2 != '=') { + } else if (ch == '<' && chNext == '<' && chNext2 != '=') { // Recognise the '<<' symbol - either a here document or a binary op - styler.ColourTo(i - 1, state); + styler.ColourTo(i - 1, state); i++; chNext = chNext2; - styler.ColourTo(i, SCE_RB_OPERATOR); + styler.ColourTo(i, SCE_RB_OPERATOR); - if (! (strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) { + if (!(strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) { // It's definitely not a here-doc, // based on Ruby's lexer/parser in the // heredoc_identifier routine. @@ -873,17 +874,17 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } preferRE = (state != SCE_RB_HERE_DELIM); } else if (ch == ':') { - styler.ColourTo(i - 1, state); + styler.ColourTo(i - 1, state); if (chNext == ':') { // Mark "::" as an operator, not symbol start styler.ColourTo(i + 1, SCE_RB_OPERATOR); advance_char(i, ch, chNext, chNext2); // pass by ref state = SCE_RB_DEFAULT; - preferRE = false; + preferRE = false; } else if (isSafeWordcharOrHigh(chNext)) { - state = SCE_RB_SYMBOL; + state = SCE_RB_SYMBOL; } else if ((chNext == '@' || chNext == '$') && - isSafeWordcharOrHigh(chNext2)) { + isSafeWordcharOrHigh(chNext2)) { // instance and global variable followed by an identifier advance_char(i, ch, chNext, chNext2); state = SCE_RB_SYMBOL; @@ -913,7 +914,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, bool doColoring = true; switch (chNext) { case '[': - if (chNext2 == ']' ) { + if (chNext2 == ']') { char ch_tmp = styler.SafeGetCharAt(i + 3); if (ch_tmp == '=') { i += 3; @@ -979,11 +980,11 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, styler.ColourTo(i, SCE_RB_SYMBOL); state = SCE_RB_DEFAULT; } - } else if (!preferRE) { - // Don't color symbol strings (yet) - // Just color the ":" and color rest as string - styler.ColourTo(i, SCE_RB_SYMBOL); - state = SCE_RB_DEFAULT; + } else if (!preferRE) { + // Don't color symbol strings (yet) + // Just color the ":" and color rest as string + styler.ColourTo(i, SCE_RB_SYMBOL); + state = SCE_RB_DEFAULT; } else { styler.ColourTo(i, SCE_RB_OPERATOR); state = SCE_RB_DEFAULT; @@ -1000,7 +1001,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, Quote.Open(chNext2); i += 2; ch = chNext2; - chNext = styler.SafeGetCharAt(i + 1); + chNext = styler.SafeGetCharAt(i + 1); have_string = true; } } else if (preferRE && !isSafeWordcharOrHigh(chNext)) { @@ -1036,8 +1037,8 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, is_real_number = false; } } else if (isoperator(ch) || ch == '.') { - styler.ColourTo(i - 1, state); - styler.ColourTo(i, SCE_RB_OPERATOR); + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_RB_OPERATOR); // If we're ending an expression or block, // assume it ends an object, and the ambivalent // constructs are binary operators @@ -1064,7 +1065,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } else if (isEOLChar(ch)) { // Make sure it's a true line-end, with no backslash if ((ch == '\r' || (ch == '\n' && chPrev != '\r')) - && chPrev != '\\') { + && chPrev != '\\') { // Assume we've hit the end of the statement. preferRE = true; } @@ -1079,11 +1080,11 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // but we don't for now. if (ch == '=' - && isSafeWordcharOrHigh(chPrev) - && (chNext == '(' - || strchr(" \t\n\r", chNext) != NULL) - && (!strcmp(prevWord, "def") - || followsDot(styler.GetStartSegment(), styler))) { + && isSafeWordcharOrHigh(chPrev) + && (chNext == '(' + || strchr(" \t\n\r", chNext) != NULL) + && (!strcmp(prevWord, "def") + || followsDot(styler.GetStartSegment(), styler))) { // = is a name only when being def'd -- Get it the next time // This means that = is always lexed as // , (op, =), @@ -1102,28 +1103,28 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // No need to handle this state -- we'll just move to the end preferRE = false; } else { - int wordStartPos = styler.GetStartSegment(); + int wordStartPos = styler.GetStartSegment(); int word_style = ClassifyWordRb(wordStartPos, i - 1, keywords, styler, prevWord); switch (word_style) { - case SCE_RB_WORD: - preferRE = RE_CanFollowKeyword(prevWord); - break; + case SCE_RB_WORD: + preferRE = RE_CanFollowKeyword(prevWord); + break; - case SCE_RB_WORD_DEMOTED: + case SCE_RB_WORD_DEMOTED: + preferRE = true; + break; + + case SCE_RB_IDENTIFIER: + if (isMatch(styler, lengthDoc, wordStartPos, "print")) { preferRE = true; - break; - - case SCE_RB_IDENTIFIER: - if (isMatch(styler, lengthDoc, wordStartPos, "print")) { - preferRE = true; - } else if (isEOLChar(ch)) { - preferRE = true; - } else { - preferRE = false; - } - break; - default: + } else if (isEOLChar(ch)) { + preferRE = true; + } else { preferRE = false; + } + break; + default: + preferRE = false; } if (ch == '.') { // We might be redefining an operator-method @@ -1178,7 +1179,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, preferRE = false; } } else if (state == SCE_RB_COMMENTLINE) { - if (isEOLChar(ch)) { + if (isEOLChar(ch)) { styler.ColourTo(i - 1, state); state = SCE_RB_DEFAULT; // Use whatever setting we had going into the comment @@ -1188,8 +1189,8 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // Slightly different: if we find an immediate '-', // the target can appear indented. - if (HereDoc.State == 0) { // '<<' encountered - HereDoc.State = 1; + if (HereDoc.State == 0) { // '<<' encountered + HereDoc.State = 1; HereDoc.DelimiterLength = 0; if (ch == '-') { HereDoc.CanBeIndented = true; @@ -1214,7 +1215,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, HereDoc.DelimiterLength = 1; } } - } else if (HereDoc.State == 1) { // collect the delimiter + } else if (HereDoc.State == 1) { // collect the delimiter if (isEOLChar(ch)) { // End the quote now, and go back for more styler.ColourTo(i - 1, state); @@ -1223,32 +1224,32 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, chNext = ch; preferRE = false; } else if (HereDoc.Quoted) { - if (ch == HereDoc.Quote) { // closing quote => end of delimiter - styler.ColourTo(i, state); - state = SCE_RB_DEFAULT; + if (ch == HereDoc.Quote) { // closing quote => end of delimiter + styler.ColourTo(i, state); + state = SCE_RB_DEFAULT; preferRE = false; } else { - if (ch == '\\' && !isEOLChar(chNext)) { + if (ch == '\\' && !isEOLChar(chNext)) { advance_char(i, ch, chNext, chNext2); - } - HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; - HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + } + HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; } } else { // an unquoted here-doc delimiter - if (isSafeAlnumOrHigh(ch) || ch == '_') { - HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; - HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; - } else { - styler.ColourTo(i - 1, state); + if (isSafeAlnumOrHigh(ch) || ch == '_') { + HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch; + HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0'; + } else { + styler.ColourTo(i - 1, state); redo_char(i, ch, chNext, chNext2, state); preferRE = false; - } + } } - if (HereDoc.DelimiterLength >= static_cast(sizeof(HereDoc.Delimiter)) - 1) { - styler.ColourTo(i - 1, state); - state = SCE_RB_ERROR; + if (HereDoc.DelimiterLength >= static_cast(sizeof(HereDoc.Delimiter)) - 1) { + styler.ColourTo(i - 1, state); + state = SCE_RB_ERROR; preferRE = false; - } + } } } else if (state == SCE_RB_HERE_Q) { // Not needed: HereDoc.State == 2 @@ -1259,7 +1260,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, if (!HereDoc.CanBeIndented) { if (isEOLChar(chPrev) - && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) { + && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) { styler.ColourTo(i - 1, state); i += HereDoc.DelimiterLength - 1; chNext = styler.SafeGetCharAt(i + 1); @@ -1286,11 +1287,11 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, || state == SCE_RB_INSTANCE_VAR || state == SCE_RB_SYMBOL) { if (state == SCE_RB_SYMBOL && - // FIDs suffices '?' and '!' - (((ch == '!' || ch == '?') && chNext != '=') || - // identifier suffix '=' - (ch == '=' && (chNext != '~' && chNext != '>' && - (chNext != '=' || chNext2 == '>'))))) { + // FIDs suffices '?' and '!' + (((ch == '!' || ch == '?') && chNext != '=') || + // identifier suffix '=' + (ch == '=' && (chNext != '~' && chNext != '>' && + (chNext != '=' || chNext2 == '>'))))) { styler.ColourTo(i, state); state = SCE_RB_DEFAULT; preferRE = false; @@ -1318,9 +1319,9 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, } else if (state == SCE_RB_POD) { // PODs end with ^=end\s, -- any whitespace can follow =end if (strchr(" \t\n\r", ch) != NULL - && i > 5 - && isEOLChar(styler[i - 5]) - && isMatch(styler, lengthDoc, i - 4, "=end")) { + && i > 5 + && isEOLChar(styler[i - 5]) + && isMatch(styler, lengthDoc, i - 4, "=end")) { styler.ColourTo(i - 1, state); state = SCE_RB_DEFAULT; preferRE = false; @@ -1335,7 +1336,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // Include the options while (isSafeAlpha(chNext)) { i++; - ch = chNext; + ch = chNext; chNext = styler.SafeGetCharAt(i + 1); } styler.ColourTo(i, state); @@ -1346,9 +1347,9 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, // Only if close quoter != open quoter Quote.Count++; - } else if (ch == '#' ) { + } else if (ch == '#') { if (chNext == '{' - && inner_string_count < INNER_STRINGS_MAX_COUNT) { + && inner_string_count < INNER_STRINGS_MAX_COUNT) { // process #{ ... } styler.ColourTo(i - 1, state); styler.ColourTo(i + 1, SCE_RB_OPERATOR); @@ -1388,7 +1389,7 @@ static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle, chNext = styler.SafeGetCharAt(i + 1); } } - // Quotes of all kinds... + // Quotes of all kinds... } 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 || @@ -1463,7 +1464,7 @@ static void getPrevWord(int pos, for (; i <= pos; i++) { *dst++ = styler[i]; } - *dst = 0; + *dst = 0; } static bool keywordIsAmbiguous(const char *prevWord) @@ -1471,11 +1472,11 @@ static bool keywordIsAmbiguous(const char *prevWord) // Order from most likely used to least likely // Lots of ways to do a loop in Ruby besides 'while/until' if (!strcmp(prevWord, "if") - || !strcmp(prevWord, "do") - || !strcmp(prevWord, "while") - || !strcmp(prevWord, "unless") - || !strcmp(prevWord, "until") - || !strcmp(prevWord, "for")) { + || !strcmp(prevWord, "do") + || !strcmp(prevWord, "while") + || !strcmp(prevWord, "unless") + || !strcmp(prevWord, "until") + || !strcmp(prevWord, "for")) { return true; } else { return false; @@ -1495,7 +1496,7 @@ static bool keywordIsModifier(const char *word, } char ch, chPrev, chPrev2; int style = SCE_RB_DEFAULT; - int lineStart = styler.GetLine(pos); + 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 @@ -1515,20 +1516,20 @@ static bool keywordIsModifier(const char *word, break; } } else { - break; + break; } } styler.Flush(); while (--pos >= lineStartPosn) { style = actual_style(styler.StyleAt(pos)); - if (style == SCE_RB_DEFAULT) { - if (iswhitespace(ch = styler[pos])) { - //continue - } else if (ch == '\r' || ch == '\n') { - // 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. + if (style == SCE_RB_DEFAULT) { + if (iswhitespace(ch = styler[pos])) { + //continue + } else if (ch == '\r' || ch == '\n') { + // 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. // Also, lineStartPosn may have been moved to more than one // line above word's line while pushing past continuations. @@ -1541,40 +1542,40 @@ static bool keywordIsModifier(const char *word, pos-=2; // gloss over the "\\\r" //continue } else { - return false; + return false; } - } - } else { + } + } else { break; - } + } } if (pos < lineStartPosn) { return false; } // First things where the action is unambiguous switch (style) { - case SCE_RB_DEFAULT: - case SCE_RB_COMMENTLINE: - case SCE_RB_POD: - case SCE_RB_CLASSNAME: - case SCE_RB_DEFNAME: - case SCE_RB_MODULE_NAME: - return false; - case SCE_RB_OPERATOR: - break; - case SCE_RB_WORD: - // Watch out for uses of 'else if' - //XXX: Make a list of other keywords where 'if' isn't a modifier - // and can appear legitimately - // Formulate this to avoid warnings from most compilers - if (strcmp(word, "if") == 0) { - char prevWord[MAX_KEYWORD_LENGTH + 1]; - getPrevWord(pos, prevWord, styler, SCE_RB_WORD); - return strcmp(prevWord, "else") != 0; - } - return true; - default: - return true; + case SCE_RB_DEFAULT: + case SCE_RB_COMMENTLINE: + case SCE_RB_POD: + case SCE_RB_CLASSNAME: + case SCE_RB_DEFNAME: + case SCE_RB_MODULE_NAME: + return false; + case SCE_RB_OPERATOR: + break; + case SCE_RB_WORD: + // Watch out for uses of 'else if' + //XXX: Make a list of other keywords where 'if' isn't a modifier + // and can appear legitimately + // Formulate this to avoid warnings from most compilers + if (strcmp(word, "if") == 0) { + char prevWord[MAX_KEYWORD_LENGTH + 1]; + getPrevWord(pos, prevWord, styler, SCE_RB_WORD); + return strcmp(prevWord, "else") != 0; + } + return true; + default: + return true; } // Assume that if the keyword follows an operator, // usually it's a block assignment, like @@ -1582,12 +1583,12 @@ static bool keywordIsModifier(const char *word, ch = styler[pos]; switch (ch) { - case ')': - case ']': - case '}': - return true; - default: - return false; + case ')': + case ']': + case '}': + return true; + default: + return false; } } @@ -1603,27 +1604,27 @@ static bool keywordDoStartsLoop(int pos, { char ch; int style; - int lineStart = styler.GetLine(pos); + int lineStart = styler.GetLine(pos); int lineStartPosn = styler.LineStart(lineStart); styler.Flush(); while (--pos >= lineStartPosn) { style = actual_style(styler.StyleAt(pos)); - if (style == SCE_RB_DEFAULT) { - if ((ch = styler[pos]) == '\r' || ch == '\n') { - // 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; - } - } else if (style == SCE_RB_WORD) { + if (style == SCE_RB_DEFAULT) { + if ((ch = styler[pos]) == '\r' || ch == '\n') { + // 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; + } + } else if (style == SCE_RB_WORD) { // Check for while or until, but write the word in backwards char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero char *dst = prevWord; int wordLen = 0; int start_word; for (start_word = pos; - start_word >= lineStartPosn && actual_style(styler.StyleAt(start_word)) == SCE_RB_WORD; - start_word--) { + start_word >= lineStartPosn && actual_style(styler.StyleAt(start_word)) == SCE_RB_WORD; + start_word--) { if (++wordLen < MAX_KEYWORD_LENGTH) { *dst++ = styler[start_word]; } @@ -1631,8 +1632,8 @@ static bool keywordDoStartsLoop(int pos, *dst = 0; // Did we see our keyword? if (!strcmp(prevWord, WHILE_BACKWARDS) - || !strcmp(prevWord, UNTIL_BACKWARDS) - || !strcmp(prevWord, FOR_BACKWARDS)) { + || !strcmp(prevWord, UNTIL_BACKWARDS) + || !strcmp(prevWord, FOR_BACKWARDS)) { return true; } // We can move pos to the beginning of the keyword, and then @@ -1650,6 +1651,19 @@ static bool keywordDoStartsLoop(int pos, return false; } +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 != ' ' && ch != '\t') + return false; + } + return false; +} + /* * Folding Ruby * @@ -1706,44 +1720,55 @@ static bool keywordDoStartsLoop(int pos, 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; + 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; - int visibleChars = 0; - int lineCurrent = styler.GetLine(startPos); - int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent) + unsigned int endPos = startPos + length; + int visibleChars = 0; + int lineCurrent = styler.GetLine(startPos); + int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK & ~SC_FOLDLEVELBASE); - int levelCurrent = levelPrev; - char chNext = styler[startPos]; - int styleNext = styler.StyleAt(startPos); - int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1); + int levelCurrent = levelPrev; + char chNext = styler[startPos]; + int styleNext = styler.StyleAt(startPos); + int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1); bool buffer_ends_with_eol = false; - for (unsigned int i = startPos; i < endPos; i++) { - char ch = chNext; - chNext = styler.SafeGetCharAt(i + 1); - int style = styleNext; - styleNext = styler.StyleAt(i + 1); - bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + for (unsigned int i = startPos; i < endPos; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + int style = styleNext; + styleNext = styler.StyleAt(i + 1); + bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); + + /*Mutiline comment patch*/ + if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { + if (!IsCommentLine(lineCurrent - 1, styler) + && IsCommentLine(lineCurrent + 1, styler)) + levelCurrent++; + else if (IsCommentLine(lineCurrent - 1, styler) + && !IsCommentLine(lineCurrent + 1, styler)) + levelCurrent--; + } + if (style == SCE_RB_COMMENTLINE) { if (foldComment && stylePrev != SCE_RB_COMMENTLINE) { if (chNext == '{') { - levelCurrent++; - } else if (chNext == '}' && levelCurrent > 0) { - levelCurrent--; - } + levelCurrent++; + } else if (chNext == '}' && levelCurrent > 0) { + levelCurrent--; + } } } else if (style == SCE_RB_OPERATOR) { - if (strchr("[{(", ch)) { - levelCurrent++; - } else if (strchr(")}]", ch)) { + if (strchr("[{(", ch)) { + levelCurrent++; + } else if (strchr(")}]", ch)) { // Don't decrement below 0 if (levelCurrent > 0) levelCurrent--; - } + } } else if (style == SCE_RB_WORD && styleNext != SCE_RB_WORD) { // Look at the keyword on the left and decide what to do char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero @@ -1753,7 +1778,7 @@ static void FoldRbDoc(unsigned int startPos, int length, int initStyle, // Don't decrement below 0 if (levelCurrent > 0) levelCurrent--; - } else if ( !strcmp(prevWord, "if") + } else if (!strcmp(prevWord, "if") || !strcmp(prevWord, "def") || !strcmp(prevWord, "class") || !strcmp(prevWord, "module") @@ -1764,49 +1789,49 @@ static void FoldRbDoc(unsigned int startPos, int length, int initStyle, || !strcmp(prevWord, "unless") || !strcmp(prevWord, "until") || !strcmp(prevWord, "for") - ) { - levelCurrent++; + ) { + 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) - lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - lev |= SC_FOLDLEVELHEADERFLAG; + } 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) + lev |= SC_FOLDLEVELWHITEFLAG; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + lev |= SC_FOLDLEVELHEADERFLAG; styler.SetLevel(lineCurrent, lev|SC_FOLDLEVELBASE); - lineCurrent++; - levelPrev = levelCurrent; - visibleChars = 0; + lineCurrent++; + levelPrev = levelCurrent; + visibleChars = 0; buffer_ends_with_eol = true; - } else if (!isspacechar(ch)) { - visibleChars++; + } else if (!isspacechar(ch)) { + visibleChars++; buffer_ends_with_eol = false; } - stylePrev = style; + stylePrev = style; } - // Fill in the real level of the next line, keeping the current flags as they will be filled in later + // Fill in the real level of the next line, keeping the current flags as they will be filled in later if (!buffer_ends_with_eol) { lineCurrent++; int new_lev = levelCurrent; if (visibleChars == 0 && foldCompact) new_lev |= SC_FOLDLEVELWHITEFLAG; - if ((levelCurrent > levelPrev) && (visibleChars > 0)) - new_lev |= SC_FOLDLEVELHEADERFLAG; - levelCurrent = new_lev; + if ((levelCurrent > levelPrev) && (visibleChars > 0)) + new_lev |= SC_FOLDLEVELHEADERFLAG; + levelCurrent = new_lev; } - styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE); + styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE); } -static const char * const rubyWordListDesc[] = { - "Keywords", - 0 +static const char *const rubyWordListDesc[] = { + "Keywords", + 0 }; LexerModule lmRuby(SCLEX_RUBY, ColouriseRbDoc, "ruby", FoldRbDoc, rubyWordListDesc); diff --git a/src/stc/scintilla/lexers/LexRust.cxx b/src/stc/scintilla/lexers/LexRust.cxx index 3b1201c7f3..80ec014cac 100644 --- a/src/stc/scintilla/lexers/LexRust.cxx +++ b/src/stc/scintilla/lexers/LexRust.cxx @@ -271,7 +271,7 @@ static void ScanNumber(Accessor& styler, int& pos) { pos++; c = styler.SafeGetCharAt(pos, '\0'); n = styler.SafeGetCharAt(pos + 1, '\0'); - if (c == '8') { + if (c == '8' || c == 's') { pos++; } else if (c == '1' && n == '6') { pos += 2; @@ -279,6 +279,8 @@ static void ScanNumber(Accessor& styler, int& pos) { pos += 2; } else if (c == '6' && n == '4') { pos += 2; + } else { + error = true; } /* See if it's a floating point literal. These literals have to be base 10. */ diff --git a/src/stc/scintilla/lexers/LexSQL.cxx b/src/stc/scintilla/lexers/LexSQL.cxx index b9f15ea1a6..176c92c320 100644 --- a/src/stc/scintilla/lexers/LexSQL.cxx +++ b/src/stc/scintilla/lexers/LexSQL.cxx @@ -54,12 +54,12 @@ static inline bool IsADoxygenChar(int ch) { ch == '}' || ch == '[' || ch == ']'); } -static inline bool IsANumberChar(int ch) { +static inline bool IsANumberChar(int ch, int chPrev) { // 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 == '+'); + ch == '.' || ((ch == '-' || ch == '+') && chPrev < 0x80 && toupper(chPrev) == 'E')); } typedef unsigned int sql_state_t; @@ -444,7 +444,6 @@ void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, StyleContext sc(startPos, length, initStyle, styler); int styleBeforeDCKeyword = SCE_SQL_DEFAULT; int offset = 0; - char qOperator = 0x00; for (; sc.More(); sc.Forward(), offset++) { // Determine if the current state should terminate. @@ -454,7 +453,7 @@ void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, break; case SCE_SQL_NUMBER: // We stop the number definition on non-numerical non-dot non-eE non-sign char - if (!IsANumberChar(sc.ch)) { + if (!IsANumberChar(sc.ch, sc.chPrev)) { sc.SetState(SCE_SQL_DEFAULT); } break; @@ -559,29 +558,34 @@ void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, } break; case SCE_SQL_QOPERATOR: - if (qOperator == 0x00) { - qOperator = sc.ch; - } else { - char qComplement = 0x00; - - if (qOperator == '<') { - qComplement = '>'; - } else if (qOperator == '(') { - qComplement = ')'; - } else if (qOperator == '{') { - qComplement = '}'; - } else if (qOperator == '[') { - qComplement = ']'; - } else { - qComplement = qOperator; - } - - if (sc.Match(qComplement, '\'')) { - sc.Forward(); - sc.ForwardSetState(SCE_SQL_DEFAULT); - qOperator = 0x00; + // Locate the unique Q operator character + sc.Complete(); + char qOperator = 0x00; + for (int styleStartPos = sc.currentPos; styleStartPos > 0; --styleStartPos) { + if (styler.StyleAt(styleStartPos - 1) != SCE_SQL_QOPERATOR) { + qOperator = styler.SafeGetCharAt(styleStartPos + 2); + break; } - } + } + + char qComplement = 0x00; + + if (qOperator == '<') { + qComplement = '>'; + } else if (qOperator == '(') { + qComplement = ')'; + } else if (qOperator == '{') { + qComplement = '}'; + } else if (qOperator == '[') { + qComplement = ']'; + } else { + qComplement = qOperator; + } + + if (sc.Match(qComplement, '\'')) { + sc.Forward(); + sc.ForwardSetState(SCE_SQL_DEFAULT); + } break; } @@ -590,7 +594,8 @@ void SCI_METHOD LexerSQL::Lex(unsigned int startPos, int length, int initStyle, if (sc.Match('q', '\'') || sc.Match('Q', '\'')) { sc.SetState(SCE_SQL_QOPERATOR); sc.Forward(); - } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { + } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)) || + ((sc.ch == '-' || sc.ch == '+') && IsADigit(sc.chNext) && !IsADigit(sc.chPrev))) { sc.SetState(SCE_SQL_NUMBER); } else if (IsAWordStart(sc.ch)) { sc.SetState(SCE_SQL_IDENTIFIER); diff --git a/src/stc/scintilla/lexers/LexTCL.cxx b/src/stc/scintilla/lexers/LexTCL.cxx index 7c883a644b..dfcab54ea6 100644 --- a/src/stc/scintilla/lexers/LexTCL.cxx +++ b/src/stc/scintilla/lexers/LexTCL.cxx @@ -30,7 +30,7 @@ using namespace Scintilla; // Extended to accept accented characters static inline bool IsAWordChar(int ch) { return ch >= 0x80 || - (isalnum(ch) || ch == '_' || ch ==':' || ch=='.'); // : name space separator + (isalnum(ch) || ch == '_' || ch ==':' || ch=='.'); // : name space separator } static inline bool IsAWordStart(int ch) { @@ -49,17 +49,18 @@ static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *k #define isComment(s) (s==SCE_TCL_COMMENT || s==SCE_TCL_COMMENTLINE || s==SCE_TCL_COMMENT_BOX || s==SCE_TCL_BLOCK_COMMENT) bool foldComment = styler.GetPropertyInt("fold.comment") != 0; bool commentLevel = false; - bool subBrace = false; // substitution begin with a brace ${.....} + 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, - LS_COMMAND_EXPECTED = 16, LS_BRACE_ONLY = 32 } lineState = LS_DEFAULT; + LS_COMMAND_EXPECTED = 16, LS_BRACE_ONLY = 32 + } lineState = LS_DEFAULT; bool prevSlash = false; int currentLevel = 0; - bool expected = 0; - bool subParen = 0; + bool expected = 0; + bool subParen = 0; int currentLine = styler.GetLine(startPos); - if (currentLine > 0) - currentLine--; + if (currentLine > 0) + currentLine--; length += startPos - styler.LineStart(currentLine); // make sure lines overlap startPos = styler.LineStart(currentLine); @@ -71,14 +72,14 @@ static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *k WordList &keywords5 = *keywordlists[4]; WordList &keywords6 = *keywordlists[5]; WordList &keywords7 = *keywordlists[6]; - WordList &keywords8 = *keywordlists[7]; - WordList &keywords9 = *keywordlists[8]; + WordList &keywords8 = *keywordlists[7]; + WordList &keywords9 = *keywordlists[8]; if (currentLine > 0) { - int ls = styler.GetLineState(currentLine - 1); + int ls = styler.GetLineState(currentLine - 1); lineState = tLineState(ls & LS_MASK_STATE); expected = LS_COMMAND_EXPECTED == tLineState(ls & LS_COMMAND_EXPECTED); - subBrace = LS_BRACE_ONLY == tLineState(ls & LS_BRACE_ONLY); + subBrace = LS_BRACE_ONLY == tLineState(ls & LS_BRACE_ONLY); currentLevel = styler.LevelAt(currentLine - 1) >> 17; commentLevel = (styler.LevelAt(currentLine - 1) >> 16) & 1; } else @@ -86,105 +87,104 @@ static void ColouriseTCLDoc(unsigned int startPos, int length, int , WordList *k bool visibleChars = false; int previousLevel = currentLevel; - StyleContext sc(startPos, length, SCE_TCL_DEFAULT, styler); + 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 - continue; - bool atEnd = !sc.More(); // make sure we coloured the last word - if (lineState != LS_DEFAULT) { - sc.SetState(SCE_TCL_DEFAULT); - if (lineState == LS_OPEN_COMMENT) - sc.SetState(SCE_TCL_COMMENTLINE); - else if (lineState == LS_OPEN_DOUBLE_QUOTE) - sc.SetState(SCE_TCL_IN_QUOTE); - else if (lineState == LS_COMMENT_BOX && (sc.ch == '#' || (sc.ch == ' ' && sc.chNext=='#'))) - sc.SetState(SCE_TCL_COMMENT_BOX); - lineState = LS_DEFAULT; - } - if (subBrace) { // ${ overrides every thing even \ except } - if (sc.ch == '}') { - subBrace = false; - sc.SetState(SCE_TCL_OPERATOR); - sc.ForwardSetState(SCE_TCL_DEFAULT); - goto next; - } - else - sc.SetState(SCE_TCL_SUB_BRACE); - if (!sc.atLineEnd) - continue; - } else if (sc.state == SCE_TCL_DEFAULT || sc.state ==SCE_TCL_OPERATOR) { - expected &= isspacechar(static_cast(sc.ch)) || IsAWordStart(sc.ch) || sc.ch =='#'; - } else if (sc.state == SCE_TCL_SUBSTITUTION) { - switch(sc.ch) { - case '(': - subParen=true; - sc.SetState(SCE_TCL_OPERATOR); - sc.ForwardSetState(SCE_TCL_SUBSTITUTION); - continue; - case ')': - sc.SetState(SCE_TCL_OPERATOR); - subParen=false; - continue; - case '$': - continue; - case ',': - sc.SetState(SCE_TCL_OPERATOR); - if (subParen) - sc.ForwardSetState(SCE_TCL_SUBSTITUTION); - continue; - default : - // maybe spaces should be allowed ??? - if (!IsAWordChar(sc.ch)) { // probably the code is wrong - sc.SetState(SCE_TCL_DEFAULT); - subParen = 0; - } - break; - } - } else if (isComment(sc.state)) { - } else if (!IsAWordChar(sc.ch)) { - if ((sc.state == SCE_TCL_IDENTIFIER && expected) || sc.state == SCE_TCL_MODIFIER) { - char w[100]; - char *s=w; - sc.GetCurrent(w, sizeof(w)); - if (w[strlen(w)-1]=='\r') - w[strlen(w)-1]=0; - while(*s == ':') // ignore leading : like in ::set a 10 - ++s; - bool quote = sc.state == SCE_TCL_IN_QUOTE; - if (commentLevel || expected) { - if (keywords.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD4); - } else if (sc.GetRelative(-static_cast(strlen(s))-1) == '{' && - keywords5.InList(s) && sc.ch == '}') { // {keyword} exactly no spaces - sc.ChangeState(SCE_TCL_EXPAND); - } - if (keywords6.InList(s)) { - sc.ChangeState(SCE_TCL_WORD5); - } else if (keywords7.InList(s)) { - sc.ChangeState(SCE_TCL_WORD6); - } else if (keywords8.InList(s)) { - 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); - } else if (sc.state == SCE_TCL_MODIFIER || sc.state == SCE_TCL_IDENTIFIER) { - sc.SetState(SCE_TCL_DEFAULT); - } - } + 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) { + sc.SetState(SCE_TCL_DEFAULT); + if (lineState == LS_OPEN_COMMENT) + sc.SetState(SCE_TCL_COMMENTLINE); + else if (lineState == LS_OPEN_DOUBLE_QUOTE) + sc.SetState(SCE_TCL_IN_QUOTE); + else if (lineState == LS_COMMENT_BOX && (sc.ch == '#' || (sc.ch == ' ' && sc.chNext=='#'))) + sc.SetState(SCE_TCL_COMMENT_BOX); + lineState = LS_DEFAULT; + } + if (subBrace) { // ${ overrides every thing even \ except } + if (sc.ch == '}') { + subBrace = false; + sc.SetState(SCE_TCL_OPERATOR); + sc.ForwardSetState(SCE_TCL_DEFAULT); + goto next; + } else + sc.SetState(SCE_TCL_SUB_BRACE); + if (!sc.atLineEnd) + continue; + } else if (sc.state == SCE_TCL_DEFAULT || sc.state ==SCE_TCL_OPERATOR) { + expected &= isspacechar(static_cast(sc.ch)) || IsAWordStart(sc.ch) || sc.ch =='#'; + } else if (sc.state == SCE_TCL_SUBSTITUTION) { + switch (sc.ch) { + case '(': + subParen=true; + sc.SetState(SCE_TCL_OPERATOR); + sc.ForwardSetState(SCE_TCL_SUBSTITUTION); + continue; + case ')': + sc.SetState(SCE_TCL_OPERATOR); + subParen=false; + continue; + case '$': + continue; + case ',': + sc.SetState(SCE_TCL_OPERATOR); + if (subParen) + sc.ForwardSetState(SCE_TCL_SUBSTITUTION); + continue; + default : + // maybe spaces should be allowed ??? + if (!IsAWordChar(sc.ch)) { // probably the code is wrong + sc.SetState(SCE_TCL_DEFAULT); + subParen = 0; + } + break; + } + } else if (isComment(sc.state)) { + } else if (!IsAWordChar(sc.ch)) { + if ((sc.state == SCE_TCL_IDENTIFIER && expected) || sc.state == SCE_TCL_MODIFIER) { + char w[100]; + char *s=w; + sc.GetCurrent(w, sizeof(w)); + if (w[strlen(w)-1]=='\r') + w[strlen(w)-1]=0; + while (*s == ':') // ignore leading : like in ::set a 10 + ++s; + bool quote = sc.state == SCE_TCL_IN_QUOTE; + if (commentLevel || expected) { + if (keywords.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD); + } else if (keywords2.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD2); + } else if (keywords3.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD3); + } else if (keywords4.InList(s)) { + sc.ChangeState(quote ? SCE_TCL_WORD_IN_QUOTE : SCE_TCL_WORD4); + } else if (sc.GetRelative(-static_cast(strlen(s))-1) == '{' && + keywords5.InList(s) && sc.ch == '}') { // {keyword} exactly no spaces + sc.ChangeState(SCE_TCL_EXPAND); + } + if (keywords6.InList(s)) { + sc.ChangeState(SCE_TCL_WORD5); + } else if (keywords7.InList(s)) { + sc.ChangeState(SCE_TCL_WORD6); + } else if (keywords8.InList(s)) { + 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); + } else if (sc.state == SCE_TCL_MODIFIER || sc.state == SCE_TCL_IDENTIFIER) { + sc.SetState(SCE_TCL_DEFAULT); + } + } if (atEnd) break; - if (sc.atLineEnd) { - lineState = LS_DEFAULT; + if (sc.atLineEnd) { + lineState = LS_DEFAULT; currentLine = styler.GetLine(sc.currentPos); if (foldComment && sc.state!=SCE_TCL_COMMENT && isComment(sc.state)) { if (currentLevel == 0) { @@ -206,45 +206,45 @@ next: styler.SetLevel(currentLine, flag + previousLevel + SC_FOLDLEVELBASE + (currentLevel << 17) + (commentLevel << 16)); // Update the line state, so it can be seen by next line - if (sc.state == SCE_TCL_IN_QUOTE) + if (sc.state == SCE_TCL_IN_QUOTE) { lineState = LS_OPEN_DOUBLE_QUOTE; - else { - if (prevSlash) { - if (isComment(sc.state)) - lineState = LS_OPEN_COMMENT; - } else if (sc.state == SCE_TCL_COMMENT_BOX) - lineState = LS_COMMENT_BOX; + } else { + if (prevSlash) { + if (isComment(sc.state)) + lineState = LS_OPEN_COMMENT; + } else if (sc.state == SCE_TCL_COMMENT_BOX) + lineState = LS_COMMENT_BOX; } - styler.SetLineState(currentLine, - (subBrace ? LS_BRACE_ONLY : 0) | - (expected ? LS_COMMAND_EXPECTED : 0) | lineState); - if (lineState == LS_COMMENT_BOX) - sc.ForwardSetState(SCE_TCL_COMMENT_BOX); - else if (lineState == LS_OPEN_DOUBLE_QUOTE) - sc.ForwardSetState(SCE_TCL_IN_QUOTE); - else - sc.ForwardSetState(SCE_TCL_DEFAULT); + styler.SetLineState(currentLine, + (subBrace ? LS_BRACE_ONLY : 0) | + (expected ? LS_COMMAND_EXPECTED : 0) | lineState); + if (lineState == LS_COMMENT_BOX) + sc.ForwardSetState(SCE_TCL_COMMENT_BOX); + else if (lineState == LS_OPEN_DOUBLE_QUOTE) + sc.ForwardSetState(SCE_TCL_IN_QUOTE); + else + sc.ForwardSetState(SCE_TCL_DEFAULT); prevSlash = false; previousLevel = currentLevel; goto next; } if (prevSlash) { - prevSlash = false; - if (sc.ch == '#' && IsANumberChar(sc.chNext)) - sc.ForwardSetState(SCE_TCL_NUMBER); - continue; + prevSlash = false; + if (sc.ch == '#' && IsANumberChar(sc.chNext)) + sc.ForwardSetState(SCE_TCL_NUMBER); + continue; } - prevSlash = sc.ch == '\\'; - if (isComment(sc.state)) - continue; + prevSlash = sc.ch == '\\'; + if (isComment(sc.state)) + continue; if (sc.atLineStart) { visibleChars = false; if (sc.state!=SCE_TCL_IN_QUOTE && !isComment(sc.state)) - { + { sc.SetState(SCE_TCL_DEFAULT); - expected = IsAWordStart(sc.ch)|| isspacechar(static_cast(sc.ch)); - } + expected = IsAWordStart(sc.ch)|| isspacechar(static_cast(sc.ch)); + } } switch (sc.state) { @@ -259,28 +259,28 @@ next: goto next; } else if (sc.ch == '[' || sc.ch == ']' || sc.ch == '$') { sc.SetState(SCE_TCL_OPERATOR); - expected = sc.ch == '['; - sc.ForwardSetState(SCE_TCL_IN_QUOTE); + expected = sc.ch == '['; + sc.ForwardSetState(SCE_TCL_IN_QUOTE); goto next; } - continue; - case SCE_TCL_OPERATOR: + continue; + case SCE_TCL_OPERATOR: sc.SetState(SCE_TCL_DEFAULT); break; } if (sc.ch == '#') { if (visibleChars) { - if (sc.state != SCE_TCL_IN_QUOTE && expected) + if (sc.state != SCE_TCL_IN_QUOTE && expected) sc.SetState(SCE_TCL_COMMENT); } else { - sc.SetState(SCE_TCL_COMMENTLINE); - if (sc.chNext == '~') - sc.SetState(SCE_TCL_BLOCK_COMMENT); - if (sc.atLineStart && (sc.chNext == '#' || sc.chNext == '-')) - sc.SetState(SCE_TCL_COMMENT_BOX); - } - } + sc.SetState(SCE_TCL_COMMENTLINE); + if (sc.chNext == '~') + sc.SetState(SCE_TCL_BLOCK_COMMENT); + if (sc.atLineStart && (sc.chNext == '#' || sc.chNext == '-')) + sc.SetState(SCE_TCL_COMMENT_BOX); + } + } if (!isspacechar(static_cast(sc.ch))) { visibleChars = true; @@ -293,7 +293,7 @@ next: // Determine if a new state should be entered. if (sc.state == SCE_TCL_DEFAULT) { - if (IsAWordStart(sc.ch)) { + if (IsAWordStart(sc.ch)) { sc.SetState(SCE_TCL_IDENTIFIER); } else if (IsADigit(sc.ch) && !IsAWordChar(sc.chPrev)) { sc.SetState(SCE_TCL_NUMBER); @@ -313,39 +313,38 @@ next: --currentLevel; break; case '[': - expected = true; + expected = true; case ']': case '(': case ')': sc.SetState(SCE_TCL_OPERATOR); break; case ';': - expected = true; + expected = true; break; - case '$': - subParen = 0; - if (sc.chNext != '{') { - sc.SetState(SCE_TCL_SUBSTITUTION); - } - else { - sc.SetState(SCE_TCL_OPERATOR); // $ - sc.Forward(); // { - sc.ForwardSetState(SCE_TCL_SUB_BRACE); - subBrace = true; - } - break; - case '#': - if ((isspacechar(static_cast(sc.chPrev))|| - isoperator(static_cast(sc.chPrev))) && IsADigit(sc.chNext,0x10)) - sc.SetState(SCE_TCL_NUMBER); - break; - case '-': - sc.SetState(IsADigit(sc.chNext)? SCE_TCL_NUMBER: SCE_TCL_MODIFIER); - break; - default: - if (isoperator(static_cast(sc.ch))) { - sc.SetState(SCE_TCL_OPERATOR); - } + case '$': + subParen = 0; + if (sc.chNext != '{') { + sc.SetState(SCE_TCL_SUBSTITUTION); + } else { + sc.SetState(SCE_TCL_OPERATOR); // $ + sc.Forward(); // { + sc.ForwardSetState(SCE_TCL_SUB_BRACE); + subBrace = true; + } + break; + case '#': + if ((isspacechar(static_cast(sc.chPrev))|| + isoperator(static_cast(sc.chPrev))) && IsADigit(sc.chNext,0x10)) + sc.SetState(SCE_TCL_NUMBER); + break; + case '-': + sc.SetState(IsADigit(sc.chNext)? SCE_TCL_NUMBER: SCE_TCL_MODIFIER); + break; + default: + if (isoperator(static_cast(sc.ch))) { + sc.SetState(SCE_TCL_OPERATOR); + } } } } @@ -353,18 +352,18 @@ next: sc.Complete(); } -static const char * const tclWordListDesc[] = { - "TCL Keywords", - "TK Keywords", - "iTCL Keywords", - "tkCommands", - "expand", - "user1", - "user2", - "user3", - "user4", - 0 - }; +static const char *const tclWordListDesc[] = { + "TCL Keywords", + "TK Keywords", + "iTCL Keywords", + "tkCommands", + "expand", + "user1", + "user2", + "user3", + "user4", + 0 +}; // this code supports folding in the colourizer LexerModule lmTCL(SCLEX_TCL, ColouriseTCLDoc, "tcl", 0, tclWordListDesc); diff --git a/src/stc/scintilla/lexers/LexVHDL.cxx b/src/stc/scintilla/lexers/LexVHDL.cxx index fe1b33317a..35383f3d85 100644 --- a/src/stc/scintilla/lexers/LexVHDL.cxx +++ b/src/stc/scintilla/lexers/LexVHDL.cxx @@ -72,6 +72,7 @@ static void ColouriseVHDLDoc( WordList &User = *keywordlists[6]; StyleContext sc(startPos, length, initStyle, styler); + bool isExtendedId = false; // true when parsing an extended identifier for (; sc.More(); sc.Forward()) { @@ -84,7 +85,7 @@ static void ColouriseVHDLDoc( sc.SetState(SCE_VHDL_DEFAULT); } } else if (sc.state == SCE_VHDL_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { + if (!isExtendedId && (!IsAWordChar(sc.ch) || (sc.ch == '.'))) { char s[100]; sc.GetCurrentLowered(s, sizeof(s)); if (Keywords.InList(s)) { @@ -103,6 +104,10 @@ static void ColouriseVHDLDoc( sc.ChangeState(SCE_VHDL_USERWORD); } sc.SetState(SCE_VHDL_DEFAULT); + } else if (isExtendedId && ((sc.ch == '\\') || sc.atLineEnd)) { + // extended identifiers are terminated by backslash, check for end of line in case we have invalid syntax + isExtendedId = false; + sc.ForwardSetState(SCE_VHDL_DEFAULT); } } else if (sc.state == SCE_VHDL_COMMENT || sc.state == SCE_VHDL_COMMENTLINEBANG) { if (sc.atLineEnd) { @@ -141,6 +146,9 @@ static void ColouriseVHDLDoc( sc.SetState(SCE_VHDL_BLOCK_COMMENT); } else if (sc.ch == '\"') { sc.SetState(SCE_VHDL_STRING); + } else if (sc.ch == '\\') { + isExtendedId = true; + sc.SetState(SCE_VHDL_IDENTIFIER); } else if (isoperator(static_cast(sc.ch))) { sc.SetState(SCE_VHDL_OPERATOR); } @@ -388,13 +396,14 @@ static void FoldNoBoxVHDLDoc( strcmp(s, "entity") == 0 || strcmp(s, "configuration") == 0 ) { - if (strcmp(prevWord, "end") != 0) + if (strcmp(prevWord, "end") != 0 && lastStart) { // check for instantiated unit by backward searching for the colon. - unsigned pos = lastStart-1; + unsigned pos = lastStart; char chAtPos, styleAtPos; do{// skip white spaces + pos--; styleAtPos = styler.StyleAt(pos); - chAtPos = styler.SafeGetCharAt(pos--); + chAtPos = styler.SafeGetCharAt(pos); }while(pos>0 && (chAtPos == ' ' || chAtPos == '\t' || chAtPos == '\n' || chAtPos == '\r' || diff --git a/src/stc/scintilla/lexers/LexVerilog.cxx b/src/stc/scintilla/lexers/LexVerilog.cxx index ed39c2b177..f0995be240 100644 --- a/src/stc/scintilla/lexers/LexVerilog.cxx +++ b/src/stc/scintilla/lexers/LexVerilog.cxx @@ -13,6 +13,11 @@ #include #include +#include +#include +#include +#include + #include "ILexer.h" #include "Scintilla.h" #include "SciLexer.h" @@ -24,127 +29,722 @@ #include "CharacterSet.h" #include "LexerModule.h" +#include "OptionSet.h" +#include "SubStyles.h" + #ifdef SCI_NAMESPACE using namespace Scintilla; #endif +namespace { + // Use an unnamed namespace to protect the functions and classes from name conflicts + +struct PPDefinition { + int line; + std::string key; + std::string value; + bool isUndef; + std::string arguments; + PPDefinition(int line_, const std::string &key_, const std::string &value_, bool isUndef_ = false, std::string arguments_="") : + line(line_), key(key_), value(value_), isUndef(isUndef_), arguments(arguments_) { + } +}; + +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() const { + 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 vlls; +public: + LinePPState ForLine(int line) const { + if ((line > 0) && (vlls.size() > static_cast(line))) { + return vlls[line]; + } else { + return LinePPState(); + } + } + void Add(int line, LinePPState lls) { + vlls.resize(line+1); + vlls[line] = lls; + } +}; + +// Options used for LexerVerilog +struct OptionsVerilog { + bool foldComment; + bool foldPreprocessor; + bool foldPreprocessorElse; + bool foldCompact; + bool foldAtElse; + bool foldAtModule; + bool trackPreprocessor; + bool updatePreprocessor; + bool portStyling; + bool allUppercaseDocKeyword; + OptionsVerilog() { + foldComment = false; + foldPreprocessor = false; + foldPreprocessorElse = false; + foldCompact = false; + foldAtElse = false; + foldAtModule = false; + // for backwards compatibility, preprocessor functionality is disabled by default + trackPreprocessor = false; + updatePreprocessor = false; + // for backwards compatibility, treat input/output/inout as regular keywords + portStyling = false; + // for backwards compatibility, don't treat all uppercase identifiers as documentation keywords + allUppercaseDocKeyword = false; + } +}; + +struct OptionSetVerilog : public OptionSet { + OptionSetVerilog() { + DefineProperty("fold.comment", &OptionsVerilog::foldComment, + "This option enables folding multi-line comments when using the Verilog lexer."); + DefineProperty("fold.preprocessor", &OptionsVerilog::foldPreprocessor, + "This option enables folding preprocessor directives when using the Verilog lexer."); + DefineProperty("fold.compact", &OptionsVerilog::foldCompact); + DefineProperty("fold.at.else", &OptionsVerilog::foldAtElse, + "This option enables folding on the else line of an if statement."); + DefineProperty("fold.verilog.flags", &OptionsVerilog::foldAtModule, + "This option enables folding module definitions. Typically source files " + "contain only one module definition so this option is somewhat useless."); + DefineProperty("lexer.verilog.track.preprocessor", &OptionsVerilog::trackPreprocessor, + "Set to 1 to interpret `if/`else/`endif to grey out code that is not active."); + DefineProperty("lexer.verilog.update.preprocessor", &OptionsVerilog::updatePreprocessor, + "Set to 1 to update preprocessor definitions when `define, `undef, or `undefineall found."); + DefineProperty("lexer.verilog.portstyling", &OptionsVerilog::portStyling, + "Set to 1 to style input, output, and inout ports differently from regular keywords."); + DefineProperty("lexer.verilog.allupperkeywords", &OptionsVerilog::allUppercaseDocKeyword, + "Set to 1 to style identifiers that are all uppercase as documentation keyword."); + DefineProperty("lexer.verilog.fold.preprocessor.else", &OptionsVerilog::foldPreprocessorElse, + "This option enables folding on `else and `elsif preprocessor directives."); + } +}; + +const char styleSubable[] = {0}; + +} + +class LexerVerilog : public ILexerWithSubStyles { + CharacterSet setWord; + WordList keywords; + WordList keywords2; + WordList keywords3; + WordList keywords4; + WordList keywords5; + WordList ppDefinitions; + PPStates vlls; + std::vector ppDefineHistory; + struct SymbolValue { + std::string value; + std::string arguments; + SymbolValue(const std::string &value_="", const std::string &arguments_="") : value(value_), arguments(arguments_) { + } + SymbolValue &operator = (const std::string &value_) { + value = value_; + arguments.clear(); + return *this; + } + bool IsMacro() const { + return !arguments.empty(); + } + }; + typedef std::map SymbolTable; + SymbolTable preprocessorDefinitionsStart; + OptionsVerilog options; + OptionSetVerilog osVerilog; + enum { activeFlag = 0x40 }; + SubStyles subStyles; + + // states at end of line (EOL) during fold operations: + // foldExternFlag: EOL while parsing an extern function/task declaration terminated by ';' + // foldWaitDisableFlag: EOL while parsing wait or disable statement, terminated by "fork" or '(' + // typdefFlag: EOL while parsing typedef statement, terminated by ';' + enum {foldExternFlag = 0x01, foldWaitDisableFlag = 0x02, typedefFlag = 0x04}; + // map using line number as key to store fold state information + std::map foldState; + +public: + LexerVerilog() : + setWord(CharacterSet::setAlphaNum, "._", 0x80, true), + subStyles(styleSubable, 0x80, 0x40, activeFlag) { + } + virtual ~LexerVerilog() {} + int SCI_METHOD Version() const { + return lvSubStyles; + } + void SCI_METHOD Release() { + delete this; + } + const char* SCI_METHOD PropertyNames() { + return osVerilog.PropertyNames(); + } + int SCI_METHOD PropertyType(const char* name) { + return osVerilog.PropertyType(name); + } + const char* SCI_METHOD DescribeProperty(const char* name) { + return osVerilog.DescribeProperty(name); + } + int SCI_METHOD PropertySet(const char* key, const char* val) { + return osVerilog.PropertySet(&options, key, val); + } + const char* SCI_METHOD DescribeWordListSets() { + return osVerilog.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; + } + int SCI_METHOD LineEndTypesSupported() { + return SC_LINE_END_TYPE_UNICODE; + } + int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) { + return subStyles.Allocate(styleBase, numberStyles); + } + int SCI_METHOD SubStylesStart(int styleBase) { + return subStyles.Start(styleBase); + } + int SCI_METHOD SubStylesLength(int styleBase) { + return subStyles.Length(styleBase); + } + int SCI_METHOD StyleFromSubStyle(int subStyle) { + int styleBase = subStyles.BaseStyle(MaskActive(subStyle)); + int active = subStyle & activeFlag; + return styleBase | active; + } + int SCI_METHOD PrimaryStyleFromStyle(int style) { + return MaskActive(style); + } + void SCI_METHOD FreeSubStyles() { + subStyles.Free(); + } + void SCI_METHOD SetIdentifiers(int style, const char *identifiers) { + subStyles.SetIdentifiers(style, identifiers); + } + int SCI_METHOD DistanceToSecondaryStyles() { + return activeFlag; + } + const char * SCI_METHOD GetSubStyleBases() { + return styleSubable; + } + static ILexer* LexerFactoryVerilog() { + return new LexerVerilog(); + } + static int MaskActive(int style) { + return style & ~activeFlag; + } + std::vector Tokenize(const std::string &expr) const; +}; + +int SCI_METHOD LexerVerilog::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 = &ppDefinitions; + break; + } + int firstModification = -1; + if (wordListN) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); + firstModification = 0; + if (n == 5) { + // Rebuild preprocessorDefinitions + preprocessorDefinitionsStart.clear(); + for (int nDefinition = 0; nDefinition < ppDefinitions.Length(); nDefinition++) { + const char *cpDefinition = ppDefinitions.WordAt(nDefinition); + const char *cpEquals = strchr(cpDefinition, '='); + if (cpEquals) { + std::string name(cpDefinition, cpEquals - cpDefinition); + std::string val(cpEquals+1); + size_t bracket = name.find('('); + size_t bracketEnd = name.find(')'); + if ((bracket != std::string::npos) && (bracketEnd != std::string::npos)) { + // Macro + std::string args = name.substr(bracket + 1, bracketEnd - bracket - 1); + name = name.substr(0, bracket); + preprocessorDefinitionsStart[name] = SymbolValue(val, args); + } else { + preprocessorDefinitionsStart[name] = val; + } + } else { + std::string name(cpDefinition); + std::string val("1"); + preprocessorDefinitionsStart[name] = val; + } + } + } + } + } + return firstModification; +} + static inline bool IsAWordChar(const int ch) { - return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''|| ch == '$'); + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '\''|| ch == '$'); } static inline bool IsAWordStart(const int ch) { return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$'); } -static void ColouriseVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], - Accessor &styler) { +static inline bool AllUpperCase(const char *a) { + while (*a) { + if (*a >= 'a' && *a <= 'z') return false; + a++; + } + return true; +} - WordList &keywords = *keywordlists[0]; - WordList &keywords2 = *keywordlists[1]; - WordList &keywords3 = *keywordlists[2]; - WordList &keywords4 = *keywordlists[3]; +// Functor used to truncate history +struct After { + int line; + explicit After(int line_) : line(line_) {} + bool operator()(PPDefinition &p) const { + return p.line > line; + } +}; + +static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) { + std::string restOfLine; + int i =0; + char ch = styler.SafeGetCharAt(start, '\n'); + int endLine = styler.LineEnd(styler.GetLine(start)); + while (((start+i) < endLine) && (ch != '\r')) { + char chNext = styler.SafeGetCharAt(start + i + 1, '\n'); + if (ch == '/' && (chNext == '/' || chNext == '*')) + break; + if (allowSpace || (ch != ' ')) + restOfLine += ch; + i++; + ch = chNext; + } + return restOfLine; +} + +static bool IsSpaceOrTab(int ch) { + return ch == ' ' || ch == '\t'; +} + +void SCI_METHOD LexerVerilog::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) +{ + LexAccessor styler(pAccess); + + const int kwOther=0, kwDot=0x100, kwInput=0x200, kwOutput=0x300, kwInout=0x400; + int lineState = kwOther; + bool continuationLine = false; + + int curLine = styler.GetLine(startPos); + if (curLine > 0) lineState = styler.GetLineState(curLine - 1); // Do not leak onto next line if (initStyle == SCE_V_STRINGEOL) initStyle = SCE_V_DEFAULT; + if ((MaskActive(initStyle) == SCE_V_PREPROCESSOR) || + (MaskActive(initStyle) == SCE_V_COMMENTLINE) || + (MaskActive(initStyle) == SCE_V_COMMENTLINEBANG)) { + // Set continuationLine if last character of previous line is '\' + if (curLine > 0) { + int endLinePrevious = styler.LineEnd(curLine - 1); + if (endLinePrevious > 0) { + continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\'; + } + } + } + StyleContext sc(startPos, length, initStyle, styler); + LinePPState preproc = vlls.ForLine(curLine); + + bool definitionsChanged = false; + + // Truncate ppDefineHistory before current line + + if (!options.updatePreprocessor) + ppDefineHistory.clear(); + + std::vector::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(), After(curLine-1)); + if (itInvalid != ppDefineHistory.end()) { + ppDefineHistory.erase(itInvalid, ppDefineHistory.end()); + definitionsChanged = true; + } + + SymbolTable preprocessorDefinitions = preprocessorDefinitionsStart; + for (std::vector::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) { + if (itDef->isUndef) + preprocessorDefinitions.erase(itDef->key); + else + preprocessorDefinitions[itDef->key] = SymbolValue(itDef->value, itDef->arguments); + } + + int activitySet = preproc.IsInactive() ? activeFlag : 0; + int lineEndNext = styler.LineEnd(curLine); + bool isEscapedId = false; // true when parsing an escaped Identifier for (; sc.More(); sc.Forward()) { + if (sc.atLineStart) { + if (sc.state == SCE_V_STRING) { + // Prevent SCE_V_STRINGEOL from leaking back to previous line + sc.SetState(SCE_V_STRING); + } + if ((MaskActive(sc.state) == SCE_V_PREPROCESSOR) && (!continuationLine)) { + sc.SetState(SCE_V_DEFAULT|activitySet); + } + if (preproc.IsInactive()) { + activitySet = activeFlag; + sc.SetState(sc.state | activitySet); + } + } - if (sc.atLineStart && (sc.state == SCE_V_STRING)) { - // Prevent SCE_V_STRINGEOL from leaking back to previous line - sc.SetState(SCE_V_STRING); + if (sc.atLineEnd) { + curLine++; + lineEndNext = styler.LineEnd(curLine); + vlls.Add(curLine, preproc); + // Update the line state, so it can be seen by next line + styler.SetLineState(curLine, lineState); + isEscapedId = false; // EOL terminates an escaped Identifier } // Handle line continuation generically. if (sc.ch == '\\') { - if (sc.chNext == '\n' || sc.chNext == '\r') { + if (static_cast((sc.currentPos+1)) >= lineEndNext) { + curLine++; + lineEndNext = styler.LineEnd(curLine); + vlls.Add(curLine, preproc); + // Update the line state, so it can be seen by next line + styler.SetLineState(curLine, lineState); sc.Forward(); if (sc.ch == '\r' && sc.chNext == '\n') { + // Even in UTF-8, \r and \n are separate sc.Forward(); } + continuationLine = true; + sc.Forward(); continue; } } + // for comment keyword + if (MaskActive(sc.state) == SCE_V_COMMENT_WORD && !IsAWordChar(sc.ch)) { + char s[100]; + int state = lineState & 0xff; + sc.GetCurrent(s, sizeof(s)); + if (keywords5.InList(s)) { + sc.ChangeState(SCE_V_COMMENT_WORD|activitySet); + } else { + sc.ChangeState(state|activitySet); + } + sc.SetState(state|activitySet); + } + + const bool atLineEndBeforeSwitch = sc.atLineEnd; + // Determine if the current state should terminate. - if (sc.state == SCE_V_OPERATOR) { - sc.SetState(SCE_V_DEFAULT); - } else if (sc.state == SCE_V_NUMBER) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_IDENTIFIER) { - if (!IsAWordChar(sc.ch) || (sc.ch == '.')) { - char s[100]; - sc.GetCurrent(s, sizeof(s)); - if (keywords.InList(s)) { - sc.ChangeState(SCE_V_WORD); - } else if (keywords2.InList(s)) { - sc.ChangeState(SCE_V_WORD2); - } else if (keywords3.InList(s)) { - sc.ChangeState(SCE_V_WORD3); - } else if (keywords4.InList(s)) { - sc.ChangeState(SCE_V_USER); + switch (MaskActive(sc.state)) { + case SCE_V_OPERATOR: + sc.SetState(SCE_V_DEFAULT|activitySet); + break; + case SCE_V_NUMBER: + if (!(IsAWordChar(sc.ch) || (sc.ch == '?'))) { + sc.SetState(SCE_V_DEFAULT|activitySet); } - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_PREPROCESSOR) { - if (!IsAWordChar(sc.ch)) { - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_COMMENT) { - if (sc.Match('*', '/')) { - sc.Forward(); - sc.ForwardSetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) { - if (sc.atLineStart) { - sc.SetState(SCE_V_DEFAULT); - } - } else if (sc.state == SCE_V_STRING) { - if (sc.ch == '\\') { - if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + break; + case SCE_V_IDENTIFIER: + if (!isEscapedId &&(!IsAWordChar(sc.ch) || (sc.ch == '.'))) { + char s[100]; + lineState &= 0xff00; + sc.GetCurrent(s, sizeof(s)); + if (options.portStyling && (strcmp(s, "input") == 0)) { + lineState = kwInput; + sc.ChangeState(SCE_V_INPUT|activitySet); + } else if (options.portStyling && (strcmp(s, "output") == 0)) { + lineState = kwOutput; + sc.ChangeState(SCE_V_OUTPUT|activitySet); + } else if (options.portStyling && (strcmp(s, "inout") == 0)) { + lineState = kwInout; + sc.ChangeState(SCE_V_INOUT|activitySet); + } else if (lineState == kwInput) { + sc.ChangeState(SCE_V_INPUT|activitySet); + } else if (lineState == kwOutput) { + sc.ChangeState(SCE_V_OUTPUT|activitySet); + } else if (lineState == kwInout) { + sc.ChangeState(SCE_V_INOUT|activitySet); + } else if (lineState == kwDot) { + lineState = kwOther; + if (options.portStyling) + sc.ChangeState(SCE_V_PORT_CONNECT|activitySet); + } else if (keywords.InList(s)) { + sc.ChangeState(SCE_V_WORD|activitySet); + } else if (keywords2.InList(s)) { + sc.ChangeState(SCE_V_WORD2|activitySet); + } else if (keywords3.InList(s)) { + sc.ChangeState(SCE_V_WORD3|activitySet); + } else if (keywords4.InList(s)) { + sc.ChangeState(SCE_V_USER|activitySet); + } else if (options.allUppercaseDocKeyword && AllUpperCase(s)) { + sc.ChangeState(SCE_V_USER|activitySet); + } + sc.SetState(SCE_V_DEFAULT|activitySet); + } + break; + case SCE_V_PREPROCESSOR: + if (!IsAWordChar(sc.ch) || sc.atLineEnd) { + sc.SetState(SCE_V_DEFAULT|activitySet); + } + break; + case SCE_V_COMMENT: + if (sc.Match('*', '/')) { sc.Forward(); + sc.ForwardSetState(SCE_V_DEFAULT|activitySet); + } else if (IsAWordStart(sc.ch)) { + lineState = sc.state | (lineState & 0xff00); + sc.SetState(SCE_V_COMMENT_WORD|activitySet); } - } else if (sc.ch == '\"') { - sc.ForwardSetState(SCE_V_DEFAULT); - } else if (sc.atLineEnd) { - sc.ChangeState(SCE_V_STRINGEOL); - sc.ForwardSetState(SCE_V_DEFAULT); - } + break; + case SCE_V_COMMENTLINE: + case SCE_V_COMMENTLINEBANG: + if (sc.atLineStart) { + sc.SetState(SCE_V_DEFAULT|activitySet); + } else if (IsAWordStart(sc.ch)) { + lineState = sc.state | (lineState & 0xff00); + sc.SetState(SCE_V_COMMENT_WORD|activitySet); + } + break; + case SCE_V_STRING: + if (sc.ch == '\\') { + if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { + sc.Forward(); + } + } else if (sc.ch == '\"') { + sc.ForwardSetState(SCE_V_DEFAULT|activitySet); + } else if (sc.atLineEnd) { + sc.ChangeState(SCE_V_STRINGEOL|activitySet); + sc.ForwardSetState(SCE_V_DEFAULT|activitySet); + } + break; + } + + if (sc.atLineEnd && !atLineEndBeforeSwitch) { + // State exit processing consumed characters up to end of line. + curLine++; + lineEndNext = styler.LineEnd(curLine); + vlls.Add(curLine, preproc); + // Update the line state, so it can be seen by next line + styler.SetLineState(curLine, lineState); + isEscapedId = false; // EOL terminates an escaped Identifier } // Determine if a new state should be entered. - if (sc.state == SCE_V_DEFAULT) { + if (MaskActive(sc.state) == SCE_V_DEFAULT) { if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) { - sc.SetState(SCE_V_NUMBER); + sc.SetState(SCE_V_NUMBER|activitySet); } else if (IsAWordStart(sc.ch)) { - sc.SetState(SCE_V_IDENTIFIER); + sc.SetState(SCE_V_IDENTIFIER|activitySet); } else if (sc.Match('/', '*')) { - sc.SetState(SCE_V_COMMENT); + sc.SetState(SCE_V_COMMENT|activitySet); sc.Forward(); // Eat the * so it isn't used for the end of the comment } else if (sc.Match('/', '/')) { if (sc.Match("//!")) // Nice to have a different comment style - sc.SetState(SCE_V_COMMENTLINEBANG); + sc.SetState(SCE_V_COMMENTLINEBANG|activitySet); else - sc.SetState(SCE_V_COMMENTLINE); + sc.SetState(SCE_V_COMMENTLINE|activitySet); } else if (sc.ch == '\"') { - sc.SetState(SCE_V_STRING); + sc.SetState(SCE_V_STRING|activitySet); } else if (sc.ch == '`') { - sc.SetState(SCE_V_PREPROCESSOR); + sc.SetState(SCE_V_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_V_DEFAULT); + sc.SetState(SCE_V_DEFAULT|activitySet); + styler.SetLineState(curLine, lineState); + } 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("else")) { + if (!preproc.CurrentIfTaken()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) { + sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); + } + } else if (!preproc.IsInactive()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) { + sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); + } + } + } else if (sc.Match("elsif")) { + // Ensure only one chosen out of `if .. `elsif .. `elsif .. `else .. `endif + if (!preproc.CurrentIfTaken()) { + // Similar to `ifdef + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); + bool ifGood = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end(); + if (ifGood) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); + } + } else if (!preproc.IsInactive()) { + preproc.InvertCurrentLevel(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + if (!activitySet) + sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); + } + } else if (sc.Match("endif")) { + preproc.EndSection(); + activitySet = preproc.IsInactive() ? activeFlag : 0; + sc.ChangeState(SCE_V_PREPROCESSOR|activitySet); + } else if (sc.Match("define")) { + if (options.updatePreprocessor && !preproc.IsInactive()) { + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true); + size_t startName = 0; + while ((startName < restOfLine.length()) && IsSpaceOrTab(restOfLine[startName])) + startName++; + size_t endName = startName; + while ((endName < restOfLine.length()) && setWord.Contains(static_cast(restOfLine[endName]))) + endName++; + std::string key = restOfLine.substr(startName, endName-startName); + if ((endName < restOfLine.length()) && (restOfLine.at(endName) == '(')) { + // Macro + size_t endArgs = endName; + while ((endArgs < restOfLine.length()) && (restOfLine[endArgs] != ')')) + endArgs++; + std::string args = restOfLine.substr(endName + 1, endArgs - endName - 1); + size_t startValue = endArgs+1; + while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue])) + startValue++; + std::string value; + if (startValue < restOfLine.length()) + value = restOfLine.substr(startValue); + preprocessorDefinitions[key] = SymbolValue(value, args); + ppDefineHistory.push_back(PPDefinition(curLine, key, value, false, args)); + definitionsChanged = true; + } else { + // Value + size_t startValue = endName; + while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue])) + startValue++; + std::string value = restOfLine.substr(startValue); + preprocessorDefinitions[key] = value; + ppDefineHistory.push_back(PPDefinition(curLine, key, value)); + definitionsChanged = true; + } + } + } else if (sc.Match("undefineall")) { + if (options.updatePreprocessor && !preproc.IsInactive()) { + // remove all preprocessor definitions + std::map::iterator itDef; + for(itDef = preprocessorDefinitions.begin(); itDef != preprocessorDefinitions.end(); ++itDef) { + ppDefineHistory.push_back(PPDefinition(curLine, itDef->first, "", true)); + } + preprocessorDefinitions.clear(); + definitionsChanged = true; + } + } else if (sc.Match("undef")) { + if (options.updatePreprocessor && !preproc.IsInactive()) { + std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, true); + std::vector tokens = Tokenize(restOfLine); + std::string key; + if (tokens.size() >= 1) { + key = tokens[0]; + preprocessorDefinitions.erase(key); + ppDefineHistory.push_back(PPDefinition(curLine, key, "", true)); + definitionsChanged = true; + } + } + } + } } + } else if (sc.ch == '\\') { + // escaped identifier, everything is ok up to whitespace + isEscapedId = true; + sc.SetState(SCE_V_IDENTIFIER|activitySet); } else if (isoperator(static_cast(sc.ch)) || sc.ch == '@' || sc.ch == '#') { - sc.SetState(SCE_V_OPERATOR); + sc.SetState(SCE_V_OPERATOR|activitySet); + if (sc.ch == '.') lineState = kwDot; + if (sc.ch == ';') lineState = kwOther; } } + if (isEscapedId && isspacechar(sc.ch)) { + isEscapedId = false; + } + } + if (definitionsChanged) { + styler.ChangeLexerState(startPos, startPos + length); } sc.Complete(); } @@ -153,7 +753,7 @@ static bool IsStreamCommentStyle(int style) { return style == SCE_V_COMMENT; } -static bool IsCommentLine(int line, Accessor &styler) { +static bool IsCommentLine(int line, LexAccessor &styler) { int pos = styler.LineStart(line); int eolPos = styler.LineStart(line + 1) - 1; for (int i = pos; i < eolPos; i++) { @@ -169,44 +769,60 @@ static bool IsCommentLine(int line, Accessor &styler) { } 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 {". -static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle, - Accessor &styler) { - bool foldComment = styler.GetPropertyInt("fold.comment") != 0; - bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0; - bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; - bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; - // Verilog specific folding options: - // fold_at_module - - // Generally used methodology in verilog code is - // one module per file, so folding at module definition is useless. - // fold_at_brace/parenthese - - // Folding of long port lists can be convenient. - bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0; +void SCI_METHOD LexerVerilog::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess) +{ + LexAccessor styler(pAccess); bool foldAtBrace = 1; bool foldAtParenthese = 1; + int lineCurrent = styler.GetLine(startPos); + // Move back one line to be compatible with LexerModule::Fold behavior, fixes problem with foldComment behavior + if (lineCurrent > 0) { + lineCurrent--; + int newStartPos = styler.LineStart(lineCurrent); + length += startPos - newStartPos; + startPos = newStartPos; + initStyle = 0; + if (startPos > 0) { + initStyle = styler.StyleAt(startPos - 1); + } + } 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 = styler.StyleAt(startPos); - int style = initStyle; + int styleNext = MaskActive(styler.StyleAt(startPos)); + int style = MaskActive(initStyle); + + // restore fold state (if it exists) for prior line + int stateCurrent = 0; + std::map::iterator foldStateIterator = foldState.find(lineCurrent-1); + if (foldStateIterator != foldState.end()) { + stateCurrent = foldStateIterator->second; + } + + // remove all foldState entries after lineCurrent-1 + foldStateIterator = foldState.upper_bound(lineCurrent-1); + if (foldStateIterator != foldState.end()) { + foldState.erase(foldStateIterator, foldState.end()); + } + 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); + styleNext = MaskActive(styler.StyleAt(i + 1)); bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); - if (foldComment && IsStreamCommentStyle(style)) { + if (options.foldComment && IsStreamCommentStyle(style)) { if (!IsStreamCommentStyle(stylePrev)) { levelNext++; } else if (!IsStreamCommentStyle(styleNext) && !atEOL) { @@ -214,7 +830,7 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle levelNext--; } } - if (foldComment && atEOL && IsCommentLine(lineCurrent, styler)) + if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler)) { if (!IsCommentLine(lineCurrent - 1, styler) && IsCommentLine(lineCurrent + 1, styler)) @@ -223,7 +839,7 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle && !IsCommentLine(lineCurrent+1, styler)) levelNext--; } - if (foldComment && (style == SCE_V_COMMENTLINE)) { + if (options.foldComment && (style == SCE_V_COMMENTLINE)) { if ((ch == '/') && (chNext == '/')) { char chNext2 = styler.SafeGetCharAt(i + 2); if (chNext2 == '{') { @@ -233,87 +849,157 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle } } } - if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) { + if (options.foldPreprocessor && (style == SCE_V_PREPROCESSOR)) { if (ch == '`') { unsigned int j = i + 1; while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) { j++; } if (styler.Match(j, "if")) { + if (options.foldPreprocessorElse) { + // Measure the minimum before a begin to allow + // folding on "end else begin" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + } levelNext++; - } else if (styler.Match(j, "end")) { + } else if (options.foldPreprocessorElse && styler.Match(j, "else")) { + levelNext--; + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (options.foldPreprocessorElse && styler.Match(j, "elsif")) { + levelNext--; + // Measure the minimum before a begin to allow + // folding on "end else begin" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (styler.Match(j, "endif")) { levelNext--; } } } - if (style == SCE_V_OPERATOR) { - if (foldAtParenthese) { + if (style == SCE_V_OPERATOR) { + if (foldAtParenthese) { + if (ch == '(') { + levelNext++; + } else if (ch == ')') { + levelNext--; + } + } + // semicolons terminate external declarations + if (ch == ';') { + // extern and pure virtual declarations terminated by semicolon + if (stateCurrent & foldExternFlag) { + levelNext--; + stateCurrent &= ~foldExternFlag; + } + // wait and disable statements terminated by semicolon + if (stateCurrent & foldWaitDisableFlag) { + stateCurrent &= ~foldWaitDisableFlag; + } + // typedef statements terminated by semicolon + if (stateCurrent & typedefFlag) { + stateCurrent &= ~typedefFlag; + } + } + // wait and disable statements containing '(' will not contain "fork" keyword, special processing is not needed if (ch == '(') { - levelNext++; - } else if (ch == ')') { - levelNext--; + if (stateCurrent & foldWaitDisableFlag) { + stateCurrent &= ~foldWaitDisableFlag; + } } - } } - if (style == SCE_V_OPERATOR) { - if (foldAtBrace) { - if (ch == '{') { - levelNext++; - } else if (ch == '}') { - levelNext--; + if (style == SCE_V_OPERATOR) { + if (foldAtBrace) { + if (ch == '{') { + levelNext++; + } else if (ch == '}') { + levelNext--; + } } - } } - if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) { - unsigned int j = i; - if (styler.Match(j, "case") || - styler.Match(j, "casex") || - styler.Match(j, "casez") || - styler.Match(j, "class") || - styler.Match(j, "function") || - styler.Match(j, "generate") || - 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, "endgenerate") || - 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--; - } + if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) { + unsigned int j = i; + if (styler.Match(j, "case") || + styler.Match(j, "casex") || + styler.Match(j, "casez") || + styler.Match(j, "function") || + styler.Match(j, "generate") || + 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, "module") && options.foldAtModule)) { + levelNext++; + } else if (styler.Match(j, "begin")) { + // Measure the minimum before a begin to allow + // folding on "end else begin" + if (levelMinCurrent > levelNext) { + levelMinCurrent = levelNext; + } + levelNext++; + } else if (styler.Match(j, "class")) { + // class does not introduce a block when used in a typedef statement + if (!(stateCurrent & typedefFlag)) + levelNext++; + } else if (styler.Match(j, "fork")) { + // fork does not introduce a block when used in a wait or disable statement + if (stateCurrent & foldWaitDisableFlag) { + stateCurrent &= ~foldWaitDisableFlag; + } else + levelNext++; + } else if (styler.Match(j, "endcase") || + styler.Match(j, "endclass") || + styler.Match(j, "endfunction") || + styler.Match(j, "endgenerate") || + 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") && options.foldAtModule) || + (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j + 3)))) { + levelNext--; + } else if (styler.Match(j, "extern") || + styler.Match(j, "pure")) { + // extern and pure virtual functions/tasks are terminated by ';' not endfunction/endtask + stateCurrent |= foldExternFlag; + } else if (styler.Match(j, "disable") || + styler.Match(j, "wait")) { + // fork does not introduce a block when used in a wait or disable statement + stateCurrent |= foldWaitDisableFlag; + } else if (styler.Match(j, "typedef")) { + stateCurrent |= typedefFlag; + } } if (atEOL) { int levelUse = levelCurrent; - if (foldAtElse) { + if (options.foldAtElse||options.foldPreprocessorElse) { 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; + if (stateCurrent) { + foldState[lineCurrent] = stateCurrent; + } if (lev != styler.LevelAt(lineCurrent)) { styler.SetLevel(lineCurrent, lev); } @@ -327,9 +1013,31 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle } } -static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[], - Accessor &styler) { - FoldNoBoxVerilogDoc(startPos, length, initStyle, styler); +std::vector LexerVerilog::Tokenize(const std::string &expr) const { + // Break into tokens + std::vector tokens; + const char *cp = expr.c_str(); + while (*cp) { + std::string word; + if (setWord.Contains(static_cast(*cp))) { + // Identifiers and numbers + while (setWord.Contains(static_cast(*cp))) { + word += *cp; + cp++; + } + } else if (IsSpaceOrTab(*cp)) { + while (IsSpaceOrTab(*cp)) { + cp++; + } + continue; + } else { + // Should handle strings, characters, and comments here + word += *cp; + cp++; + } + tokens.push_back(word); + } + return tokens; } static const char * const verilogWordLists[] = { @@ -337,9 +1045,9 @@ static const char * const verilogWordLists[] = { "Secondary keywords and identifiers", "System Tasks", "User defined tasks and identifiers", - "Unused", + "Documentation comment keywords", + "Preprocessor definitions", 0, }; - -LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists); +LexerModule lmVerilog(SCLEX_VERILOG, LexerVerilog::LexerFactoryVerilog, "verilog", verilogWordLists); diff --git a/src/stc/scintilla/lexlib/LexAccessor.h b/src/stc/scintilla/lexlib/LexAccessor.h index 35e15726c8..8e3455d0c3 100644 --- a/src/stc/scintilla/lexlib/LexAccessor.h +++ b/src/stc/scintilla/lexlib/LexAccessor.h @@ -58,6 +58,9 @@ public: validLen(0), startSeg(0), startPosStyling(0), documentVersion(pAccess->Version()) { + // Prevent warnings by static analyzers about uninitialized buf and styleBuf. + buf[0] = 0; + styleBuf[0] = 0; switch (codePage) { case 65001: encodingType = encUnicode; diff --git a/src/stc/scintilla/lexlib/SubStyles.h b/src/stc/scintilla/lexlib/SubStyles.h index 5791078196..f5b15e9cfa 100644 --- a/src/stc/scintilla/lexlib/SubStyles.h +++ b/src/stc/scintilla/lexlib/SubStyles.h @@ -166,7 +166,8 @@ public: } const WordClassifier &Classifier(int baseStyle) const { - return classifiers[BlockFromBaseStyle(baseStyle)]; + const int block = BlockFromBaseStyle(baseStyle); + return classifiers[block >= 0 ? block : 0]; } }; diff --git a/src/stc/scintilla/lexlib/WordList.cxx b/src/stc/scintilla/lexlib/WordList.cxx index 68b384a954..be7fda5056 100644 --- a/src/stc/scintilla/lexlib/WordList.cxx +++ b/src/stc/scintilla/lexlib/WordList.cxx @@ -69,6 +69,8 @@ static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = fa WordList::WordList(bool onlyLineEnds_) : words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) { + // Prevent warnings by static analyzers about uninitialized starts. + starts[0] = -1; } WordList::~WordList() { diff --git a/src/stc/scintilla/src/AutoComplete.cxx b/src/stc/scintilla/src/AutoComplete.cxx index d154a913a1..27eed53b99 100644 --- a/src/stc/scintilla/src/AutoComplete.cxx +++ b/src/stc/scintilla/src/AutoComplete.cxx @@ -167,7 +167,9 @@ void AutoComplete::SetList(const char *list) { char item[maxItemLen]; for (size_t i = 0; i < sortMatrix.size(); ++i) { int wordLen = IndexSort.indices[sortMatrix[i] * 2 + 2] - IndexSort.indices[sortMatrix[i] * 2]; - strncpy(item, list + IndexSort.indices[sortMatrix[i] * 2], wordLen); + if (wordLen > maxItemLen-2) + wordLen = maxItemLen - 2; + memcpy(item, list + IndexSort.indices[sortMatrix[i] * 2], wordLen); if ((i+1) == sortMatrix.size()) { // Last item so remove separator if present if ((wordLen > 0) && (item[wordLen-1] == separator)) diff --git a/src/stc/scintilla/src/Catalogue.cxx b/src/stc/scintilla/src/Catalogue.cxx index 3fd006f7ac..b02a0108ce 100644 --- a/src/stc/scintilla/src/Catalogue.cxx +++ b/src/stc/scintilla/src/Catalogue.cxx @@ -123,6 +123,7 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmGui4Cli); LINK_LEXER(lmHaskell); LINK_LEXER(lmHTML); + LINK_LEXER(lmIHex); LINK_LEXER(lmInno); LINK_LEXER(lmKix); LINK_LEXER(lmKVIrc); @@ -174,12 +175,14 @@ int Scintilla_LinkLexers() { LINK_LEXER(lmSpecman); LINK_LEXER(lmSpice); LINK_LEXER(lmSQL); + LINK_LEXER(lmSrec); LINK_LEXER(lmSTTXT); LINK_LEXER(lmTACL); LINK_LEXER(lmTADS3); LINK_LEXER(lmTAL); LINK_LEXER(lmTCL); LINK_LEXER(lmTCMD); + LINK_LEXER(lmTEHex); LINK_LEXER(lmTeX); LINK_LEXER(lmTxt2tags); LINK_LEXER(lmVB); diff --git a/src/stc/scintilla/src/CellBuffer.cxx b/src/stc/scintilla/src/CellBuffer.cxx index a770dc3351..dfa1350c05 100644 --- a/src/stc/scintilla/src/CellBuffer.cxx +++ b/src/stc/scintilla/src/CellBuffer.cxx @@ -10,6 +10,7 @@ #include #include +#include #include #include "Platform.h" @@ -786,6 +787,10 @@ const Action &CellBuffer::GetUndoStep() const { void CellBuffer::PerformUndoStep() { const Action &actionStep = uh.GetUndoStep(); if (actionStep.at == insertAction) { + if (substance.Length() < actionStep.lenData) { + throw std::runtime_error( + "CellBuffer::PerformUndoStep: deletion must be less than document length."); + } BasicDeleteChars(actionStep.position, actionStep.lenData); } else if (actionStep.at == removeAction) { BasicInsertString(actionStep.position, actionStep.data, actionStep.lenData); diff --git a/src/stc/scintilla/src/Document.cxx b/src/stc/scintilla/src/Document.cxx index d0909b808f..7d34dace1c 100644 --- a/src/stc/scintilla/src/Document.cxx +++ b/src/stc/scintilla/src/Document.cxx @@ -37,6 +37,7 @@ #include "Document.h" #include "RESearch.h" #include "UniConversion.h" +#include "UnicodeFromUTF8.h" #ifdef SCI_NAMESPACE using namespace Scintilla; @@ -766,19 +767,6 @@ bool Document::NextCharacter(int &pos, int moveDir) const { } } -static inline int UnicodeFromBytes(const unsigned char *us) { - if (us[0] < 0xC2) { - return us[0]; - } else if (us[0] < 0xE0) { - return ((us[0] & 0x1F) << 6) + (us[1] & 0x3F); - } else if (us[0] < 0xF0) { - return ((us[0] & 0xF) << 12) + ((us[1] & 0x3F) << 6) + (us[2] & 0x3F); - } else if (us[0] < 0xF5) { - return ((us[0] & 0x7) << 18) + ((us[1] & 0x3F) << 12) + ((us[2] & 0x3F) << 6) + (us[3] & 0x3F); - } - return us[0]; -} - // Return -1 on out-of-bounds int SCI_METHOD Document::GetRelativePosition(int positionStart, int characterOffset) const { int pos = positionStart; @@ -799,6 +787,27 @@ int SCI_METHOD Document::GetRelativePosition(int positionStart, int characterOff return pos; } +int Document::GetRelativePositionUTF16(int positionStart, int characterOffset) const { + int pos = positionStart; + if (dbcsCodePage) { + const int increment = (characterOffset > 0) ? 1 : -1; + while (characterOffset != 0) { + const int posNext = NextPosition(pos, increment); + if (posNext == pos) + return INVALID_POSITION; + if (abs(pos-posNext) > 3) // 4 byte character = 2*UTF16. + characterOffset -= increment; + pos = posNext; + characterOffset -= increment; + } + } else { + pos = positionStart + characterOffset; + if ((pos < 0) || (pos > Length())) + return INVALID_POSITION; + } + return pos; +} + int SCI_METHOD Document::GetCharacterAndWidth(int position, int *pWidth) const { int character; int bytesInCharacter = 1; @@ -819,7 +828,7 @@ int SCI_METHOD Document::GetCharacterAndWidth(int position, int *pWidth) const { character = 0xDC80 + leadByte; } else { bytesInCharacter = utf8status & UTF8MaskWidth; - character = UnicodeFromBytes(charBytes); + character = UnicodeFromUTF8(charBytes); } } } else { @@ -1320,6 +1329,21 @@ int Document::CountCharacters(int startPos, int endPos) const { return count; } +int Document::CountUTF16(int startPos, int endPos) const { + startPos = MovePositionOutsideChar(startPos, 1, false); + endPos = MovePositionOutsideChar(endPos, -1, false); + int count = 0; + int i = startPos; + while (i < endPos) { + count++; + const int next = NextPosition(i, 1); + if ((next - i) > 3) + count++; + i = next; + } + return count; +} + int Document::FindColumn(int line, int column) { int position = LineStart(line); if ((line >= 0) && (line < LinesTotal())) { @@ -1610,7 +1634,7 @@ Document::CharacterExtracted Document::ExtractCharacter(int position) const { // Treat as invalid and use up just one byte return CharacterExtracted(unicodeReplacementChar, 1); } else { - return CharacterExtracted(UnicodeFromBytes(charBytes), utf8status & UTF8MaskWidth); + return CharacterExtracted(UnicodeFromUTF8(charBytes), utf8status & UTF8MaskWidth); } } @@ -2359,6 +2383,9 @@ public: doc(doc_), position(position_), characterIndex(0), lenBytes(0), lenCharacters(0) { buffered[0] = 0; buffered[1] = 0; + if (doc) { + ReadCharacter(); + } } UTF8Iterator(const UTF8Iterator &other) { doc = other.doc; @@ -2381,10 +2408,8 @@ public: } return *this; } - wchar_t operator*() { - if (lenCharacters == 0) { - ReadCharacter(); - } + wchar_t operator*() const { + assert(lenCharacters != 0); return buffered[characterIndex]; } UTF8Iterator &operator++() { diff --git a/src/stc/scintilla/src/Document.h b/src/stc/scintilla/src/Document.h index e808bb37f4..5e66dc2b62 100644 --- a/src/stc/scintilla/src/Document.h +++ b/src/stc/scintilla/src/Document.h @@ -279,6 +279,7 @@ public: int NextPosition(int pos, int moveDir) const; bool NextCharacter(int &pos, int moveDir) const; // Returns true if pos changed int SCI_METHOD GetRelativePosition(int positionStart, int characterOffset) const; + int GetRelativePositionUTF16(int positionStart, int characterOffset) const; int SCI_METHOD GetCharacterAndWidth(int position, int *pWidth) const; int SCI_METHOD CodePage() const; bool SCI_METHOD IsDBCSLeadByte(char ch) const; @@ -322,6 +323,7 @@ public: int GetLineIndentPosition(int line) const; int GetColumn(int position); int CountCharacters(int startPos, int endPos) const; + int CountUTF16(int startPos, int endPos) const; int FindColumn(int line, int column); void Indent(bool forwards, int lineBottom, int lineTop); static std::string TransformLineEnds(const char *s, size_t len, int eolModeWanted); diff --git a/src/stc/scintilla/src/EditModel.cxx b/src/stc/scintilla/src/EditModel.cxx index fe65a8bf8d..b50ade258f 100644 --- a/src/stc/scintilla/src/EditModel.cxx +++ b/src/stc/scintilla/src/EditModel.cxx @@ -65,6 +65,7 @@ EditModel::EditModel() { imeInteraction = imeWindowed; foldFlags = 0; hotspot = Range(invalidPosition); + hoverIndicatorPos = invalidPosition; wrapWidth = LineLayout::wrapWidthInfinite; pdoc = new Document(); pdoc->AddRef(); diff --git a/src/stc/scintilla/src/EditModel.h b/src/stc/scintilla/src/EditModel.h index d8def32942..fce26bd22e 100644 --- a/src/stc/scintilla/src/EditModel.h +++ b/src/stc/scintilla/src/EditModel.h @@ -48,6 +48,7 @@ public: ContractionState cs; // Hotspot support Range hotspot; + int hoverIndicatorPos; // Wrapping support int wrapWidth; diff --git a/src/stc/scintilla/src/EditView.cxx b/src/stc/scintilla/src/EditView.cxx index 4976d3614b..5372e3abd4 100644 --- a/src/stc/scintilla/src/EditView.cxx +++ b/src/stc/scintilla/src/EditView.cxx @@ -173,6 +173,7 @@ const XYPOSITION epsilon = 0.0001f; // A small nudge to avoid floating point pre EditView::EditView() { ldTabstops = NULL; + tabWidthMinimumPixels = 2; // needed for calculating tab stops for fractional proportional fonts hideSelection = false; drawOverstrikeCaret = true; bufferedDraw = true; @@ -220,10 +221,10 @@ void EditView::ClearAllTabstops() { } XYPOSITION EditView::NextTabstopPos(int line, XYPOSITION x, XYPOSITION tabWidth) const { - int next = GetNextTabstop(line, static_cast(x + 2)); + int next = GetNextTabstop(line, static_cast(x + tabWidthMinimumPixels)); if (next > 0) return static_cast(next); - return (static_cast((x + 2) / tabWidth) + 1) * tabWidth; + return (static_cast((x + tabWidthMinimumPixels) / tabWidth) + 1) * tabWidth; } bool EditView::ClearTabstops(int line) { @@ -445,7 +446,7 @@ void EditView::LayoutLine(const EditModel &model, int line, Surface *surface, co ll->positions[0] = 0; bool lastSegItalics = false; - BreakFinder bfLayout(ll, NULL, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs); + BreakFinder bfLayout(ll, NULL, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs, NULL); while (bfLayout.More()) { const TextSegment ts = bfLayout.Next(); @@ -793,7 +794,7 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle XYPOSITION xEol = static_cast(ll->positions[lineEnd] - subLineStart); // Fill the virtual space and show selections within it - if (virtualSpace) { + if (virtualSpace > 0.0f) { rcSegment.left = xEol + xStart; rcSegment.right = xEol + xStart + virtualSpace; surface->FillRectangle(rcSegment, background.isSet ? background : vsDraw.styles[ll->styles[ll->numCharsInLine]].back); @@ -940,18 +941,18 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle } static void DrawIndicator(int indicNum, int startPos, int endPos, Surface *surface, const ViewStyle &vsDraw, - const LineLayout *ll, int xStart, PRectangle rcLine, int subLine) { + const LineLayout *ll, int xStart, PRectangle rcLine, int subLine, Indicator::DrawState drawState, int value) { 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); + vsDraw.indicators[indicNum].Draw(surface, rcIndic, rcLine, drawState, value); } static void DrawIndicators(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, - int line, int xStart, PRectangle rcLine, int subLine, int lineEnd, bool under) { + int line, int xStart, PRectangle rcLine, int subLine, int lineEnd, bool under, int hoverIndicatorPos) { // Draw decorators const int posLineStart = model.pdoc->LineStart(line); const int lineStart = ll->LineStart(subLine); @@ -967,8 +968,12 @@ static void DrawIndicators(Surface *surface, const EditModel &model, const ViewS int endPos = deco->rs.EndRun(startPos); if (endPos > posLineEnd) endPos = posLineEnd; + const bool hover = vsDraw.indicators[deco->indicator].IsDynamic() && + ((hoverIndicatorPos >= startPos) && (hoverIndicatorPos <= endPos)); + const int value = deco->rs.ValueAt(startPos); + Indicator::DrawState drawState = hover ? Indicator::drawHover : Indicator::drawNormal; DrawIndicator(deco->indicator, startPos - posLineStart, endPos - posLineStart, - surface, vsDraw, ll, xStart, rcLine, subLine); + surface, vsDraw, ll, xStart, rcLine, subLine, drawState, value); startPos = endPos; if (!deco->rs.ValueAt(startPos)) { startPos = deco->rs.EndRun(startPos); @@ -986,13 +991,13 @@ static void DrawIndicators(Surface *surface, const EditModel &model, const ViewS if (rangeLine.ContainsCharacter(model.braces[0])) { int braceOffset = model.braces[0] - posLineStart; if (braceOffset < ll->numCharsInLine) { - DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine); + DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine, Indicator::drawNormal, 1); } } if (rangeLine.ContainsCharacter(model.braces[1])) { int braceOffset = model.braces[1] - posLineStart; if (braceOffset < ll->numCharsInLine) { - DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine); + DrawIndicator(braceIndicator, braceOffset, braceOffset + 1, surface, vsDraw, ll, xStart, rcLine, subLine, Indicator::drawNormal, 1); } } } @@ -1247,7 +1252,7 @@ void EditView::DrawBackground(Surface *surface, const EditModel &model, const Vi // Does not take margin into account but not significant const int xStartVisible = static_cast(subLineStart)-xStart; - BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs); + BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs, NULL); const bool drawWhitespaceBackground = vsDraw.WhitespaceBackgroundDrawn() && !background.isSet; @@ -1424,7 +1429,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi // Foreground drawing loop BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible, - (((phasesDraw == phasesOne) && selBackDrawn) || vsDraw.selColours.fore.isSet), model.pdoc, &model.reprs); + (((phasesDraw == phasesOne) && selBackDrawn) || vsDraw.selColours.fore.isSet), model.pdoc, &model.reprs, &vsDraw); while (bfFore.More()) { @@ -1447,6 +1452,30 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi if (vsDraw.hotspotColours.fore.isSet) textFore = vsDraw.hotspotColours.fore; } + if (vsDraw.indicatorsSetFore > 0) { + // At least one indicator sets the text colour so see if it applies to this segment + for (Decoration *deco = model.pdoc->decorations.root; deco; deco = deco->next) { + const int indicatorValue = deco->rs.ValueAt(ts.start + posLineStart); + if (indicatorValue) { + const Indicator &indicator = vsDraw.indicators[deco->indicator]; + const bool hover = indicator.IsDynamic() && + ((model.hoverIndicatorPos >= ts.start + posLineStart) && + (model.hoverIndicatorPos <= ts.end() + posLineStart)); + if (hover) { + if (indicator.sacHover.style == INDIC_TEXTFORE) { + textFore = indicator.sacHover.fore; + } + } else { + if (indicator.sacNormal.style == INDIC_TEXTFORE) { + if (indicator.Flags() & SC_INDICFLAG_VALUEFORE) + textFore = indicatorValue & SC_INDICVALUEMASK; + else + textFore = indicator.sacNormal.fore; + } + } + } + } + } const int inSelection = hideSelection ? 0 : model.sel.CharacterInSelection(iDoc); if (inSelection && (vsDraw.selColours.fore.isSet)) { textFore = (inSelection == 1) ? vsDraw.selColours.fore : vsDraw.selAdditionalForeground; @@ -1662,7 +1691,7 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl } if (phase & drawIndicatorsBack) { - DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, true); + DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, true, model.hoverIndicatorPos); DrawEdgeLine(surface, vsDraw, ll, rcLine, lineRange, xStart); DrawMarkUnderline(surface, model, vsDraw, line, rcLine); } @@ -1677,7 +1706,7 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl } if (phase & drawIndicatorsFore) { - DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, false); + DrawIndicators(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, lineRange.end, false, model.hoverIndicatorPos); } // End of the drawing of the current line @@ -1975,11 +2004,11 @@ long EditView::FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, vsPrint.Refresh(*surfaceMeasure, model.pdoc->tabInChars); // Recalculate fixedColumnWidth } - int linePrintStart = model.pdoc->LineFromPosition(pfr->chrg.cpMin); + int linePrintStart = model.pdoc->LineFromPosition(static_cast(pfr->chrg.cpMin)); int linePrintLast = linePrintStart + (pfr->rc.bottom - pfr->rc.top) / vsPrint.lineHeight - 1; if (linePrintLast < linePrintStart) linePrintLast = linePrintStart; - int linePrintMax = model.pdoc->LineFromPosition(pfr->chrg.cpMax); + int linePrintMax = model.pdoc->LineFromPosition(static_cast(pfr->chrg.cpMax)); if (linePrintLast > linePrintMax) linePrintLast = linePrintMax; //Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n", @@ -1997,7 +2026,7 @@ long EditView::FormatRange(bool draw, Sci_RangeToFormat *pfr, Surface *surface, int lineDoc = linePrintStart; - int nPrintPos = pfr->chrg.cpMin; + int nPrintPos = static_cast(pfr->chrg.cpMin); int visibleLine = 0; int widthPrint = pfr->rc.right - pfr->rc.left - vsPrint.fixedColumnWidth; if (printParameters.wrapState == eWrapNone) diff --git a/src/stc/scintilla/src/EditView.h b/src/stc/scintilla/src/EditView.h index 70af6b2bf0..79a88657ae 100644 --- a/src/stc/scintilla/src/EditView.h +++ b/src/stc/scintilla/src/EditView.h @@ -51,6 +51,7 @@ class EditView { public: PrintParameters printParameters; PerLine *ldTabstops; + int tabWidthMinimumPixels; bool hideSelection; bool drawOverstrikeCaret; diff --git a/src/stc/scintilla/src/Editor.cxx b/src/stc/scintilla/src/Editor.cxx index 64017c58da..77d9ce5e74 100644 --- a/src/stc/scintilla/src/Editor.cxx +++ b/src/stc/scintilla/src/Editor.cxx @@ -8,10 +8,10 @@ #include #include #include -#include #include #include +#include #include #include #include @@ -630,6 +630,7 @@ void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition ancho sel.RangeMain() = rangeNew; SetRectangularRange(); ClaimSelection(); + SetHoverIndicatorPosition(sel.MainCaret()); if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { RedrawSelMargin(); @@ -657,6 +658,7 @@ void Editor::SetSelection(SelectionPosition currentPos_) { SelectionRange(SelectionPosition(currentPos_), sel.RangeMain().anchor); } ClaimSelection(); + SetHoverIndicatorPosition(sel.MainCaret()); if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { RedrawSelMargin(); @@ -678,6 +680,7 @@ void Editor::SetEmptySelection(SelectionPosition currentPos_) { sel.RangeMain() = rangeNew; SetRectangularRange(); ClaimSelection(); + SetHoverIndicatorPosition(sel.MainCaret()); if (marginView.highlightDelimiter.NeedsDrawing(currentLine)) { RedrawSelMargin(); @@ -1333,7 +1336,9 @@ void Editor::ShowCaretAtCurrentPosition() { void Editor::DropCaret() { caret.active = false; - FineTickerCancel(tickCaret); + if (FineTickerAvailable()) { + FineTickerCancel(tickCaret); + } InvalidateCaret(); } @@ -1867,28 +1872,9 @@ void Editor::AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS) { // Also treats \0 and naked trail bytes 0x80 to 0xBF as valid // characters representing themselves. } else { - // Unroll 1 to 3 byte UTF-8 sequences. See reference data at: - // http://www.cl.cam.ac.uk/~mgk25/unicode.html - // http://www.cl.cam.ac.uk/~mgk25/ucs/examples/UTF-8-test.txt - if (byte < 0xE0) { - int byte2 = static_cast(s[1]); - if ((byte2 & 0xC0) == 0x80) { - // Two-byte-character lead-byte followed by a trail-byte. - byte = (((byte & 0x1F) << 6) | (byte2 & 0x3F)); - } - // A two-byte-character lead-byte not followed by trail-byte - // represents itself. - } else if (byte < 0xF0) { - int byte2 = static_cast(s[1]); - int byte3 = static_cast(s[2]); - if (((byte2 & 0xC0) == 0x80) && ((byte3 & 0xC0) == 0x80)) { - // Three-byte-character lead byte followed by two trail bytes. - byte = (((byte & 0x0F) << 12) | ((byte2 & 0x3F) << 6) | - (byte3 & 0x3F)); - } - // A three-byte-character lead-byte not followed by two trail-bytes - // represents itself. - } + unsigned int utf32[1] = { 0 }; + UTF32FromUTF8(s, len, utf32, ELEMENTS(utf32)); + byte = utf32[0]; } NotifyChar(byte); } @@ -1898,6 +1884,13 @@ void Editor::AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS) { } } +void Editor::FillVirtualSpace() { + const bool tmpOverstrike = inOverstrike; + inOverstrike = false; // not allow to be deleted twice. + AddCharUTF("", 0); + inOverstrike = tmpOverstrike; +} + void Editor::InsertPaste(const char *text, int len) { if (multiPasteMode == SC_MULTIPASTE_ONCE) { SelectionPosition selStart = sel.Start(); @@ -1979,6 +1972,7 @@ void Editor::ClearSelection(bool retainMultipleSelections) { ThinRectangularRange(); sel.RemoveDuplicates(); ClaimSelection(); + SetHoverIndicatorPosition(sel.MainCaret()); } void Editor::ClearAll() { @@ -2062,6 +2056,7 @@ void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, int len) { sel.RangeMain().caret.SetPosition(PositionFromLineX(line, xInsert)); if ((XFromPosition(sel.MainCaret()) < xInsert) && (i + 1 < len)) { while (XFromPosition(sel.MainCaret()) < xInsert) { + assert(pdoc); const int lengthInserted = pdoc->InsertString(sel.MainCaret(), " ", 1); sel.RangeMain().caret.Add(lengthInserted); } @@ -3283,7 +3278,6 @@ int Editor::KeyCommand(unsigned int iMessage) { break; case SCI_EDITTOGGLEOVERTYPE: inOverstrike = !inOverstrike; - DropCaret(); ShowCaretAtCurrentPosition(); ContainerNeedsUpdate(SC_UPDATE_CONTENT); NotifyUpdateUI(); @@ -3645,7 +3639,10 @@ long Editor::FindText( if (!pdoc->HasCaseFolder()) pdoc->SetCaseFolder(CaseFolderForEncoding()); try { - int pos = pdoc->FindText(ft->chrg.cpMin, ft->chrg.cpMax, ft->lpstrText, + long pos = pdoc->FindText( + static_cast(ft->chrg.cpMin), + static_cast(ft->chrg.cpMax), + ft->lpstrText, (wParam & SCFIND_MATCHCASE) != 0, (wParam & SCFIND_WHOLEWORD) != 0, (wParam & SCFIND_WORDSTART) != 0, @@ -3656,7 +3653,7 @@ long Editor::FindText( ft->chrgText.cpMin = pos; ft->chrgText.cpMax = pos + lengthFound; } - return pos; + return static_cast(pos); } catch (RegexError &) { errorStatus = SC_STATUS_WARN_REGEX; return -1; @@ -3690,7 +3687,7 @@ long Editor::SearchText( sptr_t lParam) { ///< The text to search for. const char *txt = reinterpret_cast(lParam); - int pos; + long pos; int lengthFound = istrlen(txt); if (!pdoc->HasCaseFolder()) pdoc->SetCaseFolder(CaseFolderForEncoding()); @@ -3717,7 +3714,7 @@ long Editor::SearchText( return -1; } if (pos != -1) { - SetSelection(pos, pos + lengthFound); + SetSelection(static_cast(pos), static_cast(pos + lengthFound)); } return pos; @@ -3750,7 +3747,7 @@ long Editor::SearchInTarget(const char *text, int length) { if (!pdoc->HasCaseFolder()) pdoc->SetCaseFolder(CaseFolderForEncoding()); try { - int pos = pdoc->FindText(targetStart, targetEnd, text, + long pos = pdoc->FindText(targetStart, targetEnd, text, (searchFlags & SCFIND_MATCHCASE) != 0, (searchFlags & SCFIND_WHOLEWORD) != 0, (searchFlags & SCFIND_WORDSTART) != 0, @@ -3758,8 +3755,8 @@ long Editor::SearchInTarget(const char *text, int length) { searchFlags, &lengthFound); if (pos != -1) { - targetStart = pos; - targetEnd = pos + lengthFound; + targetStart = static_cast(pos); + targetEnd = static_cast(pos + lengthFound); } return pos; } catch (RegexError &) { @@ -3779,9 +3776,9 @@ void Editor::GoToLine(int lineNo) { } static bool Close(Point pt1, Point pt2, Point threshold) { - if (abs(pt1.x - pt2.x) > threshold.x) + if (std::abs(pt1.x - pt2.x) > threshold.x) return false; - if (abs(pt1.y - pt2.y) > threshold.y) + if (std::abs(pt1.y - pt2.y) > threshold.y) return false; return true; } @@ -4000,7 +3997,7 @@ bool Editor::PointInSelMargin(Point pt) const { PRectangle rcSelMargin = GetClientRectangle(); rcSelMargin.right = static_cast(vs.textStart - vs.leftMarginWidth); rcSelMargin.left = static_cast(vs.textStart - vs.fixedColumnWidth); - return rcSelMargin.Contains(pt); + return rcSelMargin.ContainsWholePixel(pt); } else { return false; } @@ -4109,6 +4106,7 @@ static bool AllowVirtualSpace(int virtualSpaceOptions, bool rectangular) { } void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, int modifiers) { + SetHoverIndicatorPoint(pt); //Platform::DebugPrintf("ButtonDown %d %d = %d alt=%d %d\n", curTime, lastClickTime, curTime - lastClickTime, alt, inDragDrop); ptMouseLast = pt; const bool ctrl = (modifiers & SCI_CTRL) != 0; @@ -4307,6 +4305,36 @@ bool Editor::PointIsHotspot(Point pt) { return PositionIsHotspot(pos); } +void Editor::SetHoverIndicatorPosition(int position) { + int hoverIndicatorPosPrev = hoverIndicatorPos; + hoverIndicatorPos = INVALID_POSITION; + if (vs.indicatorsDynamic == 0) + return; + if (position != INVALID_POSITION) { + for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) { + if (vs.indicators[deco->indicator].IsDynamic()) { + if (pdoc->decorations.ValueAt(deco->indicator, position)) { + hoverIndicatorPos = position; + } + } + } + } + if (hoverIndicatorPosPrev != hoverIndicatorPos) { + if (hoverIndicatorPosPrev != INVALID_POSITION) + InvalidateRange(hoverIndicatorPosPrev, hoverIndicatorPosPrev + 1); + if (hoverIndicatorPos != INVALID_POSITION) + InvalidateRange(hoverIndicatorPos, hoverIndicatorPos + 1); + } +} + +void Editor::SetHoverIndicatorPoint(Point pt) { + if (vs.indicatorsDynamic == 0) { + SetHoverIndicatorPosition(INVALID_POSITION); + } else { + SetHoverIndicatorPosition(PositionFromLocation(pt, true, true)); + } +} + void Editor::SetHotSpotRange(Point *pt) { if (pt) { int pos = PositionFromLocation(*pt, false, true); @@ -4449,12 +4477,18 @@ void Editor::ButtonMoveWithModifiers(Point pt, int modifiers) { // Display regular (drag) cursor over selection if (PointInSelection(pt) && !SelectionEmpty()) { DisplayCursor(Window::cursorArrow); - } else if (PointIsHotspot(pt)) { - DisplayCursor(Window::cursorHand); - SetHotSpotRange(&pt); } else { - DisplayCursor(Window::cursorText); - SetHotSpotRange(NULL); + SetHoverIndicatorPoint(pt); + if (PointIsHotspot(pt)) { + DisplayCursor(Window::cursorHand); + SetHotSpotRange(&pt); + } else { + if (hoverIndicatorPos != invalidPosition) + DisplayCursor(Window::cursorHand); + else + DisplayCursor(Window::cursorText); + SetHotSpotRange(NULL); + } } } } @@ -4467,6 +4501,8 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) { //Platform::DebugPrintf("ButtonUp %d %d\n", HaveMouseCapture(), inDragDrop); SelectionPosition newPos = SPositionFromLocation(pt, false, false, AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular())); + if (hoverIndicatorPos != INVALID_POSITION) + InvalidateRange(newPos.Position(), newPos.Position() + 1); newPos = MovePositionOutsideChar(newPos, sel.MainCaret() - newPos.Position()); if (inDragDrop == ddInitial) { inDragDrop = ddNone; @@ -4671,12 +4707,10 @@ void Editor::FineTickerCancel(TickReason) { void Editor::SetFocusState(bool focusState) { hasFocus = focusState; NotifyFocus(hasFocus); - if (hasFocus) { - ShowCaretAtCurrentPosition(); - } else { + if (!hasFocus) { CancelModes(); - DropCaret(); } + ShowCaretAtCurrentPosition(); } int Editor::PositionAfterArea(PRectangle rcArea) const { @@ -4784,6 +4818,7 @@ void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) { void Editor::SetAnnotationHeights(int start, int end) { if (vs.annotationVisible) { + RefreshStyleData(); bool changedHeight = false; for (int line=start; lineLinesTotal(); line++) { int linesWrapped = 1; @@ -4834,6 +4869,9 @@ void Editor::SetDocPointer(Document *document) { view.llc.Deallocate(); NeedWrapping(); + hotspot = Range(invalidPosition); + hoverIndicatorPos = invalidPosition; + view.ClearAllTabstops(); pdoc->AddWatcher(this, 0); @@ -5287,7 +5325,7 @@ sptr_t Editor::StringResult(sptr_t lParam, const char *val) { sptr_t Editor::BytesResult(sptr_t lParam, const unsigned char *val, size_t len) { // No NUL termination: len is number of valid/displayed bytes - if (lParam) { + if ((lParam) && (len > 0)) { char *ptr = CharPtrFromSPtr(lParam); if (val) memcpy(ptr, val, len); @@ -5505,6 +5543,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_GETTARGETEND: return targetEnd; + case SCI_SETTARGETRANGE: + targetStart = static_cast(wParam); + targetEnd = static_cast(lParam); + break; + case SCI_TARGETFROMSELECTION: if (sel.MainCaret() < sel.MainAnchor()) { targetStart = sel.MainCaret(); @@ -5515,6 +5558,11 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { } break; + case SCI_GETTARGETTEXT: { + std::string text = RangeText(targetStart, targetEnd); + return BytesResult(lParam, reinterpret_cast(text.c_str()), text.length()); + } + case SCI_REPLACETARGET: PLATFORM_ASSERT(lParam); return ReplaceTarget(false, CharPtrFromSPtr(lParam), static_cast(wParam)); @@ -5603,12 +5651,12 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { if (lParam == 0) return 0; Sci_TextRange *tr = reinterpret_cast(lParam); - int cpMax = tr->chrg.cpMax; + int cpMax = static_cast(tr->chrg.cpMax); if (cpMax == -1) cpMax = pdoc->Length(); PLATFORM_ASSERT(cpMax <= pdoc->Length()); - int len = cpMax - tr->chrg.cpMin; // No -1 as cpMin and cpMax are referring to inter character positions - pdoc->GetCharRange(tr->lpstrText, tr->chrg.cpMin, len); + int len = static_cast(cpMax - tr->chrg.cpMin); // No -1 as cpMin and cpMax are referring to inter character positions + pdoc->GetCharRange(tr->lpstrText, static_cast(tr->chrg.cpMin), len); // Spec says copied text is terminated with a NUL tr->lpstrText[len] = '\0'; return len; // Not including NUL @@ -5846,9 +5894,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return 0; Sci_TextRange *tr = reinterpret_cast(lParam); int iPlace = 0; - for (int iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) { - tr->lpstrText[iPlace++] = pdoc->CharAt(iChar); - tr->lpstrText[iPlace++] = pdoc->StyleAt(iChar); + for (long iChar = tr->chrg.cpMin; iChar < tr->chrg.cpMax; iChar++) { + tr->lpstrText[iPlace++] = pdoc->CharAt(static_cast(iChar)); + tr->lpstrText[iPlace++] = pdoc->StyleAt(static_cast(iChar)); } tr->lpstrText[iPlace] = '\0'; tr->lpstrText[iPlace + 1] = '\0'; @@ -6179,6 +6227,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return TextWidth(static_cast(wParam), CharPtrFromSPtr(lParam)); case SCI_TEXTHEIGHT: + RefreshStyleData(); return vs.lineHeight; case SCI_SETENDATLASTLINE: @@ -6759,23 +6808,55 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_INDICSETSTYLE: if (wParam <= INDIC_MAX) { - vs.indicators[wParam].style = static_cast(lParam); + vs.indicators[wParam].sacNormal.style = static_cast(lParam); + vs.indicators[wParam].sacHover.style = static_cast(lParam); InvalidateStyleRedraw(); } break; case SCI_INDICGETSTYLE: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].style : 0; + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacNormal.style : 0; case SCI_INDICSETFORE: if (wParam <= INDIC_MAX) { - vs.indicators[wParam].fore = ColourDesired(static_cast(lParam)); + vs.indicators[wParam].sacNormal.fore = ColourDesired(static_cast(lParam)); + vs.indicators[wParam].sacHover.fore = ColourDesired(static_cast(lParam)); InvalidateStyleRedraw(); } break; case SCI_INDICGETFORE: - return (wParam <= INDIC_MAX) ? vs.indicators[wParam].fore.AsLong() : 0; + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacNormal.fore.AsLong() : 0; + + case SCI_INDICSETHOVERSTYLE: + if (wParam <= INDIC_MAX) { + vs.indicators[wParam].sacHover.style = static_cast(lParam); + InvalidateStyleRedraw(); + } + break; + + case SCI_INDICGETHOVERSTYLE: + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacHover.style : 0; + + case SCI_INDICSETHOVERFORE: + if (wParam <= INDIC_MAX) { + vs.indicators[wParam].sacHover.fore = ColourDesired(static_cast(lParam)); + InvalidateStyleRedraw(); + } + break; + + case SCI_INDICGETHOVERFORE: + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].sacHover.fore.AsLong() : 0; + + case SCI_INDICSETFLAGS: + if (wParam <= INDIC_MAX) { + vs.indicators[wParam].SetFlags(static_cast(lParam)); + InvalidateStyleRedraw(); + } + break; + + case SCI_INDICGETFLAGS: + return (wParam <= INDIC_MAX) ? vs.indicators[wParam].Flags() : 0; case SCI_INDICSETUNDER: if (wParam <= INDIC_MAX) { diff --git a/src/stc/scintilla/src/Editor.h b/src/stc/scintilla/src/Editor.h index 27a2469aa6..1fc907ac72 100644 --- a/src/stc/scintilla/src/Editor.h +++ b/src/stc/scintilla/src/Editor.h @@ -388,6 +388,7 @@ protected: // ScintillaBase subclass needs access to much of Editor int InsertSpace(int position, unsigned int spaces); void AddChar(char ch); virtual void AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS=false); + void FillVirtualSpace(); void InsertPaste(const char *text, int len); enum PasteShape { pasteStream=0, pasteRectangular = 1, pasteLine = 2 }; void InsertPasteShape(const char *text, int len, PasteShape shape); @@ -544,6 +545,8 @@ protected: // ScintillaBase subclass needs access to much of Editor bool PointIsHotspot(Point pt); void SetHotSpotRange(Point *pt); Range GetHotSpotRange() const; + void SetHoverIndicatorPosition(int position); + void SetHoverIndicatorPoint(Point pt); int CodePage() const; virtual bool ValidCodePage(int /* codePage */) const { return true; } diff --git a/src/stc/scintilla/src/Indicator.cxx b/src/stc/scintilla/src/Indicator.cxx index d8ad64ed6b..62df0b7161 100644 --- a/src/stc/scintilla/src/Indicator.cxx +++ b/src/stc/scintilla/src/Indicator.cxx @@ -23,10 +23,17 @@ static PRectangle PixelGridAlign(const PRectangle &rc) { return PRectangle::FromInts(int(rc.left + 0.5), int(rc.top), int(rc.right + 0.5), int(rc.bottom)); } -void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) const { - surface->PenColour(fore); +void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine, DrawState drawState, int value) const { + StyleAndColour sacDraw = sacNormal; + if (Flags() & SC_INDICFLAG_VALUEFORE) { + sacDraw.fore = value & SC_INDICVALUEMASK; + } + if (drawState == drawHover) { + sacDraw = sacHover; + } + surface->PenColour(sacDraw.fore); int ymid = static_cast(rc.bottom + rc.top) / 2; - if (style == INDIC_SQUIGGLE) { + if (sacDraw.style == INDIC_SQUIGGLE) { int x = int(rc.left+0.5); int xLast = int(rc.right+0.5); int y = 0; @@ -42,7 +49,7 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r } surface->LineTo(x, static_cast(rc.top) + y); } - } else if (style == INDIC_SQUIGGLEPIXMAP) { + } else if (sacDraw.style == INDIC_SQUIGGLEPIXMAP) { PRectangle rcSquiggle = PixelGridAlign(rc); int width = Platform::Minimum(4000, static_cast(rcSquiggle.Width())); @@ -51,17 +58,17 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r for (int x = 0; x < width; x++) { if (x%2) { // Two halfway columns have a full pixel in middle flanked by light pixels - image.SetPixel(x, 0, fore, alphaSide); - image.SetPixel(x, 1, fore, alphaFull); - image.SetPixel(x, 2, fore, alphaSide); + image.SetPixel(x, 0, sacDraw.fore, alphaSide); + image.SetPixel(x, 1, sacDraw.fore, alphaFull); + image.SetPixel(x, 2, sacDraw.fore, alphaSide); } else { // Extreme columns have a full pixel at bottom or top and a mid-tone pixel in centre - image.SetPixel(x, (x%4) ? 0 : 2, fore, alphaFull); - image.SetPixel(x, 1, fore, alphaSide2); + image.SetPixel(x, (x % 4) ? 0 : 2, sacDraw.fore, alphaFull); + image.SetPixel(x, 1, sacDraw.fore, alphaSide2); } } surface->DrawRGBAImage(rcSquiggle, image.GetWidth(), image.GetHeight(), image.Pixels()); - } else if (style == INDIC_SQUIGGLELOW) { + } else if (sacDraw.style == INDIC_SQUIGGLELOW) { surface->MoveTo(static_cast(rc.left), static_cast(rc.top)); int x = static_cast(rc.left) + 3; int y = 0; @@ -72,7 +79,7 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r x += 3; } surface->LineTo(static_cast(rc.right), static_cast(rc.top) + y); // Finish the line - } else if (style == INDIC_TT) { + } else if (sacDraw.style == INDIC_TT) { surface->MoveTo(static_cast(rc.left), ymid); int x = static_cast(rc.left) + 5; while (x < rc.right) { @@ -88,7 +95,7 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r surface->MoveTo(x-3, ymid); surface->LineTo(x-3, ymid+2); } - } else if (style == INDIC_DIAGONAL) { + } else if (sacDraw.style == INDIC_DIAGONAL) { int x = static_cast(rc.left); while (x < rc.right) { surface->MoveTo(x, static_cast(rc.top) + 2); @@ -101,24 +108,28 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r surface->LineTo(endX, endY); x += 4; } - } else if (style == INDIC_STRIKE) { + } else if (sacDraw.style == INDIC_STRIKE) { surface->MoveTo(static_cast(rc.left), static_cast(rc.top) - 4); surface->LineTo(static_cast(rc.right), static_cast(rc.top) - 4); - } else if (style == INDIC_HIDDEN) { + } else if ((sacDraw.style == INDIC_HIDDEN) || (sacDraw.style == INDIC_TEXTFORE)) { // Draw nothing - } else if (style == INDIC_BOX) { + } else if (sacDraw.style == INDIC_BOX) { surface->MoveTo(static_cast(rc.left), ymid + 1); surface->LineTo(static_cast(rc.right), ymid + 1); surface->LineTo(static_cast(rc.right), static_cast(rcLine.top) + 1); surface->LineTo(static_cast(rc.left), static_cast(rcLine.top) + 1); surface->LineTo(static_cast(rc.left), ymid + 1); - } else if (style == INDIC_ROUNDBOX || style == INDIC_STRAIGHTBOX) { + } else if (sacDraw.style == INDIC_ROUNDBOX || + sacDraw.style == INDIC_STRAIGHTBOX || + sacDraw.style == INDIC_FULLBOX) { PRectangle rcBox = rcLine; - rcBox.top = rcLine.top + 1; + if (sacDraw.style != INDIC_FULLBOX) + rcBox.top = rcLine.top + 1; rcBox.left = rc.left; rcBox.right = rc.right; - surface->AlphaRectangle(rcBox, (style == INDIC_ROUNDBOX) ? 1 : 0, fore, fillAlpha, fore, outlineAlpha, 0); - } else if (style == INDIC_DOTBOX) { + surface->AlphaRectangle(rcBox, (sacDraw.style == INDIC_ROUNDBOX) ? 1 : 0, + sacDraw.fore, fillAlpha, sacDraw.fore, outlineAlpha, 0); + } else if (sacDraw.style == INDIC_DOTBOX) { PRectangle rcBox = PixelGridAlign(rc); rcBox.top = rcLine.top + 1; rcBox.bottom = rcLine.bottom; @@ -128,36 +139,42 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r // Draw horizontal lines top and bottom for (int x=0; x(rcBox.Height()); y += static_cast(rcBox.Height()) - 1) { - image.SetPixel(x, y, fore, ((x + y) % 2) ? outlineAlpha : fillAlpha); + image.SetPixel(x, y, sacDraw.fore, ((x + y) % 2) ? outlineAlpha : fillAlpha); } } // Draw vertical lines left and right for (int y = 1; y(rcBox.Height()); y++) { for (int x=0; xDrawRGBAImage(rcBox, image.GetWidth(), image.GetHeight(), image.Pixels()); - } else if (style == INDIC_DASH) { + } else if (sacDraw.style == INDIC_DASH) { int x = static_cast(rc.left); while (x < rc.right) { surface->MoveTo(x, ymid); surface->LineTo(Platform::Minimum(x + 4, static_cast(rc.right)), ymid); x += 7; } - } else if (style == INDIC_DOTS) { + } else if (sacDraw.style == INDIC_DOTS) { int x = static_cast(rc.left); while (x < static_cast(rc.right)) { PRectangle rcDot = PRectangle::FromInts(x, ymid, x + 1, ymid + 1); - surface->FillRectangle(rcDot, fore); + surface->FillRectangle(rcDot, sacDraw.fore); x += 2; } - } else if (style == INDIC_COMPOSITIONTHICK) { + } else if (sacDraw.style == INDIC_COMPOSITIONTHICK) { PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom); - surface->FillRectangle(rcComposition, fore); + surface->FillRectangle(rcComposition, sacDraw.fore); + } else if (sacDraw.style == INDIC_COMPOSITIONTHIN) { + PRectangle rcComposition(rc.left+1, rcLine.bottom-2, rc.right-1, rcLine.bottom-1); + surface->FillRectangle(rcComposition, sacDraw.fore); } else { // Either INDIC_PLAIN or unknown surface->MoveTo(static_cast(rc.left), ymid); surface->LineTo(static_cast(rc.right), ymid); } } +void Indicator::SetFlags(int attributes_) { + attributes = attributes_; +} diff --git a/src/stc/scintilla/src/Indicator.h b/src/stc/scintilla/src/Indicator.h index 96cba3c054..c22ec71c64 100644 --- a/src/stc/scintilla/src/Indicator.h +++ b/src/stc/scintilla/src/Indicator.h @@ -12,21 +12,45 @@ namespace Scintilla { #endif +struct StyleAndColour { + int style; + ColourDesired fore; + StyleAndColour() : style(INDIC_PLAIN), fore(0, 0, 0) { + } + StyleAndColour(int style_, ColourDesired fore_ = ColourDesired(0, 0, 0)) : style(style_), fore(fore_) { + } + bool operator==(const StyleAndColour &other) const { + return (style == other.style) && (fore == other.fore); + } +}; + /** */ class Indicator { public: - int style; - ColourDesired fore; + enum DrawState { drawNormal, drawHover }; + StyleAndColour sacNormal; + StyleAndColour sacHover; bool under; int fillAlpha; int outlineAlpha; - Indicator() : style(INDIC_PLAIN), fore(ColourDesired(0,0,0)), under(false), fillAlpha(30), outlineAlpha(50) { + int attributes; + Indicator() : under(false), fillAlpha(30), outlineAlpha(50), attributes(0) { } Indicator(int style_, ColourDesired fore_=ColourDesired(0,0,0), bool under_=false, int fillAlpha_=30, int outlineAlpha_=50) : - style(style_), fore(fore_), under(under_), fillAlpha(fillAlpha_), outlineAlpha(outlineAlpha_) { + sacNormal(style_, fore_), sacHover(style_, fore_), under(under_), fillAlpha(fillAlpha_), outlineAlpha(outlineAlpha_), attributes(0) { } - void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine) const; + void Draw(Surface *surface, const PRectangle &rc, const PRectangle &rcLine, DrawState drawState, int value) const; + bool IsDynamic() const { + return !(sacNormal == sacHover); + } + bool OverridesTextFore() const { + return sacNormal.style == INDIC_TEXTFORE || sacHover.style == INDIC_TEXTFORE; + } + int Flags() const { + return attributes; + } + void SetFlags(int attributes_); }; #ifdef SCI_NAMESPACE diff --git a/src/stc/scintilla/src/MarginView.cxx b/src/stc/scintilla/src/MarginView.cxx index b7ef485138..a6fc1f40b3 100644 --- a/src/stc/scintilla/src/MarginView.cxx +++ b/src/stc/scintilla/src/MarginView.cxx @@ -263,8 +263,10 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect PLATFORM_ASSERT(visibleLine < model.cs.LinesDisplayed()); const int lineDoc = model.cs.DocFromDisplay(visibleLine); PLATFORM_ASSERT(model.cs.GetVisible(lineDoc)); - const bool firstSubLine = visibleLine == model.cs.DisplayFromDoc(lineDoc); - const bool lastSubLine = visibleLine == model.cs.DisplayLastFromDoc(lineDoc); + const int firstVisibleLine = model.cs.DisplayFromDoc(lineDoc); + const int lastVisibleLine = model.cs.DisplayLastFromDoc(lineDoc); + const bool firstSubLine = visibleLine == firstVisibleLine; + const bool lastSubLine = visibleLine == lastVisibleLine; int marks = model.pdoc->GetMark(lineDoc); if (!firstSubLine) @@ -403,9 +405,9 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect } } } else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) { - if (firstSubLine) { - const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc); - if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) { + const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc); + if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) { + if (firstSubLine) { surface->FillRectangle(rcMarker, vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back); if (vs.ms[margin].style == SC_MARGIN_RTEXT) { @@ -414,6 +416,12 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect } DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker, stMargin, 0, stMargin.length, drawAll); + } else { + // if we're displaying annotation lines, color the margin to match the associated document line + const int annotationLines = model.pdoc->AnnotationLines(lineDoc); + if (annotationLines && (visibleLine > lastVisibleLine - annotationLines)) { + surface->FillRectangle(rcMarker, vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back); + } } } } diff --git a/src/stc/scintilla/src/PositionCache.cxx b/src/stc/scintilla/src/PositionCache.cxx index 6663995036..860a780d9a 100644 --- a/src/stc/scintilla/src/PositionCache.cxx +++ b/src/stc/scintilla/src/PositionCache.cxx @@ -440,7 +440,7 @@ void BreakFinder::Insert(int val) { } BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lineRange_, int posLineStart_, - int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_) : + int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw) : ll(ll_), lineRange(lineRange_), posLineStart(posLineStart_), @@ -475,7 +475,17 @@ BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lin } } } - + if (pvsDraw && pvsDraw->indicatorsSetFore > 0) { + for (Decoration *deco = pdoc->decorations.root; deco; deco = deco->next) { + if (pvsDraw->indicators[deco->indicator].OverridesTextFore()) { + int startPos = deco->rs.EndRun(posLineStart); + while (startPos < (posLineStart + lineRange.end)) { + Insert(startPos - posLineStart); + startPos = deco->rs.EndRun(startPos); + } + } + } + } Insert(ll->edgeColumn); Insert(lineRange.end); saeNext = (!selAndEdge.empty()) ? selAndEdge[0] : -1; diff --git a/src/stc/scintilla/src/PositionCache.h b/src/stc/scintilla/src/PositionCache.h index 9d9821f8fa..edc0a5ddb3 100644 --- a/src/stc/scintilla/src/PositionCache.h +++ b/src/stc/scintilla/src/PositionCache.h @@ -168,7 +168,7 @@ public: // Try to make each subdivided run lengthEachSubdivision or shorter. enum { lengthEachSubdivision = 100 }; BreakFinder(const LineLayout *ll_, const Selection *psel, Range rangeLine_, int posLineStart_, - int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_); + int xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw); ~BreakFinder(); TextSegment Next(); bool More() const; diff --git a/src/stc/scintilla/src/RESearch.cxx b/src/stc/scintilla/src/RESearch.cxx index dbf1423e78..2824a5b707 100644 --- a/src/stc/scintilla/src/RESearch.cxx +++ b/src/stc/scintilla/src/RESearch.cxx @@ -342,8 +342,8 @@ static int GetHexaChar(unsigned char hd1, unsigned char hd2) { /** * Called when the parser finds a backslash not followed * by a valid expression (like \( in non-Posix mode). - * @param pattern: pointer on the char after the backslash. - * @param incr: (out) number of chars to skip after expression evaluation. + * @param pattern : pointer on the char after the backslash. + * @param incr : (out) number of chars to skip after expression evaluation. * @return the char if it resolves to a simple char, * or -1 for a char class. In this case, bittab is changed. */ diff --git a/src/stc/scintilla/src/ScintillaBase.cxx b/src/stc/scintilla/src/ScintillaBase.cxx index f9d70ce537..b52fb9a043 100644 --- a/src/stc/scintilla/src/ScintillaBase.cxx +++ b/src/stc/scintilla/src/ScintillaBase.cxx @@ -449,12 +449,12 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) { PRectangle rcClient = GetClientRectangle(); int offset = vs.lineHeight + static_cast(rc.Height()); // adjust so it displays above the text. - if (rc.bottom > rcClient.bottom) { + if (rc.bottom > rcClient.bottom && rc.Height() < rcClient.Height()) { rc.top -= offset; rc.bottom -= offset; } // adjust so it displays below the text. - if (rc.top < rcClient.top) { + if (rc.top < rcClient.top && rc.Height() < rcClient.Height()) { rc.top += offset; rc.bottom += offset; } @@ -587,7 +587,7 @@ void LexState::SetLexerModule(const LexerModule *lex) { } void LexState::SetLexer(uptr_t wParam) { - lexLanguage = wParam; + lexLanguage = static_cast(wParam); if (lexLanguage == SCLEX_CONTAINER) { SetLexerModule(0); } else { @@ -999,7 +999,7 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return DocumentLexState()->PropGetInt(reinterpret_cast(wParam), static_cast(lParam)); case SCI_SETKEYWORDS: - DocumentLexState()->SetWordList(wParam, reinterpret_cast(lParam)); + DocumentLexState()->SetWordList(static_cast(wParam), reinterpret_cast(lParam)); break; case SCI_SETLEXERLANGUAGE: @@ -1011,7 +1011,7 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara case SCI_PRIVATELEXERCALL: return reinterpret_cast( - DocumentLexState()->PrivateCall(wParam, reinterpret_cast(lParam))); + DocumentLexState()->PrivateCall(static_cast(wParam), reinterpret_cast(lParam))); case SCI_GETSTYLEBITSNEEDED: return 8; @@ -1023,7 +1023,8 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return DocumentLexState()->PropertyType(reinterpret_cast(wParam)); case SCI_DESCRIBEPROPERTY: - return StringResult(lParam, DocumentLexState()->DescribeProperty(reinterpret_cast(wParam))); + return StringResult(lParam, + DocumentLexState()->DescribeProperty(reinterpret_cast(wParam))); case SCI_DESCRIBEKEYWORDSETS: return StringResult(lParam, DocumentLexState()->DescribeWordListSets()); @@ -1032,26 +1033,27 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara return DocumentLexState()->LineEndTypesSupported(); case SCI_ALLOCATESUBSTYLES: - return DocumentLexState()->AllocateSubStyles(wParam, lParam); + return DocumentLexState()->AllocateSubStyles(static_cast(wParam), static_cast(lParam)); case SCI_GETSUBSTYLESSTART: - return DocumentLexState()->SubStylesStart(wParam); + return DocumentLexState()->SubStylesStart(static_cast(wParam)); case SCI_GETSUBSTYLESLENGTH: - return DocumentLexState()->SubStylesLength(wParam); + return DocumentLexState()->SubStylesLength(static_cast(wParam)); case SCI_GETSTYLEFROMSUBSTYLE: - return DocumentLexState()->StyleFromSubStyle(wParam); + return DocumentLexState()->StyleFromSubStyle(static_cast(wParam)); case SCI_GETPRIMARYSTYLEFROMSTYLE: - return DocumentLexState()->PrimaryStyleFromStyle(wParam); + return DocumentLexState()->PrimaryStyleFromStyle(static_cast(wParam)); case SCI_FREESUBSTYLES: DocumentLexState()->FreeSubStyles(); break; case SCI_SETIDENTIFIERS: - DocumentLexState()->SetIdentifiers(wParam, reinterpret_cast(lParam)); + DocumentLexState()->SetIdentifiers(static_cast(wParam), + reinterpret_cast(lParam)); break; case SCI_DISTANCETOSECONDARYSTYLES: diff --git a/src/stc/scintilla/src/UniConversion.cxx b/src/stc/scintilla/src/UniConversion.cxx index d19828a526..04053b0570 100644 --- a/src/stc/scintilla/src/UniConversion.cxx +++ b/src/stc/scintilla/src/UniConversion.cxx @@ -17,7 +17,6 @@ using namespace Scintilla; namespace Scintilla { #endif -enum { SURROGATE_LEAD_FIRST = 0xD800 }; enum { SURROGATE_TRAIL_FIRST = 0xDC00 }; enum { SURROGATE_TRAIL_LAST = 0xDFFF }; enum { SUPPLEMENTAL_PLANE_FIRST = 0x10000 }; @@ -43,7 +42,7 @@ unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen) { } void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len) { - int k = 0; + unsigned int k = 0; for (unsigned int i = 0; i < tlen && uptr[i];) { unsigned int uch = uptr[i]; if (uch < 0x80) { @@ -67,7 +66,8 @@ void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned } i++; } - putf[len] = '\0'; + if (k < len) + putf[k] = '\0'; } unsigned int UTF8CharLength(unsigned char ch) { @@ -82,10 +82,10 @@ unsigned int UTF8CharLength(unsigned char ch) { } } -unsigned int UTF16Length(const char *s, unsigned int len) { - unsigned int ulen = 0; - unsigned int charLen; - for (unsigned int i=0; i(s[i]); if (ch < 0x80) { charLen = 1; @@ -103,10 +103,10 @@ unsigned int UTF16Length(const char *s, unsigned int len) { return ulen; } -unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen) { - unsigned int ui=0; +size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen) { + size_t ui = 0; const unsigned char *us = reinterpret_cast(s); - unsigned int i=0; + size_t i = 0; while ((i= 1) && (ch < 0x80 + 0x40 + 0x20)) { diff --git a/src/stc/scintilla/src/UniConversion.h b/src/stc/scintilla/src/UniConversion.h index 760f504760..08898cac38 100644 --- a/src/stc/scintilla/src/UniConversion.h +++ b/src/stc/scintilla/src/UniConversion.h @@ -19,8 +19,8 @@ const int unicodeReplacementChar = 0xFFFD; 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); +size_t UTF16Length(const char *s, size_t len); +size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen); unsigned int UTF32FromUTF8(const char *s, unsigned int len, unsigned int *tbuf, unsigned int tlen); unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf); @@ -55,6 +55,12 @@ inline bool UTF8IsNEL(const unsigned char *us) { return (us[0] == 0xc2) && (us[1] == 0x85); } +enum { SURROGATE_LEAD_FIRST = 0xD800 }; +enum { SURROGATE_LEAD_LAST = 0xDBFF }; +inline unsigned int UTF16CharLength(wchar_t uch) { + return ((uch >= SURROGATE_LEAD_FIRST) && (uch <= SURROGATE_LEAD_LAST)) ? 2 : 1; +} + #ifdef SCI_NAMESPACE } #endif diff --git a/src/stc/scintilla/src/ViewStyle.cxx b/src/stc/scintilla/src/ViewStyle.cxx index b60905caff..e56c8f3756 100644 --- a/src/stc/scintilla/src/ViewStyle.cxx +++ b/src/stc/scintilla/src/ViewStyle.cxx @@ -101,8 +101,14 @@ ViewStyle::ViewStyle(const ViewStyle &source) { markers[mrk] = source.markers[mrk]; } CalcLargestMarkerHeight(); + indicatorsDynamic = 0; + indicatorsSetFore = 0; for (int ind=0; ind<=INDIC_MAX; ind++) { indicators[ind] = source.indicators[ind]; + if (indicators[ind].IsDynamic()) + indicatorsDynamic++; + if (indicators[ind].OverridesTextFore()) + indicatorsSetFore++; } selColours = source.selColours; @@ -197,6 +203,8 @@ void ViewStyle::Init(size_t stylesSize_) { indicators[2] = Indicator(INDIC_PLAIN, ColourDesired(0xff, 0, 0)); technology = SC_TECHNOLOGY_DEFAULT; + indicatorsDynamic = 0; + indicatorsSetFore = 0; lineHeight = 1; lineOverlap = 0; maxAscent = 1; @@ -318,6 +326,14 @@ void ViewStyle::Refresh(Surface &surface, int tabInChars) { FontRealised *fr = Find(styles[k]); styles[k].Copy(fr->font, *fr); } + indicatorsDynamic = 0; + indicatorsSetFore = 0; + for (int ind = 0; ind <= INDIC_MAX; ind++) { + if (indicators[ind].IsDynamic()) + indicatorsDynamic++; + if (indicators[ind].OverridesTextFore()) + indicatorsSetFore++; + } maxAscent = 1; maxDescent = 1; FindMaxAscentDescent(); diff --git a/src/stc/scintilla/src/ViewStyle.h b/src/stc/scintilla/src/ViewStyle.h index 4a4ffcdf0e..930ad104c4 100644 --- a/src/stc/scintilla/src/ViewStyle.h +++ b/src/stc/scintilla/src/ViewStyle.h @@ -83,6 +83,8 @@ public: LineMarker markers[MARKER_MAX + 1]; int largestMarkerHeight; Indicator indicators[INDIC_MAX + 1]; + unsigned int indicatorsDynamic; + unsigned int indicatorsSetFore; int technology; int lineHeight; int lineOverlap; diff --git a/src/stc/stc.cpp b/src/stc/stc.cpp index 5acbaa2476..e810df7d4b 100644 --- a/src/stc/stc.cpp +++ b/src/stc/stc.cpp @@ -449,6 +449,7 @@ void wxStyledTextCtrl::SetAnchor(int posAnchor) // Retrieve the text of the line containing the caret. // Returns the index of the caret on the line. +// Result is NUL-terminated. wxString wxStyledTextCtrl::GetCurLine(int* linePos) { int len = LineLength(GetCurrentLine()); if (!len) { @@ -1069,6 +1070,43 @@ bool wxStyledTextCtrl::IndicatorGetUnder(int indic) const return SendMsg(SCI_INDICGETUNDER, indic, 0) != 0; } +// Set a hover indicator to plain, squiggle or TT. +void wxStyledTextCtrl::IndicatorSetHoverStyle(int indic, int style) +{ + SendMsg(SCI_INDICSETHOVERSTYLE, indic, style); +} + +// Retrieve the hover style of an indicator. +int wxStyledTextCtrl::IndicatorGetHoverStyle(int indic) const +{ + return SendMsg(SCI_INDICGETHOVERSTYLE, indic, 0); +} + +// Set the foreground hover colour of an indicator. +void wxStyledTextCtrl::IndicatorSetHoverForeground(int indic, const wxColour& fore) +{ + SendMsg(SCI_INDICSETHOVERFORE, indic, wxColourAsLong(fore)); +} + +// Retrieve the foreground hover colour of an indicator. +wxColour wxStyledTextCtrl::IndicatorGetHoverForeground(int indic) const +{ + long c = SendMsg(SCI_INDICGETHOVERFORE, indic, 0); + return wxColourFromLong(c); +} + +// Set the attributes of an indicator. +void wxStyledTextCtrl::IndicatorSetFlags(int indic, int flags) +{ + SendMsg(SCI_INDICSETFLAGS, indic, flags); +} + +// Retrieve the attributes of an indicator. +int wxStyledTextCtrl::IndicatorGetFlags(int indic) const +{ + return SendMsg(SCI_INDICGETFLAGS, indic, 0); +} + // Set the foreground colour of all whitespace and whether to use this setting. void wxStyledTextCtrl::SetWhitespaceForeground(bool useSetting, const wxColour& fore) { @@ -1833,6 +1871,24 @@ int wxStyledTextCtrl::GetTargetEnd() const return SendMsg(SCI_GETTARGETEND, 0, 0); } +// Sets both the start and end of the target in one call. +void wxStyledTextCtrl::SetTargetRange(int start, int end) +{ + SendMsg(SCI_SETTARGETRANGE, start, end); +} + +// Retrieve the text in the target. +wxString wxStyledTextCtrl::GetTargetText() const { + int startPos = GetTargetStart(); + int endPos = GetTargetEnd(); + wxMemoryBuffer mbuf(endPos-startPos+1); // leave room for the null... + char* buf = (char*)mbuf.GetWriteBuf(endPos-startPos+1); + SendMsg(SCI_GETTARGETTEXT, 0, (sptr_t)buf); + mbuf.UngetWriteBuf(endPos-startPos); + mbuf.AppendByte(0); + return stc2wx(buf); +} + // Replace the target text with the argument text. // Text is counted so it can contain NULs. // Returns the length of the replacement text. @@ -2320,6 +2376,7 @@ int wxStyledTextCtrl::GetMultiPaste() const } // Retrieve the value of a tag from a regular expression search. +// Result is NUL-terminated. wxString wxStyledTextCtrl::GetTag(int tagNumber) const { const int msg = SCI_GETTAG; int len = SendMsg(msg, tagNumber, (sptr_t)NULL); @@ -3531,18 +3588,6 @@ int wxStyledTextCtrl::GetGapPosition() const return SendMsg(SCI_GETGAPPOSITION, 0, 0); } -// Always interpret keyboard input as Unicode -void wxStyledTextCtrl::SetKeysUnicode(bool keysUnicode) -{ - SendMsg(SCI_SETKEYSUNICODE, keysUnicode, 0); -} - -// Are keys always interpreted as Unicode? -bool wxStyledTextCtrl::GetKeysUnicode() const -{ - return SendMsg(SCI_GETKEYSUNICODE, 0, 0) != 0; -} - // Set the alpha fill colour of the given indicator. void wxStyledTextCtrl::IndicatorSetAlpha(int indicator, int alpha) { @@ -4211,6 +4256,7 @@ void wxStyledTextCtrl::SetRepresentation(const wxString& encodedCharacter, const } // Set the way a character is drawn. +// Result is NUL-terminated. wxString wxStyledTextCtrl::GetRepresentation(const wxString& encodedCharacter) const { int msg = SCI_GETREPRESENTATION; int len = SendMsg(msg, (sptr_t)(const char*)wx2stc(encodedCharacter), (sptr_t)NULL); @@ -4324,6 +4370,7 @@ void* wxStyledTextCtrl::PrivateLexerCall(int operation, void* pointer) { } // Retrieve a '\n' separated list of properties understood by the current lexer. +// Result is NUL-terminated. wxString wxStyledTextCtrl::PropertyNames() const { const int msg = SCI_PROPERTYNAMES; int len = SendMsg(msg, 0, (sptr_t)NULL); @@ -4344,6 +4391,7 @@ int wxStyledTextCtrl::PropertyType(const wxString& name) } // Describe a property. +// Result is NUL-terminated. wxString wxStyledTextCtrl::DescribeProperty(const wxString& name) const { const int msg = SCI_DESCRIBEPROPERTY; int len = SendMsg(msg, (sptr_t)(const char*)wx2stc(name), (sptr_t)NULL); @@ -4358,6 +4406,7 @@ wxString wxStyledTextCtrl::DescribeProperty(const wxString& name) const { } // Retrieve a '\n' separated list of descriptions of the keyword sets understood by the current lexer. +// Result is NUL-terminated. wxString wxStyledTextCtrl::DescribeKeyWordSets() const { const int msg = SCI_DESCRIBEKEYWORDSETS; int len = SendMsg(msg, 0, (sptr_t)NULL); @@ -4428,6 +4477,7 @@ int wxStyledTextCtrl::DistanceToSecondaryStyles() const } // Get the set of base styles that can be extended with sub styles +// Result is NUL-terminated. wxString wxStyledTextCtrl::GetSubStyleBases() const { int msg = SCI_GETSUBSTYLEBASES; int len = SendMsg(msg, 0, (sptr_t)NULL); @@ -5380,7 +5430,7 @@ wxStyledTextEvent::wxStyledTextEvent(const wxStyledTextEvent& event): /*static*/ wxVersionInfo wxStyledTextCtrl::GetLibraryVersionInfo() { - return wxVersionInfo("Scintilla", 3, 5, 2, "Scintilla 3.5.2"); + return wxVersionInfo("Scintilla", 3, 5, 5, "Scintilla 3.5.5"); } #endif // wxUSE_STC diff --git a/src/stc/stc.cpp.in b/src/stc/stc.cpp.in index d40b68b2f7..db4217516c 100644 --- a/src/stc/stc.cpp.in +++ b/src/stc/stc.cpp.in @@ -1205,7 +1205,7 @@ wxStyledTextEvent::wxStyledTextEvent(const wxStyledTextEvent& event): /*static*/ wxVersionInfo wxStyledTextCtrl::GetLibraryVersionInfo() { - return wxVersionInfo("Scintilla", 3, 5, 2, "Scintilla 3.5.2"); + return wxVersionInfo("Scintilla", 3, 5, 5, "Scintilla 3.5.5"); } #endif // wxUSE_STC