[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 ®exp, 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