[geany/geany] 6d109b: Update to Scintilla 5.1.3 and Lexilla 5.1.2

Thomas Martitz git-noreply at xxxxx
Mon Nov 15 06:46:40 UTC 2021


Branch:      refs/heads/master
Author:      Thomas Martitz <thomas.martitz at mailbox.org>
Committer:   Thomas Martitz <thomas.martitz at mailbox.org>
Date:        Mon, 15 Nov 2021 06:46:40 UTC
Commit:      6d109b309165ff0bfb17a2b21056bd498d54c032
             https://github.com/geany/geany/commit/6d109b309165ff0bfb17a2b21056bd498d54c032

Log Message:
-----------
Update to Scintilla 5.1.3 and Lexilla 5.1.2

Notable changes:
Scintilla:
- Add SC_ELEMENT_FOLD_LINE to set the colour of fold lines. Add SC_ELEMENT_HIDDEN_LINE to show where lines are hidden.
- On GTK, fix the line spacing so that underscores and accents are visible for some fonts such as DejaVu Sans Mono 10.

Lexilla
- Implement conditional group rules in CSS. Issue #25, Pull request #28.
- Check PHP numeric literals, showing invalid values with default style instead of numeric. Issue #20.

The CSS change causes compatiblity trouble. We exposed the changed
style in filetypes.css. Users must update local copies.


Modified Paths:
--------------
    data/filedefs/filetypes.css
    scintilla/gtk/PlatGTK.cxx
    scintilla/gtk/ScintillaGTK.cxx
    scintilla/gtk/ScintillaGTK.h
    scintilla/gtk/ScintillaGTKAccessible.cxx
    scintilla/include/Scintilla.h
    scintilla/include/Scintilla.iface
    scintilla/include/ScintillaCall.h
    scintilla/include/ScintillaMessages.h
    scintilla/include/ScintillaTypes.h
    scintilla/lexilla/include/SciLexer.h
    scintilla/lexilla/lexers/LexCSS.cxx
    scintilla/lexilla/lexers/LexHTML.cxx
    scintilla/lexilla/lexers/LexMarkdown.cxx
    scintilla/lexilla/lexlib/WordList.cxx
    scintilla/lexilla/lexlib/WordList.h
    scintilla/lexilla/version.txt
    scintilla/src/AutoComplete.cxx
    scintilla/src/AutoComplete.h
    scintilla/src/CallTip.cxx
    scintilla/src/CallTip.h
    scintilla/src/CaseConvert.cxx
    scintilla/src/CaseFolder.cxx
    scintilla/src/CaseFolder.h
    scintilla/src/CellBuffer.cxx
    scintilla/src/ContractionState.cxx
    scintilla/src/Decoration.cxx
    scintilla/src/Document.cxx
    scintilla/src/Document.h
    scintilla/src/EditModel.cxx
    scintilla/src/EditModel.h
    scintilla/src/EditView.cxx
    scintilla/src/Editor.cxx
    scintilla/src/Editor.h
    scintilla/src/Geometry.cxx
    scintilla/src/Geometry.h
    scintilla/src/Indicator.cxx
    scintilla/src/KeyMap.cxx
    scintilla/src/KeyMap.h
    scintilla/src/LineMarker.cxx
    scintilla/src/MarginView.cxx
    scintilla/src/MarginView.h
    scintilla/src/PositionCache.cxx
    scintilla/src/PositionCache.h
    scintilla/src/RESearch.cxx
    scintilla/src/RESearch.h
    scintilla/src/ScintillaBase.cxx
    scintilla/src/Selection.cxx
    scintilla/src/Selection.h
    scintilla/src/Style.cxx
    scintilla/src/Style.h
    scintilla/src/UniConversion.h
    scintilla/src/UniqueString.cxx
    scintilla/src/UniqueString.h
    scintilla/src/ViewStyle.cxx
    scintilla/src/ViewStyle.h
    scintilla/version.txt
    src/highlightingmappings.h

Modified: data/filedefs/filetypes.css
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -24,7 +24,7 @@ pseudoelement=string_2
 extended_identifier=keyword_1
 extended_pseudoclass=string_1
 extended_pseudoelement=string_2
-media=parameter
+group_rule=parameter
 
 [keywords]
 # CSS 1 properties


