diff --git a/scintilla/cppcheck.suppress b/scintilla/cppcheck.suppress
index dc1f264e1..4bf51148f 100644
--- a/scintilla/cppcheck.suppress
+++ b/scintilla/cppcheck.suppress
@@ -71,6 +71,9 @@ unreadVariable:scintilla/lexers/LexVisualProlog.cxx
// bp.itBracket not actually redundant as needed by return statements
redundantAssignment:scintilla/lexers/LexCPP.cxx
+// safety initializations at start of GetCharacterExtents
+redundantAssignment:scintilla/gtk/ScintillaGTKAccessible.cxx
+
// Suppress everything in catch.hpp as won't be changing
*:scintilla/test/unit/catch.hpp
// For now, suppress all test source files as, since Catch 2, cppcheck shows many warnings showing
diff --git a/scintilla/doc/ScintillaDoc.html b/scintilla/doc/ScintillaDoc.html
index 40bb8f430..ad030d235 100644
--- a/scintilla/doc/ScintillaDoc.html
+++ b/scintilla/doc/ScintillaDoc.html
@@ -2470,6 +2470,8 @@ struct Sci_TextToFind {
SCI_SETPUNCTUATIONCHARS(<unused>, const char *characters)
SCI_GETPUNCTUATIONCHARS(<unused>, char *characters) → int
SCI_SETCHARSDEFAULT
+ SCI_SETCHARACTERCATEGORYOPTIMIZATION(int countCharacters)
+ SCI_GETCHARACTERCATEGORYOPTIMIZATION → int
SCI_WORDENDPOSITION(int pos, bool onlyWordCharacters) → int
SCI_WORDSTARTPOSITION(int pos, bool onlyWordCharacters) → int
@@ -2597,6 +2599,15 @@ struct Sci_TextToFind {
characters with codes less than 0x20, with word characters set to alphanumeric and '_'.
+ SCI_SETCHARACTERCATEGORYOPTIMIZATION(int countCharacters)
+ SCI_GETCHARACTERCATEGORYOPTIMIZATION → int
+ Optimize speed of character category features like determining whether a character is a space or number at the expense of memory.
+ Mostly used for Unicode documents.
+ The countCharacters parameter determines how many character starting from 0 are added to a look-up table with one byte used for each character.
+ It is reasonable to cover the set of characters likely to be used in a document so 0x100 for simple Roman text,
+ 0x1000 to cover most simple alphabets, 0x10000 to cover most of East Asian languages, and 0x110000 to cover all possible characters.
+
+
Word keyboard commands are:
- SCI_WORDLEFT
diff --git a/scintilla/doc/ScintillaHistory.html b/scintilla/doc/ScintillaHistory.html
index 381dc4ecd..8e8d734dd 100644
--- a/scintilla/doc/ScintillaHistory.html
+++ b/scintilla/doc/ScintillaHistory.html
@@ -571,6 +571,16 @@
Implement high-priority idle on Win32 to make redraw smoother and more efficient.
-
+ Add SCI_SETCHARACTERCATEGORYOPTIMIZATION API to optimize speed
+ of character category features like determining whether a character is a space or number
+ at the expense of memory.
+ Feature #1259.
+
+ -
+ Fix flicker when inserting primary selection on GTK.
+ Bug #2087.
+
+ -
Avoid potential long hangs with idle styling for huge documents on Cocoa and GTK.
diff --git a/scintilla/include/Scintilla.h b/scintilla/include/Scintilla.h
index 1d119370d..f1e01c710 100644
--- a/scintilla/include/Scintilla.h
+++ b/scintilla/include/Scintilla.h
@@ -106,8 +106,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_GETIMEINTERACTION 2678
#define SCI_SETIMEINTERACTION 2679
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
-#define SCI_ISIMEOPEN 2719
-#define SCI_ISIMEMODECJK 2720
+#define SCI_ISIMEOPEN 2722
+#define SCI_ISIMEMODECJK 2723
// <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
#define MARKER_MAX 31
#define SC_MARK_CIRCLE 0
@@ -273,6 +273,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_SETCARETPERIOD 2076
#define SCI_SETWORDCHARS 2077
#define SCI_GETWORDCHARS 2646
+#define SCI_SETCHARACTERCATEGORYOPTIMIZATION 2720
+#define SCI_GETCHARACTERCATEGORYOPTIMIZATION 2721
#define SCI_BEGINUNDOACTION 2078
#define SCI_ENDUNDOACTION 2079
#define INDIC_PLAIN 0
diff --git a/scintilla/include/Scintilla.iface b/scintilla/include/Scintilla.iface
index e19f3cfb2..9ffd4157c 100644
--- a/scintilla/include/Scintilla.iface
+++ b/scintilla/include/Scintilla.iface
@@ -267,8 +267,8 @@ get int GetIMEInteraction=2678(,)
set void SetIMEInteraction=2679(int imeInteraction,)
# >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>
-get bool IsIMEOpen=2719(,)
-get bool IsIMEModeCJK=2720(,)
+get bool IsIMEOpen=2722(,)
+get bool IsIMEModeCJK=2723(,)
# <<<<<<<<<<<<<<< END NON STD SCI PATCH <<<<<<<<<<<<<<<
enu MarkerSymbol=SC_MARK_
@@ -615,6 +615,12 @@ set void SetWordChars=2077(, string characters)
# Returns the number of characters
get int GetWordChars=2646(, stringresult characters)
+# Set the number of characters to have directly indexed categories
+set void SetCharacterCategoryOptimization=2720(int countCharacters,)
+
+# Get the number of characters to have directly indexed categories
+get int GetCharacterCategoryOptimization=2721(,)
+
# Start a sequence of actions that is undone and redone as a unit.
# May be nested.
fun void BeginUndoAction=2078(,)
diff --git a/scintilla/lexers/LexCIL.cxx b/scintilla/lexers/LexCIL.cxx
index 6d5307666..6f498315a 100644
--- a/scintilla/lexers/LexCIL.cxx
+++ b/scintilla/lexers/LexCIL.cxx
@@ -28,7 +28,6 @@
#include "Accessor.h"
#include "StyleContext.h"
#include "CharacterSet.h"
-#include "CharacterCategory.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
diff --git a/scintilla/lexers/LexCPP.cxx b/scintilla/lexers/LexCPP.cxx
index 49921fd8e..3b8bbfa16 100644
--- a/scintilla/lexers/LexCPP.cxx
+++ b/scintilla/lexers/LexCPP.cxx
@@ -245,12 +245,24 @@ struct PPDefinition {
}
};
+const int inactiveFlag = 0x40;
+
class LinePPState {
- int state;
- int ifTaken;
- int level;
+ // Track the state of preprocessor conditionals to allow showing active and inactive
+ // code in different styles.
+ // Only works up to 31 levels of conditional nesting.
+
+ // state is a bit mask with 1 bit per level
+ // bit is 1 for level if section inactive, so any bits set = inactive style
+ int state = 0;
+ // ifTaken is a bit mask with 1 bit per level
+ // bit is 1 for level if some branch at this level has been taken
+ int ifTaken = 0;
+ // level is the nesting level of #if constructs
+ int level = -1;
+ static const int maximumNestingLevel = 31;
bool ValidLevel() const noexcept {
- return level >= 0 && level < 32;
+ return level >= 0 && level < maximumNestingLevel;
}
int maskLevel() const noexcept {
if (level >= 0) {
@@ -260,11 +272,17 @@ class LinePPState {
}
}
public:
- LinePPState() noexcept : state(0), ifTaken(0), level(-1) {
+ LinePPState() noexcept {
+ }
+ bool IsActive() const noexcept {
+ return state == 0;
}
bool IsInactive() const noexcept {
return state != 0;
}
+ int ActiveState() const noexcept {
+ return state ? inactiveFlag : 0;
+ }
bool CurrentIfTaken() const noexcept {
return (ifTaken & maskLevel()) != 0;
}
@@ -521,7 +539,6 @@ class LexerCPP : public ILexer4 {
OptionSetCPP osCPP;
EscapeSequence escapeSeq;
SparseState rawStringTerminators;
- enum { activeFlag = 0x40 };
enum { ssIdentifier, ssDocKeyword };
SubStyles subStyles;
std::string returnBuffer;
@@ -534,7 +551,7 @@ public:
setMultOp(CharacterSet::setNone, "*/%"),
setRelOp(CharacterSet::setNone, "=!<>"),
setLogicalOp(CharacterSet::setNone, "|&"),
- subStyles(styleSubable, 0x80, 0x40, activeFlag) {
+ subStyles(styleSubable, 0x80, 0x40, inactiveFlag) {
}
// Deleted so LexerCPP objects can not be copied.
LexerCPP(const LexerCPP &) = delete;
@@ -585,8 +602,8 @@ public:
}
int SCI_METHOD StyleFromSubStyle(int subStyle) override {
const int styleBase = subStyles.BaseStyle(MaskActive(subStyle));
- const int active = subStyle & activeFlag;
- return styleBase | active;
+ const int inactive = subStyle & inactiveFlag;
+ return styleBase | inactive;
}
int SCI_METHOD PrimaryStyleFromStyle(int style) noexcept override {
return MaskActive(style);
@@ -598,7 +615,7 @@ public:
subStyles.SetIdentifiers(style, identifiers);
}
int SCI_METHOD DistanceToSecondaryStyles() noexcept override {
- return activeFlag;
+ return inactiveFlag;
}
const char * SCI_METHOD GetSubStyleBases() noexcept override {
return styleSubable;
@@ -606,7 +623,7 @@ public:
int SCI_METHOD NamedStyles() override {
return std::max(subStyles.LastAllocated() + 1,
sizeLexicalClasses) +
- activeFlag;
+ inactiveFlag;
}
const char * SCI_METHOD NameOfStyle(int style) override {
if (style >= NamedStyles())
@@ -624,11 +641,11 @@ public:
if (firstSubStyle >= 0) {
const int lastSubStyle = subStyles.LastAllocated();
if (((style >= firstSubStyle) && (style <= (lastSubStyle))) ||
- ((style >= firstSubStyle + activeFlag) && (style <= (lastSubStyle + activeFlag)))) {
+ ((style >= firstSubStyle + inactiveFlag) && (style <= (lastSubStyle + inactiveFlag)))) {
int styleActive = style;
if (style > lastSubStyle) {
returnBuffer = "inactive ";
- styleActive -= activeFlag;
+ styleActive -= inactiveFlag;
}
const int styleMain = StyleFromSubStyle(styleActive);
returnBuffer += lexicalClasses[styleMain].tags;
@@ -637,9 +654,9 @@ public:
}
if (style < sizeLexicalClasses)
return lexicalClasses[style].tags;
- if (style >= activeFlag) {
+ if (style >= inactiveFlag) {
returnBuffer = "inactive ";
- const int styleActive = style - activeFlag;
+ const int styleActive = style - inactiveFlag;
if (styleActive < sizeLexicalClasses)
returnBuffer += lexicalClasses[styleActive].tags;
else
@@ -664,7 +681,7 @@ public:
return new LexerCPP(false);
}
constexpr static int MaskActive(int style) noexcept {
- return style & ~activeFlag;
+ return style & ~inactiveFlag;
}
void EvaluateTokens(std::vector &tokens, const SymbolTable &preprocessorDefinitions);
std::vector Tokenize(const std::string &expr) const;
@@ -822,7 +839,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1);
SparseState rawSTNew(lineCurrent);
- int activitySet = preproc.IsInactive() ? activeFlag : 0;
+ int activitySet = preproc.ActiveState();
const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_C_IDENTIFIER);
const WordClassifier &classifierDocKeyWords = subStyles.Classifier(SCE_C_COMMENTDOCKEYWORD);
@@ -849,7 +866,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
isIncludePreprocessor = false;
inRERange = false;
if (preproc.IsInactive()) {
- activitySet = activeFlag;
+ activitySet = inactiveFlag;
sc.SetState(sc.state | activitySet);
}
}
@@ -1274,6 +1291,8 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
isIncludePreprocessor = true;
} else {
if (options.trackPreprocessor) {
+ // If #if is nested too deeply (>31 levels) the active/inactive appearance
+ // will stop reflecting the code.
if (sc.Match("ifdef") || sc.Match("ifndef")) {
const bool isIfDef = sc.Match("ifdef");
const int startRest = isIfDef ? 5 : 6;
@@ -1285,41 +1304,52 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
const bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions);
preproc.StartSection(ifGood);
} else if (sc.Match("else")) {
+ // #else is shown as active if either preceding or following section is active
+ // as that means that it contributed to the result.
if (!preproc.CurrentIfTaken()) {
+ // Inactive, may become active if parent scope active
+ assert(sc.state == (SCE_C_PREPROCESSOR|inactiveFlag));
preproc.InvertCurrentLevel();
- activitySet = preproc.IsInactive() ? activeFlag : 0;
+ activitySet = preproc.ActiveState();
+ // If following is active then show "else" as active
if (!activitySet)
- sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
- } else if (!preproc.IsInactive()) {
+ sc.ChangeState(SCE_C_PREPROCESSOR);
+ } else if (preproc.IsActive()) {
+ // Active -> inactive
+ assert(sc.state == SCE_C_PREPROCESSOR);
preproc.InvertCurrentLevel();
- activitySet = preproc.IsInactive() ? activeFlag : 0;
- if (!activitySet)
- sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
+ activitySet = preproc.ActiveState();
+ // Continue to show "else" as active as it ends active section.
}
} else if (sc.Match("elif")) {
// Ensure only one chosen out of #if .. #elif .. #elif .. #else .. #endif
+ // #elif is shown as active if either preceding or following section is active
+ // as that means that it contributed to the result.
if (!preproc.CurrentIfTaken()) {
+ // Inactive, if expression true then may become active if parent scope active
+ assert(sc.state == (SCE_C_PREPROCESSOR|inactiveFlag));
// Similar to #if
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 4, true);
const bool ifGood = EvaluateExpression(restOfLine, preprocessorDefinitions);
if (ifGood) {
preproc.InvertCurrentLevel();
- activitySet = preproc.IsInactive() ? activeFlag : 0;
+ activitySet = preproc.ActiveState();
if (!activitySet)
- sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
+ sc.ChangeState(SCE_C_PREPROCESSOR);
}
- } else if (!preproc.IsInactive()) {
+ } else if (preproc.IsActive()) {
+ // Active -> inactive
+ assert(sc.state == SCE_C_PREPROCESSOR);
preproc.InvertCurrentLevel();
- activitySet = preproc.IsInactive() ? activeFlag : 0;
- if (!activitySet)
- sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
+ activitySet = preproc.ActiveState();
+ // Continue to show "elif" as active as it ends active section.
}
} else if (sc.Match("endif")) {
preproc.EndSection();
- activitySet = preproc.IsInactive() ? activeFlag : 0;
+ activitySet = preproc.ActiveState();
sc.ChangeState(SCE_C_PREPROCESSOR|activitySet);
} else if (sc.Match("define")) {
- if (options.updatePreprocessor && !preproc.IsInactive()) {
+ if (options.updatePreprocessor && preproc.IsActive()) {
std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true);
size_t startName = 0;
while ((startName < restOfLine.length()) && IsSpaceOrTab(restOfLine[startName]))
@@ -1357,7 +1387,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
}
}
} else if (sc.Match("undef")) {
- if (options.updatePreprocessor && !preproc.IsInactive()) {
+ if (options.updatePreprocessor && preproc.IsActive()) {
const std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, false);
std::vector tokens = Tokenize(restOfLine);
if (tokens.size() >= 1) {
diff --git a/scintilla/lexers/LexHaskell.cxx b/scintilla/lexers/LexHaskell.cxx
index ee8c87e39..8ed53d772 100644
--- a/scintilla/lexers/LexHaskell.cxx
+++ b/scintilla/lexers/LexHaskell.cxx
@@ -26,6 +26,7 @@
#include
#include
+#include
#include