[geany/geany] 5d4e7c: Merge pull request #2930

Thomas Martitz git-noreply at xxxxx
Wed Nov 17 15:12:03 UTC 2021


Branch:      refs/heads/master
Author:      Thomas Martitz <thomas.martitz at mailbox.org>
Committer:   GitHub <noreply at github.com>
Date:        Wed, 17 Nov 2021 15:12:03 UTC
Commit:      5d4e7cfd5b12647b4cab9bda7278abd7f63e9c2f
             https://github.com/geany/geany/commit/5d4e7cfd5b12647b4cab9bda7278abd7f63e9c2f

Log Message:
-----------
Merge pull request #2930

Update to Scintilla 5.1.4 and Lexilla 5.1.3


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/lexers/LexPython.cxx
    scintilla/lexilla/lexers/LexRust.cxx
    scintilla/lexilla/lexlib/Accessor.h
    scintilla/lexilla/lexlib/LexerBase.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/CharClassify.cxx
    scintilla/src/CharacterType.h
    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/PerLine.cxx
    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/src/XPM.cxx
    scintilla/src/XPM.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
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -114,7 +114,7 @@ class FontHandle : public Font {
 	FontHandle(FontHandle &&) = delete;
 	FontHandle &operator=(const FontHandle &) = delete;
 	FontHandle &operator=(FontHandle &&) = delete;
-	~FontHandle() {
+	~FontHandle() override {
 		if (pfd)
 			pango_font_description_free(pfd);
 		pfd = nullptr;
@@ -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
70 lines changed, 48 insertions(+), 22 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,9 @@ ScintillaGTK::~ScintillaGTK() {
 	}
 	ClearPrimarySelection();
 	wPreedit.Destroy();
+	if (settingsHandlerId) {
+		g_signal_handler_disconnect(settings, settingsHandlerId);
+	}
 }
 
 void ScintillaGTK::RealizeThis(GtkWidget *widget) {
@@ -341,6 +359,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 +696,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;
 	}
@@ -1277,7 +1300,7 @@ struct CaseMapper {
 }
 
 std::string ScintillaGTK::CaseMapString(const std::string &s, CaseMapping caseMapping) {
-	if ((s.size() == 0) || (caseMapping == CaseMapping::same))
+	if (s.empty() || (caseMapping == CaseMapping::same))
 		return s;
 
 	if (IsUnicodeMode()) {
@@ -1540,20 +1563,26 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio
 
 void ScintillaGTK::InsertSelection(GtkClipboard *clipBoard, GtkSelectionData *selectionData) {
 	const gint length = gtk_selection_data_get_length(selectionData);
+	const GdkAtom selection = gtk_selection_data_get_selection(selectionData);
 	if (length >= 0) {
-		GdkAtom selection = gtk_selection_data_get_selection(selectionData);
 		SelectionText selText;
 		GetGtkSelectionText(selectionData, selText);
 
 		UndoGroup ug(pdoc);
 		if (selection == GDK_SELECTION_CLIPBOARD) {
 			ClearSelection(multiPasteMode == MultiPaste::Each);
 		}
+		if (selection == GDK_SELECTION_PRIMARY) {
+			SetSelection(posPrimary, posPrimary);
+		}
 
 		InsertPasteShape(selText.Data(), selText.Length(),
 				 selText.rectangular ? PasteShape::rectangular : PasteShape::stream);
 		EnsureCaretVisible();
 	} else {
+		if (selection == GDK_SELECTION_PRIMARY) {
+			SetSelection(posPrimary, posPrimary);
+		}
 		GdkAtom target = gtk_selection_data_get_target(selectionData);
 		if (target == atomUTF8) {
 			// In case data is actually only stored as text/plain;charset=utf-8 not UTF8_STRING
@@ -1627,7 +1656,7 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
 	std::unique_ptr<SelectionText> newline_normalized;
 	{
 		std::string tmpstr = Document::TransformLineEnds(text->Data(), text->Length(), EndOfLine::Lf);
-		newline_normalized.reset(new SelectionText());
+		newline_normalized = std::make_unique<SelectionText>();
 		newline_normalized->Copy(tmpstr, CpUtf8, CharacterSet::Ansi, text->rectangular, false);
 		text = newline_normalized.get();
 	}
@@ -1854,12 +1883,11 @@ gint ScintillaGTK::PressThis(GdkEventButton *event) {
 			ButtonDownWithModifiers(pt, event->time, ModifierFlags(shift, ctrl, alt, meta));
 		} else if (event->button == 2) {
 			// Grab the primary selection if it exists
-			const SelectionPosition pos = SPositionFromLocation(pt, false, false, UserVirtualSpace());
+			posPrimary = SPositionFromLocation(pt, false, false, UserVirtualSpace());
 			if (OwnPrimarySelection() && primary.Empty())
 				CopySelectionRange(&primary);
 
 			sel.Clear();
-			SetSelection(pos, pos);
 			RequestSelection(GDK_SELECTION_PRIMARY);
 		} else if (event->button == 3) {
 			if (!PointInSelection(pt))
@@ -2423,7 +2451,7 @@ std::vector<int> MapImeIndicators(PangoAttrList *attrs, const char *u8Str) {
 void ScintillaGTK::SetCandidateWindowPos() {
 	// Composition box accompanies candidate box.
 	const Point pt = PointMainCaret();
-	GdkRectangle imeBox = {0}; // No need to set width
+	GdkRectangle imeBox {};
 	imeBox.x = static_cast<gint>(pt.x);
 	imeBox.y = static_cast<gint>(pt.y + std::max(4, vs.lineHeight/4));
 	// prevent overlapping with current line
@@ -2985,7 +3013,7 @@ gboolean ScintillaGTK::IdleCallback(gpointer pSci) {
 	// Idler will be automatically stopped, if there is nothing
 	// to do while idle.
 	const bool ret = sciThis->Idle();
-	if (ret == false) {
+	if (!ret) {
 		// FIXME: This will remove the idler from GTK, we don't want to
 		// remove it as it is removed automatically when this function
 		// returns false (although, it should be harmless).
@@ -3021,9 +3049,7 @@ void ScintillaGTK::SetDocPointer(Document *document) {
 		sciAccessible = ScintillaGTKAccessible::FromAccessible(accessible);
 		if (sciAccessible && pdoc) {
 			oldDoc = pdoc;
-			if (oldDoc) {
-				oldDoc->AddRef();
-			}
+			oldDoc->AddRef();
 		}
 	}
 


Modified: scintilla/gtk/ScintillaGTK.h
6 lines changed, 5 insertions(+), 1 deletions(-)
===================================================================
@@ -34,6 +34,7 @@ class ScintillaGTK : public ScintillaBase {
 	int horizontalScrollBarHeight;
 
 	SelectionText primary;
+	SelectionPosition posPrimary;
 
 	GdkEvent *evbtn;
 	guint buttonMouse;
@@ -62,6 +63,9 @@ class ScintillaGTK : public ScintillaBase {
 	GtkIMContext *im_context;
 	GUnicodeScript lastNonCommonScript;
 
+	GtkSettings *settings;
+	gulong settingsHandlerId;
+
 	// Wheel mouse support
 	unsigned int linesPerScroll;
 	gint64 lastWheelMouseTime;
@@ -89,7 +93,7 @@ class ScintillaGTK : public ScintillaBase {
 	ScintillaGTK(ScintillaGTK &&) = delete;
 	ScintillaGTK &operator=(const ScintillaGTK &) = delete;
 	ScintillaGTK &operator=(ScintillaGTK &&) = delete;
-	virtual ~ScintillaGTK();
+	~ScintillaGTK() override;
 	static ScintillaGTK *FromWidget(GtkWidget *widget) noexcept;
 	static void ClassInit(OBJECT_CLASS *object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class);
 private:


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
7 lines changed, 7 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
@@ -901,6 +907,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
 #define CARETSTYLE_BLOCK 2
 #define CARETSTYLE_OVERSTRIKE_BAR 0
 #define CARETSTYLE_OVERSTRIKE_BLOCK 0x10
+#define CARETSTYLE_CURSES 0x20
 #define CARETSTYLE_INS_MASK 0xF
 #define CARETSTYLE_BLOCK_AFTER 0x100
 #define SCI_SETCARETSTYLE 2512


Modified: scintilla/include/Scintilla.iface
17 lines changed, 16 insertions(+), 1 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,)
 
@@ -2475,6 +2489,7 @@ val CARETSTYLE_LINE=1
 val CARETSTYLE_BLOCK=2
 val CARETSTYLE_OVERSTRIKE_BAR=0
 val CARETSTYLE_OVERSTRIKE_BLOCK=0x10
+val CARETSTYLE_CURSES=0x20
 val CARETSTYLE_INS_MASK=0xF
 val CARETSTYLE_BLOCK_AFTER=0x100
 
@@ -3113,7 +3128,7 @@ fun int DescribeKeyWordSets=4017(, stringresult descriptions)
 
 # Bit set of LineEndType enumertion for which line ends beyond the standard
 # LF, CR, and CRLF are supported by the lexer.
-get int GetLineEndTypesSupported=4018(,)
+get LineEndType GetLineEndTypesSupported=4018(,)
 
 # Allocate a set of sub styles for a particular base style, returning start of range
 fun int AllocateSubStyles=4020(int styleBase, int numberStyles)


Modified: scintilla/include/ScintillaCall.h
6 lines changed, 5 insertions(+), 1 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);
@@ -850,7 +854,7 @@ class ScintillaCall {
 	std::string DescribeProperty(const char *name);
 	int DescribeKeyWordSets(char *descriptions);
 	std::string DescribeKeyWordSets();
-	int LineEndTypesSupported();
+	Scintilla::LineEndType LineEndTypesSupported();
 	int AllocateSubStyles(int styleBase, int numberStyles);
 	int SubStylesStart(int styleBase);
 	int SubStylesLength(int styleBase);


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
3 lines changed, 3 insertions(+), 0 deletions(-)
===================================================================
@@ -180,6 +180,8 @@ enum class Element {
 	WhiteSpaceBack = 61,
 	HotSpotActive = 70,
 	HotSpotActiveBack = 71,
+	FoldLine = 80,
+	HiddenLine = 81,
 };
 
 enum class Layer {
@@ -437,6 +439,7 @@ enum class CaretStyle {
 	Block = 2,
 	OverstrikeBar = 0,
 	OverstrikeBlock = 0x10,
+	Curses = 0x20,
 	InsMask = 0xF,
 	BlockAfter = 0x100,
 };


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/lexers/LexPython.cxx
21 lines changed, 11 insertions(+), 10 deletions(-)
===================================================================
@@ -71,7 +71,7 @@ bool IsPyComment(Accessor &styler, Sci_Position pos, Sci_Position len) {
 	return len > 0 && styler[pos] == '#';
 }
 
-bool IsPyStringTypeChar(int ch, literalsAllowed allowed) noexcept {
+constexpr bool IsPyStringTypeChar(int ch, literalsAllowed allowed) noexcept {
 	return
 		((allowed & litB) && (ch == 'b' || ch == 'B')) ||
 		((allowed & litU) && (ch == 'u' || ch == 'U')) ||
@@ -93,17 +93,17 @@ bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) n
 	return false;
 }
 
-bool IsPyFStringState(int st) noexcept {
+constexpr bool IsPyFStringState(int st) noexcept {
 	return ((st == SCE_P_FCHARACTER) || (st == SCE_P_FSTRING) ||
 		(st == SCE_P_FTRIPLE) || (st == SCE_P_FTRIPLEDOUBLE));
 }
 
-bool IsPySingleQuoteStringState(int st) noexcept {
+constexpr bool IsPySingleQuoteStringState(int st) noexcept {
 	return ((st == SCE_P_CHARACTER) || (st == SCE_P_STRING) ||
 		(st == SCE_P_FCHARACTER) || (st == SCE_P_FSTRING));
 }
 
-bool IsPyTripleQuoteStringState(int st) noexcept {
+constexpr bool IsPyTripleQuoteStringState(int st) noexcept {
 	return ((st == SCE_P_TRIPLE) || (st == SCE_P_TRIPLEDOUBLE) ||
 		(st == SCE_P_FTRIPLE) || (st == SCE_P_FTRIPLEDOUBLE));
 }
@@ -232,7 +232,7 @@ struct OptionsPython {
 	bool foldCompact;
 	bool unicodeIdentifiers;
 
-	OptionsPython() {
+	OptionsPython() noexcept {
 		whingeLevel = 0;
 		base2or8Literals = true;
 		stringsU = true;
@@ -436,6 +436,8 @@ Sci_Position SCI_METHOD LexerPython::WordListSet(int n, const char *wl) {
 	case 1:
 		wordListN = &keywords2;
 		break;
+	default:
+		break;
 	}
 	Sci_Position firstModification = -1;
 	if (wordListN) {
@@ -635,7 +637,7 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
 						style = SCE_P_WORD2;
 					}
 				} else {
-					int subStyle = classifierIdentifiers.ValueFor(s);
+					const int subStyle = classifierIdentifiers.ValueFor(s);
 					if (subStyle >= 0) {
 						style = subStyle;
 					}
@@ -895,8 +897,8 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
 			const int style = styler.StyleAt(lookAtPos) & 31;
 			quote = options.foldQuotes && IsPyTripleQuoteStringState(style);
 		}
-		const int quote_start = (quote && !prevQuote);
-		const int quote_continue = (quote && prevQuote);
+		const bool quote_start = (quote && !prevQuote);
+		const bool quote_continue = (quote && prevQuote);
 		if (!quote || !prevQuote)
 			indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
 		if (quote)
@@ -921,8 +923,7 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
 		int minCommentLevel = indentCurrentLevel;
 		while (!quote &&
 				(lineNext < docLines) &&
-				((indentNext & SC_FOLDLEVELWHITEFLAG) ||
-				 (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {
+				((indentNext & SC_FOLDLEVELWHITEFLAG) || (IsCommentLine(lineNext, styler)))) {
 
 			if (IsCommentLine(lineNext, styler) && indentNext < minCommentLevel) {
 				minCommentLevel = indentNext;


Modified: scintilla/lexilla/lexers/LexRust.cxx
12 lines changed, 5 insertions(+), 7 deletions(-)
===================================================================
@@ -286,6 +286,8 @@ static void ScanNumber(Accessor& styler, Sci_Position& pos) {
 			pos += 2;
 		} else if (c == '6' && n == '4') {
 			pos += 2;
+		} else if (styler.Match(pos, "128")) {
+			pos += 3;
 		} else if (styler.Match(pos, "size")) {
 			pos += 4;
 		} else {
@@ -524,7 +526,7 @@ static void ResumeBlockComment(Accessor &styler, Sci_Position& pos, Sci_Position
 				level++;
 			}
 		}
-		else {
+		else if (pos < max) {
 			pos++;
 		}
 		if (pos >= max) {
@@ -557,12 +559,8 @@ static void ResumeLineComment(Accessor &styler, Sci_Position& pos, Sci_Position
 		maybe_doc_comment = true;
 	}
 
-	while (pos < max && c != '\n') {
-		if (pos == styler.LineEnd(styler.GetLine(pos)))
-			styler.SetLineState(styler.GetLine(pos), 0);
-		pos++;
-		c = styler.SafeGetCharAt(pos, '\0');
-	}
+	pos = styler.LineEnd(styler.GetLine(pos));
+	styler.SetLineState(styler.GetLine(pos), SCE_RUST_DEFAULT);
 
 	if (state == DocComment || (state == UnknownComment && maybe_doc_comment))
 		styler.ColourTo(pos - 1, SCE_RUST_COMMENTLINEDOC);


Modified: scintilla/lexilla/lexlib/Accessor.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -23,7 +23,7 @@ class Accessor : public LexAccessor {
 	PropSetSimple *pprops;
 	Accessor(Scintilla::IDocument *pAccess_, PropSetSimple *pprops_);
 	int GetPropertyInt(std::string_view key, int defaultValue=0) const;
-	int IndentAmount(Sci_Position line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0);
+	int IndentAmount(Sci_Position line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = nullptr);
 };
 
 }


Modified: scintilla/lexilla/lexlib/LexerBase.cxx
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -31,15 +31,15 @@ LexerBase::LexerBase(const LexicalClass *lexClasses_, size_t nClasses_) :
 	lexClasses(lexClasses_), nClasses(nClasses_) {
 	for (int wl = 0; wl < numWordLists; wl++)
 		keyWordLists[wl] = new WordList;
-	keyWordLists[numWordLists] = 0;
+	keyWordLists[numWordLists] = nullptr;
 }
 
 LexerBase::~LexerBase() {
 	for (int wl = 0; wl < numWordLists; wl++) {
 		delete keyWordLists[wl];
-		keyWordLists[wl] = 0;
+		keyWordLists[wl] = nullptr;
 	}
-	keyWordLists[numWordLists] = 0;
+	keyWordLists[numWordLists] = nullptr;
 }
 
 void SCI_METHOD LexerBase::Release() {


Modified: scintilla/lexilla/lexlib/WordList.cxx
93 lines changed, 38 insertions(+), 55 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;
 }
@@ -71,84 +80,58 @@ WordList::~WordList() {
 }
 
 WordList::operator bool() const noexcept {
-	return len ? true : false;
+	return len != 0;
 }
 
 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;
 	}
@@ -161,7 +144,7 @@ bool WordList::Set(const char *s) {
  * so '^GTK_' matches 'GTK_X', 'GTK_MAJOR_VERSION', and 'GTK_'.
  */
 bool WordList::InList(const char *s) const noexcept {
-	if (0 == words)
+	if (!words)
 		return false;
 	const unsigned char firstChar = s[0];
 	int j = starts[firstChar];
@@ -203,7 +186,7 @@ bool WordList::InList(const char *s) const noexcept {
  * The marker is ~ in this case.
  */
 bool WordList::InListAbbreviated(const char *s, const char marker) const noexcept {
-	if (0 == words)
+	if (!words)
 		return false;
 	const unsigned char firstChar = s[0];
 	int j = starts[firstChar];
@@ -257,7 +240,7 @@ bool WordList::InListAbbreviated(const char *s, const char marker) const noexcep
 * No multiple markers check is done and wont work.
 */
 bool WordList::InListAbridged(const char *s, const char marker) const noexcept {
-	if (0 == words)
+	if (!words)
 		return false;
 	const unsigned char firstChar = s[0];
 	int j = starts[firstChar];


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
+513


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
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -37,7 +37,7 @@ struct CountWidths {
 	// from the Base Multilingual Plane and those from other planes.
 	Sci::Position countBasePlane;
 	Sci::Position countOtherPlanes;
-	CountWidths(Sci::Position countBasePlane_=0, Sci::Position countOtherPlanes_=0) noexcept :
+	explicit CountWidths(Sci::Position countBasePlane_=0, Sci::Position countOtherPlanes_=0) noexcept :
 		countBasePlane(countBasePlane_),
 		countOtherPlanes(countOtherPlanes_) {
 	}
@@ -523,7 +523,7 @@ void UndoHistory::TentativeCommit() {
 }
 
 bool UndoHistory::TentativeActive() const noexcept {
-	return tentativePoint >= 0; 
+	return tentativePoint >= 0;
 }
 
 int UndoHistory::TentativeSteps() noexcept {
@@ -1286,7 +1286,7 @@ void CellBuffer::EndUndoAction() {
 }
 
 void CellBuffer::AddUndoAction(Sci::Position token, bool mayCoalesce) {
-	bool startSequence;
+	bool startSequence = false;
 	uh.AppendAction(ActionType::container, token, nullptr, 0, startSequence, mayCoalesce);
 }
 


Modified: scintilla/src/CharClassify.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -24,7 +24,7 @@ void CharClassify::SetDefaultCharClasses(bool includeWordClass) {
 	for (int ch = 0; ch < maxChar; ch++) {
 		if (ch == '\r' || ch == '\n')
 			charClass[ch] = CharacterClass::newLine;
-		else if (ch < 0x20 || ch == ' ')
+		else if (IsControl(ch) || ch == ' ')
 			charClass[ch] = CharacterClass::space;
 		else if (includeWordClass && (ch >= 0x80 || IsAlphaNumeric(ch) || ch == '_'))
 			charClass[ch] = CharacterClass::word;


Modified: scintilla/src/CharacterType.h
84 lines changed, 57 insertions(+), 27 deletions(-)
===================================================================
@@ -12,14 +12,33 @@ namespace Scintilla::Internal {
 
 // Functions for classifying characters
 
+/**
+ * Check if a character is a space.
+ * This is ASCII specific but is safe with chars >= 0x80.
+ */
 constexpr bool IsASpace(int ch) noexcept {
     return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
 }
 
-constexpr bool IsASpaceOrTab(int ch) noexcept {
+constexpr bool IsSpaceOrTab(int ch) noexcept {
 	return (ch == ' ') || (ch == '\t');
 }
 
+constexpr bool IsControl(int ch) noexcept {
+	return ((ch >= 0) && (ch <= 0x1F)) || (ch == 0x7F);
+}
+
+constexpr bool IsEOLCharacter(int ch) noexcept {
+	return ch == '\r' || ch == '\n';
+}
+
+constexpr bool IsBreakSpace(int ch) noexcept {
+	// used for text breaking, treat C0 control character as space.
+	// by default C0 control character is handled as special representation,
+	// so not appears in normal text. 0x7F DEL is omitted to simplify the code.
+	return ch >= 0 && ch <= ' ';
+}
+
 constexpr bool IsADigit(int ch) noexcept {
 	return (ch >= '0') && (ch <= '9');
 }
@@ -57,33 +76,44 @@ constexpr bool IsAlphaNumeric(int ch) noexcept {
 		((ch >= 'A') && (ch <= 'Z'));
 }
 
-/**
- * Check if a character is a space.
- * This is ASCII specific but is safe with chars >= 0x80.
- */
-constexpr bool isspacechar(int ch) noexcept {
-    return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
-}
-
-constexpr bool iswordchar(int ch) noexcept {
-	return IsAlphaNumeric(ch) || ch == '.' || ch == '_';
-}
-
-constexpr bool iswordstart(int ch) noexcept {
-	return IsAlphaNumeric(ch) || ch == '_';
-}
-
-constexpr bool isoperator(int ch) noexcept {
-	if (IsAlphaNumeric(ch))
-		return false;
-	if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
-	        ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
-	        ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
-	        ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
-	        ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
-	        ch == '?' || ch == '!' || ch == '.' || ch == '~')
+constexpr bool IsPunctuation(int ch) noexcept {
+	switch (ch) {
+	case '!':
+	case '"':
+	case '#':
+	case '$':
+	case '%':
+	case '&':
+	case '\'':
+	case '(':
+	case ')':
+	case '*':
+	case '+':
+	case ',':
+	case '-':
+	case '.':
+	case '/':
+	case ':':
+	case ';':
+	case '<':
+	case '=':
+	case '>':
+	case '?':
+	case '@':
+	case '[':
+	case '\\':
+	case ']':
+	case '^':
+	case '_':
+	case '`':
+	case '{':
+	case '|':
+	case '}':
+	case '~':
 		return true;
-	return false;
+	default:
+		return false;
+	}
 }
 
 // Simple case functions for ASCII supersets.


Modified: scintilla/src/ContractionState.cxx
6 lines changed, 2 insertions(+), 4 deletions(-)
===================================================================
@@ -95,9 +95,7 @@ ContractionState<LINE>::ContractionState() noexcept : linesInDocument(1) {
 }
 
 template <typename LINE>
-ContractionState<LINE>::~ContractionState() {
-	Clear();
-}
+ContractionState<LINE>::~ContractionState() = default;
 
 template <typename LINE>
 void ContractionState<LINE>::EnsureData() {
@@ -197,7 +195,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
211 lines changed, 98 insertions(+), 113 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_) {
 }
@@ -1113,53 +1127,74 @@ bool Document::IsDBCSDualByteAt(Sci::Position pos) const noexcept {
 		&& IsDBCSTrailByteNoExcept(cb.CharAt(pos + 1));
 }
 
-static constexpr bool IsSpaceOrTab(int ch) noexcept {
-	return ch == ' ' || ch == '\t';
-}
-
-// Need to break text into segments near lengthSegment but taking into
-// account the encoding to not break inside a UTF-8 or DBCS character
-// and also trying to avoid breaking inside a pair of combining characters.
+// Need to break text into segments near end but taking into account the
+// encoding to not break inside a UTF-8 or DBCS character and also trying
+// to avoid breaking inside a pair of combining characters, or inside
+// ligatures.
+// TODO: implement grapheme cluster boundaries,
+// see https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries.
+//
 // The segment length must always be long enough (more than 4 bytes)
 // so that there will be at least one whole character to make a segment.
 // For UTF-8, text must consist only of valid whole characters.
 // In preference order from best to worst:
-//   1) Break after space
-//   2) Break before punctuation
-//   3) Break after whole character
-
-int Document::SafeSegment(const char *text, int length, int lengthSegment) const noexcept {
-	if (length <= lengthSegment)
-		return length;
-	int lastSpaceBreak = -1;
-	int lastPunctuationBreak = -1;
-	int lastEncodingAllowedBreak = 0;
-	for (int j=0; j < lengthSegment;) {
-		const unsigned char ch = text[j];
-		if (j > 0) {
-			if (IsSpaceOrTab(text[j - 1]) && !IsSpaceOrTab(text[j])) {
-				lastSpaceBreak = j;
+//   1) Break before or after spaces or controls
+//   2) Break at word and punctuation boundary for better kerning and ligature support
+//   3) Break after whole character, this may break combining characters
+
+size_t Document::SafeSegment(std::string_view text) const noexcept {
+	// check space first as most written language use spaces.
+	for (std::string_view::iterator it = text.end() - 1; it != text.begin(); --it) {
+		if (IsBreakSpace(*it)) {
+			return it - text.begin();
+		}
+	}
+
+	if (!dbcsCodePage || dbcsCodePage == CpUtf8) {
+		// backward iterate for UTF-8 and single byte encoding to find word and punctuation boundary.
+		std::string_view::iterator it = text.end() - 1;
+		const bool punctuation = IsPunctuation(*it);
+		do {
+			--it;
+			if (punctuation != IsPunctuation(*it)) {
+				return it - text.begin() + 1;
 			}
-			if (ch < 'A') {
-				lastPunctuationBreak = j;
+		} while (it != text.begin());
+
+		it = text.end() - 1;
+		if (dbcsCodePage) {
+			// for UTF-8 go back to the start of last character.
+			for (int trail = 0; trail < UTF8MaxBytes - 1 && UTF8IsTrailByte(*it); trail++) {
+				--it;
 			}
 		}
-		lastEncodingAllowedBreak = j;
+		return it - text.begin();
+	}
 
-		if (dbcsCodePage == CpUtf8) {
-			j += UTF8BytesOfLead[ch];
-		} else if (dbcsCodePage) {
-			j += IsDBCSLeadByteNoExcept(ch) ? 2 : 1;
-		} else {
-			j++;
+	{
+		// forward iterate for DBCS to find word and punctuation boundary.
+		size_t lastPunctuationBreak = 0;
+		size_t lastEncodingAllowedBreak = 0;
+		CharacterClass ccPrev = CharacterClass::space;
+		for (size_t j = 0; j < text.length();) {
+			const unsigned char ch = text[j];
+			lastEncodingAllowedBreak = j++;
+
+			CharacterClass cc = CharacterClass::word;
+			if (UTF8IsAscii(ch)) {
+				if (IsPunctuation(ch)) {
+					cc = CharacterClass::punctuation;
+				}
+			} else {
+				j += IsDBCSLeadByteNoExcept(ch);
+			}
+			if (cc != ccPrev) {
+				ccPrev = cc;
+				lastPunctuationBreak = lastEncodingAllowedBreak;
+			}
 		}
+		return lastPunctuationBreak ? lastPunctuationBreak : lastEncodingAllowedBreak;
 	}
-	if (lastSpaceBreak >= 0) {
-		return lastSpaceBreak;
-	} else if (lastPunctuationBreak >= 0) {
-		return lastPunctuationBreak;
-	}
-	return lastEncodingAllowedBreak;
 }
 
 EncodingFamily Document::CodePageFamily() const noexcept {
@@ -1204,7 +1239,7 @@ bool Document::DeleteChars(Sci::Position pos, Sci::Position len) {
 			    DocModification(
 			        ModificationFlags::BeforeDelete | ModificationFlags::User,
 			        pos, len,
-			        0, 0));
+				0, nullptr));
 			const Sci::Line prevLinesTotal = LinesTotal();
 			const bool startSavePoint = cb.IsSavePoint();
 			bool startSequence = false;
@@ -2067,7 +2102,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) {
@@ -2405,7 +2440,7 @@ Sci::Line Document::GetMaxLineState() const noexcept {
 
 void SCI_METHOD Document::ChangeLexerState(Sci_Position start, Sci_Position end) {
 	const DocModification mh(ModificationFlags::LexerState, start,
-		end-start, 0, 0, 0);
+		end-start, 0, nullptr, 0);
 	NotifyModified(mh);
 }
 
@@ -2418,20 +2453,20 @@ StyledText Document::MarginStyledText(Sci::Line line) const noexcept {
 void Document::MarginSetText(Sci::Line line, const char *text) {
 	Margins()->SetText(line, text);
 	const DocModification mh(ModificationFlags::ChangeMargin, LineStart(line),
-		0, 0, 0, line);
+		0, 0, nullptr, line);
 	NotifyModified(mh);
 }
 
 void Document::MarginSetStyle(Sci::Line line, int style) {
 	Margins()->SetStyle(line, style);
 	NotifyModified(DocModification(ModificationFlags::ChangeMargin, LineStart(line),
-		0, 0, 0, line));
+		0, 0, nullptr, line));
 }
 
 void Document::MarginSetStyles(Sci::Line line, const unsigned char *styles) {
 	Margins()->SetStyles(line, styles);
 	NotifyModified(DocModification(ModificationFlags::ChangeMargin, LineStart(line),
-		0, 0, 0, line));
+		0, 0, nullptr, line));
 }
 
 void Document::MarginClearAll() {
@@ -2454,7 +2489,7 @@ void Document::AnnotationSetText(Sci::Line line, const char *text) {
 		Annotations()->SetText(line, text);
 		const int linesAfter = AnnotationLines(line);
 		DocModification mh(ModificationFlags::ChangeAnnotation, LineStart(line),
-			0, 0, 0, line);
+			0, 0, nullptr, line);
 		mh.annotationLinesAdded = linesAfter - linesBefore;
 		NotifyModified(mh);
 	}
@@ -2464,7 +2499,7 @@ void Document::AnnotationSetStyle(Sci::Line line, int style) {
 	if (line >= 0 && line < LinesTotal()) {
 		Annotations()->SetStyle(line, style);
 		const DocModification mh(ModificationFlags::ChangeAnnotation, LineStart(line),
-			0, 0, 0, line);
+			0, 0, nullptr, line);
 		NotifyModified(mh);
 	}
 }
@@ -2497,7 +2532,7 @@ void Document::EOLAnnotationSetText(Sci::Line line, const char *text) {
 	if (line >= 0 && line < LinesTotal()) {
 		EOLAnnotations()->SetText(line, text);
 		const DocModification mh(ModificationFlags::ChangeEOLAnnotation, LineStart(line),
-			0, 0, 0, line);
+			0, 0, nullptr, line);
 		NotifyModified(mh);
 	}
 }
@@ -2506,7 +2541,7 @@ void Document::EOLAnnotationSetStyle(Sci::Line line, int style) {
 	if (line >= 0 && line < LinesTotal()) {
 		EOLAnnotations()->SetStyle(line, style);
 		const DocModification mh(ModificationFlags::ChangeEOLAnnotation, LineStart(line),
-			0, 0, 0, line);
+			0, 0, nullptr, line);
 		NotifyModified(mh);
 	}
 }
@@ -2586,49 +2621,8 @@ void Document::NotifyModified(DocModification mh) {
 	}
 }
 
-// Used for word part navigation.
-static bool IsASCIIPunctuationCharacter(unsigned int ch) noexcept {
-	switch (ch) {
-	case '!':
-	case '"':
-	case '#':
-	case '$':
-	case '%':
-	case '&':
-	case '\'':
-	case '(':
-	case ')':
-	case '*':
-	case '+':
-	case ',':
-	case '-':
-	case '.':
-	case '/':
-	case ':':
-	case ';':
-	case '<':
-	case '=':
-	case '>':
-	case '?':
-	case '@':
-	case '[':
-	case '\\':
-	case ']':
-	case '^':
-	case '_':
-	case '`':
-	case '{':
-	case '|':
-	case '}':
-	case '~':
-		return true;
-	default:
-		return false;
-	}
-}
-
 bool Document::IsWordPartSeparator(unsigned int ch) const {
-	return (WordCharacterClass(ch) == CharacterClass::word) && IsASCIIPunctuationCharacter(ch);
+	return (WordCharacterClass(ch) == CharacterClass::word) && IsPunctuation(ch);
 }
 
 Sci::Position Document::WordPartLeft(Sci::Position pos) const {
@@ -2658,15 +2652,15 @@ Sci::Position Document::WordPartLeft(Sci::Position pos) const {
 					pos -= CharacterBefore(pos).widthBytes;
 				if (!IsADigit(CharacterAfter(pos).character))
 					pos += CharacterAfter(pos).widthBytes;
-			} else if (IsASCIIPunctuationCharacter(ceStart.character)) {
-				while (pos > 0 && IsASCIIPunctuationCharacter(CharacterAfter(pos).character))
+			} else if (IsPunctuation(ceStart.character)) {
+				while (pos > 0 && IsPunctuation(CharacterAfter(pos).character))
 					pos -= CharacterBefore(pos).widthBytes;
-				if (!IsASCIIPunctuationCharacter(CharacterAfter(pos).character))
+				if (!IsPunctuation(CharacterAfter(pos).character))
 					pos += CharacterAfter(pos).widthBytes;
-			} else if (isspacechar(ceStart.character)) {
-				while (pos > 0 && isspacechar(CharacterAfter(pos).character))
+			} else if (IsASpace(ceStart.character)) {
+				while (pos > 0 && IsASpace(CharacterAfter(pos).character))
 					pos -= CharacterBefore(pos).widthBytes;
-				if (!isspacechar(CharacterAfter(pos).character))
+				if (!IsASpace(CharacterAfter(pos).character))
 					pos += CharacterAfter(pos).widthBytes;
 			} else if (!IsASCII(ceStart.character)) {
 				while (pos > 0 && !IsASCII(CharacterAfter(pos).character))
@@ -2709,30 +2703,26 @@ Sci::Position Document::WordPartRight(Sci::Position pos) const {
 	} else if (IsADigit(ceStart.character)) {
 		while (pos < length && IsADigit(CharacterAfter(pos).character))
 			pos += CharacterAfter(pos).widthBytes;
-	} else if (IsASCIIPunctuationCharacter(ceStart.character)) {
-		while (pos < length && IsASCIIPunctuationCharacter(CharacterAfter(pos).character))
+	} else if (IsPunctuation(ceStart.character)) {
+		while (pos < length && IsPunctuation(CharacterAfter(pos).character))
 			pos += CharacterAfter(pos).widthBytes;
-	} else if (isspacechar(ceStart.character)) {
-		while (pos < length && isspacechar(CharacterAfter(pos).character))
+	} else if (IsASpace(ceStart.character)) {
+		while (pos < length && IsASpace(CharacterAfter(pos).character))
 			pos += CharacterAfter(pos).widthBytes;
 	} else {
 		pos += CharacterAfter(pos).widthBytes;
 	}
 	return pos;
 }
 
-static constexpr bool IsLineEndChar(char c) noexcept {
-	return (c == '\n' || c == '\r');
-}
-
 Sci::Position Document::ExtendStyleRange(Sci::Position pos, int delta, bool singleLine) noexcept {
-	const int sStart = cb.StyleAt(pos);
+	const char sStart = cb.StyleAt(pos);
 	if (delta < 0) {
-		while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))))
+		while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsEOLCharacter(cb.CharAt(pos))))
 			pos--;
 		pos++;
 	} else {
-		while (pos < (LengthNoExcept()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))))
+		while (pos < (LengthNoExcept()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsEOLCharacter(cb.CharAt(pos))))
 			pos++;
 	}
 	return pos;
@@ -2798,11 +2788,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,
@@ -2977,7 +2962,7 @@ class UTF8Iterator {
 	typedef wchar_t* pointer;
 	typedef wchar_t& reference;
 
-	UTF8Iterator(const Document *doc_=nullptr, Sci::Position position_=0) noexcept :
+	explicit UTF8Iterator(const Document *doc_=nullptr, Sci::Position position_=0) noexcept :
 		doc(doc_), position(position_), characterIndex(0), lenBytes(0), lenCharacters(0), buffered{} {
 		buffered[0] = 0;
 		buffered[1] = 0;
@@ -3199,7 +3184,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
40 lines changed, 30 insertions(+), 10 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 {
@@ -332,7 +352,7 @@ class Document : PerLine, public Scintilla::IDocument, public Scintilla::ILoader
 	bool IsDBCSTrailByteNoExcept(char ch) const noexcept;
 	int DBCSDrawBytes(std::string_view text) const noexcept;
 	bool IsDBCSDualByteAt(Sci::Position pos) const noexcept;
-	int SafeSegment(const char *text, int length, int lengthSegment) const noexcept;
+	size_t SafeSegment(std::string_view text) const noexcept;
 	EncodingFamily CodePageFamily() const noexcept;
 
 	// Gateways to modifying document


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
202 lines changed, 120 insertions(+), 82 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
 
 #include <cstddef>
 #include <cstdlib>
+#include <cstdint>
 #include <cassert>
 #include <cstring>
 #include <cstdio>
@@ -367,12 +368,6 @@ inline char CaseForce(Style::CaseForce caseForce, char chDoc, char chPrevious) n
 	}
 }
 
-constexpr bool IsControlCharacter(int ch) noexcept {
-	// iscntrl returns true for lots of chars > 127 which are displayable,
-	// currently only check C0 control characters.
-	return (ch >= 0 && ch < ' ') || (ch == 127);
-}
-
 bool ViewIsASCII(std::string_view text) {
 	return std::all_of(text.cbegin(), text.cend(), IsASCII);
 }
@@ -469,7 +464,7 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
 		ll->positions[0] = 0;
 		bool lastSegItalics = false;
 
-		BreakFinder bfLayout(ll, nullptr, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs, nullptr);
+		BreakFinder bfLayout(ll, nullptr, Range(0, numCharsInLine), posLineStart, 0, BreakFinder::BreakFor::Text, model.pdoc, &model.reprs, nullptr);
 		while (bfLayout.More()) {
 
 			const TextSegment ts = bfLayout.Next();
@@ -569,46 +564,55 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
 				ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual
 			ll->lines = 0;
 			// Calculate line start positions based upon width.
-			Sci::Position lastGoodBreak = 0;
 			Sci::Position lastLineStart = 0;
-			XYACCUMULATOR startOffset = 0;
+			XYACCUMULATOR startOffset = width;
 			Sci::Position p = 0;
-			while (p < ll->numCharsInLine) {
-				if ((ll->positions[p + 1] - startOffset) >= width) {
+			const Wrap wrapState = vstyle.wrap.state;
+			const Sci::Position numCharsInLine = ll->numCharsInLine;
+			while (p < numCharsInLine) {
+				while (p < numCharsInLine && ll->positions[p + 1] < startOffset) {
+					p++;
+				}
+				if (p < numCharsInLine) {
+					// backtrack to find lastGoodBreak
+					Sci::Position lastGoodBreak = p;
+					if (p > 0) {
+						lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) - posLineStart;
+					}
+					if (wrapState != Wrap::Char) {
+						Sci::Position pos = lastGoodBreak;
+						while (pos > lastLineStart) {
+							// style boundary and space
+							if (wrapState != Wrap::WhiteSpace && (ll->styles[pos - 1] != ll->styles[pos])) {
+								break;
+							}
+							if (IsBreakSpace(ll->chars[pos - 1]) && !IsBreakSpace(ll->chars[pos])) {
+								break;
+							}
+							pos = model.pdoc->MovePositionOutsideChar(pos + posLineStart - 1, -1) - posLineStart;
+						}
+						if (pos > lastLineStart) {
+							lastGoodBreak = pos;
+						}
+					}
 					if (lastGoodBreak == lastLineStart) {
 						// Try moving to start of last character
 						if (p > 0) {
-							lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1)
-								- posLineStart;
+							lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) - posLineStart;
 						}
 						if (lastGoodBreak == lastLineStart) {
 							// Ensure at least one character on line.
-							lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1)
-								- posLineStart;
+							lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1) - posLineStart;
 						}
 					}
 					lastLineStart = lastGoodBreak;
 					ll->lines++;
-					ll->SetLineStart(ll->lines, static_cast<int>(lastGoodBreak));
-					startOffset = ll->positions[lastGoodBreak];
+					ll->SetLineStart(ll->lines, static_cast<int>(lastLineStart));
+					startOffset = ll->positions[lastLineStart];
 					// take into account the space for start wrap mark and indent
-					startOffset -= ll->wrapIndent;
-					p = lastGoodBreak + 1;
-					continue;
+					startOffset += width - ll->wrapIndent;
+					p = lastLineStart + 1;
 				}
-				if (p > 0) {
-					if (vstyle.wrap.state == Wrap::Char) {
-						lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1)
-							- posLineStart;
-						p = model.pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
-						continue;
-					} else if ((vstyle.wrap.state == Wrap::Word) && (ll->styles[p] != ll->styles[p - 1])) {
-						lastGoodBreak = p;
-					} else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) {
-						lastGoodBreak = p;
-					}
-				}
-				p++;
 			}
 			ll->lines++;
 		}
@@ -951,19 +955,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 +1462,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 +1607,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)
@@ -1635,7 +1639,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
 			}
 			const bool caretBlinkState = (model.caret.active && model.caret.on) || (!additionalCaretsBlink && !mainCaret);
 			const bool caretVisibleState = additionalCaretsVisible || mainCaret;
-			if ((xposCaret >= 0) && vsDraw.IsCaretVisible() &&
+			if ((xposCaret >= 0) && vsDraw.IsCaretVisible(mainCaret) &&
 				(drawDrag || (caretBlinkState && caretVisibleState))) {
 				bool canDrawBlockCaret = true;
 				bool drawBlockCaret = false;
@@ -1659,7 +1663,8 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
 				if (xposCaret > 0)
 					caretWidthOffset = 0.51f;	// Move back so overlaps both character cells.
 				xposCaret += xStart;
-				const ViewStyle::CaretShape caretShape = drawDrag ? ViewStyle::CaretShape::line : vsDraw.CaretShapeForMode(model.inOverstrike);
+				const ViewStyle::CaretShape caretShape = drawDrag ? ViewStyle::CaretShape::line :
+					vsDraw.CaretShapeForMode(model.inOverstrike, mainCaret);
 				if (drawDrag) {
 					/* Dragging text, use a line caret */
 					rcCaret.left = std::round(xposCaret - caretWidthOffset);
@@ -1672,7 +1677,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
 				} else if ((caretShape == ViewStyle::CaretShape::block) || imeCaretBlockOverride) {
 					/* Block caret */
 					rcCaret.left = xposCaret;
-					if (canDrawBlockCaret && !(IsControlCharacter(ll->chars[offset]))) {
+					if (canDrawBlockCaret && !(IsControl(ll->chars[offset]))) {
 						drawBlockCaret = true;
 						rcCaret.right = xposCaret + widthOverstrikeCaret;
 					} else {
@@ -1732,6 +1737,21 @@ static void DrawWrapIndentAndMarker(Surface *surface, const ViewStyle &vsDraw, c
 	}
 }
 
+// On the curses platform, the terminal is drawing its own caret, so if the caret is within
+// the main selection, do not draw the selection at that position.
+// Use iDoc from DrawBackground and DrawForeground here because TextSegment has been adjusted
+// such that, if the caret is inside the main selection, the beginning or end of that selection
+// is at the end of a text segment.
+// This function should only be called if iDoc is within the main selection.
+static InSelection CharacterInCursesSelection(Sci::Position iDoc, const EditModel &model, const ViewStyle &vsDraw) {
+	const SelectionPosition &posCaret = model.sel.RangeMain().caret;
+	const bool caretAtStart = posCaret < model.sel.RangeMain().anchor && posCaret.Position() == iDoc;
+	const bool caretAtEnd = posCaret > model.sel.RangeMain().anchor &&
+		vsDraw.DrawCaretInsideSelection(false, false) &&
+		model.pdoc->MovePositionOutsideChar(posCaret.Position() - 1, -1) == iDoc;
+	return (caretAtStart || caretAtEnd) ? InSelection::inNone : InSelection::inMain;
+}
+
 void EditView::DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
 	PRectangle rcLine, Range lineRange, Sci::Position posLineStart, int xStart,
 	int subLine, std::optional<ColourRGBA> background) const {
@@ -1742,7 +1762,8 @@ void EditView::DrawBackground(Surface *surface, const EditModel &model, const Vi
 	// Does not take margin into account but not significant
 	const XYPOSITION xStartVisible = static_cast<XYPOSITION>(subLineStart-xStart);
 
-	BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs, nullptr);
+	const BreakFinder::BreakFor breakFor = selBackDrawn ? BreakFinder::BreakFor::Selection : BreakFinder::BreakFor::Text;
+	BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, breakFor, model.pdoc, &model.reprs, &vsDraw);
 
 	const bool drawWhitespaceBackground = vsDraw.WhitespaceBackgroundDrawn() && !background;
 
@@ -1765,8 +1786,10 @@ void EditView::DrawBackground(Surface *surface, const EditModel &model, const Vi
 			if (rcSegment.right > rcLine.right)
 				rcSegment.right = rcLine.right;
 
-			const InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc);
-			const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc);
+			InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc);
+			if (FlagSet(vsDraw.caret.style, CaretStyle::Curses) && (inSelection == InSelection::inMain))
+				inSelection = CharacterInCursesSelection(iDoc, model, vsDraw);
+			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) {
@@ -1958,8 +1981,9 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
 	const XYPOSITION xStartVisible = static_cast<XYPOSITION>(subLineStart-xStart);
 
 	// Foreground drawing loop
-	BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible,
-		(((phasesDraw == PhasesDraw::One) && selBackDrawn) || vsDraw.SelectionTextDrawn()), model.pdoc, &model.reprs, &vsDraw);
+	const BreakFinder::BreakFor breakFor = (((phasesDraw == PhasesDraw::One) && selBackDrawn) || vsDraw.SelectionTextDrawn())
+		? BreakFinder::BreakFor::ForegroundAndSelection : BreakFinder::BreakFor::Foreground;
+	BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible, breakFor, model.pdoc, &model.reprs, &vsDraw);
 
 	while (bfFore.More()) {
 
@@ -1977,7 +2001,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);
@@ -2009,7 +2033,9 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
 					}
 				}
 			}
-			const InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc);
+			InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc);
+			if (FlagSet(vsDraw.caret.style, CaretStyle::Curses) && (inSelection == InSelection::inMain))
+				inSelection = CharacterInCursesSelection(iDoc, model, vsDraw);
 			const std::optional<ColourRGBA> selectionFore = SelectionForeground(model, vsDraw, inSelection);
 			if (selectionFore) {
 				textFore = *selectionFore;
@@ -2124,7 +2150,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 +2307,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 +2366,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 +2435,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 +2470,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 +2616,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 +2726,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
60 lines changed, 44 insertions(+), 16 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));
 }
 
@@ -756,9 +772,9 @@ void Editor::MultipleSelectAdd(AddNumber addNumber) {
 			searchRanges.push_back(rangeTarget);
 		}
 
-		for (std::vector<Range>::const_iterator it = searchRanges.begin(); it != searchRanges.end(); ++it) {
-			Sci::Position searchStart = it->start;
-			const Sci::Position searchEnd = it->end;
+		for (const Range range : searchRanges) {
+			Sci::Position searchStart = range.start;
+			const Sci::Position searchEnd = range.end;
 			for (;;) {
 				Sci::Position lengthFound = selectedText.length();
 				const Sci::Position pos = pdoc->FindText(searchStart, searchEnd,
@@ -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);
 
@@ -2174,10 +2193,10 @@ void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, Sci::Posit
 	sel.RangeMain().caret = RealizeVirtualSpace(sel.RangeMain().caret);
 	const int xInsert = XFromPosition(sel.RangeMain().caret);
 	bool prevCr = false;
-	while ((len > 0) && IsEOLChar(ptr[len-1]))
+	while ((len > 0) && IsEOLCharacter(ptr[len-1]))
 		len--;
 	for (Sci::Position i = 0; i < len; i++) {
-		if (IsEOLChar(ptr[i])) {
+		if (IsEOLCharacter(ptr[i])) {
 			if ((ptr[i] == '\r') || (!prevCr))
 				line++;
 			if (line >= pdoc->LinesTotal()) {
@@ -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;
@@ -7564,7 +7592,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
 		return vs.ElementColour(Element::Caret)->OpaqueRGB();
 
 	case Message::SetCaretStyle:
-		if (static_cast<CaretStyle>(wParam) <= (CaretStyle::Block | CaretStyle::OverstrikeBlock | CaretStyle::BlockAfter))
+		if (static_cast<CaretStyle>(wParam) <= (CaretStyle::Block | CaretStyle::OverstrikeBlock | CaretStyle::Curses | CaretStyle::BlockAfter))
 			vs.caret.style = static_cast<CaretStyle>(wParam);
 		else
 			/* Default to the line caret */
@@ -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 inse@@ 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