Modified: scintilla/gtk/PlatGTK.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -1073,7 +1073,7 @@ XYPOSITION SurfaceImpl::Ascent(const Font *font_) {
 	if (PFont(font_)->pfd) {
 		PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
 					    PFont(font_)->pfd, pango_context_get_language(pcontext));
-		ascent = std::round(floatFromPangoUnits(
+		ascent = std::ceil(floatFromPangoUnits(
 					    pango_font_metrics_get_ascent(metrics)));
 		pango_font_metrics_unref(metrics);
 	}
@@ -1087,7 +1087,7 @@ XYPOSITION SurfaceImpl::Descent(const Font *font_) {
 	if (PFont(font_)->pfd) {
 		PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
 					    PFont(font_)->pfd, pango_context_get_language(pcontext));
-		const XYPOSITION descent = std::round(floatFromPangoUnits(
+		const XYPOSITION descent = std::ceil(floatFromPangoUnits(
 				pango_font_metrics_get_descent(metrics)));
 		pango_font_metrics_unref(metrics);
 		return descent;


Modified: scintilla/gtk/ScintillaGTK.cxx
50 lines changed, 38 insertions(+), 12 deletions(-)
===================================================================
@@ -5,6 +5,7 @@
 
 #include <cstddef>
 #include <cstdlib>
+#include <cstdint>
 #include <cassert>
 #include <cstring>
 #include <cstdio>
@@ -179,6 +180,18 @@ GdkAtom SelectionOfGSD(GtkSelectionData *sd) noexcept {
 	return gtk_selection_data_get_selection(sd);
 }
 
+bool SettingGet(GtkSettings *settings, const gchar *name, gpointer value) noexcept {
+	if (!settings) {
+		return false;
+	}
+	if (!g_object_class_find_property(G_OBJECT_GET_CLASS(
+		G_OBJECT(settings)), name)) {
+		return false;
+	}
+	g_object_get(G_OBJECT(settings), name, value, nullptr);
+	return true;
+}
+
 }
 
 FontOptions::FontOptions(GtkWidget *widget) noexcept {
@@ -218,6 +231,8 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
 	preeditInitialized(false),
 	im_context(nullptr),
 	lastNonCommonScript(G_UNICODE_SCRIPT_INVALID_CODE),
+	settings(nullptr),
+	settingsHandlerId(0),
 	lastWheelMouseTime(0),
 	lastWheelMouseDirection(0),
 	wheelMouseIntensity(0),
@@ -264,6 +279,12 @@ ScintillaGTK::~ScintillaGTK() {
 	}
 	ClearPrimarySelection();
 	wPreedit.Destroy();
+	if (settingsHandlerId) {
+		g_signal_handler_disconnect(settings, settingsHandlerId);
+	}
+	if (settings) {
+		g_object_unref(settings);
+	}
 }
 
 void ScintillaGTK::RealizeThis(GtkWidget *widget) {
@@ -341,6 +362,15 @@ void ScintillaGTK::RealizeThis(GtkWidget *widget) {
 	cursor = gdk_cursor_new_for_display(pdisplay, GDK_LEFT_PTR);
 	gdk_window_set_cursor(PWindow(scrollbarh), cursor);
 	UnRefCursor(cursor);
+
+	using NotifyLambda = void (*)(GObject *, GParamSpec *, ScintillaGTK *);
+	if (settings) {
+		settingsHandlerId = g_signal_connect(settings, "notify::gtk-xft-dpi",
+			G_CALLBACK(static_cast<NotifyLambda>([](GObject *, GParamSpec *, ScintillaGTK *sciThis) {
+				sciThis->InvalidateStyleRedraw();
+			})),
+			this);
+	}
 }
 
 void ScintillaGTK::Realize(GtkWidget *widget) {
@@ -669,20 +699,16 @@ void ScintillaGTK::Init() {
 	gtk_container_add(GTK_CONTAINER(PWidget(wPreedit)), predrw);
 	gtk_widget_show(predrw);
 
+	settings = gtk_settings_get_default();
+
 	// Set caret period based on GTK settings
 	gboolean blinkOn = false;
-	if (g_object_class_find_property(G_OBJECT_GET_CLASS(
-			G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink")) {
-		g_object_get(G_OBJECT(
-				     gtk_settings_get_default()), "gtk-cursor-blink", &blinkOn, nullptr);
-	}
-	if (blinkOn &&
-			g_object_class_find_property(G_OBJECT_GET_CLASS(
-						G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink-time")) {
-		gint value;
-		g_object_get(G_OBJECT(
-				     gtk_settings_get_default()), "gtk-cursor-blink-time", &value, nullptr);
-		caret.period = static_cast<int>(value / 1.75);
+	SettingGet(settings, "gtk-cursor-blink", &blinkOn);
+	if (blinkOn) {
+		gint value = 500;
+		if (SettingGet(settings, "gtk-cursor-blink-time", &value)) {
+			caret.period = static_cast<int>(value / 1.75);
+		}
 	} else {
 		caret.period = 0;
 	}


Modified: scintilla/gtk/ScintillaGTK.h
3 lines changed, 3 insertions(+), 0 deletions(-)
===================================================================
@@ -62,6 +62,9 @@ class ScintillaGTK : public ScintillaBase {
 	GtkIMContext *im_context;
 	GUnicodeScript lastNonCommonScript;
 
+	GtkSettings *settings;
+	gulong settingsHandlerId;
+
 	// Wheel mouse support
 	unsigned int linesPerScroll;
 	gint64 lastWheelMouseTime;


Modified: scintilla/gtk/ScintillaGTKAccessible.cxx
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -53,6 +53,7 @@
 
 #include <cstddef>
 #include <cstdlib>
+#include <cstdint>
 #include <cassert>
 #include <cstring>
 


Modified: scintilla/include/Scintilla.h
6 lines changed, 6 insertions(+), 0 deletions(-)
===================================================================
@@ -272,6 +272,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
 #define SCI_STYLEGETWEIGHT 2064
 #define SCI_STYLESETCHARACTERSET 2066
 #define SCI_STYLESETHOTSPOT 2409
+#define SCI_STYLESETCHECKMONOSPACED 2254
+#define SCI_STYLEGETCHECKMONOSPACED 2255
 #define SC_ELEMENT_LIST 0
 #define SC_ELEMENT_LIST_BACK 1
 #define SC_ELEMENT_LIST_SELECTED 2
@@ -291,6 +293,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
 #define SC_ELEMENT_WHITE_SPACE_BACK 61
 #define SC_ELEMENT_HOT_SPOT_ACTIVE 70
 #define SC_ELEMENT_HOT_SPOT_ACTIVE_BACK 71
+#define SC_ELEMENT_FOLD_LINE 80
+#define SC_ELEMENT_HIDDEN_LINE 81
 #define SCI_SETELEMENTCOLOUR 2753
 #define SCI_GETELEMENTCOLOUR 2754
 #define SCI_RESETELEMENTCOLOUR 2755
@@ -310,6 +314,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
 #define SCI_SETSELECTIONLAYER 2763
 #define SCI_GETCARETLINELAYER 2764
 #define SCI_SETCARETLINELAYER 2765
+#define SCI_GETCARETLINEHIGHLIGHTSUBLINE 2773
+#define SCI_SETCARETLINEHIGHLIGHTSUBLINE 2774
 #define SCI_SETCARETFORE 2069
 #define SCI_ASSIGNCMDKEY 2070
 #define SCI_CLEARCMDKEY 2071


Modified: scintilla/include/Scintilla.iface
14 lines changed, 14 insertions(+), 0 deletions(-)
===================================================================
@@ -677,6 +677,12 @@ set void StyleSetCharacterSet=2066(int style, CharacterSet characterSet)
 # Set a style to be a hotspot or not.
 set void StyleSetHotSpot=2409(int style, bool hotspot)
 
+# Indicate that a style may be monospaced over ASCII graphics characters which enables optimizations.
+set void StyleSetCheckMonospaced=2254(int style, bool checkMonospaced)
+
+# Get whether a style may be monospaced.
+get bool StyleGetCheckMonospaced=2255(int style,)
+
 enu Element=SC_ELEMENT_
 val SC_ELEMENT_LIST=0
 val SC_ELEMENT_LIST_BACK=1
@@ -697,6 +703,8 @@ val SC_ELEMENT_WHITE_SPACE=60
 val SC_ELEMENT_WHITE_SPACE_BACK=61
 val SC_ELEMENT_HOT_SPOT_ACTIVE=70
 val SC_ELEMENT_HOT_SPOT_ACTIVE_BACK=71
+val SC_ELEMENT_FOLD_LINE=80
+val SC_ELEMENT_HIDDEN_LINE=81
 
 # Set the colour of an element. Translucency (alpha) may or may not be significant
 # and this may depend on the platform. The alpha byte should commonly be 0xff for opaque.
@@ -753,6 +761,12 @@ get Layer GetCaretLineLayer=2764(,)
 # Set the layer of the background of the line containing the caret.
 set void SetCaretLineLayer=2765(Layer layer,)
 
+# Get only highlighting subline instead of whole line.
+get bool GetCaretLineHighlightSubLine=2773(,)
+
+# Set only highlighting subline instead of whole line.
+set void SetCaretLineHighlightSubLine=2774(bool subLine,)
+
 # Set the foreground colour of the caret.
 set void SetCaretFore=2069(colour fore,)
 


Modified: scintilla/include/ScintillaCall.h
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -196,6 +196,8 @@ class ScintillaCall {
 	Scintilla::FontWeight StyleGetWeight(int style);
 	void StyleSetCharacterSet(int style, Scintilla::CharacterSet characterSet);
 	void StyleSetHotSpot(int style, bool hotspot);
+	void StyleSetCheckMonospaced(int style, bool checkMonospaced);
+	bool StyleGetCheckMonospaced(int style);
 	void SetElementColour(Scintilla::Element element, ColourAlpha colourElement);
 	ColourAlpha ElementColour(Scintilla::Element element);
 	void ResetElementColour(Scintilla::Element element);
@@ -212,6 +214,8 @@ class ScintillaCall {
 	void SetSelectionLayer(Scintilla::Layer layer);
 	Scintilla::Layer CaretLineLayer();
 	void SetCaretLineLayer(Scintilla::Layer layer);
+	bool CaretLineHighlightSubLine();
+	void SetCaretLineHighlightSubLine(bool subLine);
 	void SetCaretFore(Colour fore);
 	void AssignCmdKey(int keyDefinition, int sciCommand);
 	void ClearCmdKey(int keyDefinition);


Modified: scintilla/include/ScintillaMessages.h
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -133,6 +133,8 @@ enum class Message {
 	StyleGetWeight = 2064,
 	StyleSetCharacterSet = 2066,
 	StyleSetHotSpot = 2409,
+	StyleSetCheckMonospaced = 2254,
+	StyleGetCheckMonospaced = 2255,
 	SetElementColour = 2753,
 	GetElementColour = 2754,
 	ResetElementColour = 2755,
@@ -149,6 +151,8 @@ enum class Message {
 	SetSelectionLayer = 2763,
 	GetCaretLineLayer = 2764,
 	SetCaretLineLayer = 2765,
+	GetCaretLineHighlightSubLine = 2773,
+	SetCaretLineHighlightSubLine = 2774,
 	SetCaretFore = 2069,
 	AssignCmdKey = 2070,
 	ClearCmdKey = 2071,


Modified: scintilla/include/ScintillaTypes.h
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -180,6 +180,8 @@ enum class Element {
 	WhiteSpaceBack = 61,
 	HotSpotActive = 70,
 	HotSpotActiveBack = 71,
+	FoldLine = 80,
+	HiddenLine = 81,
 };
 
 enum class Layer {


Modified: scintilla/lexilla/include/SciLexer.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -765,7 +765,7 @@
 #define SCE_CSS_EXTENDED_IDENTIFIER 19
 #define SCE_CSS_EXTENDED_PSEUDOCLASS 20
 #define SCE_CSS_EXTENDED_PSEUDOELEMENT 21
-#define SCE_CSS_MEDIA 22
+#define SCE_CSS_GROUP_RULE 22
 #define SCE_CSS_VARIABLE 23
 #define SCE_POV_DEFAULT 0
 #define SCE_POV_COMMENT 1


Modified: scintilla/lexilla/lexers/LexCSS.cxx
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -209,7 +209,7 @@ static void ColouriseCssDoc(Sci_PositionU startPos, Sci_Position length, int ini
 			case '{':
 				nestingLevel++;
 				switch (lastState) {
-				case SCE_CSS_MEDIA:
+				case SCE_CSS_GROUP_RULE:
 					sc.SetState(SCE_CSS_DEFAULT);
 					break;
 				case SCE_CSS_TAG:
@@ -458,8 +458,8 @@ static void ColouriseCssDoc(Sci_PositionU startPos, Sci_Position length, int ini
 					sc.ChangeState(SCE_CSS_VALUE);
 				break;
 			case SCE_CSS_DIRECTIVE:
-				if (op == '@' && strcmp(s2, "media") == 0)
-					sc.ChangeState(SCE_CSS_MEDIA);
+				if (op == '@' && (strcmp(s2, "media") == 0 || strcmp(s2, "supports") == 0 || strcmp(s2, "document") == 0 || strcmp(s2, "-moz-document") == 0))
+					sc.ChangeState(SCE_CSS_GROUP_RULE);
 				break;
 			}
 		}
@@ -492,7 +492,7 @@ static void ColouriseCssDoc(Sci_PositionU startPos, Sci_Position length, int ini
 		} else if (IsCssOperator(sc.ch)
 			&& (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']')
 			&& (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!')
-			&& ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_MEDIA) || sc.ch == ';' || sc.ch == '{')
+			&& ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_GROUP_RULE) || sc.ch == ';' || sc.ch == '{')
 		) {
 			if (sc.state != SCE_CSS_OPERATOR)
 				lastState = sc.state;


Modified: scintilla/lexilla/lexers/LexHTML.cxx
140 lines changed, 127 insertions(+), 13 deletions(-)
===================================================================
@@ -524,6 +524,119 @@ bool isDjangoBlockEnd(const int ch, const int chNext, const std::string &blockTy
 	}
 }
 
+class PhpNumberState {
+	enum NumberBase { BASE_10 = 0, BASE_2, BASE_8, BASE_16 };
+	static constexpr const char *const digitList[] = { "_0123456789", "_01", "_01234567", "_0123456789abcdefABCDEF" };
+
+	NumberBase base = BASE_10;
+	bool decimalPart = false;
+	bool exponentPart = false;
+	bool invalid = false;
+	bool finished = false;
+
+	bool leadingZero = false;
+	bool invalidBase8 = false;
+
+	bool betweenDigits = false;
+	bool decimalChar = false;
+	bool exponentChar = false;
+
+public:
+	inline bool isInvalid() { return invalid; }
+	inline bool isFinished() { return finished; }
+
+	bool init(int ch, int chPlus1, int chPlus2) {
+		base = BASE_10;
+		decimalPart = false;
+		exponentPart = false;
+		invalid = false;
+		finished = false;
+
+		leadingZero = false;
+		invalidBase8 = false;
+
+		betweenDigits = false;
+		decimalChar = false;
+		exponentChar = false;
+
+		if (ch == '.' && strchr(digitList[BASE_10] + !betweenDigits, chPlus1) != nullptr) {
+			decimalPart = true;
+			betweenDigits = true;
+		} else if (ch == '0' && (chPlus1 == 'b' || chPlus1 == 'B')) {
+			base = BASE_2;
+		} else if (ch == '0' && (chPlus1 == 'o' || chPlus1 == 'O')) {
+			base = BASE_8;
+		} else if (ch == '0' && (chPlus1 == 'x' || chPlus1 == 'X')) {
+			base = BASE_16;
+		} else if (strchr(digitList[BASE_10] + !betweenDigits, ch) != nullptr) {
+			leadingZero = ch == '0';
+			betweenDigits = true;
+			check(chPlus1, chPlus2);
+			if (finished && leadingZero) {
+				// single zero should be base 10
+				base = BASE_10;
+			}
+		} else {
+			return false;
+		}
+		return true;
+	}
+
+	bool check(int ch, int chPlus1) {
+		if (strchr(digitList[base] + !betweenDigits, ch) != nullptr) {
+			if (leadingZero) {
+				invalidBase8 = invalidBase8 || strchr(digitList[BASE_8] + !betweenDigits, ch) == nullptr;
+			}
+
+			betweenDigits = ch != '_';
+			decimalChar = false;
+			exponentChar = false;
+		} else if (ch == '_') {
+			invalid = true;
+
+			betweenDigits = false;
+			decimalChar = false;
+			// exponentChar is unchanged
+		} else if (base == BASE_10 && ch == '.' && (
+					!(decimalPart || exponentPart) || strchr(digitList[BASE_10] + !betweenDigits, chPlus1) != nullptr)
+			  ) {
+			invalid = invalid || !betweenDigits || decimalPart || exponentPart;
+			decimalPart = true;
+
+			betweenDigits = false;
+			decimalChar = true;
+			exponentChar = false;
+		} else if (base == BASE_10 && (ch == 'e' || ch == 'E')) {
+			invalid = invalid || !(betweenDigits || decimalChar) || exponentPart;
+			exponentPart = true;
+
+			betweenDigits = false;
+			decimalChar = false;
+			exponentChar = true;
+		} else if (base == BASE_10 && (ch == '-' || ch == '+') && exponentChar) {
+			invalid = invalid || strchr(digitList[BASE_10] + !betweenDigits, chPlus1) == nullptr;
+
+			betweenDigits = false;
+			decimalChar = false;
+			// exponentChar is unchanged
+		} else if (IsPhpWordChar(ch)) {
+			invalid = true;
+
+			betweenDigits = false;
+			decimalChar = false;
+			exponentChar = false;
+		} else {
+			invalid = invalid || !(betweenDigits || decimalChar);
+			finished = true;
+			if (base == BASE_10 && leadingZero && !decimalPart && !exponentPart) {
+				base = BASE_8;
+				invalid = invalid || invalidBase8;
+			}
+		}
+		return finished;
+	}
+};
+
 bool isPHPStringState(int state) {
 	return
 	    (state == SCE_HPHP_HSTRING) ||
@@ -960,6 +1073,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
 	}
 	styler.StartAt(startPos);
 	std::string prevWord;
+	PhpNumberState phpNumber;
 	std::string phpStringDelimiter;
 	int StateToPrint = initStyle;
 	int state = stateForPrintState(StateToPrint);
@@ -1254,7 +1368,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
 		/////////////////////////////////////
 		// handle the start of PHP pre-processor = Non-HTML
 		else if ((state != SCE_H_ASPAT) &&
-		         !isStringState(state) &&
+		         !isPHPStringState(state) &&
 		         (state != SCE_HPHP_COMMENT) &&
 		         (state != SCE_HPHP_COMMENTLINE) &&
 		         (ch == '<') &&
@@ -1430,6 +1544,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
 				 (chPrev == '<') &&
 				 (ch == '!') &&
 				 (StateToPrint != SCE_H_CDATA) &&
+				 (!isStringState(StateToPrint)) &&
 				 (!IsCommentState(StateToPrint)) &&
 				 (!IsScriptCommentState(StateToPrint))) {
 			beforePreProc = state;
@@ -2273,7 +2388,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
 			break;
 			///////////// start - PHP state handling
 		case SCE_HPHP_WORD:
-			if (!IsAWordChar(ch)) {
+			if (!IsPhpWordChar(ch)) {
 				classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);
 				if (ch == '/' && chNext == '*') {
 					i++;
@@ -2306,15 +2421,9 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
 			}
 			break;
 		case SCE_HPHP_NUMBER:
-			// recognize bases 8,10 or 16 integers OR floating-point numbers
-			if (!IsADigit(ch)
-				&& strchr(".xXabcdefABCDEF_", ch) == NULL
-				&& ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) {
-				styler.ColourTo(i - 1, SCE_HPHP_NUMBER);
-				if (IsOperator(ch))
-					state = SCE_HPHP_OPERATOR;
-				else
-					state = SCE_HPHP_DEFAULT;
+			if (phpNumber.check(chNext, chNext2)) {
+				styler.ColourTo(i, phpNumber.isInvalid() ? SCE_HPHP_DEFAULT : SCE_HPHP_NUMBER);
+				state = SCE_HPHP_DEFAULT;
 			}
 			break;
 		case SCE_HPHP_VARIABLE:
@@ -2395,8 +2504,13 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
 		case SCE_HPHP_OPERATOR:
 		case SCE_HPHP_DEFAULT:
 			styler.ColourTo(i - 1, StateToPrint);
-			if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) {
-				state = SCE_HPHP_NUMBER;
+			if (phpNumber.init(ch, chNext, chNext2)) {
+				if (phpNumber.isFinished()) {
+					styler.ColourTo(i, phpNumber.isInvalid() ? SCE_HPHP_DEFAULT : SCE_HPHP_NUMBER);
+					state = SCE_HPHP_DEFAULT;
+				} else {
+					state = SCE_HPHP_NUMBER;
+				}
 			} else if (IsAWordStart(ch)) {
 				state = SCE_HPHP_WORD;
 			} else if (ch == '/' && chNext == '*') {


Modified: scintilla/lexilla/lexers/LexMarkdown.cxx
9 lines changed, 7 insertions(+), 2 deletions(-)
===================================================================
@@ -56,8 +56,13 @@
 
 using namespace Lexilla;
 
-static inline bool IsNewline(const int ch) {
-    return (ch == '\n' || ch == '\r');
+namespace {
+
+constexpr bool IsNewline(const int ch) {
+    // sc.GetRelative(i) returns '\0' if out of range
+    return (ch == '\n' || ch == '\r' || ch == '\0');
+}
+
 }
 
 // True if can follow ch down to the end with possibly trailing whitespace


Modified: scintilla/lexilla/lexlib/WordList.cxx
85 lines changed, 34 insertions(+), 51 deletions(-)
===================================================================
@@ -11,18 +11,20 @@
 
 #include <algorithm>
 #include <iterator>
+#include <memory>
 
 #include "WordList.h"
 
 using namespace Lexilla;
 
+namespace {
+
 /**
  * Creates an array that points into each word in the string and puts \0 terminators
  * after each word.
  */
-static char **ArrayFromWordList(char *wordlist, size_t slen, int *len, bool onlyLineEnds = false) {
-	int prev = '\n';
-	int words = 0;
+std::unique_ptr<char *[]> ArrayFromWordList(char *wordlist, size_t slen, size_t *len, bool onlyLineEnds = false) {
+	size_t words = 0;
 	// For rapid determination of whether a character is a separator, build
 	// a look up table.
 	bool wordSeparator[256] = {};	// Initialise all to false.
@@ -32,26 +34,27 @@ static char **ArrayFromWordList(char *wordlist, size_t slen, int *len, bool only
 		wordSeparator[static_cast<unsigned int>(' ')] = true;
 		wordSeparator[static_cast<unsigned int>('\t')] = true;
 	}
+	unsigned char prev = '\n';
 	for (int j = 0; wordlist[j]; j++) {
-		const int curr = static_cast<unsigned char>(wordlist[j]);
+		const unsigned char curr = wordlist[j];
 		if (!wordSeparator[curr] && wordSeparator[prev])
 			words++;
 		prev = curr;
 	}
-	char **keywords = new char *[words + 1];
-	int wordsStore = 0;
+	std::unique_ptr<char *[]> keywords = std::make_unique<char *[]>(words + 1);
+	size_t wordsStore = 0;
 	if (words) {
-		prev = '\0';
+		unsigned char previous = '\0';
 		for (size_t k = 0; k < slen; k++) {
 			if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
-				if (!prev) {
+				if (!previous) {
 					keywords[wordsStore] = &wordlist[k];
 					wordsStore++;
 				}
 			} else {
 				wordlist[k] = '\0';
 			}
-			prev = wordlist[k];
+			previous = wordlist[k];
 		}
 	}
 	assert(wordsStore < (words + 1));
@@ -60,8 +63,14 @@ static char **ArrayFromWordList(char *wordlist, size_t slen, int *len, bool only
 	return keywords;
 }
 
-WordList::WordList(bool onlyLineEnds_) :
-	words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) {
+bool cmpWords(const char *a, const char *b) noexcept {
+	return strcmp(a, b) < 0;
+}
+
+}
+
+WordList::WordList(bool onlyLineEnds_) noexcept :
+	words(nullptr), list(nullptr), len(0), onlyLineEnds(onlyLineEnds_) {
 	// Prevent warnings by static analyzers about uninitialized starts.
 	starts[0] = -1;
 }
@@ -77,78 +86,52 @@ WordList::operator bool() const noexcept {
 bool WordList::operator!=(const WordList &other) const noexcept {
 	if (len != other.len)
 		return true;
-	for (int i=0; i<len; i++) {
+	for (size_t i=0; i<len; i++) {
 		if (strcmp(words[i], other.words[i]) != 0)
 			return true;
 	}
 	return false;
 }
 
 int WordList::Length() const noexcept {
-	return len;
+	return static_cast<int>(len);
 }
 
 void WordList::Clear() noexcept {
-	if (words) {
-		delete []list;
-		delete []words;
-	}
-	words = nullptr;
+	delete []list;
 	list = nullptr;
+	delete []words;
+	words = nullptr;
 	len = 0;
 }
 
-#ifdef _MSC_VER
-
-static bool cmpWords(const char *a, const char *b) {
-	return strcmp(a, b) < 0;
-}
-
-#else
-
-static int cmpWords(const void *a, const void *b) {
-	return strcmp(*static_cast<const char * const *>(a), *static_cast<const char * const *>(b));
-}
-
-static void SortWordList(char **words, unsigned int len) {
-	qsort(words, len, sizeof(*words), cmpWords);
-}
-
-#endif
-
 bool WordList::Set(const char *s) {
 	const size_t lenS = strlen(s) + 1;
-	char *listTemp = new char[lenS];
-	memcpy(listTemp, s, lenS);
-	int lenTemp = 0;
-	char **wordsTemp = ArrayFromWordList(listTemp, lenS - 1, &lenTemp, onlyLineEnds);
-#ifdef _MSC_VER
-	std::sort(wordsTemp, wordsTemp + lenTemp, cmpWords);
-#else
-	SortWordList(wordsTemp, lenTemp);
-#endif
+	std::unique_ptr<char[]> listTemp = std::make_unique<char[]>(lenS);
+	memcpy(listTemp.get(), s, lenS);
+	size_t lenTemp = 0;
+	std::unique_ptr<char *[]> wordsTemp = ArrayFromWordList(listTemp.get(), lenS - 1, &lenTemp, onlyLineEnds);
+	std::sort(wordsTemp.get(), wordsTemp.get() + lenTemp, cmpWords);
 
 	if (lenTemp == len) {
 		bool changed = false;
-		for (int i = 0; i < lenTemp; i++) {
+		for (size_t i = 0; i < lenTemp; i++) {
 			if (strcmp(words[i], wordsTemp[i]) != 0) {
 				changed = true;
 				break;
 			}
 		}
 		if (!changed) {
-			delete []listTemp;
-			delete []wordsTemp;
 			return false;
 		}
 	}
 
 	Clear();
-	words = wordsTemp;
-	list = listTemp;
+	words = wordsTemp.release();
+	list = listTemp.release();
 	len = lenTemp;
 	std::fill(starts, std::end(starts), -1);
-	for (int l = len - 1; l >= 0; l--) {
+	for (int l = static_cast<int>(len - 1); l >= 0; l--) {
 		unsigned char indexChar = words[l][0];
 		starts[indexChar] = l;
 	}


Modified: scintilla/lexilla/lexlib/WordList.h
9 lines changed, 7 insertions(+), 2 deletions(-)
===================================================================
@@ -16,11 +16,16 @@ class WordList {
 	// Each word contains at least one character - a empty word acts as sentinel at the end.
 	char **words;
 	char *list;
-	int len;
+	size_t len;
 	bool onlyLineEnds;	///< Delimited by any white space or only line ends
 	int starts[256];
 public:
-	explicit WordList(bool onlyLineEnds_ = false);
+	explicit WordList(bool onlyLineEnds_ = false) noexcept;
+	// Deleted so WordList objects can not be copied.
+	WordList(const WordList &) = delete;
+	WordList(WordList &&) = delete;
+	WordList &operator=(const WordList &) = delete;
+	WordList &operator=(WordList &&) = delete;
 	~WordList();
 	operator bool() const noexcept;
 	bool operator!=(const WordList &other) const noexcept;


Modified: scintilla/lexilla/version.txt
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1 +1 @@
-511
+512


Modified: scintilla/src/AutoComplete.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -211,7 +211,7 @@ void AutoComplete::Show(bool show) {
 		lb->Select(0);
 }
 
-void AutoComplete::Cancel() {
+void AutoComplete::Cancel() noexcept {
 	if (lb->Created()) {
 		lb->Clear();
 		lb->Destroy();
@@ -272,7 +272,7 @@ void AutoComplete::Select(const char *word) {
 			}
 		} else if (cond < 0) {
 			end = pivot - 1;
-		} else if (cond > 0) {
+		} else { // cond > 0
 			start = pivot + 1;
 		}
 	}


Modified: scintilla/src/AutoComplete.h
7 lines changed, 6 insertions(+), 1 deletions(-)
===================================================================
@@ -43,6 +43,11 @@ class AutoComplete {
 	Scintilla::Ordering autoSort;
 
 	AutoComplete();
+	// Deleted so AutoComplete objects can not be copied.
+	AutoComplete(const AutoComplete &) = delete;
+	AutoComplete(AutoComplete &&) = delete;
+	AutoComplete &operator=(const AutoComplete &) = delete;
+	AutoComplete &operator=(AutoComplete &&) = delete;
 	~AutoComplete();
 
 	/// Is the auto completion list displayed?
@@ -79,7 +84,7 @@ class AutoComplete {
 	std::string GetValue(int item) const;
 
 	void Show(bool show);
-	void Cancel();
+	void Cancel() noexcept;
 
 	/// Move the current list element by delta, scrolling appropriately
 	void Move(int delta);


Modified: scintilla/src/CallTip.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -313,7 +313,7 @@ PRectangle CallTip::CallTipStart(Sci::Position pos, Point pt, int textHeight, co
 	}
 }
 
-void CallTip::CallTipCancel() {
+void CallTip::CallTipCancel() noexcept {
 	inCallTipMode = false;
 	if (wCallTip.Created()) {
 		wCallTip.Destroy();
@@ -345,7 +345,7 @@ void CallTip::SetPosition(bool aboveText) noexcept {
 }
 
 bool CallTip::UseStyleCallTip() const noexcept {
-	return useStyleCallTip; 
+	return useStyleCallTip;
 }
 
 // It might be better to have two access functions for this and to use


Modified: scintilla/src/CallTip.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -75,7 +75,7 @@ class CallTip {
 		Scintilla::CharacterSet characterSet, Scintilla::Technology technology, const char *localeName,
 		const Window &wParent);
 
-	void CallTipCancel();
+	void CallTipCancel() noexcept;
 
 	/// Set a range of characters to be displayed in a highlight style.
 	/// Commonly used to highlight the current parameter.


Modified: scintilla/src/CaseConvert.cxx
10 lines changed, 7 insertions(+), 3 deletions(-)
===================================================================
@@ -607,9 +607,13 @@ class CaseConverter : public ICaseConverter {
 	std::vector<ConversionString> conversions;
 
 public:
-	CaseConverter() noexcept {
-	}
-	virtual ~CaseConverter() = default;
+	CaseConverter() = default;
+	// Deleted so CaseConverter objects can not be copied.
+	CaseConverter(const CaseConverter &) = delete;
+	CaseConverter(CaseConverter &&) = delete;
+	CaseConverter &operator=(const CaseConverter &) = delete;
+	CaseConverter &operator=(CaseConverter &&) = delete;
+	virtual ~CaseConverter() noexcept = default;
 	bool Initialised() const noexcept {
 		return !characters.empty();
 	}


Modified: scintilla/src/CaseFolder.cxx
3 lines changed, 0 insertions(+), 3 deletions(-)
===================================================================
@@ -23,9 +23,6 @@ CaseFolderTable::CaseFolderTable() noexcept : mapping{}  {
 	}
 }
 
-CaseFolderTable::~CaseFolderTable() {
-}
-
 size_t CaseFolderTable::Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
 	if (lenMixed > sizeFolded) {
 		return 0;


Modified: scintilla/src/CaseFolder.h
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -21,7 +21,6 @@ class CaseFolderTable : public CaseFolder {
 	char mapping[256];
 public:
 	CaseFolderTable() noexcept;
-	~CaseFolderTable() override;
 	size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) override;
 	void SetTranslation(char ch, char chTranslation) noexcept;
 	void StandardASCII() noexcept;


Modified: scintilla/src/CellBuffer.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -523,7 +523,7 @@ void UndoHistory::TentativeCommit() {
 }
 
 bool UndoHistory::TentativeActive() const noexcept {
-	return tentativePoint >= 0; 
+	return tentativePoint >= 0;
 }
 
 int UndoHistory::TentativeSteps() noexcept {


Modified: scintilla/src/ContractionState.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -197,7 +197,7 @@ Sci::Line ContractionState<LINE>::DocFromDisplay(Sci::Line lineDisplay) const no
 	if (OneToOne()) {
 		return lineDisplay;
 	} else {
-		if (lineDisplay <= 0) {
+		if (lineDisplay < 0) {
 			return 0;
 		}
 		if (lineDisplay > LinesDisplayed()) {


Modified: scintilla/src/Decoration.cxx
12 lines changed, 2 insertions(+), 10 deletions(-)
===================================================================
@@ -39,8 +39,6 @@ class Decoration : public IDecoration {
 
 	explicit Decoration(int indicator_) : indicator(indicator_) {
 	}
-	~Decoration() override {
-	}
 
 	bool Empty() const noexcept override {
 		return (rs.Runs() == 1) && (rs.AllSameAs(0));
@@ -75,7 +73,7 @@ template <typename POS>
 class DecorationList : public IDecorationList {
 	int currentIndicator;
 	int currentValue;
-	Decoration<POS> *current;	// Cached so FillRange doesn't have to search for each call.
+	Decoration<POS> *current;	// Non-owning. Cached so FillRange doesn't have to search for each call.
 	Sci::Position lengthDocument;
 	// Ordered by indicator
 	std::vector<std::unique_ptr<Decoration<POS>>> decorationList;
@@ -90,7 +88,6 @@ class DecorationList : public IDecorationList {
 public:
 
 	DecorationList();
-	~DecorationList() override;
 
 	const std::vector<const IDecoration*> &View() const noexcept override {
 		return decorationView;
@@ -128,11 +125,6 @@ DecorationList<POS>::DecorationList() : currentIndicator(0), currentValue(1), cu
 	lengthDocument(0), clickNotified(false) {
 }
 
-template <typename POS>
-DecorationList<POS>::~DecorationList() {
-	current = nullptr;
-}
-
 template <typename POS>
 Decoration<POS> *DecorationList<POS>::DecorationFromIndicator(int indicator) noexcept {
 	for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
@@ -263,7 +255,7 @@ int DecorationList<POS>::AllOnFor(Sci::Position position) const noexcept {
 	for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
 		if (deco->rs.ValueAt(static_cast<POS>(position))) {
 			if (deco->Indicator() < static_cast<int>(Scintilla::IndicatorNumbers::Ime)) {
-				mask |= 1 << deco->Indicator();
+				mask |= 1u << deco->Indicator();
 			}
 		}
 	}


Modified: scintilla/src/Document.cxx
23 lines changed, 16 insertions(+), 7 deletions(-)
===================================================================
@@ -51,6 +51,16 @@
 using namespace Scintilla;
 using namespace Scintilla::Internal;
 
+LexInterface::LexInterface(Document *pdoc_) noexcept : pdoc(pdoc_), performingStyle(false) {
+}
+
+LexInterface::~LexInterface() noexcept = default;
+
+void LexInterface::SetInstance(ILexer5 *instance_) {
+	instance.reset(instance_);
+	pdoc->LexerChanged();
+}
+
 void LexInterface::Colourise(Sci::Position start, Sci::Position end) {
 	if (pdoc && instance && !performingStyle) {
 		// Protect against reentrance, which may occur, for example, when
@@ -86,6 +96,10 @@ LineEndType LexInterface::LineEndTypesSupported() {
 	return LineEndType::Default;
 }
 
+bool LexInterface::UseContainerLexing() const noexcept {
+	return !instance;
+}
+
 ActionDuration::ActionDuration(double duration_, double minDuration_, double maxDuration_) noexcept :
 	duration(duration_), minDuration(minDuration_), maxDuration(maxDuration_) {
 }
@@ -2067,7 +2081,7 @@ Sci::Position Document::FindText(Sci::Position minPos, Sci::Position maxPos, con
 			const unsigned char charStartSearch =  search[0];
 			if (forward && ((0 == dbcsCodePage) || (CpUtf8 == dbcsCodePage && !UTF8IsTrailByte(charStartSearch)))) {
 				// This is a fast case where there is no need to test byte values to iterate
-				// so becomes the equivalent of a memchr+memcmp loop. 
+				// so becomes the equivalent of a memchr+memcmp loop.
 				// UTF-8 search will not be self-synchronizing when starts with trail byte
 				const std::string_view suffix(search + 1, lengthFind - 1);
 				while (pos < endSearch) {
@@ -2798,11 +2812,6 @@ Sci::Position Document::BraceMatch(Sci::Position position, Sci::Position /*maxRe
 class BuiltinRegex : public RegexSearchBase {
 public:
 	explicit BuiltinRegex(CharClassify *charClassTable) : search(charClassTable) {}
-	BuiltinRegex(const BuiltinRegex &) = delete;
-	BuiltinRegex(BuiltinRegex &&) = delete;
-	BuiltinRegex &operator=(const BuiltinRegex &) = delete;
-	BuiltinRegex &operator=(BuiltinRegex &&) = delete;
-	~BuiltinRegex() override = default;
 
 	Sci::Position FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s,
                         bool caseSensitive, bool word, bool wordStart, FindOption flags,
@@ -3199,7 +3208,7 @@ bool MatchOnLines(const Document *doc, const Regex &regexp, const RESearchRange
 	}
 #endif
 	if (matched) {
-		for (size_t co = 0; co < match.size(); co++) {
+		for (size_t co = 0; co < match.size() && co < RESearch::MAXTAG; co++) {
 			search.bopat[co] = match[co].first.Pos();
 			search.eopat[co] = match[co].second.PosRoundUp();
 			const Sci::Position lenMatch = search.eopat[co] - search.bopat[co];


Modified: scintilla/src/Document.h
38 lines changed, 29 insertions(+), 9 deletions(-)
===================================================================
@@ -90,7 +90,7 @@ class Range {
  */
 class RegexSearchBase {
 public:
-	virtual ~RegexSearchBase() {}
+	virtual ~RegexSearchBase() = default;
 
 	virtual Sci::Position FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s,
                         bool caseSensitive, bool word, bool wordStart, Scintilla::FindOption flags, Sci::Position *length) = 0;
@@ -164,21 +164,41 @@ class HighlightDelimiter {
 	bool isEnabled;
 };
 
+struct LexerReleaser {
+	// Called by unique_ptr to destroy/free the Resource
+	void operator()(Scintilla::ILexer5 *pLexer) noexcept {
+		if (pLexer) {
+			try {
+				pLexer->Release();
+			} catch (...) {
+				// ILexer5::Release must not throw, ignore if it does.
+			}
+		}
+	}
+};
+
+using LexerInstance = std::unique_ptr<Scintilla::ILexer5, LexerReleaser>;
+
+// LexInterface defines the interface to ILexer used in Document.
+// The LexState subclass is actually created and that is used within ScintillaBase
+// to provide more methods that are exposed through Scintilla's external API.
 class LexInterface {
 protected:
 	Document *pdoc;
-	Scintilla::ILexer5 *instance;
+	LexerInstance instance;
 	bool performingStyle;	///< Prevent reentrance
 public:
-	explicit LexInterface(Document *pdoc_) noexcept : pdoc(pdoc_), instance(nullptr), performingStyle(false) {
-	}
-	virtual ~LexInterface() {
-	}
+	explicit LexInterface(Document *pdoc_) noexcept;
+	// Deleted so LexInterface objects can not be copied.
+	LexInterface(const LexInterface &) = delete;
+	LexInterface(LexInterface &&) = delete;
+	LexInterface &operator=(const LexInterface &) = delete;
+	LexInterface &operator=(LexInterface &&) = delete;
+	virtual ~LexInterface() noexcept;
+	void SetInstance(ILexer5 *instance_);
 	void Colourise(Sci::Position start, Sci::Position end);
 	virtual Scintilla::LineEndType LineEndTypesSupported();
-	bool UseContainerLexing() const noexcept {
-		return instance == nullptr;
-	}
+	bool UseContainerLexing() const noexcept;
 };
 
 struct RegexError : public std::runtime_error {


Modified: scintilla/src/EditModel.cxx
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
 
 #include <cstddef>
 #include <cstdlib>
+#include <cstdint>
 #include <cassert>
 #include <cstring>
 #include <cmath>


Modified: scintilla/src/EditModel.h
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -64,7 +64,6 @@ class EditModel {
 	virtual Sci::Line TopLineOfMain() const = 0;
 	virtual Point GetVisibleOriginInMain() const = 0;
 	virtual Sci::Line LinesOnScreen() const = 0;
-	virtual Range GetHotSpotRange() const noexcept = 0;
 	bool BidirectionalEnabled() const noexcept;
 	bool BidirectionalR2L() const noexcept;
 	void SetDefaultFoldDisplayText(const char *text);


Modified: scintilla/src/EditView.cxx
95 lines changed, 54 insertions(+), 41 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
 
 #include <cstddef>
 #include <cstdlib>
+#include <cstdint>
 #include <cassert>
 #include <cstring>
 #include <cstdio>
@@ -951,19 +952,19 @@ static void DrawCaretLineFramed(Surface *surface, const ViewStyle &vsDraw, const
 	// Avoid double drawing the corners by removing the left and right sides when drawing top and bottom borders
 	const PRectangle rcWithoutLeftRight = rcLine.Inset(Point(width, 0.0));
 
-	if (subLine == 0 || ll->wrapIndent == 0 || vsDraw.caretLine.layer != Layer::Base) {
+	if (subLine == 0 || ll->wrapIndent == 0 || vsDraw.caretLine.layer != Layer::Base || vsDraw.caretLine.subLine) {
 		// Left
 		surface->FillRectangleAligned(Side(rcLine, Edge::left, width), colourFrame);
 	}
-	if (subLine == 0) {
+	if (subLine == 0 || vsDraw.caretLine.subLine) {
 		// Top
 		surface->FillRectangleAligned(Side(rcWithoutLeftRight, Edge::top, width), colourFrame);
 	}
-	if (subLine == ll->lines - 1 || vsDraw.caretLine.layer != Layer::Base) {
+	if (subLine == ll->lines - 1 || vsDraw.caretLine.layer != Layer::Base || vsDraw.caretLine.subLine) {
 		// Right
 		surface->FillRectangleAligned(Side(rcLine, Edge::right, width), colourFrame);
 	}
-	if (subLine == ll->lines - 1) {
+	if (subLine == ll->lines - 1 || vsDraw.caretLine.subLine) {
 		// Bottom
 		surface->FillRectangleAligned(Side(rcWithoutLeftRight, Edge::bottom, width), colourFrame);
 	}
@@ -1458,7 +1459,7 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c
 		}
 	}
 
-	// For multi-phase drawing draw the text last as transparent over any box 
+	// For multi-phase drawing draw the text last as transparent over any box
 	if (FlagSet(phase, DrawPhase::text)) {
 		if (phasesDraw != PhasesDraw::One) {
 			surface->DrawTextTransparentUTF8(rcText, fontText,
@@ -1603,7 +1604,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
 	for (size_t r = 0; (r<model.sel.Count()) || drawDrag; r++) {
 		const bool mainCaret = r == model.sel.Main();
 		SelectionPosition posCaret = (drawDrag ? model.posDrag : model.sel.Range(r).caret);
-		if ((vsDraw.DrawCaretInsideSelection(model.inOverstrike, imeCaretBlockOverride)) && 
+		if ((vsDraw.DrawCaretInsideSelection(model.inOverstrike, imeCaretBlockOverride)) &&
 			!drawDrag &&
 			posCaret > model.sel.Range(r).anchor) {
 			if (posCaret.VirtualSpace() > 0)
@@ -1766,7 +1767,7 @@ void EditView::DrawBackground(Surface *surface, const EditModel &model, const Vi
 				rcSegment.right = rcLine.right;
 
 			const InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc);
-			const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc);
+			const bool inHotspot = model.hotspot.Valid() && model.hotspot.ContainsCharacter(iDoc);
 			ColourRGBA textBack = TextBackground(model, vsDraw, ll, background, inSelection,
 				inHotspot, ll->styles[i], i);
 			if (ts.representation) {
@@ -1977,7 +1978,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
 			ColourRGBA textFore = vsDraw.styles[styleMain].fore;
 			const Font *textFont = vsDraw.styles[styleMain].font.get();
 			// Hot-spot foreground
-			const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc);
+			const bool inHotspot = model.hotspot.Valid() && model.hotspot.ContainsCharacter(iDoc);
 			if (inHotspot) {
 				if (vsDraw.ElementColour(Element::HotSpotActive))
 					textFore = *vsDraw.ElementColour(Element::HotSpotActive);
@@ -2124,7 +2125,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
 					}
 				}
 			}
-			if (ll->hotspot.Valid() && vsDraw.hotspotUnderline && ll->hotspot.ContainsCharacter(iDoc)) {
+			if (inHotspot && vsDraw.hotspotUnderline) {
 				PRectangle rcUL = rcSegment;
 				rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
 				rcUL.bottom = rcUL.top + 1;
@@ -2281,27 +2282,40 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl
 	}
 }
 
-static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, Sci::Line line, PRectangle rcLine) {
+static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
+	Sci::Line line, PRectangle rcLine, int subLine) {
+	const bool lastSubLine = subLine == (ll->lines - 1);
 	const bool expanded = model.pcs->GetExpanded(line);
 	const FoldLevel level = model.pdoc->GetFoldLevel(line);
 	const FoldLevel levelNext = model.pdoc->GetFoldLevel(line + 1);
 	if (LevelIsHeader(level) &&
 		(LevelNumber(level) < LevelNumber(levelNext))) {
+		const ColourRGBA foldLineColour = vsDraw.ElementColour(Element::FoldLine).value_or(
+			vsDraw.styles[StyleDefault].fore);
 		// Paint the line above the fold
-		if ((expanded && (FlagSet(model.foldFlags, FoldFlag::LineBeforeExpanded)))
+		if ((subLine == 0) &&
+			((expanded && (FlagSet(model.foldFlags, FoldFlag::LineBeforeExpanded)))
 			||
-			(!expanded && (FlagSet(model.foldFlags, FoldFlag::LineBeforeContracted)))) {
-			PRectangle rcFoldLine = rcLine;
-			rcFoldLine.bottom = rcFoldLine.top + 1;
-			surface->FillRectangleAligned(rcFoldLine, Fill(vsDraw.styles[StyleDefault].fore));
+			(!expanded && (FlagSet(model.foldFlags, FoldFlag::LineBeforeContracted))))) {
+			surface->FillRectangleAligned(Side(rcLine, Edge::top, 1.0), foldLineColour);
 		}
 		// Paint the line below the fold
-		if ((expanded && (FlagSet(model.foldFlags, FoldFlag::LineAfterExpanded)))
+		if (lastSubLine &&
+			((expanded && (FlagSet(model.foldFlags, FoldFlag::LineAfterExpanded)))
 			||
-			(!expanded && (FlagSet(model.foldFlags, FoldFlag::LineAfterContracted)))) {
-			PRectangle rcFoldLine = rcLine;
-			rcFoldLine.top = rcFoldLine.bottom - 1;
-			surface->FillRectangleAligned(rcFoldLine, Fill(vsDraw.styles[StyleDefault].fore));
+			(!expanded && (FlagSet(model.foldFlags, FoldFlag::LineAfterContracted))))) {
+			surface->FillRectangleAligned(Side(rcLine, Edge::bottom, 1.0), foldLineColour);
+			// If contracted fold line drawn then don't overwrite with hidden line
+			// as fold lines are more specific then hidden lines.
+			if (!expanded) {
+				return;
+			}
+		}
+	}
+	if (lastSubLine && model.pcs->GetVisible(line) && !model.pcs->GetVisible(line + 1)) {
+		std::optional<ColourRGBA> hiddenLineColour = vsDraw.ElementColour(Element::HiddenLine);
+		if (hiddenLineColour) {
+			surface->FillRectangleAligned(Side(rcLine, Edge::bottom, 1.0), *hiddenLineColour);
 		}
 	}
 }
@@ -2327,10 +2341,9 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan
 		const int screenLinePaintFirst = static_cast<int>(rcArea.top) / vsDraw.lineHeight;
 		const int xStart = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x);
 
-		SelectionPosition posCaret = model.sel.RangeMain().caret;
-		if (model.posDrag.IsValid())
-			posCaret = model.posDrag;
+		const SelectionPosition posCaret = model.posDrag.IsValid() ? model.posDrag : model.sel.RangeMain().caret;
 		const Sci::Line lineCaret = model.pdoc->SciLineFromPosition(posCaret.Position());
+		const int caretOffset = static_cast<int>(posCaret.Position() - model.pdoc->LineStart(lineCaret));
 
 		PRectangle rcTextArea = rcClient;
 		if (vsDraw.marginInside) {
@@ -2397,8 +2410,8 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan
 				durLayout += ep.Duration(true);
 #endif
 				if (ll) {
-					ll->containsCaret = !hideSelection && (lineDoc == lineCaret);
-					ll->hotspot = model.GetHotSpotRange();
+					ll->containsCaret = !hideSelection && (lineDoc == lineCaret)
+						&& (ll->lines == 1 || !vsDraw.caretLine.subLine || ll->InLine(caretOffset, subLine));
 
 					PRectangle rcLine = rcTextArea;
 					rcLine.top = static_cast<XYPOSITION>(ypos);
@@ -2432,7 +2445,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan
 					ll->RestoreBracesHighlight(rangeLine, model.braces, bracesIgnoreStyle);
 
 					if (FlagSet(phase, DrawPhase::foldLines)) {
-						DrawFoldLines(surface, model, vsDraw, lineDoc, rcLine);
+						DrawFoldLines(surface, model, vsDraw, ll.get(), lineDoc, rcLine, subLine);
 					}
 
 					if (FlagSet(phase, DrawPhase::carets)) {
@@ -2578,24 +2591,24 @@ Sci::Position EditView::FormatRange(bool draw, const RangeToFormat *pfr, Surface
 	vsPrint.braceBadLightIndicatorSet = false;
 
 	// Set colours for printing according to users settings
-	for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) {
-		if (printParameters.colourMode == PrintOption::InvertLight) {
-			vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore);
-			vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back);
-		} else if (printParameters.colourMode == PrintOption::BlackOnWhite) {
-			vsPrint.styles[sty].fore = ColourRGBA(0, 0, 0);
-			vsPrint.styles[sty].back = ColourRGBA(0xff, 0xff, 0xff);
-		} else if (printParameters.colourMode == PrintOption::ColourOnWhite) {
-			vsPrint.styles[sty].back = ColourRGBA(0xff, 0xff, 0xff);
-		} else if (printParameters.colourMode == PrintOption::ColourOnWhiteDefaultBG) {
-			if (sty <= StyleDefault) {
-				vsPrint.styles[sty].back = ColourRGBA(0xff, 0xff, 0xff);
-			}
+	const PrintOption colourMode = printParameters.colourMode;
+	const std::vector<Style>::iterator endStyles = (colourMode == PrintOption::ColourOnWhiteDefaultBG) ?
+		vsPrint.styles.begin() + StyleLineNumber : vsPrint.styles.end();
+	for (std::vector<Style>::iterator it = vsPrint.styles.begin(); it != endStyles; ++it) {
+		if (colourMode == PrintOption::InvertLight) {
+			it->fore = InvertedLight(it->fore);
+			it->back = InvertedLight(it->back);
+		} else if (colourMode == PrintOption::BlackOnWhite) {
+			it->fore = ColourRGBA(0, 0, 0);
+			it->back = ColourRGBA(0xff, 0xff, 0xff);
+		} else if (colourMode == PrintOption::ColourOnWhite || colourMode == PrintOption::ColourOnWhiteDefaultBG) {
+			it->back = ColourRGBA(0xff, 0xff, 0xff);
 		}
 	}
 	// White background for the line numbers if PrintOption::ScreenColours isn't used
-	if (printParameters.colourMode != PrintOption::ScreenColours)
+	if (colourMode != PrintOption::ScreenColours) {
 		vsPrint.styles[StyleLineNumber].back = ColourRGBA(0xff, 0xff, 0xff);
+	}
 
 	// Printing uses different margins, so reset screen margins
 	vsPrint.leftMarginWidth = 0;
@@ -2688,7 +2701,7 @@ Sci::Position EditView::FormatRange(bool draw, const RangeToFormat *pfr, Surface
 				vsPrint.styles[StyleLineNumber].font.get(), number);
 			surface->FlushCachedState();
 			surface->DrawTextNoClip(rcNumber, vsPrint.styles[StyleLineNumber].font.get(),
-				static_cast<XYPOSITION>(ypos + vsPrint.maxAscent), number,
+				ypos + vsPrint.maxAscent, number,
 				vsPrint.styles[StyleLineNumber].fore,
 				vsPrint.styles[StyleLineNumber].back);
 		}


Modified: scintilla/src/Editor.cxx
48 lines changed, 38 insertions(+), 10 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
 
 #include <cstddef>
 #include <cstdlib>
+#include <cstdint>
 #include <cassert>
 #include <cstring>
 #include <cstdio>
@@ -117,7 +118,7 @@ static constexpr bool IsAllSpacesOrTabs(std::string_view sv) noexcept {
 	return true;
 }
 
-Editor::Editor() : durationWrapOneByte(0.000001, 0.0000001, 0.00001) {
+Editor::Editor() : durationWrapOneByte(0.000001, 0.00000001, 0.00001) {
 	ctrlID = 0;
 
 	stylesValid = false;
@@ -479,12 +480,17 @@ void Editor::DiscardOverdraw() {
 }
 
 void Editor::Redraw() {
+	if (redrawPendingText) {
+		return;
+	}
 	//Platform::DebugPrintf("Redraw all\n");
 	const PRectangle rcClient = GetClientRectangle();
 	wMain.InvalidateRectangle(rcClient);
-	if (wMargin.GetID())
+	if (wMargin.GetID()) {
 		wMargin.InvalidateAll();
-	//wMain.InvalidateAll();
+	} else if (paintState == PaintState::notPainting) {
+		redrawPendingText = true;
+	}
 }
 
 void Editor::RedrawSelMargin(Sci::Line line, bool allAfter) {
@@ -498,11 +504,15 @@ void Editor::RedrawSelMargin(Sci::Line line, bool allAfter) {
 		Redraw();
 		return;
 	}
+	if (redrawPendingMargin) {
+		return;
+	}
 	PRectangle rcMarkers = GetClientRectangle();
 	if (!markersInText) {
 		// Normal case: just draw the margin
 		rcMarkers.right = rcMarkers.left + vs.fixedColumnWidth;
 	}
+	const PRectangle rcMarkersFull = rcMarkers;
 	if (line != -1) {
 		PRectangle rcLine = RectangleFromRange(Range(pdoc->LineStart(line)), 0);
 
@@ -529,6 +539,9 @@ void Editor::RedrawSelMargin(Sci::Line line, bool allAfter) {
 		wMargin.InvalidateRectangle(rcMarkers);
 	} else {
 		wMain.InvalidateRectangle(rcMarkers);
+		if (rcMarkers == rcMarkersFull) {
+			redrawPendingMargin = true;
+		}
 	}
 }
 
@@ -552,6 +565,9 @@ PRectangle Editor::RectangleFromRange(Range r, int overlap) {
 }
 
 void Editor::InvalidateRange(Sci::Position start, Sci::Position end) {
+	if (redrawPendingText) {
+		return;
+	}
 	RedrawRect(RectangleFromRange(Range(start, end), view.LinesOverlap() ? vs.lineOverlap : 0));
 }
 
@@ -1717,6 +1733,9 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) {
 }
 
 void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
+	redrawPendingText = false;
+	redrawPendingMargin = false;
+
 	//Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n",
 	//	paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
 
@@ -4780,10 +4799,6 @@ void Editor::SetHotSpotRange(const Point *pt) {
 	}
 }
 
-Range Editor::GetHotSpotRange() const noexcept {
-	return hotspot;
-}
-
 void Editor::ButtonMoveWithModifiers(Point pt, unsigned int, KeyMod modifiers) {
 	if (ptMouseLast != pt) {
 		DwellEnd(true);
@@ -5748,6 +5763,9 @@ void Editor::StyleSetMessage(Message iMessage, uptr_t wParam, sptr_t lParam) {
 	case Message::StyleSetHotSpot:
 		vs.styles[wParam].hotspot = lParam != 0;
 		break;
+	case Message::StyleSetCheckMonospaced:
+		vs.styles[wParam].checkMonospaced = lParam != 0;
+		break;
 	default:
 		break;
 	}
@@ -5787,6 +5805,8 @@ sptr_t Editor::StyleGetMessage(Message iMessage, uptr_t wParam, sptr_t lParam) {
 		return vs.styles[wParam].changeable ? 1 : 0;
 	case Message::StyleGetHotSpot:
 		return vs.styles[wParam].hotspot ? 1 : 0;
+	case Message::StyleGetCheckMonospaced:
+		return vs.styles[wParam].checkMonospaced ? 1 : 0;
 	default:
 		break;
 	}
@@ -7202,6 +7222,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
 	case Message::StyleSetVisible:
 	case Message::StyleSetChangeable:
 	case Message::StyleSetHotSpot:
+	case Message::StyleSetCheckMonospaced:
 		StyleSetMessage(iMessage, wParam, lParam);
 		break;
 
@@ -7220,6 +7241,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
 	case Message::StyleGetVisible:
 	case Message::StyleGetChangeable:
 	case Message::StyleGetHotSpot:
+	case Message::StyleGetCheckMonospaced:
 		return StyleGetMessage(iMessage, wParam, lParam);
 
 	case Message::StyleResetDefault:
@@ -7300,6 +7322,13 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
 		InvalidateStyleRedraw();
 		break;
 
+	case Message::GetCaretLineHighlightSubLine:
+		return vs.caretLine.subLine;
+	case Message::SetCaretLineHighlightSubLine:
+		vs.caretLine.subLine = wParam != 0;
+		InvalidateStyleRedraw();
+		break;
+
 	case Message::GetCaretLineFrame:
 		return vs.caretLine.frame;
 	case Message::SetCaretLineFrame:
@@ -7377,8 +7406,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
 		break;
 
 	case Message::HideLines:
-		if (wParam > 0)
-			pcs->SetVisible(LineFromUPtr(wParam), lParam, false);
+		pcs->SetVisible(LineFromUPtr(wParam), lParam, false);
 		SetScrollBars();
 		Redraw();
 		break;
@@ -7903,7 +7931,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
 		break;
 
 	case Message::MultiEdgeAddLine:
-		vs.AddMultiEdge(wParam, lParam);
+		vs.AddMultiEdge(static_cast<int>(wParam), ColourRGBA::FromIpRGB(lParam));
 		InvalidateStyleRedraw();
 		break;
 


Modified: scintilla/src/Editor.h
7 lines changed, 5 insertions(+), 2 deletions(-)
===================================================================
@@ -188,6 +188,10 @@ class Editor : public EditModel, public DocWatcher {
 	Window wMain;	///< The Scintilla parent window
 	Window wMargin;	///< May be separate when using a scroll view for wMain
 
+	// Optimization that avoids superfluous invalidations
+	bool redrawPendingText = false;
+	bool redrawPendingMargin = false;
+
 	/** Style resources may be expensive to allocate so are cached between uses.
 	 * When a style attribute is changed, this cache is flushed. */
 	bool stylesValid;
@@ -581,7 +585,6 @@ class Editor : public EditModel, public DocWatcher {
 	bool PositionIsHotspot(Sci::Position position) const;
 	bool PointIsHotspot(Point pt);
 	void SetHotSpotRange(const Point *pt);
-	Range GetHotSpotRange() const noexcept override;
 	void SetHoverIndicatorPosition(Sci::Position position);
 	void SetHoverIndicatorPoint(Point pt);
 
@@ -637,7 +640,7 @@ class Editor : public EditModel, public DocWatcher {
 		return Point(static_cast<XYPOSITION>(wParam) - vs.ExternalMarginWidth(), static_cast<XYPOSITION>(lParam));
 	}
 
-	constexpr std::optional<FoldLevel> OptionalFoldLevel(Scintilla::sptr_t lParam) {
+	static constexpr std::optional<FoldLevel> OptionalFoldLevel(Scintilla::sptr_t lParam) {
 		if (lParam >= 0) {
 			return static_cast<FoldLevel>(lParam);
 		}


Modified: scintilla/src/Geometry.cxx
24 lines changed, 24 insertions(+), 0 deletions(-)
===================================================================
@@ -12,6 +12,14 @@
 
 #include "Geometry.h"
 
+namespace {
+
+constexpr unsigned int Mixed(unsigned char a, unsigned char b, double proportion) noexcept {
+	return static_cast<unsigned int>(a + proportion * (b - a));
+}
+
+}
+
 namespace Scintilla::Internal {
 
 PRectangle Clamp(PRectangle rc, Edge edge, XYPOSITION position) noexcept {
@@ -95,4 +103,20 @@ PRectangle PixelAlignOutside(const PRectangle &rc, int pixelDivisions) noexcept
 		std::floor(rc.bottom * pixelDivisions) / pixelDivisions);
 }
 
+ColourRGBA ColourRGBA::MixedWith(ColourRGBA other) const noexcept {
+	const unsigned int red = (GetRed() + other.GetRed()) / 2;
+	const unsigned int green = (GetGreen() + other.GetGreen()) / 2;
+	const unsigned int blue = (GetBlue() + other.GetBlue()) / 2;
+	const unsigned int alpha = (GetAlpha() + other.GetAlpha()) / 2;
+	return ColourRGBA(red, green, blue, alpha);
+}
+
+ColourRGBA ColourRGBA::MixedWith(ColourRGBA other, double proportion) const noexcept {
+	return ColourRGBA(
+		Mixed(GetRed(), other.GetRed(), proportion),
+		Mixed(GetGreen(), other.GetGreen(), proportion),
+		Mixed(GetBlue(), other.GetBlue(), proportion),
+		Mixed(GetAlpha(), other.GetAlpha(), proportion));
+}
+
 }


Modified: scintilla/src/Geometry.h
28 lines changed, 6 insertions(+), 22 deletions(-)
===================================================================
@@ -161,9 +161,6 @@ PRectangle PixelAlignOutside(const PRectangle &rc, int pixelDivisions) noexcept;
 constexpr const float componentMaximum = 255.0f;
 class ColourRGBA {
 	int co;
-	constexpr static unsigned int Mixed(unsigned char a, unsigned char b, double proportion) noexcept {
-		return static_cast<unsigned int>(a + proportion * (b - a));
-	}
 public:
 	constexpr explicit ColourRGBA(int co_ = 0) noexcept : co(co_) {
 	}
@@ -236,21 +233,8 @@ class ColourRGBA {
 		return GetAlpha() == 0xff;
 	}
 
-	constexpr ColourRGBA MixedWith(ColourRGBA other) const noexcept {
-		const unsigned int red = (GetRed() + other.GetRed()) / 2;
-		const unsigned int green = (GetGreen() + other.GetGreen()) / 2;
-		const unsigned int blue = (GetBlue() + other.GetBlue()) / 2;
-		const unsigned int alpha = (GetAlpha() + other.GetAlpha()) / 2;
-		return ColourRGBA(red, green, blue, alpha);
-	}
-
-	constexpr ColourRGBA MixedWith(ColourRGBA other, double proportion) const noexcept {
-		return ColourRGBA(
-			Mixed(GetRed(), other.GetRed(), proportion),
-			Mixed(GetGreen(), other.GetGreen(), proportion),
-			Mixed(GetBlue(), other.GetBlue(), proportion),
-			Mixed(GetAlpha(), other.GetAlpha(), proportion));
-	}
+	ColourRGBA MixedWith(ColourRGBA other) const noexcept;
+	ColourRGBA MixedWith(ColourRGBA other, double proportion) const noexcept;
 };
 
 /**
@@ -260,7 +244,7 @@ class Stroke {
 public:
 	ColourRGBA colour;
 	XYPOSITION width;
-	constexpr Stroke(ColourRGBA colour_, XYPOSITION width_=1.0) noexcept : 
+	constexpr Stroke(ColourRGBA colour_, XYPOSITION width_=1.0) noexcept :
 		colour(colour_), width(width_) {
 	}
 	constexpr float WidthF() const noexcept {
@@ -274,7 +258,7 @@ class Stroke {
 class Fill {
 public:
 	ColourRGBA colour;
-	constexpr Fill(ColourRGBA colour_) noexcept : 
+	constexpr Fill(ColourRGBA colour_) noexcept :
 		colour(colour_) {
 	}
 };
@@ -286,10 +270,10 @@ class FillStroke {
 public:
 	Fill fill;
 	Stroke stroke;
-	constexpr FillStroke(ColourRGBA colourFill_, ColourRGBA colourStroke_, XYPOSITION widthStroke_=1.0) noexcept : 
+	constexpr FillStroke(ColourRGBA colourFill_, ColourRGBA colourStroke_, XYPOSITION widthStroke_=1.0) noexcept :
 		fill(colourFill_), stroke(colourStroke_, widthStroke_) {
 	}
-	constexpr FillStroke(ColourRGBA colourBoth, XYPOSITION widthStroke_=1.0) noexcept : 
+	constexpr FillStroke(ColourRGBA colourBoth, XYPOSITION widthStroke_=1.0) noexcept :
 		fill(colourBoth), stroke(colourBoth, widthStroke_) {
 	}
 };


Modified: scintilla/src/Indicator.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -47,7 +47,7 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r
 
 	const XYPOSITION ymid = PixelAlign(rc.Centre().y, pixelDivisions);
 
-	// This is a reasonable clip for indicators beneath text like underlines 
+	// This is a reasonable clip for indicators beneath text like underlines
 	PRectangle rcClip = rcAligned;
 	rcClip.bottom = rcFullHeightAligned.bottom;
 
@@ -242,7 +242,7 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r
 			const XYPOSITION widthDot = std::round(strokeWidth);
 			XYPOSITION x = std::floor(rc.left);
 			while (x < rc.right) {
-				const PRectangle rcDot = PRectangle(x, ymid, 
+				const PRectangle rcDot = PRectangle(x, ymid,
 					x + widthDot, ymid + widthDot);
 				surface->FillRectangle(rcDot, sacDraw.fore);
 				x += widthDot * 2;


Modified: scintilla/src/KeyMap.cxx
4 lines changed, 0 insertions(+), 4 deletions(-)
===================================================================
@@ -32,10 +32,6 @@ KeyMap::KeyMap() {
 	}
 }
 
-KeyMap::~KeyMap() {
-	Clear();
-}
-
 void KeyMap::Clear() noexcept {
 	kmap.clear();
 }


Modified: scintilla/src/KeyMap.h
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -52,7 +52,6 @@ class KeyMap {
 
 public:
 	KeyMap();
-	~KeyMap();
 	void Clear() noexcept;
 	void AssignCmdKey(Scintilla::Keys key, Scintilla::KeyMod modifiers, Scintilla::Message msg);
 	Scintilla::Message Find(Scintilla::Keys key, Scintilla::KeyMod modifiers) const;	// 0 returned on failure


Modified: scintilla/src/LineMarker.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -326,7 +326,7 @@ void LineMarker::DrawFoldingMark(Surface *surface, const PRectangle &rcWhole, Fo
 void LineMarker::AlignedPolygon(Surface *surface, const Point *pts, size_t npts) const {
 	const XYPOSITION move = strokeWidth / 2.0;
 	std::vector<Point> points;
-	std::transform(pts, pts + npts, std::back_inserter(points), [=](Point pt)->Point {
+	std::transform(pts, pts + npts, std::back_inserter(points), [=](Point pt) noexcept ->Point {
 		return Point(pt.x + move, pt.y + move);
 	});
 	surface->Polygon(points.data(), std::size(points), FillStroke(back, fore, strokeWidth));


Modified: scintilla/src/MarginView.cxx
528 lines changed, 274 insertions(+), 254 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
 
 #include <cstddef>
 #include <cstdlib>
+#include <cstdint>
 #include <cassert>
 #include <cstring>
 #include <cstdio>
@@ -166,301 +167,320 @@ void MarginView::RefreshPixMaps(Surface *surfaceWindow, const ViewStyle &vsDraw)
 	}
 }
 
-static MarkerOutline SubstituteMarkerIfEmpty(MarkerOutline markerCheck, MarkerOutline markerDefault, const ViewStyle &vs) noexcept {
+namespace {
+
+MarkerOutline SubstituteMarkerIfEmpty(MarkerOutline markerCheck, MarkerOutline markerDefault, const ViewStyle &vs) noexcept {
 	if (vs.markers[static_cast<size_t>(markerCheck)].markType == MarkerSymbol::Empty)
 		return markerDefault;
 	return markerCheck;
 }
 
+constexpr MarkerOutline TailFromNextLevel(FoldLevel levelNextNum) noexcept {
+	return (levelNextNum > FoldLevel::Base) ? MarkerOutline::FolderMidTail : MarkerOutline::FolderTail;
+}
+
+int FoldingMark(FoldLevel level, FoldLevel levelNext, bool firstSubLine, bool lastSubLine,
+	bool isExpanded, bool needWhiteClosure, MarkerOutline folderOpenMid, MarkerOutline folderEnd) noexcept {
+
+	const FoldLevel levelNum = LevelNumberPart(level);
+	const FoldLevel levelNextNum = LevelNumberPart(levelNext);
+
+	if (LevelIsHeader(level)) {
+		if (firstSubLine) {
+			if (levelNum < levelNextNum) {
+				if (levelNum == FoldLevel::Base) {
+					return 1 << (isExpanded ? MarkerOutline::FolderOpen : MarkerOutline::Folder);
+				} else {
+					return 1 << (isExpanded ? folderOpenMid : folderEnd);
+				}
+			} else if (levelNum > FoldLevel::Base) {
+				return 1 << MarkerOutline::FolderSub;
+			}
+		} else {
+			if (levelNum < levelNextNum) {
+				if (isExpanded) {
+					return 1 << MarkerOutline::FolderSub;
+				} else if (levelNum > FoldLevel::Base) {
+					return 1 << MarkerOutline::FolderSub;
+				}
+			} else if (levelNum > FoldLevel::Base) {
+				return 1 << MarkerOutline::FolderSub;
+			}
+		}
+	} else if (LevelIsWhitespace(level)) {
+		if (needWhiteClosure) {
+			if (LevelIsWhitespace(levelNext)) {
+				return 1 << MarkerOutline::FolderSub;
+			} else {
+				return 1 << TailFromNextLevel(levelNextNum);
+			}
+		} else if (levelNum > FoldLevel::Base) {
+			if (levelNextNum < levelNum) {
+				return 1 << TailFromNextLevel(levelNextNum);
+			} else {
+				return 1 << MarkerOutline::FolderSub;
+			}
+		}
+	} else if (levelNum > FoldLevel::Base) {
+		if (levelNextNum < levelNum) {
+			if (LevelIsWhitespace(levelNext)) {
+				return 1 << MarkerOutline::FolderSub;
+			} else if (lastSubLine) {
+				return 1 << TailFromNextLevel(levelNextNum);
+			} else {
+				return 1 << MarkerOutline::FolderSub;
+			}
+		} else {
+			return 1 << MarkerOutline::FolderSub;
+		}
+	}
+
+	// No folding mark on this line
+	return 0;
+}
+
+}
+
+void MarginView::PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcOneMargin, const MarginStyle &marginStyle,
+	const EditModel &model, const ViewStyle &vs) {
+	const Point ptOrigin = model.GetVisibleOriginInMain();
+	const Sci::Line lineStartPaint = static_cast<Sci::Line>(rcOneMargin.top + ptOrigin.y) / vs.lineHeight;
+	Sci::Line visibleLine = model.TopLineOfMain() + lineStartPaint;
+	XYPOSITION yposScreen = lineStartPaint * vs.lineHeight - ptOrigin.y;
+	// Work out whether the top line is whitespace located after a
+	// lessening of fold level which implies a 'fold tail' but which should not
+	// be displayed until the last of a sequence of whitespace.
+	bool needWhiteClosure = false;
+	if (marginStyle.ShowsFolding()) {
+		const FoldLevel level = model.pdoc->GetFoldLevel(model.pcs->DocFromDisplay(visibleLine));
+		if (LevelIsWhitespace(level)) {
+			Sci::Line lineBack = model.pcs->DocFromDisplay(visibleLine);
+			FoldLevel levelPrev = level;
+			while ((lineBack > 0) && LevelIsWhitespace(levelPrev)) {
+				lineBack--;
+				levelPrev = model.pdoc->GetFoldLevel(lineBack);
+			}
+			if (!LevelIsHeader(levelPrev)) {
+				if (LevelNumber(level) < LevelNumber(levelPrev))
+					needWhiteClosure = true;
+			}
+		}
+	}
+
+	// Old code does not know about new markers needed to distinguish all cases
+	const MarkerOutline folderOpenMid = SubstituteMarkerIfEmpty(MarkerOutline::FolderOpenMid,
+		MarkerOutline::FolderOpen, vs);
+	const MarkerOutline folderEnd = SubstituteMarkerIfEmpty(MarkerOutline::FolderEnd,
+		MarkerOutline::Folder, vs);
+
+	while ((visibleLine < model.pcs->LinesDisplayed()) && yposScreen < rc.bottom) {
+
+		PLATFORM_ASSERT(visibleLine < model.pcs->LinesDisplayed());
+		const Sci::Line lineDoc = model.pcs->DocFromDisplay(visibleLine);
+		PLATFORM_ASSERT((lineDoc == 0) || model.pcs->GetVisible(lineDoc));
+		const Sci::Line firstVisibleLine = model.pcs->DisplayFromDoc(lineDoc);
+		const Sci::Line lastVisibleLine = model.pcs->DisplayLastFromDoc(lineDoc);
+		const bool firstSubLine = visibleLine == firstVisibleLine;
+		const bool lastSubLine = visibleLine == lastVisibleLine;
+
+		int marks = firstSubLine ? model.pdoc->GetMark(lineDoc) : 0;
+
+		bool headWithTail = false;
+
+		if (marginStyle.ShowsFolding()) {
+			// Decide which fold indicator should be displayed
+			const FoldLevel level = model.pdoc->GetFoldLevel(lineDoc);
+			const FoldLevel levelNext = model.pdoc->GetFoldLevel(lineDoc + 1);
+			const FoldLevel levelNum = LevelNumberPart(level);
+			const FoldLevel levelNextNum = LevelNumberPart(levelNext);
+			const bool isExpanded = model.pcs->GetExpanded(lineDoc);
+
+			marks |= FoldingMark(level, levelNext, firstSubLine, lastSubLine,
+				isExpanded, needWhiteClosure, folderOpenMid, folderEnd);
+
+			// Change needWhiteClosure and headWithTail if needed
+			if (LevelIsHeader(level)) {
+				needWhiteClosure = false;
+				const Sci::Line firstFollowupLine = model.pcs->DocFromDisplay(model.pcs->DisplayFromDoc(lineDoc + 1));
+				const FoldLevel firstFollowupLineLevel = model.pdoc->GetFoldLevel(firstFollowupLine);
+				const FoldLevel secondFollowupLineLevelNum = LevelNumberPart(model.pdoc->GetFoldLevel(firstFollowupLine + 1));
+				if (!isExpanded) {
+					if (LevelIsWhitespace(firstFollowupLineLevel) &&
+						(levelNum > secondFollowupLineLevelNum))
+						needWhiteClosure = true;
+
+					if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine))
+						headWithTail = true;
+				}
+			} else if (LevelIsWhitespace(level)) {
+				if (needWhiteClosure) {
+					needWhiteClosure = LevelIsWhitespace(levelNext);
+				}
+			} else if (levelNum > FoldLevel::Base) {
+				if (levelNextNum < levelNum) {
+					needWhiteClosure = LevelIsWhitespace(levelNext);
+				}
+			}
+		}
+
+		const PRectangle rcMarker(
+			rcOneMargin.left,
+			yposScreen,
+			rcOneMargin.right,
+			yposScreen + vs.lineHeight);
+		if (marginStyle.style == MarginType::Number) {
+			if (firstSubLine) {
+				std::string sNumber;
+				if (lineDoc >= 0) {
+					sNumber = std::to_string(lineDoc + 1);
+				}
+				if (FlagSet(model.foldFlags, (FoldFlag::LevelNumbers | FoldFlag::LineState))) {
+					char number[100] = "";
+					if (FlagSet(model.foldFlags, FoldFlag::LevelNumbers)) {
+						const FoldLevel lev = model.pdoc->GetFoldLevel(lineDoc);
+						sprintf(number, "%c%c %03X %03X",
+							LevelIsHeader(lev) ? 'H' : '_',
+							LevelIsWhitespace(lev) ? 'W' : '_',
+							LevelNumber(lev),
+							static_cast<int>(lev) >> 16
+						);
+					} else {
+						const int state = model.pdoc->GetLineState(lineDoc);
+						sprintf(number, "%0X", state);
+					}
+					sNumber = number;
+				}
+				PRectangle rcNumber = rcMarker;
+				// Right justify
+				const XYPOSITION width = surface->WidthText(vs.styles[StyleLineNumber].font.get(), sNumber);
+				const XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;
+				rcNumber.left = xpos;
+				DrawTextNoClipPhase(surface, rcNumber, vs.styles[StyleLineNumber],
+					rcNumber.top + vs.maxAscent, sNumber, DrawPhase::all);
+			} else if (FlagSet(vs.wrap.visualFlags, WrapVisualFlag::Margin)) {
+				PRectangle rcWrapMarker = rcMarker;
+				rcWrapMarker.right -= wrapMarkerPaddingRight;
+				rcWrapMarker.left = rcWrapMarker.right - vs.styles[StyleLineNumber].aveCharWidth;
+				if (!customDrawWrapMarker) {
+					DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[StyleLineNumber].fore);
+				} else {
+					customDrawWrapMarker(surface, rcWrapMarker, false, vs.styles[StyleLineNumber].fore);
+				}
+			}
+		} else if (marginStyle.style == MarginType::Text || marginStyle.style == MarginType::RText) {
+			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);
+					PRectangle rcText = rcMarker;
+					if (marginStyle.style == MarginType::RText) {
+						const int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
+						rcText.left = rcText.right - width - 3;
+					}
+					DrawStyledText(surface, vs, vs.marginStyleOffset, rcText,
+						stMargin, 0, stMargin.length, DrawPhase::all);
+				} else {
+					// if we're displaying annotation lines, colour 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);
+					}
+				}
+			}
+		}
+
+		marks &= marginStyle.mask;
+
+		if (marks) {
+			for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+				if (marks & 1) {
+					LineMarker::FoldPart part = LineMarker::FoldPart::undefined;
+					if (marginStyle.ShowsFolding() && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
+						if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
+							part = LineMarker::FoldPart::body;
+						} else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
+							if (firstSubLine) {
+								part = headWithTail ? LineMarker::FoldPart::headWithTail : LineMarker::FoldPart::head;
+							} else {
+								if (model.pcs->GetExpanded(lineDoc) || headWithTail) {
+									part = LineMarker::FoldPart::body;
+								} else {
+									part = LineMarker::FoldPart::undefined;
+								}
+							}
+						} else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
+							part = LineMarker::FoldPart::tail;
+						}
+					}
+					vs.markers[markBit].Draw(surface, rcMarker, vs.styles[StyleLineNumber].font.get(), part, marginStyle.style);
+				}
+				marks >>= 1;
+			}
+		}
+
+		visibleLine++;
+		yposScreen += vs.lineHeight;
+	}
+}
+
 void MarginView::PaintMargin(Surface *surface, Sci::Line topLine, PRectangle rc, PRectangle rcMargin,
 	const EditModel &model, const ViewStyle &vs) {
 
-	PRectangle rcSelMargin = rcMargin;
-	rcSelMargin.right = rcMargin.left;
-	if (rcSelMargin.bottom < rc.bottom)
-		rcSelMargin.bottom = rc.bottom;
+	PRectangle rcOneMargin = rcMargin;
+	rcOneMargin.right = rcMargin.left;
+	if (rcOneMargin.bottom < rc.bottom)
+		rcOneMargin.bottom = rc.bottom;
 
 	const Point ptOrigin = model.GetVisibleOriginInMain();
-	const Font *fontLineNumber = vs.styles[StyleLineNumber].font.get();
-	for (size_t margin = 0; margin < vs.ms.size(); margin++) {
-		if (vs.ms[margin].width > 0) {
+	for (const MarginStyle &marginStyle : vs.ms) {
+		if (marginStyle.width > 0) {
 
-			rcSelMargin.left = rcSelMargin.right;
-			rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
+			rcOneMargin.left = rcOneMargin.right;
+			rcOneMargin.right = rcOneMargin.left + marginStyle.width;
 
-			if (vs.ms[margin].style != MarginType::Number) {
-				if (vs.ms[margin].ShowsFolding()) {
+			if (marginStyle.style != MarginType::Number) {
+				if (marginStyle.ShowsFolding()) {
 					// Required because of special way brush is created for selection margin
 					// Ensure patterns line up when scrolling with separate margin view
 					// by choosing correctly aligned variant.
 					const bool invertPhase = static_cast<int>(ptOrigin.y) & 1;
-					surface->FillRectangle(rcSelMargin,
+					surface->FillRectangle(rcOneMargin,
 						invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1);
 				} else {
 					ColourRGBA colour;
-					switch (vs.ms[margin].style) {
+					switch (marginStyle.style) {
 					case MarginType::Back:
 						colour = vs.styles[StyleDefault].back;
 						break;
 					case MarginType::Fore:
 						colour = vs.styles[StyleDefault].fore;
 						break;
 					case MarginType::Colour:
-						colour = vs.ms[margin].back;
+						colour = marginStyle.back;
 						break;
 					default:
 						colour = vs.styles[StyleLineNumber].back;
 						break;
 					}
-					surface->FillRectangle(rcSelMargin, colour);
+					surface->FillRectangle(rcOneMargin, colour);
 				}
 			} else {
-				surface->FillRectangle(rcSelMargin, vs.styles[StyleLineNumber].back);
+				surface->FillRectangle(rcOneMargin, vs.styles[StyleLineNumber].back);
 			}
 
-			const Sci::Line lineStartPaint = static_cast<Sci::Line>(rcMargin.top + ptOrigin.y) / vs.lineHeight;
-			Sci::Line visibleLine = model.TopLineOfMain() + lineStartPaint;
-			Sci::Position yposScreen = lineStartPaint * vs.lineHeight - static_cast<Sci::Position>(ptOrigin.y);
-			// Work out whether the top line is whitespace located after a
-			// lessening of fold level which implies a 'fold tail' but which should not
-			// be displayed until the last of a sequence of whitespace.
-			bool needWhiteClosure = false;
-			if (vs.ms[margin].ShowsFolding()) {
-				const FoldLevel level = model.pdoc->GetFoldLevel(model.pcs->DocFromDisplay(visibleLine));
-				if (LevelIsWhitespace(level)) {
-					Sci::Line lineBack = model.pcs->DocFromDisplay(visibleLine);
-					FoldLevel levelPrev = level;
-					while ((lineBack > 0) && LevelIsWhitespace(levelPrev)) {
-						lineBack--;
-						levelPrev = model.pdoc->GetFoldLevel(lineBack);
-					}
-					if (!LevelIsHeader(levelPrev)) {
-						if (LevelNumber(level) < LevelNumber(levelPrev))
-							needWhiteClosure = true;
-					}
-				}
-				if (highlightDelimiter.isEnabled) {
-					const Sci::Line lastLine = model.pcs->DocFromDisplay(topLine + model.LinesOnScreen()) + 1;
-					model.pdoc->GetHighlightDelimiters(highlightDelimiter,
-						model.pdoc->SciLineFromPosition(model.sel.MainCaret()), lastLine);
-				}
+			if (marginStyle.ShowsFolding() && highlightDelimiter.isEnabled) {
+				const Sci::Line lastLine = model.pcs->DocFromDisplay(topLine + model.LinesOnScreen()) + 1;
+				model.pdoc->GetHighlightDelimiters(highlightDelimiter,
+					model.pdoc->SciLineFromPosition(model.sel.MainCaret()), lastLine);
 			}
 
-			// Old code does not know about new markers needed to distinguish all cases
-			const MarkerOutline folderOpenMid = SubstituteMarkerIfEmpty(MarkerOutline::FolderOpenMid,
-				MarkerOutline::FolderOpen, vs);
-			const MarkerOutline folderEnd = SubstituteMarkerIfEmpty(MarkerOutline::FolderEnd,
-				MarkerOutline::Folder, vs);
-
-			while ((visibleLine < model.pcs->LinesDisplayed()) && yposScreen < rc.bottom) {
-
-				PLATFORM_ASSERT(visibleLine < model.pcs->LinesDisplayed());
-				const Sci::Line lineDoc = model.pcs->DocFromDisplay(visibleLine);
-				PLATFORM_ASSERT(model.pcs->GetVisible(lineDoc));
-				const Sci::Line firstVisibleLine = model.pcs->DisplayFromDoc(lineDoc);
-				const Sci::Line lastVisibleLine = model.pcs->DisplayLastFromDoc(lineDoc);
-				const bool firstSubLine = visibleLine == firstVisibleLine;
-				const bool lastSubLine = visibleLine == lastVisibleLine;
-
-				int marks = model.pdoc->GetMark(lineDoc);
-				if (!firstSubLine)
-					marks = 0;
-
-				bool headWithTail = false;
-
-				if (vs.ms[margin].ShowsFolding()) {
-					// Decide which fold indicator should be displayed
-					const FoldLevel level = model.pdoc->GetFoldLevel(lineDoc);
-					const FoldLevel levelNext = model.pdoc->GetFoldLevel(lineDoc + 1);
-					const FoldLevel levelNum = LevelNumberPart(level);
-					const FoldLevel levelNextNum = LevelNumberPart(levelNext);
-					if (LevelIsHeader(level)) {
-						if (firstSubLine) {
-							if (levelNum < levelNextNum) {
-								if (model.pcs->GetExpanded(lineDoc)) {
-									if (levelNum == FoldLevel::Base)
-										marks |= 1 << MarkerOutline::FolderOpen;
-									else
-										marks |= 1 << folderOpenMid;
-								} else {
-									if (levelNum == FoldLevel::Base)
-										marks |= 1 << MarkerOutline::Folder;
-									else
-										marks |= 1 << folderEnd;
-								}
-							} else if (levelNum > FoldLevel::Base) {
-								marks |= 1 << MarkerOutline::FolderSub;
-							}
-						} else {
-							if (levelNum < levelNextNum) {
-								if (model.pcs->GetExpanded(lineDoc)) {
-									marks |= 1 << MarkerOutline::FolderSub;
-								} else if (levelNum > FoldLevel::Base) {
-									marks |= 1 << MarkerOutline::FolderSub;
-								}
-							} else if (levelNum > FoldLevel::Base) {
-								marks |= 1 << MarkerOutline::FolderSub;
-							}
-						}
-						needWhiteClosure = false;
-						const Sci::Line firstFollowupLine = model.pcs->DocFromDisplay(model.pcs->DisplayFromDoc(lineDoc + 1));
-						const FoldLevel firstFollowupLineLevel = model.pdoc->GetFoldLevel(firstFollowupLine);
-						const FoldLevel secondFollowupLineLevelNum = LevelNumberPart(model.pdoc->GetFoldLevel(firstFollowupLine + 1));
-						if (!model.pcs->GetExpanded(lineDoc)) {
-							if (LevelIsWhitespace(firstFollowupLineLevel) &&
-								(levelNum > secondFollowupLineLevelNum))
-								needWhiteClosure = true;
-
-							if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine))
-								headWithTail = true;
-						}
-					} else if (LevelIsWhitespace(level)) {
-						if (needWhiteClosure) {
-							if (LevelIsWhitespace(levelNext)) {
-								marks |= 1 << MarkerOutline::FolderSub;
-							} else if (levelNextNum > FoldLevel::Base) {
-								marks |= 1 << MarkerOutline::FolderMidTail;
-								needWhiteClosure = false;
-							} else {
-								marks |= 1 << MarkerOutline::FolderTail;
-								needWhiteClosure = false;
-							}
-						} else if (levelNum > FoldLevel::Base) {
-							if (levelNextNum < levelNum) {
-								if (levelNextNum > FoldLevel::Base) {
-									marks |= 1 << MarkerOutline::FolderMidTail;
-								} else {
-									marks |= 1 << MarkerOutline::FolderTail;
-								}
-							} else {
-								marks |= 1 << MarkerOutline::FolderSub;
-							}
-						}
-					} else if (levelNum > FoldLevel::Base) {
-						if (levelNextNum < levelNum) {
-							needWhiteClosure = false;
-							if (LevelIsWhitespace(levelNext)) {
-								marks |= 1 << MarkerOutline::FolderSub;
-								needWhiteClosure = true;
-							} else if (lastSubLine) {
-								if (levelNextNum > FoldLevel::Base) {
-									marks |= 1 << MarkerOutline::FolderMidTail;
-								} else {
-									marks |= 1 << MarkerOutline::FolderTail;
-								}
-							} else {
-								marks |= 1 << MarkerOutline::FolderSub;
-							}
-						} else {
-							marks |= 1 << MarkerOutline::FolderSub;
-						}
-					}
-				}
-
-				marks &= vs.ms[margin].mask;
-
-				const PRectangle rcMarker(
-					rcSelMargin.left,
-					static_cast<XYPOSITION>(yposScreen),
-					rcSelMargin.right,
-					static_cast<XYPOSITION>(yposScreen + vs.lineHeight));
-				if (vs.ms[margin].style == MarginType::Number) {
-					if (firstSubLine) {
-						std::string sNumber;
-						if (lineDoc >= 0) {
-							sNumber = std::to_string(lineDoc + 1);
-						}
-						if (FlagSet(model.foldFlags, (FoldFlag::LevelNumbers | FoldFlag::LineState))) {
-							char number[100] = "";
-							if (FlagSet(model.foldFlags, FoldFlag::LevelNumbers)) {
-								const FoldLevel lev = model.pdoc->GetFoldLevel(lineDoc);
-								sprintf(number, "%c%c %03X %03X",
-									LevelIsHeader(lev) ? 'H' : '_',
-									LevelIsWhitespace(lev) ? 'W' : '_',
-									LevelNumber(lev),
-									static_cast<int>(lev) >> 16
-									);
-							} else {
-								const int state = model.pdoc->GetLineState(lineDoc);
-								sprintf(number, "%0X", state);
-							}
-							sNumber = number;
-						}
-						PRectangle rcNumber = rcMarker;
-						// Right justify
-						const XYPOSITION width = surface->WidthText(fontLineNumber, sNumber);
-						const XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;
-						rcNumber.left = xpos;
-						DrawTextNoClipPhase(surface, rcNumber, vs.styles[StyleLineNumber],
-							rcNumber.top + vs.maxAscent, sNumber, DrawPhase::all);
-					} else if (FlagSet(vs.wrap.visualFlags, WrapVisualFlag::Margin)) {
-						PRectangle rcWrapMarker = rcMarker;
-						rcWrapMarker.right -= wrapMarkerPaddingRight;
-						rcWrapMarker.left = rcWrapMarker.right - vs.styles[StyleLineNumber].aveCharWidth;
-						if (!customDrawWrapMarker) {
-							DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[StyleLineNumber].fore);
-						} else {
-							customDrawWrapMarker(surface, rcWrapMarker, false, vs.styles[StyleLineNumber].fore);
-						}
-					}
-				} else if (vs.ms[margin].style == MarginType::Text || vs.ms[margin].style == MarginType::RText) {
-					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);
-							PRectangle rcText = rcMarker;
-							if (vs.ms[margin].style == MarginType::RText) {
-								const int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
-								rcText.left = rcText.right - width - 3;
-							}
-							DrawStyledText(surface, vs, vs.marginStyleOffset, rcText,
-								stMargin, 0, stMargin.length, DrawPhase::all);
-						} else {
-							// if we're displaying annotation lines, colour 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);
-							}
-						}
-					}
-				}
-
-				if (marks) {
-					for (int markBit = 0; (markBit < 32) && marks; markBit++) {
-						if (marks & 1) {
-							LineMarker::FoldPart part = LineMarker::FoldPart::undefined;
-							if (vs.ms[margin].ShowsFolding() && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
-								if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
-									part = LineMarker::FoldPart::body;
-								} else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
-									if (firstSubLine) {
-										part = headWithTail ? LineMarker::FoldPart::headWithTail : LineMarker::FoldPart::head;
-									} else {
-										if (model.pcs->GetExpanded(lineDoc) || headWithTail) {
-											part = LineMarker::FoldPart::body;
-										} else {
-											part = LineMarker::FoldPart::undefined;
-										}
-									}
-								} else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
-									part = LineMarker::FoldPart::tail;
-								}
-							}
-							vs.markers[markBit].Draw(surface, rcMarker, fontLineNumber, part, vs.ms[margin].style);
-						}
-						marks >>= 1;
-					}
-				}
-
-				visibleLine++;
-				yposScreen += vs.lineHeight;
-			}
+			PaintOneMargin(surface, rc, rcOneMargin, marginStyle, model, vs);
 		}
 	}
 
 	PRectangle rcBlankMargin = rcMargin;
-	rcBlankMargin.left = rcSelMargin.right;
+	rcBlankMargin.left = rcOneMargin.right;
 	surface->FillRectangle(rcBlankMargin, vs.styles[StyleDefault].back);
 }
 


Modified: scintilla/src/MarginView.h
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -36,6 +36,8 @@ class MarginView {
 
 	void DropGraphics() noexcept;
 	void RefreshPixMaps(Surface *surfaceWindow, const ViewStyle &vsDraw);
+	void PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcMargin, const MarginStyle &marginStyle,
+		const EditModel &model, const ViewStyle &vs);
 	void PaintMargin(Surface *surface, Sci::Line topLine, PRectangle rc, PRectangle rcMargin,
 		const EditModel &model, const ViewStyle &vs);
 };


Modified: scintilla/src/PositionCache.cxx
98 lines changed, 72 insertions(+), 26 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
 
 #include <cstddef>
 #include <cstdlib>
+#include <cstdint>
 #include <cstring>
 #include <cmath>
 
@@ -71,7 +72,6 @@ LineLayout::LineLayout(Sci::Line lineNumber_, int maxLineLength_) :
 	containsCaret(false),
 	edgeColumn(0),
 	bracePreviousStyles{},
-	hotspot(0,0),
 	widthLine(wrapWidthInfinite),
 	lines(1),
 	wrapIndent(0) {
@@ -377,6 +377,14 @@ constexpr size_t AlignUp(size_t value, size_t alignment) noexcept {
 
 constexpr size_t alignmentLLC = 20;
 
+constexpr bool GraphicASCII(char ch) noexcept {
+	return ch >= ' ' && ch <= '~';
+}
+
+bool AllGraphicASCII(std::string_view text) noexcept {
+	return std::all_of(text.cbegin(), text.cend(), GraphicASCII);
+}
+
 }
 
 
@@ -533,8 +541,10 @@ std::shared_ptr<LineLayout> LineLayoutCache::Retrieve(Sci::Line lineNumber, Sci:
 	return std::make_shared<LineLayout>(lineNumber, maxChars);
 }
 
+namespace {
+
 // Simply pack the (maximum 4) character bytes into an int
-static unsigned int KeyFromString(std::string_view charBytes) noexcept {
+constexpr unsigned int KeyFromString(std::string_view charBytes) noexcept {
 	PLATFORM_ASSERT(charBytes.length() <= 4);
 	unsigned int k=0;
 	for (size_t i=0; i < charBytes.length(); i++) {
@@ -545,14 +555,21 @@ static unsigned int KeyFromString(std::string_view charBytes) noexcept {
 	return k;
 }
 
+constexpr unsigned int representationKeyCrLf = KeyFromString("\r\n");
+
+}
+
 void SpecialRepresentations::SetRepresentation(std::string_view charBytes, std::string_view value) {
 	if ((charBytes.length() <= 4) && (value.length() <= Representation::maxLength)) {
 		const unsigned int key = KeyFromString(charBytes);
-		MapRepresentation::iterator it = mapReprs.find(key);
+		const MapRepresentation::iterator it = mapReprs.find(key);
 		if (it == mapReprs.end()) {
 			// New entry so increment for first byte
 			const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
 			startByteHasReprs[ucStart]++;
+			if (key == representationKeyCrLf) {
+				crlf = true;
+			}
 		}
 		mapReprs[key] = Representation(value);
 	}
@@ -561,7 +578,7 @@ void SpecialRepresentations::SetRepresentation(std::string_view charBytes, std::
 void SpecialRepresentations::SetRepresentationAppearance(std::string_view charBytes, RepresentationAppearance appearance) {
 	if (charBytes.length() <= 4) {
 		const unsigned int key = KeyFromString(charBytes);
-		MapRepresentation::iterator it = mapReprs.find(key);
+		const MapRepresentation::iterator it = mapReprs.find(key);
 		if (it == mapReprs.end()) {
 			// Not present so fail
 			return;
@@ -573,7 +590,7 @@ void SpecialRepresentations::SetRepresentationAppearance(std::string_view charBy
 void SpecialRepresentations::SetRepresentationColour(std::string_view charBytes, ColourRGBA colour) {
 	if (charBytes.length() <= 4) {
 		const unsigned int key = KeyFromString(charBytes);
-		MapRepresentation::iterator it = mapReprs.find(key);
+		const MapRepresentation::iterator it = mapReprs.find(key);
 		if (it == mapReprs.end()) {
 			// Not present so fail
 			return;
@@ -585,24 +602,33 @@ void SpecialRepresentations::SetRepresentationColour(std::string_view charBytes,
 
 void SpecialRepresentations::ClearRepresentation(std::string_view charBytes) {
 	if (charBytes.length() <= 4) {
-		MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes));
+		const unsigned int key = KeyFromString(charBytes);
+		const MapRepresentation::iterator it = mapReprs.find(key);
 		if (it != mapReprs.end()) {
 			mapReprs.erase(it);
 			const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
 			startByteHasReprs[ucStart]--;
+			if (key == representationKeyCrLf) {
+				crlf = false;
+			}
 		}
 	}
 }
 
+const Representation *SpecialRepresentations::GetRepresentation(std::string_view charBytes) const {
+	const MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes));
+	if (it != mapReprs.end()) {
+		return &(it->second);
+	}
+	return nullptr;
+}
+
 const Representation *SpecialRepresentations::RepresentationFromCharacter(std::string_view charBytes) const {
 	if (charBytes.length() <= 4) {
 		const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
 		if (!startByteHasReprs[ucStart])
 			return nullptr;
-		MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes));
-		if (it != mapReprs.end()) {
-			return &(it->second);
-		}
+		return GetRepresentation(charBytes);
 	}
 	return nullptr;
 }
@@ -612,14 +638,15 @@ bool SpecialRepresentations::Contains(std::string_view charBytes) const {
 	const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
 	if (!startByteHasReprs[ucStart])
 		return false;
-	MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes));
+	const MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes));
 	return it != mapReprs.end();
 }
 
 void SpecialRepresentations::Clear() {
 	mapReprs.clear();
 	constexpr short none = 0;
 	std::fill(startByteHasReprs, std::end(startByteHasReprs), none);
+	crlf = false;
 }
 
 void BreakFinder::Insert(Sci::Position val) {
@@ -694,16 +721,23 @@ TextSegment BreakFinder::Next() {
 		const int prev = nextBreak;
 		while (nextBreak < lineRange.end) {
 			int charWidth = 1;
-			if (encodingFamily == EncodingFamily::unicode)
-				charWidth = UTF8DrawBytes(reinterpret_cast<unsigned char *>(&ll->chars[nextBreak]),
-					static_cast<int>(lineRange.end - nextBreak));
-			else if (encodingFamily == EncodingFamily::dbcs)
-				charWidth = pdoc->DBCSDrawBytes(
-					std::string_view(&ll->chars[nextBreak], lineRange.end - nextBreak));
-			// Special case \r\n line ends if there is a representation
-			if (preprs->Contains("\r\n") && ll->chars[nextBreak] == '\r' && ll->chars[nextBreak + 1] == '\n')
-				charWidth = 2;
-			const Representation *repr = preprs->RepresentationFromCharacter(std::string_view(&ll->chars[nextBreak], charWidth));
+			const char * const chars = &ll->chars[nextBreak];
+			const unsigned char ch = chars[0];
+			if (!UTF8IsAscii(ch) && encodingFamily != EncodingFamily::eightBit) {
+				if (encodingFamily == EncodingFamily::unicode) {
+					charWidth = UTF8DrawBytes(reinterpret_cast<const unsigned char *>(chars), static_cast<int>(lineRange.end - nextBreak));
+				} else {
+					charWidth = pdoc->DBCSDrawBytes(std::string_view(chars, lineRange.end - nextBreak));
+				}
+			}
+			const Representation *repr = nullptr;
+			if (preprs->MayContain(ch)) {
+				// Special case \r\n line ends if there is a representation
+				if (ch == '\r' && preprs->ContainsCrLf() && chars[1] == '\n') {
+					charWidth = 2;
+				}
+				repr = preprs->GetRepresentation(std::string_view(chars, charWidth));
+			}
 			if (((nextBreak > 0) && (ll->styles[nextBreak] != ll->styles[nextBreak - 1])) ||
 					repr ||
 					(nextBreak == saeNext)) {
@@ -768,10 +802,10 @@ PositionCacheEntry::PositionCacheEntry(const PositionCacheEntry &other) :
 }
 
 void PositionCacheEntry::Set(unsigned int styleNumber_, std::string_view sv,
-	const XYPOSITION *positions_, unsigned int clock_) {
+	const XYPOSITION *positions_, uint16_t clock_) {
 	Clear();
-	styleNumber = styleNumber_;
-	len = static_cast<unsigned int>(sv.length());
+	styleNumber = static_cast<uint16_t>(styleNumber_);
+	len = static_cast<uint16_t>(sv.length());
 	clock = clock_;
 	if (sv.data() && positions_) {
 		positions = std::make_unique<XYPOSITION[]>(len + (len / sizeof(XYPOSITION)) + 1);
@@ -848,7 +882,17 @@ size_t PositionCache::GetSize() const noexcept {
 
 void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber,
 	std::string_view sv, XYPOSITION *positions) {
-	allClear = false;
+	const Style &style = vstyle.styles[styleNumber];
+	if (style.monospaceASCII) {
+		if (AllGraphicASCII(sv)) {
+			const XYPOSITION monospaceCharacterWidth = style.monospaceCharacterWidth;
+			for (size_t i = 0; i < sv.length(); i++) {
+				positions[i] = monospaceCharacterWidth * (i+1);
+			}
+			return;
+		}
+	}
+
 	size_t probe = pces.size();	// Out of bounds
 	if ((!pces.empty()) && (sv.length() < 30)) {
 		// Only store short strings in the cache so it doesn't churn with
@@ -869,7 +913,8 @@ void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, uns
 			probe = probe2;
 		}
 	}
-	const Font *fontStyle = vstyle.styles[styleNumber].font.get();
+
+	const Font *fontStyle = style.font.get();
 	surface->MeasureWidths(fontStyle, sv, positions);
 	if (probe < pces.size()) {
 		// Store into cache
@@ -882,6 +927,7 @@ void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, uns
 			}
 			clock = 2;
 		}
+		allClear = false;
 		pces[probe].Set(styleNumber, sv, positions, clock);
 	}
 }


Modified: scintilla/src/PositionCache.h
21 lines changed, 13 insertions(+), 8 deletions(-)
===================================================================
@@ -79,9 +79,6 @@ class LineLayout {
 
 	std::unique_ptr<BidiData> bidiData;
 
-	// Hotspot support
-	Range hotspot;
-
 	// Wrapped line support
 	int widthLine;
 	int lines;
@@ -175,9 +172,9 @@ class LineLayoutCache {
 };
 
 class PositionCacheEntry {
-	unsigned int styleNumber:8;
-	unsigned int len:8;
-	unsigned int clock:16;
+	uint16_t styleNumber;
+	uint16_t len;
+	uint16_t clock;
 	std::unique_ptr<XYPOSITION []> positions;
 public:
 	PositionCacheEntry() noexcept;
@@ -188,7 +185,7 @@ class PositionCacheEntry {
 	void operator=(const PositionCacheEntry &) = delete;
 	void operator=(PositionCacheEntry &&) = delete;
 	~PositionCacheEntry();
-	void Set(unsigned int styleNumber_, std::string_view sv, const XYPOSITION *positions_, unsigned int clock_);
+	void Set(unsigned int styleNumber_, std::string_view sv, const XYPOSITION *positions_, uint16_t clock_);
 	void Clear() noexcept;
 	bool Retrieve(unsigned int styleNumber_, std::string_view sv, XYPOSITION *positions_) const noexcept;
 	static size_t Hash(unsigned int styleNumber_, std::string_view sv) noexcept;
@@ -212,13 +209,21 @@ typedef std::map<unsigned int, Representation> MapRepresentation;
 class SpecialRepresentations {
 	MapRepresentation mapReprs;
 	short startByteHasReprs[0x100] {};
+	bool crlf = false;
 public:
 	void SetRepresentation(std::string_view charBytes, std::string_view value);
 	void SetRepresentationAppearance(std::string_view charBytes, RepresentationAppearance appearance);
 	void SetRepresentationColour(std::string_view charBytes, ColourRGBA colour);
 	void ClearRepresentation(std::string_view charBytes);
+	const Representation *GetRepresentation(std::string_view charBytes) const;
 	const Representation *RepresentationFromCharacter(std::string_view charBytes) const;
 	bool Contains(std::string_view charBytes) const;
+	bool ContainsCrLf() const noexcept {
+		return crlf;
+	}
+	bool MayContain(unsigned char ch) const noexcept {
+		return startByteHasReprs[ch] != 0;
+	}
 	void Clear();
 };
 
@@ -268,7 +273,7 @@ class BreakFinder {
 
 class PositionCache {
 	std::vector<PositionCacheEntry> pces;
-	unsigned int clock;
+	uint16_t clock;
 	bool allClear;
 public:
 	PositionCache();


Modified: scintilla/src/RESearch.cxx
4 lines changed, 0 insertions(+), 4 deletions(-)
===================================================================
@@ -260,10 +260,6 @@ RESearch::RESearch(CharClassify *charClassTable) {
 	Clear();
 }
 
-RESearch::~RESearch() {
-	Clear();
-}
-
 void RESearch::Clear() noexcept {
 	for (int i = 0; i < MAXTAG; i++) {
 		pat[i].clear();


Modified: scintilla/src/RESearch.h
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -23,7 +23,6 @@ class RESearch {
 public:
 	explicit RESearch(CharClassify *charClassTable);
 	// No dynamic allocation so default copy constructor and assignment operator are OK.
-	~RESearch();
 	void Clear() noexcept;
 	void GrabMatches(const CharacterIndexer &ci);
 	const char *Compile(const char *pattern, Sci::Position length, bool caseSensitive, bool posix) noexcept;


Modified: scintilla/src/ScintillaBase.cxx
34 lines changed, 3 insertions(+), 31 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
 
 #include <cstddef>
 #include <cstdlib>
+#include <cstdint>
 #include <cassert>
 #include <cstring>
 
@@ -550,13 +551,8 @@ namespace Scintilla::Internal {
 class LexState : public LexInterface {
 public:
 	explicit LexState(Document *pdoc_) noexcept;
-	void SetInstance(ILexer5 *instance_);
-	// Deleted so LexState objects can not be copied.
-	LexState(const LexState &) = delete;
-	LexState(LexState &&) = delete;
-	LexState &operator=(const LexState &) = delete;
-	LexState &operator=(LexState &&) = delete;
-	~LexState() override;
+
+	// LexInterface deleted the standard operators and defined the virtual destructor so don't need to here.
 
 	const char *DescribeWordListSets();
 	void SetWordList(int n, const char *wl);
@@ -592,30 +588,6 @@ class LexState : public LexInterface {
 LexState::LexState(Document *pdoc_) noexcept : LexInterface(pdoc_) {
 }
 
-LexState::~LexState() {
-	if (instance) {
-		try {
-			instance->Release();
-		} catch (...) {
-			// ILexer5::Release must not throw, ignore if it does.
-		}
-		instance = nullptr;
-	}
-}
-
-void LexState::SetInstance(ILexer5 *instance_) {
-	if (instance) {
-		try {
-			instance->Release();
-		} catch (...) {
-			// ILexer5::Release must not throw, ignore if it does.
-		}
-		instance = nullptr;
-	}
-	instance = instance_;
-	pdoc->LexerChanged();
-}
-
 LexState *ScintillaBase::DocumentLexState() {
 	if (!pdoc->GetLexInterface()) {
 		pdoc->SetLexInterface(std::make_unique<LexState>(pdoc));


Modified: scintilla/src/Selection.cxx
3 lines changed, 0 insertions(+), 3 deletions(-)
===================================================================
@@ -194,9 +194,6 @@ Selection::Selection() : mainRange(0), moveExtends(false), tentativeMai@@ Diff output truncated at 100000 characters. @@

--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list