From 676caaaabfe9bd55e3a699ac7431cabdee987a17 Mon Sep 17 00:00:00 2001 From: Derick Payne Date: Sun, 18 Jan 2026 00:15:25 +0200 Subject: [PATCH] deps: Upgrade Lexilla 5.4.5 to 5.4.6, add np3_patches docs --- .gitignore | 3 + lexilla/lexers/LexAU3.cxx | 6 +- lexilla/lexers/LexAVS.cxx | 7 +- lexilla/lexers/LexCPP.cxx | 2 +- lexilla/lexers/LexCSS.cxx | 4 +- lexilla/lexers/LexCoffeeScript.cxx | 2 +- lexilla/lexers/LexD.cxx | 5 +- lexilla/lexers/LexInno.cxx | 1 + lexilla/lexers/LexMatlab.cxx | 8 +- lexilla/lexers/LexPython.cxx | 20 +- lexilla/lexers/LexRegistry.cxx | 6 +- lexilla/lexers/LexRuby.cxx | 2 +- lexilla/lexers/LexRust.cxx | 48 ++- lexilla/lexers/LexTCL.cxx | 14 +- lexilla/lexers/LexVHDL.cxx | 9 +- .../001_StyleContext_MatchNext.patch | 29 ++ .../002_Lexilla_CustomCatalogue.patch | 312 ++++++++++++++++++ lexilla/np3_patches/README.md | 81 +++++ 18 files changed, 512 insertions(+), 47 deletions(-) create mode 100644 lexilla/np3_patches/001_StyleContext_MatchNext.patch create mode 100644 lexilla/np3_patches/002_Lexilla_CustomCatalogue.patch create mode 100644 lexilla/np3_patches/README.md diff --git a/.gitignore b/.gitignore index 2c1c31b7b..1f4f86d08 100644 --- a/.gitignore +++ b/.gitignore @@ -67,3 +67,6 @@ Thumbs.db /np3portableapp/Notepad3Portable/App/Notepad3/x86/*.exe /np3portableapp/Notepad3Portable/App/Notepad3/x86/lng + +# Upgrade staging directory +_upgrade_staging/ diff --git a/lexilla/lexers/LexAU3.cxx b/lexilla/lexers/LexAU3.cxx index 95e123458..4813a62c2 100644 --- a/lexilla/lexers/LexAU3.cxx +++ b/lexilla/lexers/LexAU3.cxx @@ -79,12 +79,12 @@ static inline bool IsTypeCharacter(const int ch) } static inline bool IsAWordChar(const int ch) { - return ((IsASCII(ch) && isalnum(ch)) || ch == '_'); + return (ch < 0x80) && (isalnum(ch) || ch == '_'); } static inline bool IsAWordStart(const int ch) { - return ((IsASCII(ch) && isalnum(ch)) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.'); + return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.'); } static inline bool IsAOperator(char ch) { @@ -143,7 +143,7 @@ static int GetSendKey(const char *szLine, char *szKey) // Save second portion into var... szSpecial[nSpecPos++] = cTemp; // check if Second portion is all numbers for repeat fuction - if (isdigit(cTemp & 0xFF) == false) {nSpecNum = 0;} + if (isdigit(cTemp) == false) {nSpecNum = 0;} } } nPos++; // skip to next char diff --git a/lexilla/lexers/LexAVS.cxx b/lexilla/lexers/LexAVS.cxx index f5dc19fc2..60cb97289 100644 --- a/lexilla/lexers/LexAVS.cxx +++ b/lexilla/lexers/LexAVS.cxx @@ -30,17 +30,18 @@ using namespace Lexilla; static inline bool IsAWordChar(const int ch) { - return IsASCII(ch) && (isalnum(ch) || ch == '_'); + return (ch < 0x80) && (isalnum(ch) || ch == '_'); } static inline bool IsAWordStart(int ch) { - return isalpha(ch & 0xFF) || (ch != ' ' && ch != '\n' && ch != '(' && ch != '.' && ch != ','); + return isalpha(ch) || (ch != ' ' && ch != '\n' && ch != '(' && ch != '.' && ch != ','); } static inline bool IsANumberChar(int ch) { // Not exactly following number definition (several dots are seen as OK, etc.) // but probably enough in most cases. - return IsASCII(ch) && (isdigit(ch) || ch == '.' || ch == '-' || ch == '+'); + return (ch < 0x80) && + (isdigit(ch) || ch == '.' || ch == '-' || ch == '+'); } static void ColouriseAvsDoc( diff --git a/lexilla/lexers/LexCPP.cxx b/lexilla/lexers/LexCPP.cxx index ddc23b023..a0fc71dba 100644 --- a/lexilla/lexers/LexCPP.cxx +++ b/lexilla/lexers/LexCPP.cxx @@ -528,7 +528,7 @@ const LexicalClass lexicalClasses[] = { 27, "SCE_C_ESCAPESEQUENCE", "literal string escapesequence", "Escape sequence", }; -constexpr int sizeLexicalClasses{ static_cast(std::size(lexicalClasses)) }; +constexpr int sizeLexicalClasses = static_cast(std::size(lexicalClasses)); } diff --git a/lexilla/lexers/LexCSS.cxx b/lexilla/lexers/LexCSS.cxx index 5444e7db6..76ae62c83 100644 --- a/lexilla/lexers/LexCSS.cxx +++ b/lexilla/lexers/LexCSS.cxx @@ -44,11 +44,11 @@ static inline bool IsAWordChar(const unsigned int ch) { * Unfortunately, we are only getting string bytes here, and not full unicode characters. We cannot guarantee * that our byte is between U+0080 - U+00A0 (to return false), so we have to allow all characters U+0080 and higher */ - return ch >= 0x80 || isalnum(ch & 0xFF) || ch == '-' || ch == '_'; + return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_'; } inline bool IsCssOperator(const int ch) { - if (!(IsASCII(ch) && isalnum(ch)) && + if (!((ch < 0x80) && isalnum(ch)) && (ch == '{' || ch == '}' || ch == ':' || ch == ',' || ch == ';' || ch == '.' || ch == '#' || ch == '!' || ch == '@' || /* CSS2 */ diff --git a/lexilla/lexers/LexCoffeeScript.cxx b/lexilla/lexers/LexCoffeeScript.cxx index 59372c594..95f0adb1d 100644 --- a/lexilla/lexers/LexCoffeeScript.cxx +++ b/lexilla/lexers/LexCoffeeScript.cxx @@ -249,7 +249,7 @@ static void ColouriseCoffeeScriptDoc(Sci_PositionU startPos, Sci_Position length sc.SetState(SCE_COFFEESCRIPT_DEFAULT); } else if (sc.ch == '/') { sc.Forward(); - while (IsASCII(sc.ch) && islower(sc.ch)) + while ((sc.ch < 0x80) && islower(sc.ch)) sc.Forward(); // gobble regex flags sc.SetState(SCE_COFFEESCRIPT_DEFAULT); } else if (sc.ch == '\\') { diff --git a/lexilla/lexers/LexD.cxx b/lexilla/lexers/LexD.cxx index b3786c005..ba76e6c7e 100644 --- a/lexilla/lexers/LexD.cxx +++ b/lexilla/lexers/LexD.cxx @@ -234,7 +234,10 @@ Sci_Position SCI_METHOD LexerD::WordListSet(int n, const char *wl) { } Sci_Position firstModification = -1; if (wordListN) { - if (wordListN->Set(wl)) { + WordList wlNew; + wlNew.Set(wl); + if (*wordListN != wlNew) { + wordListN->Set(wl); firstModification = 0; } } diff --git a/lexilla/lexers/LexInno.cxx b/lexilla/lexers/LexInno.cxx index 6781e36ca..91e110675 100644 --- a/lexilla/lexers/LexInno.cxx +++ b/lexilla/lexers/LexInno.cxx @@ -89,6 +89,7 @@ static void ColouriseInnoDoc(Sci_PositionU startPos, Sci_Position length, int, W // using the hand-written state machine shown below styler.StartAt(startPos); styler.StartSegment(startPos); + for (Sci_Position i = startPos; i < lengthDoc; i++) { chPrev = ch; ch = chNext; diff --git a/lexilla/lexers/LexMatlab.cxx b/lexilla/lexers/LexMatlab.cxx index 2d0a562fb..9517bd4e6 100644 --- a/lexilla/lexers/LexMatlab.cxx +++ b/lexilla/lexers/LexMatlab.cxx @@ -242,7 +242,7 @@ static void ColouriseMatlabOctaveDoc( sc.SetState(SCE_MATLAB_DEFAULT); } } else if (sc.state == SCE_MATLAB_KEYWORD) { - if (!isalnum(sc.ch & 0xFF) && sc.ch != '_') { + if (!isalnum(sc.ch) && sc.ch != '_') { char s[100]; sc.GetCurrent(s, sizeof(s)); bool notKeyword = false; @@ -302,7 +302,7 @@ static void ColouriseMatlabOctaveDoc( styler.SetLineState(curLine, ComposeLineState( commentDepth, foldingLevel, expectingArgumentsBlock, inClassScope, inArgumentsScope)); } else if (sc.state == SCE_MATLAB_NUMBER) { - if (!isdigit(sc.ch & 0xFF) && sc.ch != '.' + if (!isdigit(sc.ch) && sc.ch != '.' && !(sc.ch == 'e' || sc.ch == 'E') && !((sc.ch == '+' || sc.ch == '-') && (sc.chPrev == 'e' || sc.chPrev == 'E')) && !(((sc.ch == 'x' || sc.ch == 'X') && sc.chPrev == '0') || (sc.ch >= 'a' && sc.ch <= 'f') || (sc.ch >= 'A' && sc.ch <= 'F')) @@ -394,9 +394,9 @@ static void ColouriseMatlabOctaveDoc( } } else if (sc.ch == '"') { sc.SetState(SCE_MATLAB_DOUBLEQUOTESTRING); - } else if (isdigit(sc.ch & 0xFF) || (sc.ch == '.' && isdigit(sc.chNext & 0xFF))) { + } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) { sc.SetState(SCE_MATLAB_NUMBER); - } else if (isalpha(sc.ch & 0xFF)) { + } else if (isalpha(sc.ch)) { sc.SetState(SCE_MATLAB_KEYWORD); } else if (isoperator(static_cast(sc.ch)) || sc.ch == '@' || sc.ch == '\\') { if (sc.ch == '(' || sc.ch == '[' || sc.ch == '{') { diff --git a/lexilla/lexers/LexPython.cxx b/lexilla/lexers/LexPython.cxx index edaf87daa..8e1deb918 100644 --- a/lexilla/lexers/LexPython.cxx +++ b/lexilla/lexers/LexPython.cxx @@ -54,6 +54,9 @@ namespace { The PEP for f-strings is at https://www.python.org/dev/peps/pep-0498/ */ +/* t-string are lexed identically to f-strings and use the stack of state values + and the lexer states for f-strings +*/ struct SingleFStringExpState { int state; int nestingCount; @@ -62,7 +65,7 @@ struct SingleFStringExpState { /* kwCDef, kwCTypeName only used for Cython */ enum kwType { kwOther, kwClass, kwDef, kwImport, kwCDef, kwCTypeName, kwCPDef }; -enum literalsAllowed { litNone = 0, litU = 1, litB = 2, litF = 4 }; +enum literalsAllowed { litNone = 0, litU = 1, litB = 2, litF = 4, litT = 8 }; constexpr int indicatorWhitespace = 1; @@ -74,7 +77,8 @@ constexpr bool IsPyStringTypeChar(int ch, literalsAllowed allowed) noexcept { return ((allowed & litB) && (ch == 'b' || ch == 'B')) || ((allowed & litU) && (ch == 'u' || ch == 'U')) || - ((allowed & litF) && (ch == 'f' || ch == 'F')); + ((allowed & litF) && (ch == 'f' || ch == 'F')) || + ((allowed & litT) && (ch == 't' || ch == 'T')); } constexpr bool IsQuote(int ch) { @@ -88,7 +92,7 @@ constexpr bool IsRawPrefix(int ch) { bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) noexcept { // To cover both python2 and python3 lex character prefixes as -- // ur'' is a string, but ru'' is not - // fr'', rf'', br'', rb'' are all strings + // fr'', rf'', br'', rb'', tr'', rt'' are all strings if (IsQuote(ch)) return true; if (IsPyStringTypeChar(ch, allowed)) { @@ -163,14 +167,14 @@ int GetPyStringState(Accessor &styler, Sci_Position i, Sci_PositionU *nextIndex, if (IsRawPrefix(ch)) { i++; if (IsPyStringTypeChar(chNext, allowed)) { - if (AnyOf(chNext, 'f', 'F')) + if (AnyOf(chNext, 'f', 'F', 't', 'T')) isFString = true; i++; } ch = styler.SafeGetCharAt(i); chNext = styler.SafeGetCharAt(i + 1); } else if (IsPyStringTypeChar(ch, allowed)) { - if (AnyOf(ch, 'f', 'F')) + if (AnyOf(ch, 'f', 'F', 't', 'T')) isFString = true; if (IsRawPrefix(chNext)) i += 2; @@ -291,6 +295,7 @@ struct OptionsPython { bool stringsU = true; bool stringsB = true; bool stringsF = true; + bool stringsT = true; bool stringsOverNewline = false; bool keywords2NoSubIdentifiers = false; bool fold = false; @@ -307,6 +312,8 @@ struct OptionsPython { allowedLiterals = static_cast(allowedLiterals | litB); if (stringsF) allowedLiterals = static_cast(allowedLiterals | litF); + if (stringsT) + allowedLiterals = static_cast(allowedLiterals | litT); return allowedLiterals; } }; @@ -343,6 +350,9 @@ struct OptionSetPython : public OptionSet { DefineProperty("lexer.python.strings.f.pep.701", &OptionsPython::pep701StringsF, "Set to 0 to use pre-PEP 701 / Python 3.12 f-string lexing."); + DefineProperty("lexer.python.strings.t", &OptionsPython::stringsT, + "Set to 0 to not recognise Python 3.14 t-string literals t\"var={var}\"."); + DefineProperty("lexer.python.strings.over.newline", &OptionsPython::stringsOverNewline, "Set to 1 to allow strings to span newline characters."); diff --git a/lexilla/lexers/LexRegistry.cxx b/lexilla/lexers/LexRegistry.cxx index ac08feb1e..adc4210ec 100644 --- a/lexilla/lexers/LexRegistry.cxx +++ b/lexilla/lexers/LexRegistry.cxx @@ -36,7 +36,7 @@ using namespace Scintilla; using namespace Lexilla; static const char *const RegistryWordListDesc[] = { - nullptr + 0 }; struct OptionsRegistry { @@ -250,7 +250,7 @@ void SCI_METHOD LexerRegistry::Lex(Sci_PositionU startPos, } if (context.state == SCE_REG_STRING && context.ch == '%' && - (isdigit(context.chNext & 0xFF) || context.chNext == '*')) { + (isdigit(context.chNext) || context.chNext == '*')) { context.SetState(SCE_REG_PARAMETER); } } @@ -337,7 +337,7 @@ void SCI_METHOD LexerRegistry::Lex(Sci_PositionU startPos, afterEqualSign = true; highlight = true; } else if (afterEqualSign) { - bool wordStart = isalpha(context.ch & 0xFF) && !isalpha(context.chPrev & 0xFF); + bool wordStart = isalpha(context.ch) && !isalpha(context.chPrev); if (wordStart && AtValueType(styler, currPos)) { context.SetState(SCE_REG_VALUETYPE); } diff --git a/lexilla/lexers/LexRuby.cxx b/lexilla/lexers/LexRuby.cxx index 294349c66..47d5e3564 100644 --- a/lexilla/lexers/LexRuby.cxx +++ b/lexilla/lexers/LexRuby.cxx @@ -75,7 +75,7 @@ bool isSafeWordcharOrHigh(char ch) noexcept { // Error: scintilla's KeyWords.h includes '.' as a word-char // we want to separate things that can take methods from the // methods. - return isHighBitChar(ch) || isalnum(ch & 0xFF) || ch == '_'; + return isHighBitChar(ch) || isalnum(ch) || ch == '_'; } constexpr bool isWhiteSpace(char ch) noexcept { diff --git a/lexilla/lexers/LexRust.cxx b/lexilla/lexers/LexRust.cxx index 8569ddefc..2e69832c4 100644 --- a/lexilla/lexers/LexRust.cxx +++ b/lexilla/lexers/LexRust.cxx @@ -7,12 +7,12 @@ // Copyright 1998-2005 by Neil Hodgson // The License.txt file describes the conditions under which this software may be distributed. -#include -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include +#include #include #include @@ -93,7 +93,7 @@ static const char * const rustWordLists[NUM_RUST_KEYWORD_LISTS + 1] = { "Keywords 5", "Keywords 6", "Keywords 7", - 0, + nullptr, }; struct OptionSetRust : public OptionSet { @@ -131,12 +131,42 @@ struct OptionSetRust : public OptionSet { } }; +const LexicalClass lexicalClasses[] = { + // Lexer rust SCLEX_RUST SCE_RUST_: + 0, "SCE_RUST_DEFAULT", "default", "White space", + 1, "SCE_RUST_COMMENTBLOCK", "comment", "Comment", + 2, "SCE_RUST_COMMENTLINE", "comment line", "Line comment", + 3, "SCE_RUST_COMMENTBLOCKDOC", "comment documentation", "Doc comment", + 4, "SCE_RUST_COMMENTLINEDOC", "comment documentation line", "Doc comment line", + 5, "SCE_RUST_NUMBER", "literal numeric", "Number", + 6, "SCE_RUST_WORD", "keyword", "Keywords", + 7, "SCE_RUST_WORD2", "identifier", "Keywords 2", + 8, "SCE_RUST_WORD3", "identifier", "Keywords 3", + 9, "SCE_RUST_WORD4", "identifier", "Keywords 4", + 10, "SCE_RUST_WORD5", "identifier", "Keywords 5", + 11, "SCE_RUST_WORD6", "identifier", "Keywords 6", + 12, "SCE_RUST_WORD7", "identifier", "Keywords 7", + 13, "SCE_RUST_STRING", "literal string", "Regular string", + 14, "SCE_RUST_STRINGR", "literal string raw", "Raw string", + 15, "SCE_RUST_CHARACTER", "literal string character", "Character", + 16, "SCE_RUST_OPERATOR", "operator", "Operator", + 17, "SCE_RUST_IDENTIFIER", "identifier", "Identifier", + 18, "SCE_RUST_LIFETIME", "annotation", "Lifetime", + 19, "SCE_RUST_MACRO", "macro preprocessor", "Macro", + 20, "SCE_RUST_LEXERROR", "error", "Lexical error", + 21, "SCE_RUST_BYTESTRING", "literal string", "Byte string", + 22, "SCE_RUST_BYTESTRINGR", "literal string raw", "Raw byte string", + 23, "SCE_RUST_BYTECHARACTER", "literal string character", "Byte character", + 24, "SCE_RUST_CSTRING", "literal string", "C string", + 25, "SCE_RUST_CSTRINGR", "literal string raw", "Raw C string", +}; + class LexerRust : public DefaultLexer { WordList keywords[NUM_RUST_KEYWORD_LISTS]; OptionsRust options; OptionSetRust osRust; public: - LexerRust() : DefaultLexer("rust", SCLEX_RUST) { + LexerRust() : DefaultLexer("rust", SCLEX_RUST, lexicalClasses, std::size(lexicalClasses)) { } virtual ~LexerRust() { } @@ -166,7 +196,7 @@ public: void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override; void * SCI_METHOD PrivateCall(int, void *) override { - return 0; + return nullptr; } static ILexer5 *LexerFactoryRust() { return new LexerRust(); diff --git a/lexilla/lexers/LexTCL.cxx b/lexilla/lexers/LexTCL.cxx index d52ef7978..691d79e35 100644 --- a/lexilla/lexers/LexTCL.cxx +++ b/lexilla/lexers/LexTCL.cxx @@ -31,11 +31,11 @@ using namespace Lexilla; // Extended to accept accented characters static inline bool IsAWordChar(int ch) { return ch >= 0x80 || - (isalnum(ch & 0xFF) || ch == '_' || ch ==':' || ch=='.'); // : name space separator + (isalnum(ch) || ch == '_' || ch ==':' || ch=='.'); // : name space separator } static inline bool IsAWordStart(int ch) { - return ch >= 0x80 || (ch ==':' || isalpha(ch & 0xFF) || ch == '_'); + return ch >= 0x80 || (ch ==':' || isalpha(ch) || ch == '_'); } static inline bool IsANumberChar(int ch) { @@ -48,7 +48,6 @@ static inline bool IsANumberChar(int ch) { static void ColouriseTCLDoc(Sci_PositionU startPos, Sci_Position length, int , WordList *keywordlists[], Accessor &styler) { #define isComment(s) (s==SCE_TCL_COMMENT || s==SCE_TCL_COMMENTLINE || s==SCE_TCL_COMMENT_BOX || s==SCE_TCL_BLOCK_COMMENT) - const bool fold = (styler.GetPropertyInt("fold") != 0); const bool foldComment = styler.GetPropertyInt("fold.comment") != 0; const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; bool commentLevel = false; @@ -86,8 +85,7 @@ static void ColouriseTCLDoc(Sci_PositionU startPos, Sci_Position length, int , W currentLevel = styler.LevelAt(currentLine - 1) >> 17; commentLevel = (styler.LevelAt(currentLine - 1) >> 16) & 1; } else - if (fold) { styler.SetLevel(0, SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG); } - + styler.SetLevel(0, SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG); bool visibleChars = false; int previousLevel = currentLevel; @@ -209,10 +207,8 @@ next: flag = SC_FOLDLEVELWHITEFLAG; if (currentLevel > previousLevel) flag = SC_FOLDLEVELHEADERFLAG; - - if (fold) { - styler.SetLevel(currentLine, flag + previousLevel + SC_FOLDLEVELBASE + (currentLevel << 17) + (commentLevel << 16)); - } + 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) { lineState = LS_OPEN_DOUBLE_QUOTE; diff --git a/lexilla/lexers/LexVHDL.cxx b/lexilla/lexers/LexVHDL.cxx index aacc83309..89b93ef88 100644 --- a/lexilla/lexers/LexVHDL.cxx +++ b/lexilla/lexers/LexVHDL.cxx @@ -43,12 +43,12 @@ static void ColouriseVHDLDoc( /***************************************/ static inline bool IsAWordChar(const int ch) { - return IsASCII(ch) && (isalnum(ch) || ch == '.' || ch == '_' ); + return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' ); } /***************************************/ static inline bool IsAWordStart(const int ch) { - return IsASCII(ch) && (isalnum(ch) || ch == '_'); + return (ch < 0x80) && (isalnum(ch) || ch == '_'); } /***************************************/ @@ -235,9 +235,8 @@ static void FoldNoBoxVHDLDoc( // Decided it would be smarter to have the lexer have all keywords included. Therefore I // don't check if the style for the keywords that I use to adjust the levels. char words[] = - "architecture begin block case component configuration context else elsif end entity for function " - "generate if loop package procedure process protected record then units view when"; - + "architecture begin block case component else elsif end entity for generate loop package process record then " + "procedure protected function when units"; WordList keywords; keywords.Set(words); diff --git a/lexilla/np3_patches/001_StyleContext_MatchNext.patch b/lexilla/np3_patches/001_StyleContext_MatchNext.patch new file mode 100644 index 000000000..937806fca --- /dev/null +++ b/lexilla/np3_patches/001_StyleContext_MatchNext.patch @@ -0,0 +1,29 @@ +diff --git a/_upgrade_staging/lexilla/lexlib/StyleContext.h b/lexilla/lexlib/StyleContext.h +index d148140e8..f188d1bef 100644 +--- a/_upgrade_staging/lexilla/lexlib/StyleContext.h ++++ b/lexilla/lexlib/StyleContext.h +@@ -187,6 +187,24 @@ public: + void GetCurrentLowered(char *s, Sci_PositionU len) const; + enum class Transform { none, lower }; + void GetCurrentString(std::string &string, Transform transform) const; ++ ++ // >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>> ++ ++ bool Match(char ch0, char ch1, char ch2) const noexcept { ++ return Match(ch0, ch1) && ch2 == styler.SafeGetCharAt(currentPos + 2, '\0'); ++ } ++ ++ bool MatchNext() const noexcept { ++ return ch == chNext && ch == static_cast(styler[currentPos + 2]); ++ } ++ bool MatchNext(char ch0, char ch1) const noexcept { ++ return chNext == static_cast(ch0) && ch1 == styler.SafeGetCharAt(currentPos + 2, '\0'); ++ } ++ bool MatchNext(char ch0, char ch1, char ch2) const noexcept { ++ return MatchNext(ch0, ch1) && ch2 == styler.SafeGetCharAt(currentPos + 3, '\0'); ++ } ++ ++ // <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<< + }; + + } diff --git a/lexilla/np3_patches/002_Lexilla_CustomCatalogue.patch b/lexilla/np3_patches/002_Lexilla_CustomCatalogue.patch new file mode 100644 index 000000000..85a2aef14 --- /dev/null +++ b/lexilla/np3_patches/002_Lexilla_CustomCatalogue.patch @@ -0,0 +1,312 @@ +diff --git a/_upgrade_staging/lexilla/src/Lexilla.cxx b/lexilla/src/Lexilla.cxx +index 5b3811466..b0dde49a8 100644 +--- a/_upgrade_staging/lexilla/src/Lexilla.cxx ++++ b/lexilla/src/Lexilla.cxx +@@ -28,144 +28,60 @@ using namespace Lexilla; + + //++Autogenerated -- run lexilla/scripts/LexillaGen.py to regenerate + //**\(extern const LexerModule \*;\n\) +-extern const LexerModule lmA68k; +-extern const LexerModule lmAbaqus; +-extern const LexerModule lmAda; +-extern const LexerModule lmAPDL; ++extern const LexerModule lmAHK; + extern const LexerModule lmAs; +-extern const LexerModule lmAsciidoc; + extern const LexerModule lmAsm; +-extern const LexerModule lmAsn1; +-extern const LexerModule lmASY; + extern const LexerModule lmAU3; +-extern const LexerModule lmAVE; + extern const LexerModule lmAVS; +-extern const LexerModule lmBaan; + extern const LexerModule lmBash; + extern const LexerModule lmBatch; +-extern const LexerModule lmBibTeX; +-extern const LexerModule lmBlitzBasic; +-extern const LexerModule lmBullant; +-extern const LexerModule lmCaml; +-extern const LexerModule lmCIL; +-extern const LexerModule lmClw; +-extern const LexerModule lmClwNoCase; + extern const LexerModule lmCmake; +-extern const LexerModule lmCOBOL; + extern const LexerModule lmCoffeeScript; + extern const LexerModule lmConf; + extern const LexerModule lmCPP; + extern const LexerModule lmCPPNoCase; +-extern const LexerModule lmCsound; + extern const LexerModule lmCss; ++extern const LexerModule lmCSV; + extern const LexerModule lmD; + extern const LexerModule lmDart; +-extern const LexerModule lmDataflex; + extern const LexerModule lmDiff; +-extern const LexerModule lmDMAP; +-extern const LexerModule lmDMIS; +-extern const LexerModule lmECL; +-extern const LexerModule lmEDIFACT; +-extern const LexerModule lmEiffel; +-extern const LexerModule lmEiffelkw; +-extern const LexerModule lmErlang; +-extern const LexerModule lmErrorList; +-extern const LexerModule lmESCRIPT; + extern const LexerModule lmF77; +-extern const LexerModule lmFlagShip; +-extern const LexerModule lmForth; + extern const LexerModule lmFortran; +-extern const LexerModule lmFreeBasic; +-extern const LexerModule lmFSharp; +-extern const LexerModule lmGAP; +-extern const LexerModule lmGDScript; +-extern const LexerModule lmGui4Cli; +-extern const LexerModule lmHaskell; +-extern const LexerModule lmHollywood; + extern const LexerModule lmHTML; +-extern const LexerModule lmIHex; +-extern const LexerModule lmIndent; + extern const LexerModule lmInno; + extern const LexerModule lmJSON; + extern const LexerModule lmJulia; + extern const LexerModule lmKix; +-extern const LexerModule lmKVIrc; ++extern const LexerModule lmKotlin; + extern const LexerModule lmLatex; +-extern const LexerModule lmLISP; +-extern const LexerModule lmLiterateHaskell; +-extern const LexerModule lmLot; +-extern const LexerModule lmLout; + extern const LexerModule lmLua; +-extern const LexerModule lmMagikSF; + extern const LexerModule lmMake; + extern const LexerModule lmMarkdown; + extern const LexerModule lmMatlab; +-extern const LexerModule lmMaxima; +-extern const LexerModule lmMETAPOST; +-extern const LexerModule lmMMIXAL; +-extern const LexerModule lmModula; +-extern const LexerModule lmMSSQL; +-extern const LexerModule lmMySQL; + extern const LexerModule lmNim; +-extern const LexerModule lmNimrod; +-extern const LexerModule lmNix; +-extern const LexerModule lmNncrontab; + extern const LexerModule lmNsis; + extern const LexerModule lmNull; + extern const LexerModule lmOctave; +-extern const LexerModule lmOpal; +-extern const LexerModule lmOScript; + extern const LexerModule lmPascal; +-extern const LexerModule lmPB; + extern const LexerModule lmPerl; + extern const LexerModule lmPHPSCRIPT; +-extern const LexerModule lmPLM; +-extern const LexerModule lmPO; +-extern const LexerModule lmPOV; +-extern const LexerModule lmPowerPro; + extern const LexerModule lmPowerShell; +-extern const LexerModule lmProgress; + extern const LexerModule lmProps; +-extern const LexerModule lmPS; +-extern const LexerModule lmPureBasic; + extern const LexerModule lmPython; + extern const LexerModule lmR; +-extern const LexerModule lmRaku; +-extern const LexerModule lmREBOL; + extern const LexerModule lmRegistry; + extern const LexerModule lmRuby; + extern const LexerModule lmRust; +-extern const LexerModule lmSAS; +-extern const LexerModule lmScriptol; +-extern const LexerModule lmSINEX; +-extern const LexerModule lmSmalltalk; +-extern const LexerModule lmSML; +-extern const LexerModule lmSorc; +-extern const LexerModule lmSpecman; +-extern const LexerModule lmSpice; + extern const LexerModule lmSQL; +-extern const LexerModule lmSrec; +-extern const LexerModule lmStata; +-extern const LexerModule lmSTTXT; +-extern const LexerModule lmTACL; +-extern const LexerModule lmTADS3; +-extern const LexerModule lmTAL; ++extern const LexerModule lmSysVerilog; + extern const LexerModule lmTCL; +-extern const LexerModule lmTCMD; +-extern const LexerModule lmTEHex; +-extern const LexerModule lmTeX; + extern const LexerModule lmTOML; +-extern const LexerModule lmTroff; +-extern const LexerModule lmTxt2tags; + extern const LexerModule lmVB; + extern const LexerModule lmVBScript; + extern const LexerModule lmVerilog; + extern const LexerModule lmVHDL; +-extern const LexerModule lmVisualProlog; +-extern const LexerModule lmX12; + extern const LexerModule lmXML; + extern const LexerModule lmYAML; +-extern const LexerModule lmZig; + + //--Autogenerated -- end of automatically generated section + +@@ -182,151 +98,67 @@ void AddEachLexer() { + catalogueLexilla.AddLexerModules({ + //++Autogenerated -- run scripts/LexillaGen.py to regenerate + //**\(\t\t&\*,\n\) +- &lmA68k, +- &lmAbaqus, +- &lmAda, +- &lmAPDL, ++ &lmAHK, + &lmAs, +- &lmAsciidoc, + &lmAsm, +- &lmAsn1, +- &lmASY, + &lmAU3, +- &lmAVE, + &lmAVS, +- &lmBaan, + &lmBash, + &lmBatch, +- &lmBibTeX, +- &lmBlitzBasic, +- &lmBullant, +- &lmCaml, +- &lmCIL, +- &lmClw, +- &lmClwNoCase, + &lmCmake, +- &lmCOBOL, + &lmCoffeeScript, + &lmConf, + &lmCPP, + &lmCPPNoCase, +- &lmCsound, + &lmCss, ++ &lmCSV, + &lmD, + &lmDart, +- &lmDataflex, + &lmDiff, +- &lmDMAP, +- &lmDMIS, +- &lmECL, +- &lmEDIFACT, +- &lmEiffel, +- &lmEiffelkw, +- &lmErlang, +- &lmErrorList, +- &lmESCRIPT, + &lmF77, +- &lmFlagShip, +- &lmForth, + &lmFortran, +- &lmFreeBasic, +- &lmFSharp, +- &lmGAP, +- &lmGDScript, +- &lmGui4Cli, +- &lmHaskell, +- &lmHollywood, + &lmHTML, +- &lmIHex, +- &lmIndent, + &lmInno, + &lmJSON, + &lmJulia, + &lmKix, +- &lmKVIrc, ++ &lmKotlin, + &lmLatex, +- &lmLISP, +- &lmLiterateHaskell, +- &lmLot, +- &lmLout, + &lmLua, +- &lmMagikSF, + &lmMake, + &lmMarkdown, + &lmMatlab, +- &lmMaxima, +- &lmMETAPOST, +- &lmMMIXAL, +- &lmModula, +- &lmMSSQL, +- &lmMySQL, + &lmNim, +- &lmNimrod, +- &lmNix, +- &lmNncrontab, + &lmNsis, + &lmNull, + &lmOctave, +- &lmOpal, +- &lmOScript, + &lmPascal, +- &lmPB, + &lmPerl, + &lmPHPSCRIPT, +- &lmPLM, +- &lmPO, +- &lmPOV, +- &lmPowerPro, + &lmPowerShell, +- &lmProgress, + &lmProps, +- &lmPS, +- &lmPureBasic, + &lmPython, + &lmR, +- &lmRaku, +- &lmREBOL, + &lmRegistry, + &lmRuby, + &lmRust, +- &lmSAS, +- &lmScriptol, +- &lmSINEX, +- &lmSmalltalk, +- &lmSML, +- &lmSorc, +- &lmSpecman, +- &lmSpice, + &lmSQL, +- &lmSrec, +- &lmStata, +- &lmSTTXT, +- &lmTACL, +- &lmTADS3, +- &lmTAL, ++ &lmSysVerilog, + &lmTCL, +- &lmTCMD, +- &lmTEHex, +- &lmTeX, + &lmTOML, +- &lmTroff, +- &lmTxt2tags, + &lmVB, + &lmVBScript, + &lmVerilog, + &lmVHDL, +- &lmVisualProlog, +- &lmX12, + &lmXML, + &lmYAML, +- &lmZig, + + //--Autogenerated -- end of automatically generated section +- }); ++ }); + +-} ++} // AddEachLexer() + +-} ++} // namspace + + extern "C" { + diff --git a/lexilla/np3_patches/README.md b/lexilla/np3_patches/README.md new file mode 100644 index 000000000..7d074e39c --- /dev/null +++ b/lexilla/np3_patches/README.md @@ -0,0 +1,81 @@ +# Notepad3 Lexilla Patches + +This directory contains documentation of all modifications made to the upstream Lexilla library for Notepad3 compatibility. + +## Patch Registry + +| ID | Patch File | Target File | Description | Required | +|----|------------|-------------|-------------|----------| +| 001 | `001_StyleContext_MatchNext.patch` | `lexlib/StyleContext.h` | Adds `MatchNext()` and `Match(char,char,char)` overloads | ✅ Yes | +| 002 | `002_Lexilla_CustomCatalogue.patch` | `src/Lexilla.cxx` | Custom lexer catalogue (NP3 subset only) | ✅ Yes | + +--- + +## Patch Details + +### 001: StyleContext MatchNext Extensions + +**File:** `lexlib/StyleContext.h` +**Status:** Required for NP3 lexers + +Adds the following methods to the `StyleContext` class: + +```cpp +bool Match(char ch0, char ch1, char ch2) const noexcept; +bool MatchNext() const noexcept; +bool MatchNext(char ch0, char ch1) const noexcept; +bool MatchNext(char ch0, char ch1, char ch2) const noexcept; +``` + +**Used by:** +- `lexers_x/LexKotlin.cxx` +- `lexers_x/orig/zufuliu/LexKotlin.cxx` +- `lexers_x/orig/zufuliu/LexDart.cxx` + +**Marker:** `// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>` + +--- + +### 002: Custom Lexer Catalogue + +**File:** `src/Lexilla.cxx` +**Status:** Required - DO NOT UPGRADE + +NP3 compiles only a subset of Lexilla's lexers (~47 vs 124 upstream). The `Lexilla.cxx` file contains the catalogue of registered lexers. Using the upstream version causes 80+ unresolved symbol errors. + +**NP3 Lexer Sources:** +- `lexilla/lexers/` - 41 curated upstream lexers +- `lexilla/lexers_x/` - 6 NP3-specific lexers (AHK, CSV, JSON, Kotlin, Verilog) + +--- + +## Upgrade Procedure + +When upgrading Lexilla to a new version: + +1. **DO NOT** blindly copy `lexlib/StyleContext.h` - preserve patch 001 +2. **DO NOT** copy `src/Lexilla.cxx` - keep NP3's custom catalogue +3. **Safe to copy:** `include/`, `lexlib/CharacterCategory.cxx`, individual lexers from `lexers/` +4. After upgrade, verify patches are intact: + ```powershell + git diff --no-index upstream/StyleContext.h lexilla/lexlib/StyleContext.h + ``` + +--- + +## Directory Structure + +``` +lexilla/np3_patches/ +├── README.md # This file +├── 001_StyleContext_MatchNext.patch # StyleContext extensions +└── 002_Lexilla_CustomCatalogue.patch # Custom lexer catalogue diff +``` + +--- + +## Version History + +| Lexilla Version | Upgrade Date | Notes | +|-----------------|--------------|-------| +| 5.4.5 → 5.4.6 | 2026-01-18 | Incremental upgrade, patches preserved |