[geany/geany] 6d109b: Update to Scintilla 5.1.3 and Lexilla 5.1.2
Thomas Martitz
git-noreply at xxxxx
Mon Nov 15 06:46:40 UTC 2021
Branch: refs/heads/master
Author: Thomas Martitz <thomas.martitz at mailbox.org>
Committer: Thomas Martitz <thomas.martitz at mailbox.org>
Date: Mon, 15 Nov 2021 06:46:40 UTC
Commit: 6d109b309165ff0bfb17a2b21056bd498d54c032
https://github.com/geany/geany/commit/6d109b309165ff0bfb17a2b21056bd498d54c032
Log Message:
-----------
Update to Scintilla 5.1.3 and Lexilla 5.1.2
Notable changes:
Scintilla:
- Add SC_ELEMENT_FOLD_LINE to set the colour of fold lines. Add SC_ELEMENT_HIDDEN_LINE to show where lines are hidden.
- On GTK, fix the line spacing so that underscores and accents are visible for some fonts such as DejaVu Sans Mono 10.
Lexilla
- Implement conditional group rules in CSS. Issue #25, Pull request #28.
- Check PHP numeric literals, showing invalid values with default style instead of numeric. Issue #20.
The CSS change causes compatiblity trouble. We exposed the changed
style in filetypes.css. Users must update local copies.
Modified Paths:
--------------
data/filedefs/filetypes.css
scintilla/gtk/PlatGTK.cxx
scintilla/gtk/ScintillaGTK.cxx
scintilla/gtk/ScintillaGTK.h
scintilla/gtk/ScintillaGTKAccessible.cxx
scintilla/include/Scintilla.h
scintilla/include/Scintilla.iface
scintilla/include/ScintillaCall.h
scintilla/include/ScintillaMessages.h
scintilla/include/ScintillaTypes.h
scintilla/lexilla/include/SciLexer.h
scintilla/lexilla/lexers/LexCSS.cxx
scintilla/lexilla/lexers/LexHTML.cxx
scintilla/lexilla/lexers/LexMarkdown.cxx
scintilla/lexilla/lexlib/WordList.cxx
scintilla/lexilla/lexlib/WordList.h
scintilla/lexilla/version.txt
scintilla/src/AutoComplete.cxx
scintilla/src/AutoComplete.h
scintilla/src/CallTip.cxx
scintilla/src/CallTip.h
scintilla/src/CaseConvert.cxx
scintilla/src/CaseFolder.cxx
scintilla/src/CaseFolder.h
scintilla/src/CellBuffer.cxx
scintilla/src/ContractionState.cxx
scintilla/src/Decoration.cxx
scintilla/src/Document.cxx
scintilla/src/Document.h
scintilla/src/EditModel.cxx
scintilla/src/EditModel.h
scintilla/src/EditView.cxx
scintilla/src/Editor.cxx
scintilla/src/Editor.h
scintilla/src/Geometry.cxx
scintilla/src/Geometry.h
scintilla/src/Indicator.cxx
scintilla/src/KeyMap.cxx
scintilla/src/KeyMap.h
scintilla/src/LineMarker.cxx
scintilla/src/MarginView.cxx
scintilla/src/MarginView.h
scintilla/src/PositionCache.cxx
scintilla/src/PositionCache.h
scintilla/src/RESearch.cxx
scintilla/src/RESearch.h
scintilla/src/ScintillaBase.cxx
scintilla/src/Selection.cxx
scintilla/src/Selection.h
scintilla/src/Style.cxx
scintilla/src/Style.h
scintilla/src/UniConversion.h
scintilla/src/UniqueString.cxx
scintilla/src/UniqueString.h
scintilla/src/ViewStyle.cxx
scintilla/src/ViewStyle.h
scintilla/version.txt
src/highlightingmappings.h
Modified: data/filedefs/filetypes.css
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -24,7 +24,7 @@ pseudoelement=string_2
extended_identifier=keyword_1
extended_pseudoclass=string_1
extended_pseudoelement=string_2
-media=parameter
+group_rule=parameter
[keywords]
# CSS 1 properties
Modified: scintilla/gtk/PlatGTK.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -1073,7 +1073,7 @@ XYPOSITION SurfaceImpl::Ascent(const Font *font_) {
if (PFont(font_)->pfd) {
PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
PFont(font_)->pfd, pango_context_get_language(pcontext));
- ascent = std::round(floatFromPangoUnits(
+ ascent = std::ceil(floatFromPangoUnits(
pango_font_metrics_get_ascent(metrics)));
pango_font_metrics_unref(metrics);
}
@@ -1087,7 +1087,7 @@ XYPOSITION SurfaceImpl::Descent(const Font *font_) {
if (PFont(font_)->pfd) {
PangoFontMetrics *metrics = pango_context_get_metrics(pcontext,
PFont(font_)->pfd, pango_context_get_language(pcontext));
- const XYPOSITION descent = std::round(floatFromPangoUnits(
+ const XYPOSITION descent = std::ceil(floatFromPangoUnits(
pango_font_metrics_get_descent(metrics)));
pango_font_metrics_unref(metrics);
return descent;
Modified: scintilla/gtk/ScintillaGTK.cxx
50 lines changed, 38 insertions(+), 12 deletions(-)
===================================================================
@@ -5,6 +5,7 @@
#include <cstddef>
#include <cstdlib>
+#include <cstdint>
#include <cassert>
#include <cstring>
#include <cstdio>
@@ -179,6 +180,18 @@ GdkAtom SelectionOfGSD(GtkSelectionData *sd) noexcept {
return gtk_selection_data_get_selection(sd);
}
+bool SettingGet(GtkSettings *settings, const gchar *name, gpointer value) noexcept {
+ if (!settings) {
+ return false;
+ }
+ if (!g_object_class_find_property(G_OBJECT_GET_CLASS(
+ G_OBJECT(settings)), name)) {
+ return false;
+ }
+ g_object_get(G_OBJECT(settings), name, value, nullptr);
+ return true;
+}
+
}
FontOptions::FontOptions(GtkWidget *widget) noexcept {
@@ -218,6 +231,8 @@ ScintillaGTK::ScintillaGTK(_ScintillaObject *sci_) :
preeditInitialized(false),
im_context(nullptr),
lastNonCommonScript(G_UNICODE_SCRIPT_INVALID_CODE),
+ settings(nullptr),
+ settingsHandlerId(0),
lastWheelMouseTime(0),
lastWheelMouseDirection(0),
wheelMouseIntensity(0),
@@ -264,6 +279,12 @@ ScintillaGTK::~ScintillaGTK() {
}
ClearPrimarySelection();
wPreedit.Destroy();
+ if (settingsHandlerId) {
+ g_signal_handler_disconnect(settings, settingsHandlerId);
+ }
+ if (settings) {
+ g_object_unref(settings);
+ }
}
void ScintillaGTK::RealizeThis(GtkWidget *widget) {
@@ -341,6 +362,15 @@ void ScintillaGTK::RealizeThis(GtkWidget *widget) {
cursor = gdk_cursor_new_for_display(pdisplay, GDK_LEFT_PTR);
gdk_window_set_cursor(PWindow(scrollbarh), cursor);
UnRefCursor(cursor);
+
+ using NotifyLambda = void (*)(GObject *, GParamSpec *, ScintillaGTK *);
+ if (settings) {
+ settingsHandlerId = g_signal_connect(settings, "notify::gtk-xft-dpi",
+ G_CALLBACK(static_cast<NotifyLambda>([](GObject *, GParamSpec *, ScintillaGTK *sciThis) {
+ sciThis->InvalidateStyleRedraw();
+ })),
+ this);
+ }
}
void ScintillaGTK::Realize(GtkWidget *widget) {
@@ -669,20 +699,16 @@ void ScintillaGTK::Init() {
gtk_container_add(GTK_CONTAINER(PWidget(wPreedit)), predrw);
gtk_widget_show(predrw);
+ settings = gtk_settings_get_default();
+
// Set caret period based on GTK settings
gboolean blinkOn = false;
- if (g_object_class_find_property(G_OBJECT_GET_CLASS(
- G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink")) {
- g_object_get(G_OBJECT(
- gtk_settings_get_default()), "gtk-cursor-blink", &blinkOn, nullptr);
- }
- if (blinkOn &&
- g_object_class_find_property(G_OBJECT_GET_CLASS(
- G_OBJECT(gtk_settings_get_default())), "gtk-cursor-blink-time")) {
- gint value;
- g_object_get(G_OBJECT(
- gtk_settings_get_default()), "gtk-cursor-blink-time", &value, nullptr);
- caret.period = static_cast<int>(value / 1.75);
+ SettingGet(settings, "gtk-cursor-blink", &blinkOn);
+ if (blinkOn) {
+ gint value = 500;
+ if (SettingGet(settings, "gtk-cursor-blink-time", &value)) {
+ caret.period = static_cast<int>(value / 1.75);
+ }
} else {
caret.period = 0;
}
Modified: scintilla/gtk/ScintillaGTK.h
3 lines changed, 3 insertions(+), 0 deletions(-)
===================================================================
@@ -62,6 +62,9 @@ class ScintillaGTK : public ScintillaBase {
GtkIMContext *im_context;
GUnicodeScript lastNonCommonScript;
+ GtkSettings *settings;
+ gulong settingsHandlerId;
+
// Wheel mouse support
unsigned int linesPerScroll;
gint64 lastWheelMouseTime;
Modified: scintilla/gtk/ScintillaGTKAccessible.cxx
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -53,6 +53,7 @@
#include <cstddef>
#include <cstdlib>
+#include <cstdint>
#include <cassert>
#include <cstring>
Modified: scintilla/include/Scintilla.h
6 lines changed, 6 insertions(+), 0 deletions(-)
===================================================================
@@ -272,6 +272,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SCI_STYLEGETWEIGHT 2064
#define SCI_STYLESETCHARACTERSET 2066
#define SCI_STYLESETHOTSPOT 2409
+#define SCI_STYLESETCHECKMONOSPACED 2254
+#define SCI_STYLEGETCHECKMONOSPACED 2255
#define SC_ELEMENT_LIST 0
#define SC_ELEMENT_LIST_BACK 1
#define SC_ELEMENT_LIST_SELECTED 2
@@ -291,6 +293,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SC_ELEMENT_WHITE_SPACE_BACK 61
#define SC_ELEMENT_HOT_SPOT_ACTIVE 70
#define SC_ELEMENT_HOT_SPOT_ACTIVE_BACK 71
+#define SC_ELEMENT_FOLD_LINE 80
+#define SC_ELEMENT_HIDDEN_LINE 81
#define SCI_SETELEMENTCOLOUR 2753
#define SCI_GETELEMENTCOLOUR 2754
#define SCI_RESETELEMENTCOLOUR 2755
@@ -310,6 +314,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SCI_SETSELECTIONLAYER 2763
#define SCI_GETCARETLINELAYER 2764
#define SCI_SETCARETLINELAYER 2765
+#define SCI_GETCARETLINEHIGHLIGHTSUBLINE 2773
+#define SCI_SETCARETLINEHIGHLIGHTSUBLINE 2774
#define SCI_SETCARETFORE 2069
#define SCI_ASSIGNCMDKEY 2070
#define SCI_CLEARCMDKEY 2071
Modified: scintilla/include/Scintilla.iface
14 lines changed, 14 insertions(+), 0 deletions(-)
===================================================================
@@ -677,6 +677,12 @@ set void StyleSetCharacterSet=2066(int style, CharacterSet characterSet)
# Set a style to be a hotspot or not.
set void StyleSetHotSpot=2409(int style, bool hotspot)
+# Indicate that a style may be monospaced over ASCII graphics characters which enables optimizations.
+set void StyleSetCheckMonospaced=2254(int style, bool checkMonospaced)
+
+# Get whether a style may be monospaced.
+get bool StyleGetCheckMonospaced=2255(int style,)
+
enu Element=SC_ELEMENT_
val SC_ELEMENT_LIST=0
val SC_ELEMENT_LIST_BACK=1
@@ -697,6 +703,8 @@ val SC_ELEMENT_WHITE_SPACE=60
val SC_ELEMENT_WHITE_SPACE_BACK=61
val SC_ELEMENT_HOT_SPOT_ACTIVE=70
val SC_ELEMENT_HOT_SPOT_ACTIVE_BACK=71
+val SC_ELEMENT_FOLD_LINE=80
+val SC_ELEMENT_HIDDEN_LINE=81
# Set the colour of an element. Translucency (alpha) may or may not be significant
# and this may depend on the platform. The alpha byte should commonly be 0xff for opaque.
@@ -753,6 +761,12 @@ get Layer GetCaretLineLayer=2764(,)
# Set the layer of the background of the line containing the caret.
set void SetCaretLineLayer=2765(Layer layer,)
+# Get only highlighting subline instead of whole line.
+get bool GetCaretLineHighlightSubLine=2773(,)
+
+# Set only highlighting subline instead of whole line.
+set void SetCaretLineHighlightSubLine=2774(bool subLine,)
+
# Set the foreground colour of the caret.
set void SetCaretFore=2069(colour fore,)
Modified: scintilla/include/ScintillaCall.h
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -196,6 +196,8 @@ class ScintillaCall {
Scintilla::FontWeight StyleGetWeight(int style);
void StyleSetCharacterSet(int style, Scintilla::CharacterSet characterSet);
void StyleSetHotSpot(int style, bool hotspot);
+ void StyleSetCheckMonospaced(int style, bool checkMonospaced);
+ bool StyleGetCheckMonospaced(int style);
void SetElementColour(Scintilla::Element element, ColourAlpha colourElement);
ColourAlpha ElementColour(Scintilla::Element element);
void ResetElementColour(Scintilla::Element element);
@@ -212,6 +214,8 @@ class ScintillaCall {
void SetSelectionLayer(Scintilla::Layer layer);
Scintilla::Layer CaretLineLayer();
void SetCaretLineLayer(Scintilla::Layer layer);
+ bool CaretLineHighlightSubLine();
+ void SetCaretLineHighlightSubLine(bool subLine);
void SetCaretFore(Colour fore);
void AssignCmdKey(int keyDefinition, int sciCommand);
void ClearCmdKey(int keyDefinition);
Modified: scintilla/include/ScintillaMessages.h
4 lines changed, 4 insertions(+), 0 deletions(-)
===================================================================
@@ -133,6 +133,8 @@ enum class Message {
StyleGetWeight = 2064,
StyleSetCharacterSet = 2066,
StyleSetHotSpot = 2409,
+ StyleSetCheckMonospaced = 2254,
+ StyleGetCheckMonospaced = 2255,
SetElementColour = 2753,
GetElementColour = 2754,
ResetElementColour = 2755,
@@ -149,6 +151,8 @@ enum class Message {
SetSelectionLayer = 2763,
GetCaretLineLayer = 2764,
SetCaretLineLayer = 2765,
+ GetCaretLineHighlightSubLine = 2773,
+ SetCaretLineHighlightSubLine = 2774,
SetCaretFore = 2069,
AssignCmdKey = 2070,
ClearCmdKey = 2071,
Modified: scintilla/include/ScintillaTypes.h
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -180,6 +180,8 @@ enum class Element {
WhiteSpaceBack = 61,
HotSpotActive = 70,
HotSpotActiveBack = 71,
+ FoldLine = 80,
+ HiddenLine = 81,
};
enum class Layer {
Modified: scintilla/lexilla/include/SciLexer.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -765,7 +765,7 @@
#define SCE_CSS_EXTENDED_IDENTIFIER 19
#define SCE_CSS_EXTENDED_PSEUDOCLASS 20
#define SCE_CSS_EXTENDED_PSEUDOELEMENT 21
-#define SCE_CSS_MEDIA 22
+#define SCE_CSS_GROUP_RULE 22
#define SCE_CSS_VARIABLE 23
#define SCE_POV_DEFAULT 0
#define SCE_POV_COMMENT 1
Modified: scintilla/lexilla/lexers/LexCSS.cxx
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -209,7 +209,7 @@ static void ColouriseCssDoc(Sci_PositionU startPos, Sci_Position length, int ini
case '{':
nestingLevel++;
switch (lastState) {
- case SCE_CSS_MEDIA:
+ case SCE_CSS_GROUP_RULE:
sc.SetState(SCE_CSS_DEFAULT);
break;
case SCE_CSS_TAG:
@@ -458,8 +458,8 @@ static void ColouriseCssDoc(Sci_PositionU startPos, Sci_Position length, int ini
sc.ChangeState(SCE_CSS_VALUE);
break;
case SCE_CSS_DIRECTIVE:
- if (op == '@' && strcmp(s2, "media") == 0)
- sc.ChangeState(SCE_CSS_MEDIA);
+ if (op == '@' && (strcmp(s2, "media") == 0 || strcmp(s2, "supports") == 0 || strcmp(s2, "document") == 0 || strcmp(s2, "-moz-document") == 0))
+ sc.ChangeState(SCE_CSS_GROUP_RULE);
break;
}
}
@@ -492,7 +492,7 @@ static void ColouriseCssDoc(Sci_PositionU startPos, Sci_Position length, int ini
} else if (IsCssOperator(sc.ch)
&& (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']')
&& (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!')
- && ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_MEDIA) || sc.ch == ';' || sc.ch == '{')
+ && ((sc.state != SCE_CSS_DIRECTIVE && sc.state != SCE_CSS_GROUP_RULE) || sc.ch == ';' || sc.ch == '{')
) {
if (sc.state != SCE_CSS_OPERATOR)
lastState = sc.state;
Modified: scintilla/lexilla/lexers/LexHTML.cxx
140 lines changed, 127 insertions(+), 13 deletions(-)
===================================================================
@@ -524,6 +524,119 @@ bool isDjangoBlockEnd(const int ch, const int chNext, const std::string &blockTy
}
}
+class PhpNumberState {
+ enum NumberBase { BASE_10 = 0, BASE_2, BASE_8, BASE_16 };
+ static constexpr const char *const digitList[] = { "_0123456789", "_01", "_01234567", "_0123456789abcdefABCDEF" };
+
+ NumberBase base = BASE_10;
+ bool decimalPart = false;
+ bool exponentPart = false;
+ bool invalid = false;
+ bool finished = false;
+
+ bool leadingZero = false;
+ bool invalidBase8 = false;
+
+ bool betweenDigits = false;
+ bool decimalChar = false;
+ bool exponentChar = false;
+
+public:
+ inline bool isInvalid() { return invalid; }
+ inline bool isFinished() { return finished; }
+
+ bool init(int ch, int chPlus1, int chPlus2) {
+ base = BASE_10;
+ decimalPart = false;
+ exponentPart = false;
+ invalid = false;
+ finished = false;
+
+ leadingZero = false;
+ invalidBase8 = false;
+
+ betweenDigits = false;
+ decimalChar = false;
+ exponentChar = false;
+
+ if (ch == '.' && strchr(digitList[BASE_10] + !betweenDigits, chPlus1) != nullptr) {
+ decimalPart = true;
+ betweenDigits = true;
+ } else if (ch == '0' && (chPlus1 == 'b' || chPlus1 == 'B')) {
+ base = BASE_2;
+ } else if (ch == '0' && (chPlus1 == 'o' || chPlus1 == 'O')) {
+ base = BASE_8;
+ } else if (ch == '0' && (chPlus1 == 'x' || chPlus1 == 'X')) {
+ base = BASE_16;
+ } else if (strchr(digitList[BASE_10] + !betweenDigits, ch) != nullptr) {
+ leadingZero = ch == '0';
+ betweenDigits = true;
+ check(chPlus1, chPlus2);
+ if (finished && leadingZero) {
+ // single zero should be base 10
+ base = BASE_10;
+ }
+ } else {
+ return false;
+ }
+ return true;
+ }
+
+ bool check(int ch, int chPlus1) {
+ if (strchr(digitList[base] + !betweenDigits, ch) != nullptr) {
+ if (leadingZero) {
+ invalidBase8 = invalidBase8 || strchr(digitList[BASE_8] + !betweenDigits, ch) == nullptr;
+ }
+
+ betweenDigits = ch != '_';
+ decimalChar = false;
+ exponentChar = false;
+ } else if (ch == '_') {
+ invalid = true;
+
+ betweenDigits = false;
+ decimalChar = false;
+ // exponentChar is unchanged
+ } else if (base == BASE_10 && ch == '.' && (
+ !(decimalPart || exponentPart) || strchr(digitList[BASE_10] + !betweenDigits, chPlus1) != nullptr)
+ ) {
+ invalid = invalid || !betweenDigits || decimalPart || exponentPart;
+ decimalPart = true;
+
+ betweenDigits = false;
+ decimalChar = true;
+ exponentChar = false;
+ } else if (base == BASE_10 && (ch == 'e' || ch == 'E')) {
+ invalid = invalid || !(betweenDigits || decimalChar) || exponentPart;
+ exponentPart = true;
+
+ betweenDigits = false;
+ decimalChar = false;
+ exponentChar = true;
+ } else if (base == BASE_10 && (ch == '-' || ch == '+') && exponentChar) {
+ invalid = invalid || strchr(digitList[BASE_10] + !betweenDigits, chPlus1) == nullptr;
+
+ betweenDigits = false;
+ decimalChar = false;
+ // exponentChar is unchanged
+ } else if (IsPhpWordChar(ch)) {
+ invalid = true;
+
+ betweenDigits = false;
+ decimalChar = false;
+ exponentChar = false;
+ } else {
+ invalid = invalid || !(betweenDigits || decimalChar);
+ finished = true;
+ if (base == BASE_10 && leadingZero && !decimalPart && !exponentPart) {
+ base = BASE_8;
+ invalid = invalid || invalidBase8;
+ }
+ }
+ return finished;
+ }
+};
+
bool isPHPStringState(int state) {
return
(state == SCE_HPHP_HSTRING) ||
@@ -960,6 +1073,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
}
styler.StartAt(startPos);
std::string prevWord;
+ PhpNumberState phpNumber;
std::string phpStringDelimiter;
int StateToPrint = initStyle;
int state = stateForPrintState(StateToPrint);
@@ -1254,7 +1368,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
/////////////////////////////////////
// handle the start of PHP pre-processor = Non-HTML
else if ((state != SCE_H_ASPAT) &&
- !isStringState(state) &&
+ !isPHPStringState(state) &&
(state != SCE_HPHP_COMMENT) &&
(state != SCE_HPHP_COMMENTLINE) &&
(ch == '<') &&
@@ -1430,6 +1544,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
(chPrev == '<') &&
(ch == '!') &&
(StateToPrint != SCE_H_CDATA) &&
+ (!isStringState(StateToPrint)) &&
(!IsCommentState(StateToPrint)) &&
(!IsScriptCommentState(StateToPrint))) {
beforePreProc = state;
@@ -2273,7 +2388,7 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
break;
///////////// start - PHP state handling
case SCE_HPHP_WORD:
- if (!IsAWordChar(ch)) {
+ if (!IsPhpWordChar(ch)) {
classifyWordHTPHP(styler.GetStartSegment(), i - 1, keywords5, styler);
if (ch == '/' && chNext == '*') {
i++;
@@ -2306,15 +2421,9 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
}
break;
case SCE_HPHP_NUMBER:
- // recognize bases 8,10 or 16 integers OR floating-point numbers
- if (!IsADigit(ch)
- && strchr(".xXabcdefABCDEF_", ch) == NULL
- && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) {
- styler.ColourTo(i - 1, SCE_HPHP_NUMBER);
- if (IsOperator(ch))
- state = SCE_HPHP_OPERATOR;
- else
- state = SCE_HPHP_DEFAULT;
+ if (phpNumber.check(chNext, chNext2)) {
+ styler.ColourTo(i, phpNumber.isInvalid() ? SCE_HPHP_DEFAULT : SCE_HPHP_NUMBER);
+ state = SCE_HPHP_DEFAULT;
}
break;
case SCE_HPHP_VARIABLE:
@@ -2395,8 +2504,13 @@ void SCI_METHOD LexerHTML::Lex(Sci_PositionU startPos, Sci_Position length, int
case SCE_HPHP_OPERATOR:
case SCE_HPHP_DEFAULT:
styler.ColourTo(i - 1, StateToPrint);
- if (IsADigit(ch) || (ch == '.' && IsADigit(chNext))) {
- state = SCE_HPHP_NUMBER;
+ if (phpNumber.init(ch, chNext, chNext2)) {
+ if (phpNumber.isFinished()) {
+ styler.ColourTo(i, phpNumber.isInvalid() ? SCE_HPHP_DEFAULT : SCE_HPHP_NUMBER);
+ state = SCE_HPHP_DEFAULT;
+ } else {
+ state = SCE_HPHP_NUMBER;
+ }
} else if (IsAWordStart(ch)) {
state = SCE_HPHP_WORD;
} else if (ch == '/' && chNext == '*') {
Modified: scintilla/lexilla/lexers/LexMarkdown.cxx
9 lines changed, 7 insertions(+), 2 deletions(-)
===================================================================
@@ -56,8 +56,13 @@
using namespace Lexilla;
-static inline bool IsNewline(const int ch) {
- return (ch == '\n' || ch == '\r');
+namespace {
+
+constexpr bool IsNewline(const int ch) {
+ // sc.GetRelative(i) returns '\0' if out of range
+ return (ch == '\n' || ch == '\r' || ch == '\0');
+}
+
}
// True if can follow ch down to the end with possibly trailing whitespace
Modified: scintilla/lexilla/lexlib/WordList.cxx
85 lines changed, 34 insertions(+), 51 deletions(-)
===================================================================
@@ -11,18 +11,20 @@
#include <algorithm>
#include <iterator>
+#include <memory>
#include "WordList.h"
using namespace Lexilla;
+namespace {
+
/**
* Creates an array that points into each word in the string and puts \0 terminators
* after each word.
*/
-static char **ArrayFromWordList(char *wordlist, size_t slen, int *len, bool onlyLineEnds = false) {
- int prev = '\n';
- int words = 0;
+std::unique_ptr<char *[]> ArrayFromWordList(char *wordlist, size_t slen, size_t *len, bool onlyLineEnds = false) {
+ size_t words = 0;
// For rapid determination of whether a character is a separator, build
// a look up table.
bool wordSeparator[256] = {}; // Initialise all to false.
@@ -32,26 +34,27 @@ static char **ArrayFromWordList(char *wordlist, size_t slen, int *len, bool only
wordSeparator[static_cast<unsigned int>(' ')] = true;
wordSeparator[static_cast<unsigned int>('\t')] = true;
}
+ unsigned char prev = '\n';
for (int j = 0; wordlist[j]; j++) {
- const int curr = static_cast<unsigned char>(wordlist[j]);
+ const unsigned char curr = wordlist[j];
if (!wordSeparator[curr] && wordSeparator[prev])
words++;
prev = curr;
}
- char **keywords = new char *[words + 1];
- int wordsStore = 0;
+ std::unique_ptr<char *[]> keywords = std::make_unique<char *[]>(words + 1);
+ size_t wordsStore = 0;
if (words) {
- prev = '\0';
+ unsigned char previous = '\0';
for (size_t k = 0; k < slen; k++) {
if (!wordSeparator[static_cast<unsigned char>(wordlist[k])]) {
- if (!prev) {
+ if (!previous) {
keywords[wordsStore] = &wordlist[k];
wordsStore++;
}
} else {
wordlist[k] = '\0';
}
- prev = wordlist[k];
+ previous = wordlist[k];
}
}
assert(wordsStore < (words + 1));
@@ -60,8 +63,14 @@ static char **ArrayFromWordList(char *wordlist, size_t slen, int *len, bool only
return keywords;
}
-WordList::WordList(bool onlyLineEnds_) :
- words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) {
+bool cmpWords(const char *a, const char *b) noexcept {
+ return strcmp(a, b) < 0;
+}
+
+}
+
+WordList::WordList(bool onlyLineEnds_) noexcept :
+ words(nullptr), list(nullptr), len(0), onlyLineEnds(onlyLineEnds_) {
// Prevent warnings by static analyzers about uninitialized starts.
starts[0] = -1;
}
@@ -77,78 +86,52 @@ WordList::operator bool() const noexcept {
bool WordList::operator!=(const WordList &other) const noexcept {
if (len != other.len)
return true;
- for (int i=0; i<len; i++) {
+ for (size_t i=0; i<len; i++) {
if (strcmp(words[i], other.words[i]) != 0)
return true;
}
return false;
}
int WordList::Length() const noexcept {
- return len;
+ return static_cast<int>(len);
}
void WordList::Clear() noexcept {
- if (words) {
- delete []list;
- delete []words;
- }
- words = nullptr;
+ delete []list;
list = nullptr;
+ delete []words;
+ words = nullptr;
len = 0;
}
-#ifdef _MSC_VER
-
-static bool cmpWords(const char *a, const char *b) {
- return strcmp(a, b) < 0;
-}
-
-#else
-
-static int cmpWords(const void *a, const void *b) {
- return strcmp(*static_cast<const char * const *>(a), *static_cast<const char * const *>(b));
-}
-
-static void SortWordList(char **words, unsigned int len) {
- qsort(words, len, sizeof(*words), cmpWords);
-}
-
-#endif
-
bool WordList::Set(const char *s) {
const size_t lenS = strlen(s) + 1;
- char *listTemp = new char[lenS];
- memcpy(listTemp, s, lenS);
- int lenTemp = 0;
- char **wordsTemp = ArrayFromWordList(listTemp, lenS - 1, &lenTemp, onlyLineEnds);
-#ifdef _MSC_VER
- std::sort(wordsTemp, wordsTemp + lenTemp, cmpWords);
-#else
- SortWordList(wordsTemp, lenTemp);
-#endif
+ std::unique_ptr<char[]> listTemp = std::make_unique<char[]>(lenS);
+ memcpy(listTemp.get(), s, lenS);
+ size_t lenTemp = 0;
+ std::unique_ptr<char *[]> wordsTemp = ArrayFromWordList(listTemp.get(), lenS - 1, &lenTemp, onlyLineEnds);
+ std::sort(wordsTemp.get(), wordsTemp.get() + lenTemp, cmpWords);
if (lenTemp == len) {
bool changed = false;
- for (int i = 0; i < lenTemp; i++) {
+ for (size_t i = 0; i < lenTemp; i++) {
if (strcmp(words[i], wordsTemp[i]) != 0) {
changed = true;
break;
}
}
if (!changed) {
- delete []listTemp;
- delete []wordsTemp;
return false;
}
}
Clear();
- words = wordsTemp;
- list = listTemp;
+ words = wordsTemp.release();
+ list = listTemp.release();
len = lenTemp;
std::fill(starts, std::end(starts), -1);
- for (int l = len - 1; l >= 0; l--) {
+ for (int l = static_cast<int>(len - 1); l >= 0; l--) {
unsigned char indexChar = words[l][0];
starts[indexChar] = l;
}
Modified: scintilla/lexilla/lexlib/WordList.h
9 lines changed, 7 insertions(+), 2 deletions(-)
===================================================================
@@ -16,11 +16,16 @@ class WordList {
// Each word contains at least one character - a empty word acts as sentinel at the end.
char **words;
char *list;
- int len;
+ size_t len;
bool onlyLineEnds; ///< Delimited by any white space or only line ends
int starts[256];
public:
- explicit WordList(bool onlyLineEnds_ = false);
+ explicit WordList(bool onlyLineEnds_ = false) noexcept;
+ // Deleted so WordList objects can not be copied.
+ WordList(const WordList &) = delete;
+ WordList(WordList &&) = delete;
+ WordList &operator=(const WordList &) = delete;
+ WordList &operator=(WordList &&) = delete;
~WordList();
operator bool() const noexcept;
bool operator!=(const WordList &other) const noexcept;
Modified: scintilla/lexilla/version.txt
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1 +1 @@
-511
+512
Modified: scintilla/src/AutoComplete.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -211,7 +211,7 @@ void AutoComplete::Show(bool show) {
lb->Select(0);
}
-void AutoComplete::Cancel() {
+void AutoComplete::Cancel() noexcept {
if (lb->Created()) {
lb->Clear();
lb->Destroy();
@@ -272,7 +272,7 @@ void AutoComplete::Select(const char *word) {
}
} else if (cond < 0) {
end = pivot - 1;
- } else if (cond > 0) {
+ } else { // cond > 0
start = pivot + 1;
}
}
Modified: scintilla/src/AutoComplete.h
7 lines changed, 6 insertions(+), 1 deletions(-)
===================================================================
@@ -43,6 +43,11 @@ class AutoComplete {
Scintilla::Ordering autoSort;
AutoComplete();
+ // Deleted so AutoComplete objects can not be copied.
+ AutoComplete(const AutoComplete &) = delete;
+ AutoComplete(AutoComplete &&) = delete;
+ AutoComplete &operator=(const AutoComplete &) = delete;
+ AutoComplete &operator=(AutoComplete &&) = delete;
~AutoComplete();
/// Is the auto completion list displayed?
@@ -79,7 +84,7 @@ class AutoComplete {
std::string GetValue(int item) const;
void Show(bool show);
- void Cancel();
+ void Cancel() noexcept;
/// Move the current list element by delta, scrolling appropriately
void Move(int delta);
Modified: scintilla/src/CallTip.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -313,7 +313,7 @@ PRectangle CallTip::CallTipStart(Sci::Position pos, Point pt, int textHeight, co
}
}
-void CallTip::CallTipCancel() {
+void CallTip::CallTipCancel() noexcept {
inCallTipMode = false;
if (wCallTip.Created()) {
wCallTip.Destroy();
@@ -345,7 +345,7 @@ void CallTip::SetPosition(bool aboveText) noexcept {
}
bool CallTip::UseStyleCallTip() const noexcept {
- return useStyleCallTip;
+ return useStyleCallTip;
}
// It might be better to have two access functions for this and to use
Modified: scintilla/src/CallTip.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -75,7 +75,7 @@ class CallTip {
Scintilla::CharacterSet characterSet, Scintilla::Technology technology, const char *localeName,
const Window &wParent);
- void CallTipCancel();
+ void CallTipCancel() noexcept;
/// Set a range of characters to be displayed in a highlight style.
/// Commonly used to highlight the current parameter.
Modified: scintilla/src/CaseConvert.cxx
10 lines changed, 7 insertions(+), 3 deletions(-)
===================================================================
@@ -607,9 +607,13 @@ class CaseConverter : public ICaseConverter {
std::vector<ConversionString> conversions;
public:
- CaseConverter() noexcept {
- }
- virtual ~CaseConverter() = default;
+ CaseConverter() = default;
+ // Deleted so CaseConverter objects can not be copied.
+ CaseConverter(const CaseConverter &) = delete;
+ CaseConverter(CaseConverter &&) = delete;
+ CaseConverter &operator=(const CaseConverter &) = delete;
+ CaseConverter &operator=(CaseConverter &&) = delete;
+ virtual ~CaseConverter() noexcept = default;
bool Initialised() const noexcept {
return !characters.empty();
}
Modified: scintilla/src/CaseFolder.cxx
3 lines changed, 0 insertions(+), 3 deletions(-)
===================================================================
@@ -23,9 +23,6 @@ CaseFolderTable::CaseFolderTable() noexcept : mapping{} {
}
}
-CaseFolderTable::~CaseFolderTable() {
-}
-
size_t CaseFolderTable::Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
if (lenMixed > sizeFolded) {
return 0;
Modified: scintilla/src/CaseFolder.h
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -21,7 +21,6 @@ class CaseFolderTable : public CaseFolder {
char mapping[256];
public:
CaseFolderTable() noexcept;
- ~CaseFolderTable() override;
size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) override;
void SetTranslation(char ch, char chTranslation) noexcept;
void StandardASCII() noexcept;
Modified: scintilla/src/CellBuffer.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -523,7 +523,7 @@ void UndoHistory::TentativeCommit() {
}
bool UndoHistory::TentativeActive() const noexcept {
- return tentativePoint >= 0;
+ return tentativePoint >= 0;
}
int UndoHistory::TentativeSteps() noexcept {
Modified: scintilla/src/ContractionState.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -197,7 +197,7 @@ Sci::Line ContractionState<LINE>::DocFromDisplay(Sci::Line lineDisplay) const no
if (OneToOne()) {
return lineDisplay;
} else {
- if (lineDisplay <= 0) {
+ if (lineDisplay < 0) {
return 0;
}
if (lineDisplay > LinesDisplayed()) {
Modified: scintilla/src/Decoration.cxx
12 lines changed, 2 insertions(+), 10 deletions(-)
===================================================================
@@ -39,8 +39,6 @@ class Decoration : public IDecoration {
explicit Decoration(int indicator_) : indicator(indicator_) {
}
- ~Decoration() override {
- }
bool Empty() const noexcept override {
return (rs.Runs() == 1) && (rs.AllSameAs(0));
@@ -75,7 +73,7 @@ template <typename POS>
class DecorationList : public IDecorationList {
int currentIndicator;
int currentValue;
- Decoration<POS> *current; // Cached so FillRange doesn't have to search for each call.
+ Decoration<POS> *current; // Non-owning. Cached so FillRange doesn't have to search for each call.
Sci::Position lengthDocument;
// Ordered by indicator
std::vector<std::unique_ptr<Decoration<POS>>> decorationList;
@@ -90,7 +88,6 @@ class DecorationList : public IDecorationList {
public:
DecorationList();
- ~DecorationList() override;
const std::vector<const IDecoration*> &View() const noexcept override {
return decorationView;
@@ -128,11 +125,6 @@ DecorationList<POS>::DecorationList() : currentIndicator(0), currentValue(1), cu
lengthDocument(0), clickNotified(false) {
}
-template <typename POS>
-DecorationList<POS>::~DecorationList() {
- current = nullptr;
-}
-
template <typename POS>
Decoration<POS> *DecorationList<POS>::DecorationFromIndicator(int indicator) noexcept {
for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
@@ -263,7 +255,7 @@ int DecorationList<POS>::AllOnFor(Sci::Position position) const noexcept {
for (const std::unique_ptr<Decoration<POS>> &deco : decorationList) {
if (deco->rs.ValueAt(static_cast<POS>(position))) {
if (deco->Indicator() < static_cast<int>(Scintilla::IndicatorNumbers::Ime)) {
- mask |= 1 << deco->Indicator();
+ mask |= 1u << deco->Indicator();
}
}
}
Modified: scintilla/src/Document.cxx
23 lines changed, 16 insertions(+), 7 deletions(-)
===================================================================
@@ -51,6 +51,16 @@
using namespace Scintilla;
using namespace Scintilla::Internal;
+LexInterface::LexInterface(Document *pdoc_) noexcept : pdoc(pdoc_), performingStyle(false) {
+}
+
+LexInterface::~LexInterface() noexcept = default;
+
+void LexInterface::SetInstance(ILexer5 *instance_) {
+ instance.reset(instance_);
+ pdoc->LexerChanged();
+}
+
void LexInterface::Colourise(Sci::Position start, Sci::Position end) {
if (pdoc && instance && !performingStyle) {
// Protect against reentrance, which may occur, for example, when
@@ -86,6 +96,10 @@ LineEndType LexInterface::LineEndTypesSupported() {
return LineEndType::Default;
}
+bool LexInterface::UseContainerLexing() const noexcept {
+ return !instance;
+}
+
ActionDuration::ActionDuration(double duration_, double minDuration_, double maxDuration_) noexcept :
duration(duration_), minDuration(minDuration_), maxDuration(maxDuration_) {
}
@@ -2067,7 +2081,7 @@ Sci::Position Document::FindText(Sci::Position minPos, Sci::Position maxPos, con
const unsigned char charStartSearch = search[0];
if (forward && ((0 == dbcsCodePage) || (CpUtf8 == dbcsCodePage && !UTF8IsTrailByte(charStartSearch)))) {
// This is a fast case where there is no need to test byte values to iterate
- // so becomes the equivalent of a memchr+memcmp loop.
+ // so becomes the equivalent of a memchr+memcmp loop.
// UTF-8 search will not be self-synchronizing when starts with trail byte
const std::string_view suffix(search + 1, lengthFind - 1);
while (pos < endSearch) {
@@ -2798,11 +2812,6 @@ Sci::Position Document::BraceMatch(Sci::Position position, Sci::Position /*maxRe
class BuiltinRegex : public RegexSearchBase {
public:
explicit BuiltinRegex(CharClassify *charClassTable) : search(charClassTable) {}
- BuiltinRegex(const BuiltinRegex &) = delete;
- BuiltinRegex(BuiltinRegex &&) = delete;
- BuiltinRegex &operator=(const BuiltinRegex &) = delete;
- BuiltinRegex &operator=(BuiltinRegex &&) = delete;
- ~BuiltinRegex() override = default;
Sci::Position FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s,
bool caseSensitive, bool word, bool wordStart, FindOption flags,
@@ -3199,7 +3208,7 @@ bool MatchOnLines(const Document *doc, const Regex ®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
38 lines changed, 29 insertions(+), 9 deletions(-)
===================================================================
@@ -90,7 +90,7 @@ class Range {
*/
class RegexSearchBase {
public:
- virtual ~RegexSearchBase() {}
+ virtual ~RegexSearchBase() = default;
virtual Sci::Position FindText(Document *doc, Sci::Position minPos, Sci::Position maxPos, const char *s,
bool caseSensitive, bool word, bool wordStart, Scintilla::FindOption flags, Sci::Position *length) = 0;
@@ -164,21 +164,41 @@ class HighlightDelimiter {
bool isEnabled;
};
+struct LexerReleaser {
+ // Called by unique_ptr to destroy/free the Resource
+ void operator()(Scintilla::ILexer5 *pLexer) noexcept {
+ if (pLexer) {
+ try {
+ pLexer->Release();
+ } catch (...) {
+ // ILexer5::Release must not throw, ignore if it does.
+ }
+ }
+ }
+};
+
+using LexerInstance = std::unique_ptr<Scintilla::ILexer5, LexerReleaser>;
+
+// LexInterface defines the interface to ILexer used in Document.
+// The LexState subclass is actually created and that is used within ScintillaBase
+// to provide more methods that are exposed through Scintilla's external API.
class LexInterface {
protected:
Document *pdoc;
- Scintilla::ILexer5 *instance;
+ LexerInstance instance;
bool performingStyle; ///< Prevent reentrance
public:
- explicit LexInterface(Document *pdoc_) noexcept : pdoc(pdoc_), instance(nullptr), performingStyle(false) {
- }
- virtual ~LexInterface() {
- }
+ explicit LexInterface(Document *pdoc_) noexcept;
+ // Deleted so LexInterface objects can not be copied.
+ LexInterface(const LexInterface &) = delete;
+ LexInterface(LexInterface &&) = delete;
+ LexInterface &operator=(const LexInterface &) = delete;
+ LexInterface &operator=(LexInterface &&) = delete;
+ virtual ~LexInterface() noexcept;
+ void SetInstance(ILexer5 *instance_);
void Colourise(Sci::Position start, Sci::Position end);
virtual Scintilla::LineEndType LineEndTypesSupported();
- bool UseContainerLexing() const noexcept {
- return instance == nullptr;
- }
+ bool UseContainerLexing() const noexcept;
};
struct RegexError : public std::runtime_error {
Modified: scintilla/src/EditModel.cxx
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
#include <cstddef>
#include <cstdlib>
+#include <cstdint>
#include <cassert>
#include <cstring>
#include <cmath>
Modified: scintilla/src/EditModel.h
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -64,7 +64,6 @@ class EditModel {
virtual Sci::Line TopLineOfMain() const = 0;
virtual Point GetVisibleOriginInMain() const = 0;
virtual Sci::Line LinesOnScreen() const = 0;
- virtual Range GetHotSpotRange() const noexcept = 0;
bool BidirectionalEnabled() const noexcept;
bool BidirectionalR2L() const noexcept;
void SetDefaultFoldDisplayText(const char *text);
Modified: scintilla/src/EditView.cxx
95 lines changed, 54 insertions(+), 41 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
#include <cstddef>
#include <cstdlib>
+#include <cstdint>
#include <cassert>
#include <cstring>
#include <cstdio>
@@ -951,19 +952,19 @@ static void DrawCaretLineFramed(Surface *surface, const ViewStyle &vsDraw, const
// Avoid double drawing the corners by removing the left and right sides when drawing top and bottom borders
const PRectangle rcWithoutLeftRight = rcLine.Inset(Point(width, 0.0));
- if (subLine == 0 || ll->wrapIndent == 0 || vsDraw.caretLine.layer != Layer::Base) {
+ if (subLine == 0 || ll->wrapIndent == 0 || vsDraw.caretLine.layer != Layer::Base || vsDraw.caretLine.subLine) {
// Left
surface->FillRectangleAligned(Side(rcLine, Edge::left, width), colourFrame);
}
- if (subLine == 0) {
+ if (subLine == 0 || vsDraw.caretLine.subLine) {
// Top
surface->FillRectangleAligned(Side(rcWithoutLeftRight, Edge::top, width), colourFrame);
}
- if (subLine == ll->lines - 1 || vsDraw.caretLine.layer != Layer::Base) {
+ if (subLine == ll->lines - 1 || vsDraw.caretLine.layer != Layer::Base || vsDraw.caretLine.subLine) {
// Right
surface->FillRectangleAligned(Side(rcLine, Edge::right, width), colourFrame);
}
- if (subLine == ll->lines - 1) {
+ if (subLine == ll->lines - 1 || vsDraw.caretLine.subLine) {
// Bottom
surface->FillRectangleAligned(Side(rcWithoutLeftRight, Edge::bottom, width), colourFrame);
}
@@ -1458,7 +1459,7 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c
}
}
- // For multi-phase drawing draw the text last as transparent over any box
+ // For multi-phase drawing draw the text last as transparent over any box
if (FlagSet(phase, DrawPhase::text)) {
if (phasesDraw != PhasesDraw::One) {
surface->DrawTextTransparentUTF8(rcText, fontText,
@@ -1603,7 +1604,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
for (size_t r = 0; (r<model.sel.Count()) || drawDrag; r++) {
const bool mainCaret = r == model.sel.Main();
SelectionPosition posCaret = (drawDrag ? model.posDrag : model.sel.Range(r).caret);
- if ((vsDraw.DrawCaretInsideSelection(model.inOverstrike, imeCaretBlockOverride)) &&
+ if ((vsDraw.DrawCaretInsideSelection(model.inOverstrike, imeCaretBlockOverride)) &&
!drawDrag &&
posCaret > model.sel.Range(r).anchor) {
if (posCaret.VirtualSpace() > 0)
@@ -1766,7 +1767,7 @@ void EditView::DrawBackground(Surface *surface, const EditModel &model, const Vi
rcSegment.right = rcLine.right;
const InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc);
- const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc);
+ const bool inHotspot = model.hotspot.Valid() && model.hotspot.ContainsCharacter(iDoc);
ColourRGBA textBack = TextBackground(model, vsDraw, ll, background, inSelection,
inHotspot, ll->styles[i], i);
if (ts.representation) {
@@ -1977,7 +1978,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
ColourRGBA textFore = vsDraw.styles[styleMain].fore;
const Font *textFont = vsDraw.styles[styleMain].font.get();
// Hot-spot foreground
- const bool inHotspot = (ll->hotspot.Valid()) && ll->hotspot.ContainsCharacter(iDoc);
+ const bool inHotspot = model.hotspot.Valid() && model.hotspot.ContainsCharacter(iDoc);
if (inHotspot) {
if (vsDraw.ElementColour(Element::HotSpotActive))
textFore = *vsDraw.ElementColour(Element::HotSpotActive);
@@ -2124,7 +2125,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
}
}
}
- if (ll->hotspot.Valid() && vsDraw.hotspotUnderline && ll->hotspot.ContainsCharacter(iDoc)) {
+ if (inHotspot && vsDraw.hotspotUnderline) {
PRectangle rcUL = rcSegment;
rcUL.top = rcUL.top + vsDraw.maxAscent + 1;
rcUL.bottom = rcUL.top + 1;
@@ -2281,27 +2282,40 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl
}
}
-static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, Sci::Line line, PRectangle rcLine) {
+static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
+ Sci::Line line, PRectangle rcLine, int subLine) {
+ const bool lastSubLine = subLine == (ll->lines - 1);
const bool expanded = model.pcs->GetExpanded(line);
const FoldLevel level = model.pdoc->GetFoldLevel(line);
const FoldLevel levelNext = model.pdoc->GetFoldLevel(line + 1);
if (LevelIsHeader(level) &&
(LevelNumber(level) < LevelNumber(levelNext))) {
+ const ColourRGBA foldLineColour = vsDraw.ElementColour(Element::FoldLine).value_or(
+ vsDraw.styles[StyleDefault].fore);
// Paint the line above the fold
- if ((expanded && (FlagSet(model.foldFlags, FoldFlag::LineBeforeExpanded)))
+ if ((subLine == 0) &&
+ ((expanded && (FlagSet(model.foldFlags, FoldFlag::LineBeforeExpanded)))
||
- (!expanded && (FlagSet(model.foldFlags, FoldFlag::LineBeforeContracted)))) {
- PRectangle rcFoldLine = rcLine;
- rcFoldLine.bottom = rcFoldLine.top + 1;
- surface->FillRectangleAligned(rcFoldLine, Fill(vsDraw.styles[StyleDefault].fore));
+ (!expanded && (FlagSet(model.foldFlags, FoldFlag::LineBeforeContracted))))) {
+ surface->FillRectangleAligned(Side(rcLine, Edge::top, 1.0), foldLineColour);
}
// Paint the line below the fold
- if ((expanded && (FlagSet(model.foldFlags, FoldFlag::LineAfterExpanded)))
+ if (lastSubLine &&
+ ((expanded && (FlagSet(model.foldFlags, FoldFlag::LineAfterExpanded)))
||
- (!expanded && (FlagSet(model.foldFlags, FoldFlag::LineAfterContracted)))) {
- PRectangle rcFoldLine = rcLine;
- rcFoldLine.top = rcFoldLine.bottom - 1;
- surface->FillRectangleAligned(rcFoldLine, Fill(vsDraw.styles[StyleDefault].fore));
+ (!expanded && (FlagSet(model.foldFlags, FoldFlag::LineAfterContracted))))) {
+ surface->FillRectangleAligned(Side(rcLine, Edge::bottom, 1.0), foldLineColour);
+ // If contracted fold line drawn then don't overwrite with hidden line
+ // as fold lines are more specific then hidden lines.
+ if (!expanded) {
+ return;
+ }
+ }
+ }
+ if (lastSubLine && model.pcs->GetVisible(line) && !model.pcs->GetVisible(line + 1)) {
+ std::optional<ColourRGBA> hiddenLineColour = vsDraw.ElementColour(Element::HiddenLine);
+ if (hiddenLineColour) {
+ surface->FillRectangleAligned(Side(rcLine, Edge::bottom, 1.0), *hiddenLineColour);
}
}
}
@@ -2327,10 +2341,9 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan
const int screenLinePaintFirst = static_cast<int>(rcArea.top) / vsDraw.lineHeight;
const int xStart = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x);
- SelectionPosition posCaret = model.sel.RangeMain().caret;
- if (model.posDrag.IsValid())
- posCaret = model.posDrag;
+ const SelectionPosition posCaret = model.posDrag.IsValid() ? model.posDrag : model.sel.RangeMain().caret;
const Sci::Line lineCaret = model.pdoc->SciLineFromPosition(posCaret.Position());
+ const int caretOffset = static_cast<int>(posCaret.Position() - model.pdoc->LineStart(lineCaret));
PRectangle rcTextArea = rcClient;
if (vsDraw.marginInside) {
@@ -2397,8 +2410,8 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan
durLayout += ep.Duration(true);
#endif
if (ll) {
- ll->containsCaret = !hideSelection && (lineDoc == lineCaret);
- ll->hotspot = model.GetHotSpotRange();
+ ll->containsCaret = !hideSelection && (lineDoc == lineCaret)
+ && (ll->lines == 1 || !vsDraw.caretLine.subLine || ll->InLine(caretOffset, subLine));
PRectangle rcLine = rcTextArea;
rcLine.top = static_cast<XYPOSITION>(ypos);
@@ -2432,7 +2445,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan
ll->RestoreBracesHighlight(rangeLine, model.braces, bracesIgnoreStyle);
if (FlagSet(phase, DrawPhase::foldLines)) {
- DrawFoldLines(surface, model, vsDraw, lineDoc, rcLine);
+ DrawFoldLines(surface, model, vsDraw, ll.get(), lineDoc, rcLine, subLine);
}
if (FlagSet(phase, DrawPhase::carets)) {
@@ -2578,24 +2591,24 @@ Sci::Position EditView::FormatRange(bool draw, const RangeToFormat *pfr, Surface
vsPrint.braceBadLightIndicatorSet = false;
// Set colours for printing according to users settings
- for (size_t sty = 0; sty < vsPrint.styles.size(); sty++) {
- if (printParameters.colourMode == PrintOption::InvertLight) {
- vsPrint.styles[sty].fore = InvertedLight(vsPrint.styles[sty].fore);
- vsPrint.styles[sty].back = InvertedLight(vsPrint.styles[sty].back);
- } else if (printParameters.colourMode == PrintOption::BlackOnWhite) {
- vsPrint.styles[sty].fore = ColourRGBA(0, 0, 0);
- vsPrint.styles[sty].back = ColourRGBA(0xff, 0xff, 0xff);
- } else if (printParameters.colourMode == PrintOption::ColourOnWhite) {
- vsPrint.styles[sty].back = ColourRGBA(0xff, 0xff, 0xff);
- } else if (printParameters.colourMode == PrintOption::ColourOnWhiteDefaultBG) {
- if (sty <= StyleDefault) {
- vsPrint.styles[sty].back = ColourRGBA(0xff, 0xff, 0xff);
- }
+ const PrintOption colourMode = printParameters.colourMode;
+ const std::vector<Style>::iterator endStyles = (colourMode == PrintOption::ColourOnWhiteDefaultBG) ?
+ vsPrint.styles.begin() + StyleLineNumber : vsPrint.styles.end();
+ for (std::vector<Style>::iterator it = vsPrint.styles.begin(); it != endStyles; ++it) {
+ if (colourMode == PrintOption::InvertLight) {
+ it->fore = InvertedLight(it->fore);
+ it->back = InvertedLight(it->back);
+ } else if (colourMode == PrintOption::BlackOnWhite) {
+ it->fore = ColourRGBA(0, 0, 0);
+ it->back = ColourRGBA(0xff, 0xff, 0xff);
+ } else if (colourMode == PrintOption::ColourOnWhite || colourMode == PrintOption::ColourOnWhiteDefaultBG) {
+ it->back = ColourRGBA(0xff, 0xff, 0xff);
}
}
// White background for the line numbers if PrintOption::ScreenColours isn't used
- if (printParameters.colourMode != PrintOption::ScreenColours)
+ if (colourMode != PrintOption::ScreenColours) {
vsPrint.styles[StyleLineNumber].back = ColourRGBA(0xff, 0xff, 0xff);
+ }
// Printing uses different margins, so reset screen margins
vsPrint.leftMarginWidth = 0;
@@ -2688,7 +2701,7 @@ Sci::Position EditView::FormatRange(bool draw, const RangeToFormat *pfr, Surface
vsPrint.styles[StyleLineNumber].font.get(), number);
surface->FlushCachedState();
surface->DrawTextNoClip(rcNumber, vsPrint.styles[StyleLineNumber].font.get(),
- static_cast<XYPOSITION>(ypos + vsPrint.maxAscent), number,
+ ypos + vsPrint.maxAscent, number,
vsPrint.styles[StyleLineNumber].fore,
vsPrint.styles[StyleLineNumber].back);
}
Modified: scintilla/src/Editor.cxx
48 lines changed, 38 insertions(+), 10 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
#include <cstddef>
#include <cstdlib>
+#include <cstdint>
#include <cassert>
#include <cstring>
#include <cstdio>
@@ -117,7 +118,7 @@ static constexpr bool IsAllSpacesOrTabs(std::string_view sv) noexcept {
return true;
}
-Editor::Editor() : durationWrapOneByte(0.000001, 0.0000001, 0.00001) {
+Editor::Editor() : durationWrapOneByte(0.000001, 0.00000001, 0.00001) {
ctrlID = 0;
stylesValid = false;
@@ -479,12 +480,17 @@ void Editor::DiscardOverdraw() {
}
void Editor::Redraw() {
+ if (redrawPendingText) {
+ return;
+ }
//Platform::DebugPrintf("Redraw all\n");
const PRectangle rcClient = GetClientRectangle();
wMain.InvalidateRectangle(rcClient);
- if (wMargin.GetID())
+ if (wMargin.GetID()) {
wMargin.InvalidateAll();
- //wMain.InvalidateAll();
+ } else if (paintState == PaintState::notPainting) {
+ redrawPendingText = true;
+ }
}
void Editor::RedrawSelMargin(Sci::Line line, bool allAfter) {
@@ -498,11 +504,15 @@ void Editor::RedrawSelMargin(Sci::Line line, bool allAfter) {
Redraw();
return;
}
+ if (redrawPendingMargin) {
+ return;
+ }
PRectangle rcMarkers = GetClientRectangle();
if (!markersInText) {
// Normal case: just draw the margin
rcMarkers.right = rcMarkers.left + vs.fixedColumnWidth;
}
+ const PRectangle rcMarkersFull = rcMarkers;
if (line != -1) {
PRectangle rcLine = RectangleFromRange(Range(pdoc->LineStart(line)), 0);
@@ -529,6 +539,9 @@ void Editor::RedrawSelMargin(Sci::Line line, bool allAfter) {
wMargin.InvalidateRectangle(rcMarkers);
} else {
wMain.InvalidateRectangle(rcMarkers);
+ if (rcMarkers == rcMarkersFull) {
+ redrawPendingMargin = true;
+ }
}
}
@@ -552,6 +565,9 @@ PRectangle Editor::RectangleFromRange(Range r, int overlap) {
}
void Editor::InvalidateRange(Sci::Position start, Sci::Position end) {
+ if (redrawPendingText) {
+ return;
+ }
RedrawRect(RectangleFromRange(Range(start, end), view.LinesOverlap() ? vs.lineOverlap : 0));
}
@@ -1717,6 +1733,9 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) {
}
void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
+ redrawPendingText = false;
+ redrawPendingMargin = false;
+
//Platform::DebugPrintf("Paint:%1d (%3d,%3d) ... (%3d,%3d)\n",
// paintingAllText, rcArea.left, rcArea.top, rcArea.right, rcArea.bottom);
@@ -4780,10 +4799,6 @@ void Editor::SetHotSpotRange(const Point *pt) {
}
}
-Range Editor::GetHotSpotRange() const noexcept {
- return hotspot;
-}
-
void Editor::ButtonMoveWithModifiers(Point pt, unsigned int, KeyMod modifiers) {
if (ptMouseLast != pt) {
DwellEnd(true);
@@ -5748,6 +5763,9 @@ void Editor::StyleSetMessage(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::StyleSetHotSpot:
vs.styles[wParam].hotspot = lParam != 0;
break;
+ case Message::StyleSetCheckMonospaced:
+ vs.styles[wParam].checkMonospaced = lParam != 0;
+ break;
default:
break;
}
@@ -5787,6 +5805,8 @@ sptr_t Editor::StyleGetMessage(Message iMessage, uptr_t wParam, sptr_t lParam) {
return vs.styles[wParam].changeable ? 1 : 0;
case Message::StyleGetHotSpot:
return vs.styles[wParam].hotspot ? 1 : 0;
+ case Message::StyleGetCheckMonospaced:
+ return vs.styles[wParam].checkMonospaced ? 1 : 0;
default:
break;
}
@@ -7202,6 +7222,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::StyleSetVisible:
case Message::StyleSetChangeable:
case Message::StyleSetHotSpot:
+ case Message::StyleSetCheckMonospaced:
StyleSetMessage(iMessage, wParam, lParam);
break;
@@ -7220,6 +7241,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::StyleGetVisible:
case Message::StyleGetChangeable:
case Message::StyleGetHotSpot:
+ case Message::StyleGetCheckMonospaced:
return StyleGetMessage(iMessage, wParam, lParam);
case Message::StyleResetDefault:
@@ -7300,6 +7322,13 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
InvalidateStyleRedraw();
break;
+ case Message::GetCaretLineHighlightSubLine:
+ return vs.caretLine.subLine;
+ case Message::SetCaretLineHighlightSubLine:
+ vs.caretLine.subLine = wParam != 0;
+ InvalidateStyleRedraw();
+ break;
+
case Message::GetCaretLineFrame:
return vs.caretLine.frame;
case Message::SetCaretLineFrame:
@@ -7377,8 +7406,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
break;
case Message::HideLines:
- if (wParam > 0)
- pcs->SetVisible(LineFromUPtr(wParam), lParam, false);
+ pcs->SetVisible(LineFromUPtr(wParam), lParam, false);
SetScrollBars();
Redraw();
break;
@@ -7903,7 +7931,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
break;
case Message::MultiEdgeAddLine:
- vs.AddMultiEdge(wParam, lParam);
+ vs.AddMultiEdge(static_cast<int>(wParam), ColourRGBA::FromIpRGB(lParam));
InvalidateStyleRedraw();
break;
Modified: scintilla/src/Editor.h
7 lines changed, 5 insertions(+), 2 deletions(-)
===================================================================
@@ -188,6 +188,10 @@ class Editor : public EditModel, public DocWatcher {
Window wMain; ///< The Scintilla parent window
Window wMargin; ///< May be separate when using a scroll view for wMain
+ // Optimization that avoids superfluous invalidations
+ bool redrawPendingText = false;
+ bool redrawPendingMargin = false;
+
/** Style resources may be expensive to allocate so are cached between uses.
* When a style attribute is changed, this cache is flushed. */
bool stylesValid;
@@ -581,7 +585,6 @@ class Editor : public EditModel, public DocWatcher {
bool PositionIsHotspot(Sci::Position position) const;
bool PointIsHotspot(Point pt);
void SetHotSpotRange(const Point *pt);
- Range GetHotSpotRange() const noexcept override;
void SetHoverIndicatorPosition(Sci::Position position);
void SetHoverIndicatorPoint(Point pt);
@@ -637,7 +640,7 @@ class Editor : public EditModel, public DocWatcher {
return Point(static_cast<XYPOSITION>(wParam) - vs.ExternalMarginWidth(), static_cast<XYPOSITION>(lParam));
}
- constexpr std::optional<FoldLevel> OptionalFoldLevel(Scintilla::sptr_t lParam) {
+ static constexpr std::optional<FoldLevel> OptionalFoldLevel(Scintilla::sptr_t lParam) {
if (lParam >= 0) {
return static_cast<FoldLevel>(lParam);
}
Modified: scintilla/src/Geometry.cxx
24 lines changed, 24 insertions(+), 0 deletions(-)
===================================================================
@@ -12,6 +12,14 @@
#include "Geometry.h"
+namespace {
+
+constexpr unsigned int Mixed(unsigned char a, unsigned char b, double proportion) noexcept {
+ return static_cast<unsigned int>(a + proportion * (b - a));
+}
+
+}
+
namespace Scintilla::Internal {
PRectangle Clamp(PRectangle rc, Edge edge, XYPOSITION position) noexcept {
@@ -95,4 +103,20 @@ PRectangle PixelAlignOutside(const PRectangle &rc, int pixelDivisions) noexcept
std::floor(rc.bottom * pixelDivisions) / pixelDivisions);
}
+ColourRGBA ColourRGBA::MixedWith(ColourRGBA other) const noexcept {
+ const unsigned int red = (GetRed() + other.GetRed()) / 2;
+ const unsigned int green = (GetGreen() + other.GetGreen()) / 2;
+ const unsigned int blue = (GetBlue() + other.GetBlue()) / 2;
+ const unsigned int alpha = (GetAlpha() + other.GetAlpha()) / 2;
+ return ColourRGBA(red, green, blue, alpha);
+}
+
+ColourRGBA ColourRGBA::MixedWith(ColourRGBA other, double proportion) const noexcept {
+ return ColourRGBA(
+ Mixed(GetRed(), other.GetRed(), proportion),
+ Mixed(GetGreen(), other.GetGreen(), proportion),
+ Mixed(GetBlue(), other.GetBlue(), proportion),
+ Mixed(GetAlpha(), other.GetAlpha(), proportion));
+}
+
}
Modified: scintilla/src/Geometry.h
28 lines changed, 6 insertions(+), 22 deletions(-)
===================================================================
@@ -161,9 +161,6 @@ PRectangle PixelAlignOutside(const PRectangle &rc, int pixelDivisions) noexcept;
constexpr const float componentMaximum = 255.0f;
class ColourRGBA {
int co;
- constexpr static unsigned int Mixed(unsigned char a, unsigned char b, double proportion) noexcept {
- return static_cast<unsigned int>(a + proportion * (b - a));
- }
public:
constexpr explicit ColourRGBA(int co_ = 0) noexcept : co(co_) {
}
@@ -236,21 +233,8 @@ class ColourRGBA {
return GetAlpha() == 0xff;
}
- constexpr ColourRGBA MixedWith(ColourRGBA other) const noexcept {
- const unsigned int red = (GetRed() + other.GetRed()) / 2;
- const unsigned int green = (GetGreen() + other.GetGreen()) / 2;
- const unsigned int blue = (GetBlue() + other.GetBlue()) / 2;
- const unsigned int alpha = (GetAlpha() + other.GetAlpha()) / 2;
- return ColourRGBA(red, green, blue, alpha);
- }
-
- constexpr ColourRGBA MixedWith(ColourRGBA other, double proportion) const noexcept {
- return ColourRGBA(
- Mixed(GetRed(), other.GetRed(), proportion),
- Mixed(GetGreen(), other.GetGreen(), proportion),
- Mixed(GetBlue(), other.GetBlue(), proportion),
- Mixed(GetAlpha(), other.GetAlpha(), proportion));
- }
+ ColourRGBA MixedWith(ColourRGBA other) const noexcept;
+ ColourRGBA MixedWith(ColourRGBA other, double proportion) const noexcept;
};
/**
@@ -260,7 +244,7 @@ class Stroke {
public:
ColourRGBA colour;
XYPOSITION width;
- constexpr Stroke(ColourRGBA colour_, XYPOSITION width_=1.0) noexcept :
+ constexpr Stroke(ColourRGBA colour_, XYPOSITION width_=1.0) noexcept :
colour(colour_), width(width_) {
}
constexpr float WidthF() const noexcept {
@@ -274,7 +258,7 @@ class Stroke {
class Fill {
public:
ColourRGBA colour;
- constexpr Fill(ColourRGBA colour_) noexcept :
+ constexpr Fill(ColourRGBA colour_) noexcept :
colour(colour_) {
}
};
@@ -286,10 +270,10 @@ class FillStroke {
public:
Fill fill;
Stroke stroke;
- constexpr FillStroke(ColourRGBA colourFill_, ColourRGBA colourStroke_, XYPOSITION widthStroke_=1.0) noexcept :
+ constexpr FillStroke(ColourRGBA colourFill_, ColourRGBA colourStroke_, XYPOSITION widthStroke_=1.0) noexcept :
fill(colourFill_), stroke(colourStroke_, widthStroke_) {
}
- constexpr FillStroke(ColourRGBA colourBoth, XYPOSITION widthStroke_=1.0) noexcept :
+ constexpr FillStroke(ColourRGBA colourBoth, XYPOSITION widthStroke_=1.0) noexcept :
fill(colourBoth), stroke(colourBoth, widthStroke_) {
}
};
Modified: scintilla/src/Indicator.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -47,7 +47,7 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r
const XYPOSITION ymid = PixelAlign(rc.Centre().y, pixelDivisions);
- // This is a reasonable clip for indicators beneath text like underlines
+ // This is a reasonable clip for indicators beneath text like underlines
PRectangle rcClip = rcAligned;
rcClip.bottom = rcFullHeightAligned.bottom;
@@ -242,7 +242,7 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r
const XYPOSITION widthDot = std::round(strokeWidth);
XYPOSITION x = std::floor(rc.left);
while (x < rc.right) {
- const PRectangle rcDot = PRectangle(x, ymid,
+ const PRectangle rcDot = PRectangle(x, ymid,
x + widthDot, ymid + widthDot);
surface->FillRectangle(rcDot, sacDraw.fore);
x += widthDot * 2;
Modified: scintilla/src/KeyMap.cxx
4 lines changed, 0 insertions(+), 4 deletions(-)
===================================================================
@@ -32,10 +32,6 @@ KeyMap::KeyMap() {
}
}
-KeyMap::~KeyMap() {
- Clear();
-}
-
void KeyMap::Clear() noexcept {
kmap.clear();
}
Modified: scintilla/src/KeyMap.h
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -52,7 +52,6 @@ class KeyMap {
public:
KeyMap();
- ~KeyMap();
void Clear() noexcept;
void AssignCmdKey(Scintilla::Keys key, Scintilla::KeyMod modifiers, Scintilla::Message msg);
Scintilla::Message Find(Scintilla::Keys key, Scintilla::KeyMod modifiers) const; // 0 returned on failure
Modified: scintilla/src/LineMarker.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -326,7 +326,7 @@ void LineMarker::DrawFoldingMark(Surface *surface, const PRectangle &rcWhole, Fo
void LineMarker::AlignedPolygon(Surface *surface, const Point *pts, size_t npts) const {
const XYPOSITION move = strokeWidth / 2.0;
std::vector<Point> points;
- std::transform(pts, pts + npts, std::back_inserter(points), [=](Point pt)->Point {
+ std::transform(pts, pts + npts, std::back_inserter(points), [=](Point pt) noexcept ->Point {
return Point(pt.x + move, pt.y + move);
});
surface->Polygon(points.data(), std::size(points), FillStroke(back, fore, strokeWidth));
Modified: scintilla/src/MarginView.cxx
528 lines changed, 274 insertions(+), 254 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
#include <cstddef>
#include <cstdlib>
+#include <cstdint>
#include <cassert>
#include <cstring>
#include <cstdio>
@@ -166,301 +167,320 @@ void MarginView::RefreshPixMaps(Surface *surfaceWindow, const ViewStyle &vsDraw)
}
}
-static MarkerOutline SubstituteMarkerIfEmpty(MarkerOutline markerCheck, MarkerOutline markerDefault, const ViewStyle &vs) noexcept {
+namespace {
+
+MarkerOutline SubstituteMarkerIfEmpty(MarkerOutline markerCheck, MarkerOutline markerDefault, const ViewStyle &vs) noexcept {
if (vs.markers[static_cast<size_t>(markerCheck)].markType == MarkerSymbol::Empty)
return markerDefault;
return markerCheck;
}
+constexpr MarkerOutline TailFromNextLevel(FoldLevel levelNextNum) noexcept {
+ return (levelNextNum > FoldLevel::Base) ? MarkerOutline::FolderMidTail : MarkerOutline::FolderTail;
+}
+
+int FoldingMark(FoldLevel level, FoldLevel levelNext, bool firstSubLine, bool lastSubLine,
+ bool isExpanded, bool needWhiteClosure, MarkerOutline folderOpenMid, MarkerOutline folderEnd) noexcept {
+
+ const FoldLevel levelNum = LevelNumberPart(level);
+ const FoldLevel levelNextNum = LevelNumberPart(levelNext);
+
+ if (LevelIsHeader(level)) {
+ if (firstSubLine) {
+ if (levelNum < levelNextNum) {
+ if (levelNum == FoldLevel::Base) {
+ return 1 << (isExpanded ? MarkerOutline::FolderOpen : MarkerOutline::Folder);
+ } else {
+ return 1 << (isExpanded ? folderOpenMid : folderEnd);
+ }
+ } else if (levelNum > FoldLevel::Base) {
+ return 1 << MarkerOutline::FolderSub;
+ }
+ } else {
+ if (levelNum < levelNextNum) {
+ if (isExpanded) {
+ return 1 << MarkerOutline::FolderSub;
+ } else if (levelNum > FoldLevel::Base) {
+ return 1 << MarkerOutline::FolderSub;
+ }
+ } else if (levelNum > FoldLevel::Base) {
+ return 1 << MarkerOutline::FolderSub;
+ }
+ }
+ } else if (LevelIsWhitespace(level)) {
+ if (needWhiteClosure) {
+ if (LevelIsWhitespace(levelNext)) {
+ return 1 << MarkerOutline::FolderSub;
+ } else {
+ return 1 << TailFromNextLevel(levelNextNum);
+ }
+ } else if (levelNum > FoldLevel::Base) {
+ if (levelNextNum < levelNum) {
+ return 1 << TailFromNextLevel(levelNextNum);
+ } else {
+ return 1 << MarkerOutline::FolderSub;
+ }
+ }
+ } else if (levelNum > FoldLevel::Base) {
+ if (levelNextNum < levelNum) {
+ if (LevelIsWhitespace(levelNext)) {
+ return 1 << MarkerOutline::FolderSub;
+ } else if (lastSubLine) {
+ return 1 << TailFromNextLevel(levelNextNum);
+ } else {
+ return 1 << MarkerOutline::FolderSub;
+ }
+ } else {
+ return 1 << MarkerOutline::FolderSub;
+ }
+ }
+
+ // No folding mark on this line
+ return 0;
+}
+
+}
+
+void MarginView::PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcOneMargin, const MarginStyle &marginStyle,
+ const EditModel &model, const ViewStyle &vs) {
+ const Point ptOrigin = model.GetVisibleOriginInMain();
+ const Sci::Line lineStartPaint = static_cast<Sci::Line>(rcOneMargin.top + ptOrigin.y) / vs.lineHeight;
+ Sci::Line visibleLine = model.TopLineOfMain() + lineStartPaint;
+ XYPOSITION yposScreen = lineStartPaint * vs.lineHeight - ptOrigin.y;
+ // Work out whether the top line is whitespace located after a
+ // lessening of fold level which implies a 'fold tail' but which should not
+ // be displayed until the last of a sequence of whitespace.
+ bool needWhiteClosure = false;
+ if (marginStyle.ShowsFolding()) {
+ const FoldLevel level = model.pdoc->GetFoldLevel(model.pcs->DocFromDisplay(visibleLine));
+ if (LevelIsWhitespace(level)) {
+ Sci::Line lineBack = model.pcs->DocFromDisplay(visibleLine);
+ FoldLevel levelPrev = level;
+ while ((lineBack > 0) && LevelIsWhitespace(levelPrev)) {
+ lineBack--;
+ levelPrev = model.pdoc->GetFoldLevel(lineBack);
+ }
+ if (!LevelIsHeader(levelPrev)) {
+ if (LevelNumber(level) < LevelNumber(levelPrev))
+ needWhiteClosure = true;
+ }
+ }
+ }
+
+ // Old code does not know about new markers needed to distinguish all cases
+ const MarkerOutline folderOpenMid = SubstituteMarkerIfEmpty(MarkerOutline::FolderOpenMid,
+ MarkerOutline::FolderOpen, vs);
+ const MarkerOutline folderEnd = SubstituteMarkerIfEmpty(MarkerOutline::FolderEnd,
+ MarkerOutline::Folder, vs);
+
+ while ((visibleLine < model.pcs->LinesDisplayed()) && yposScreen < rc.bottom) {
+
+ PLATFORM_ASSERT(visibleLine < model.pcs->LinesDisplayed());
+ const Sci::Line lineDoc = model.pcs->DocFromDisplay(visibleLine);
+ PLATFORM_ASSERT((lineDoc == 0) || model.pcs->GetVisible(lineDoc));
+ const Sci::Line firstVisibleLine = model.pcs->DisplayFromDoc(lineDoc);
+ const Sci::Line lastVisibleLine = model.pcs->DisplayLastFromDoc(lineDoc);
+ const bool firstSubLine = visibleLine == firstVisibleLine;
+ const bool lastSubLine = visibleLine == lastVisibleLine;
+
+ int marks = firstSubLine ? model.pdoc->GetMark(lineDoc) : 0;
+
+ bool headWithTail = false;
+
+ if (marginStyle.ShowsFolding()) {
+ // Decide which fold indicator should be displayed
+ const FoldLevel level = model.pdoc->GetFoldLevel(lineDoc);
+ const FoldLevel levelNext = model.pdoc->GetFoldLevel(lineDoc + 1);
+ const FoldLevel levelNum = LevelNumberPart(level);
+ const FoldLevel levelNextNum = LevelNumberPart(levelNext);
+ const bool isExpanded = model.pcs->GetExpanded(lineDoc);
+
+ marks |= FoldingMark(level, levelNext, firstSubLine, lastSubLine,
+ isExpanded, needWhiteClosure, folderOpenMid, folderEnd);
+
+ // Change needWhiteClosure and headWithTail if needed
+ if (LevelIsHeader(level)) {
+ needWhiteClosure = false;
+ const Sci::Line firstFollowupLine = model.pcs->DocFromDisplay(model.pcs->DisplayFromDoc(lineDoc + 1));
+ const FoldLevel firstFollowupLineLevel = model.pdoc->GetFoldLevel(firstFollowupLine);
+ const FoldLevel secondFollowupLineLevelNum = LevelNumberPart(model.pdoc->GetFoldLevel(firstFollowupLine + 1));
+ if (!isExpanded) {
+ if (LevelIsWhitespace(firstFollowupLineLevel) &&
+ (levelNum > secondFollowupLineLevelNum))
+ needWhiteClosure = true;
+
+ if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine))
+ headWithTail = true;
+ }
+ } else if (LevelIsWhitespace(level)) {
+ if (needWhiteClosure) {
+ needWhiteClosure = LevelIsWhitespace(levelNext);
+ }
+ } else if (levelNum > FoldLevel::Base) {
+ if (levelNextNum < levelNum) {
+ needWhiteClosure = LevelIsWhitespace(levelNext);
+ }
+ }
+ }
+
+ const PRectangle rcMarker(
+ rcOneMargin.left,
+ yposScreen,
+ rcOneMargin.right,
+ yposScreen + vs.lineHeight);
+ if (marginStyle.style == MarginType::Number) {
+ if (firstSubLine) {
+ std::string sNumber;
+ if (lineDoc >= 0) {
+ sNumber = std::to_string(lineDoc + 1);
+ }
+ if (FlagSet(model.foldFlags, (FoldFlag::LevelNumbers | FoldFlag::LineState))) {
+ char number[100] = "";
+ if (FlagSet(model.foldFlags, FoldFlag::LevelNumbers)) {
+ const FoldLevel lev = model.pdoc->GetFoldLevel(lineDoc);
+ sprintf(number, "%c%c %03X %03X",
+ LevelIsHeader(lev) ? 'H' : '_',
+ LevelIsWhitespace(lev) ? 'W' : '_',
+ LevelNumber(lev),
+ static_cast<int>(lev) >> 16
+ );
+ } else {
+ const int state = model.pdoc->GetLineState(lineDoc);
+ sprintf(number, "%0X", state);
+ }
+ sNumber = number;
+ }
+ PRectangle rcNumber = rcMarker;
+ // Right justify
+ const XYPOSITION width = surface->WidthText(vs.styles[StyleLineNumber].font.get(), sNumber);
+ const XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;
+ rcNumber.left = xpos;
+ DrawTextNoClipPhase(surface, rcNumber, vs.styles[StyleLineNumber],
+ rcNumber.top + vs.maxAscent, sNumber, DrawPhase::all);
+ } else if (FlagSet(vs.wrap.visualFlags, WrapVisualFlag::Margin)) {
+ PRectangle rcWrapMarker = rcMarker;
+ rcWrapMarker.right -= wrapMarkerPaddingRight;
+ rcWrapMarker.left = rcWrapMarker.right - vs.styles[StyleLineNumber].aveCharWidth;
+ if (!customDrawWrapMarker) {
+ DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[StyleLineNumber].fore);
+ } else {
+ customDrawWrapMarker(surface, rcWrapMarker, false, vs.styles[StyleLineNumber].fore);
+ }
+ }
+ } else if (marginStyle.style == MarginType::Text || marginStyle.style == MarginType::RText) {
+ const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc);
+ if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
+ if (firstSubLine) {
+ surface->FillRectangle(rcMarker,
+ vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
+ PRectangle rcText = rcMarker;
+ if (marginStyle.style == MarginType::RText) {
+ const int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
+ rcText.left = rcText.right - width - 3;
+ }
+ DrawStyledText(surface, vs, vs.marginStyleOffset, rcText,
+ stMargin, 0, stMargin.length, DrawPhase::all);
+ } else {
+ // if we're displaying annotation lines, colour the margin to match the associated document line
+ const int annotationLines = model.pdoc->AnnotationLines(lineDoc);
+ if (annotationLines && (visibleLine > lastVisibleLine - annotationLines)) {
+ surface->FillRectangle(rcMarker, vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
+ }
+ }
+ }
+ }
+
+ marks &= marginStyle.mask;
+
+ if (marks) {
+ for (int markBit = 0; (markBit < 32) && marks; markBit++) {
+ if (marks & 1) {
+ LineMarker::FoldPart part = LineMarker::FoldPart::undefined;
+ if (marginStyle.ShowsFolding() && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
+ if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
+ part = LineMarker::FoldPart::body;
+ } else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
+ if (firstSubLine) {
+ part = headWithTail ? LineMarker::FoldPart::headWithTail : LineMarker::FoldPart::head;
+ } else {
+ if (model.pcs->GetExpanded(lineDoc) || headWithTail) {
+ part = LineMarker::FoldPart::body;
+ } else {
+ part = LineMarker::FoldPart::undefined;
+ }
+ }
+ } else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
+ part = LineMarker::FoldPart::tail;
+ }
+ }
+ vs.markers[markBit].Draw(surface, rcMarker, vs.styles[StyleLineNumber].font.get(), part, marginStyle.style);
+ }
+ marks >>= 1;
+ }
+ }
+
+ visibleLine++;
+ yposScreen += vs.lineHeight;
+ }
+}
+
void MarginView::PaintMargin(Surface *surface, Sci::Line topLine, PRectangle rc, PRectangle rcMargin,
const EditModel &model, const ViewStyle &vs) {
- PRectangle rcSelMargin = rcMargin;
- rcSelMargin.right = rcMargin.left;
- if (rcSelMargin.bottom < rc.bottom)
- rcSelMargin.bottom = rc.bottom;
+ PRectangle rcOneMargin = rcMargin;
+ rcOneMargin.right = rcMargin.left;
+ if (rcOneMargin.bottom < rc.bottom)
+ rcOneMargin.bottom = rc.bottom;
const Point ptOrigin = model.GetVisibleOriginInMain();
- const Font *fontLineNumber = vs.styles[StyleLineNumber].font.get();
- for (size_t margin = 0; margin < vs.ms.size(); margin++) {
- if (vs.ms[margin].width > 0) {
+ for (const MarginStyle &marginStyle : vs.ms) {
+ if (marginStyle.width > 0) {
- rcSelMargin.left = rcSelMargin.right;
- rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
+ rcOneMargin.left = rcOneMargin.right;
+ rcOneMargin.right = rcOneMargin.left + marginStyle.width;
- if (vs.ms[margin].style != MarginType::Number) {
- if (vs.ms[margin].ShowsFolding()) {
+ if (marginStyle.style != MarginType::Number) {
+ if (marginStyle.ShowsFolding()) {
// Required because of special way brush is created for selection margin
// Ensure patterns line up when scrolling with separate margin view
// by choosing correctly aligned variant.
const bool invertPhase = static_cast<int>(ptOrigin.y) & 1;
- surface->FillRectangle(rcSelMargin,
+ surface->FillRectangle(rcOneMargin,
invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1);
} else {
ColourRGBA colour;
- switch (vs.ms[margin].style) {
+ switch (marginStyle.style) {
case MarginType::Back:
colour = vs.styles[StyleDefault].back;
break;
case MarginType::Fore:
colour = vs.styles[StyleDefault].fore;
break;
case MarginType::Colour:
- colour = vs.ms[margin].back;
+ colour = marginStyle.back;
break;
default:
colour = vs.styles[StyleLineNumber].back;
break;
}
- surface->FillRectangle(rcSelMargin, colour);
+ surface->FillRectangle(rcOneMargin, colour);
}
} else {
- surface->FillRectangle(rcSelMargin, vs.styles[StyleLineNumber].back);
+ surface->FillRectangle(rcOneMargin, vs.styles[StyleLineNumber].back);
}
- const Sci::Line lineStartPaint = static_cast<Sci::Line>(rcMargin.top + ptOrigin.y) / vs.lineHeight;
- Sci::Line visibleLine = model.TopLineOfMain() + lineStartPaint;
- Sci::Position yposScreen = lineStartPaint * vs.lineHeight - static_cast<Sci::Position>(ptOrigin.y);
- // Work out whether the top line is whitespace located after a
- // lessening of fold level which implies a 'fold tail' but which should not
- // be displayed until the last of a sequence of whitespace.
- bool needWhiteClosure = false;
- if (vs.ms[margin].ShowsFolding()) {
- const FoldLevel level = model.pdoc->GetFoldLevel(model.pcs->DocFromDisplay(visibleLine));
- if (LevelIsWhitespace(level)) {
- Sci::Line lineBack = model.pcs->DocFromDisplay(visibleLine);
- FoldLevel levelPrev = level;
- while ((lineBack > 0) && LevelIsWhitespace(levelPrev)) {
- lineBack--;
- levelPrev = model.pdoc->GetFoldLevel(lineBack);
- }
- if (!LevelIsHeader(levelPrev)) {
- if (LevelNumber(level) < LevelNumber(levelPrev))
- needWhiteClosure = true;
- }
- }
- if (highlightDelimiter.isEnabled) {
- const Sci::Line lastLine = model.pcs->DocFromDisplay(topLine + model.LinesOnScreen()) + 1;
- model.pdoc->GetHighlightDelimiters(highlightDelimiter,
- model.pdoc->SciLineFromPosition(model.sel.MainCaret()), lastLine);
- }
+ if (marginStyle.ShowsFolding() && highlightDelimiter.isEnabled) {
+ const Sci::Line lastLine = model.pcs->DocFromDisplay(topLine + model.LinesOnScreen()) + 1;
+ model.pdoc->GetHighlightDelimiters(highlightDelimiter,
+ model.pdoc->SciLineFromPosition(model.sel.MainCaret()), lastLine);
}
- // Old code does not know about new markers needed to distinguish all cases
- const MarkerOutline folderOpenMid = SubstituteMarkerIfEmpty(MarkerOutline::FolderOpenMid,
- MarkerOutline::FolderOpen, vs);
- const MarkerOutline folderEnd = SubstituteMarkerIfEmpty(MarkerOutline::FolderEnd,
- MarkerOutline::Folder, vs);
-
- while ((visibleLine < model.pcs->LinesDisplayed()) && yposScreen < rc.bottom) {
-
- PLATFORM_ASSERT(visibleLine < model.pcs->LinesDisplayed());
- const Sci::Line lineDoc = model.pcs->DocFromDisplay(visibleLine);
- PLATFORM_ASSERT(model.pcs->GetVisible(lineDoc));
- const Sci::Line firstVisibleLine = model.pcs->DisplayFromDoc(lineDoc);
- const Sci::Line lastVisibleLine = model.pcs->DisplayLastFromDoc(lineDoc);
- const bool firstSubLine = visibleLine == firstVisibleLine;
- const bool lastSubLine = visibleLine == lastVisibleLine;
-
- int marks = model.pdoc->GetMark(lineDoc);
- if (!firstSubLine)
- marks = 0;
-
- bool headWithTail = false;
-
- if (vs.ms[margin].ShowsFolding()) {
- // Decide which fold indicator should be displayed
- const FoldLevel level = model.pdoc->GetFoldLevel(lineDoc);
- const FoldLevel levelNext = model.pdoc->GetFoldLevel(lineDoc + 1);
- const FoldLevel levelNum = LevelNumberPart(level);
- const FoldLevel levelNextNum = LevelNumberPart(levelNext);
- if (LevelIsHeader(level)) {
- if (firstSubLine) {
- if (levelNum < levelNextNum) {
- if (model.pcs->GetExpanded(lineDoc)) {
- if (levelNum == FoldLevel::Base)
- marks |= 1 << MarkerOutline::FolderOpen;
- else
- marks |= 1 << folderOpenMid;
- } else {
- if (levelNum == FoldLevel::Base)
- marks |= 1 << MarkerOutline::Folder;
- else
- marks |= 1 << folderEnd;
- }
- } else if (levelNum > FoldLevel::Base) {
- marks |= 1 << MarkerOutline::FolderSub;
- }
- } else {
- if (levelNum < levelNextNum) {
- if (model.pcs->GetExpanded(lineDoc)) {
- marks |= 1 << MarkerOutline::FolderSub;
- } else if (levelNum > FoldLevel::Base) {
- marks |= 1 << MarkerOutline::FolderSub;
- }
- } else if (levelNum > FoldLevel::Base) {
- marks |= 1 << MarkerOutline::FolderSub;
- }
- }
- needWhiteClosure = false;
- const Sci::Line firstFollowupLine = model.pcs->DocFromDisplay(model.pcs->DisplayFromDoc(lineDoc + 1));
- const FoldLevel firstFollowupLineLevel = model.pdoc->GetFoldLevel(firstFollowupLine);
- const FoldLevel secondFollowupLineLevelNum = LevelNumberPart(model.pdoc->GetFoldLevel(firstFollowupLine + 1));
- if (!model.pcs->GetExpanded(lineDoc)) {
- if (LevelIsWhitespace(firstFollowupLineLevel) &&
- (levelNum > secondFollowupLineLevelNum))
- needWhiteClosure = true;
-
- if (highlightDelimiter.IsFoldBlockHighlighted(firstFollowupLine))
- headWithTail = true;
- }
- } else if (LevelIsWhitespace(level)) {
- if (needWhiteClosure) {
- if (LevelIsWhitespace(levelNext)) {
- marks |= 1 << MarkerOutline::FolderSub;
- } else if (levelNextNum > FoldLevel::Base) {
- marks |= 1 << MarkerOutline::FolderMidTail;
- needWhiteClosure = false;
- } else {
- marks |= 1 << MarkerOutline::FolderTail;
- needWhiteClosure = false;
- }
- } else if (levelNum > FoldLevel::Base) {
- if (levelNextNum < levelNum) {
- if (levelNextNum > FoldLevel::Base) {
- marks |= 1 << MarkerOutline::FolderMidTail;
- } else {
- marks |= 1 << MarkerOutline::FolderTail;
- }
- } else {
- marks |= 1 << MarkerOutline::FolderSub;
- }
- }
- } else if (levelNum > FoldLevel::Base) {
- if (levelNextNum < levelNum) {
- needWhiteClosure = false;
- if (LevelIsWhitespace(levelNext)) {
- marks |= 1 << MarkerOutline::FolderSub;
- needWhiteClosure = true;
- } else if (lastSubLine) {
- if (levelNextNum > FoldLevel::Base) {
- marks |= 1 << MarkerOutline::FolderMidTail;
- } else {
- marks |= 1 << MarkerOutline::FolderTail;
- }
- } else {
- marks |= 1 << MarkerOutline::FolderSub;
- }
- } else {
- marks |= 1 << MarkerOutline::FolderSub;
- }
- }
- }
-
- marks &= vs.ms[margin].mask;
-
- const PRectangle rcMarker(
- rcSelMargin.left,
- static_cast<XYPOSITION>(yposScreen),
- rcSelMargin.right,
- static_cast<XYPOSITION>(yposScreen + vs.lineHeight));
- if (vs.ms[margin].style == MarginType::Number) {
- if (firstSubLine) {
- std::string sNumber;
- if (lineDoc >= 0) {
- sNumber = std::to_string(lineDoc + 1);
- }
- if (FlagSet(model.foldFlags, (FoldFlag::LevelNumbers | FoldFlag::LineState))) {
- char number[100] = "";
- if (FlagSet(model.foldFlags, FoldFlag::LevelNumbers)) {
- const FoldLevel lev = model.pdoc->GetFoldLevel(lineDoc);
- sprintf(number, "%c%c %03X %03X",
- LevelIsHeader(lev) ? 'H' : '_',
- LevelIsWhitespace(lev) ? 'W' : '_',
- LevelNumber(lev),
- static_cast<int>(lev) >> 16
- );
- } else {
- const int state = model.pdoc->GetLineState(lineDoc);
- sprintf(number, "%0X", state);
- }
- sNumber = number;
- }
- PRectangle rcNumber = rcMarker;
- // Right justify
- const XYPOSITION width = surface->WidthText(fontLineNumber, sNumber);
- const XYPOSITION xpos = rcNumber.right - width - vs.marginNumberPadding;
- rcNumber.left = xpos;
- DrawTextNoClipPhase(surface, rcNumber, vs.styles[StyleLineNumber],
- rcNumber.top + vs.maxAscent, sNumber, DrawPhase::all);
- } else if (FlagSet(vs.wrap.visualFlags, WrapVisualFlag::Margin)) {
- PRectangle rcWrapMarker = rcMarker;
- rcWrapMarker.right -= wrapMarkerPaddingRight;
- rcWrapMarker.left = rcWrapMarker.right - vs.styles[StyleLineNumber].aveCharWidth;
- if (!customDrawWrapMarker) {
- DrawWrapMarker(surface, rcWrapMarker, false, vs.styles[StyleLineNumber].fore);
- } else {
- customDrawWrapMarker(surface, rcWrapMarker, false, vs.styles[StyleLineNumber].fore);
- }
- }
- } else if (vs.ms[margin].style == MarginType::Text || vs.ms[margin].style == MarginType::RText) {
- const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc);
- if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
- if (firstSubLine) {
- surface->FillRectangle(rcMarker,
- vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
- PRectangle rcText = rcMarker;
- if (vs.ms[margin].style == MarginType::RText) {
- const int width = WidestLineWidth(surface, vs, vs.marginStyleOffset, stMargin);
- rcText.left = rcText.right - width - 3;
- }
- DrawStyledText(surface, vs, vs.marginStyleOffset, rcText,
- stMargin, 0, stMargin.length, DrawPhase::all);
- } else {
- // if we're displaying annotation lines, colour the margin to match the associated document line
- const int annotationLines = model.pdoc->AnnotationLines(lineDoc);
- if (annotationLines && (visibleLine > lastVisibleLine - annotationLines)) {
- surface->FillRectangle(rcMarker, vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
- }
- }
- }
- }
-
- if (marks) {
- for (int markBit = 0; (markBit < 32) && marks; markBit++) {
- if (marks & 1) {
- LineMarker::FoldPart part = LineMarker::FoldPart::undefined;
- if (vs.ms[margin].ShowsFolding() && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
- if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
- part = LineMarker::FoldPart::body;
- } else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
- if (firstSubLine) {
- part = headWithTail ? LineMarker::FoldPart::headWithTail : LineMarker::FoldPart::head;
- } else {
- if (model.pcs->GetExpanded(lineDoc) || headWithTail) {
- part = LineMarker::FoldPart::body;
- } else {
- part = LineMarker::FoldPart::undefined;
- }
- }
- } else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
- part = LineMarker::FoldPart::tail;
- }
- }
- vs.markers[markBit].Draw(surface, rcMarker, fontLineNumber, part, vs.ms[margin].style);
- }
- marks >>= 1;
- }
- }
-
- visibleLine++;
- yposScreen += vs.lineHeight;
- }
+ PaintOneMargin(surface, rc, rcOneMargin, marginStyle, model, vs);
}
}
PRectangle rcBlankMargin = rcMargin;
- rcBlankMargin.left = rcSelMargin.right;
+ rcBlankMargin.left = rcOneMargin.right;
surface->FillRectangle(rcBlankMargin, vs.styles[StyleDefault].back);
}
Modified: scintilla/src/MarginView.h
2 lines changed, 2 insertions(+), 0 deletions(-)
===================================================================
@@ -36,6 +36,8 @@ class MarginView {
void DropGraphics() noexcept;
void RefreshPixMaps(Surface *surfaceWindow, const ViewStyle &vsDraw);
+ void PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcMargin, const MarginStyle &marginStyle,
+ const EditModel &model, const ViewStyle &vs);
void PaintMargin(Surface *surface, Sci::Line topLine, PRectangle rc, PRectangle rcMargin,
const EditModel &model, const ViewStyle &vs);
};
Modified: scintilla/src/PositionCache.cxx
98 lines changed, 72 insertions(+), 26 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
#include <cstddef>
#include <cstdlib>
+#include <cstdint>
#include <cstring>
#include <cmath>
@@ -71,7 +72,6 @@ LineLayout::LineLayout(Sci::Line lineNumber_, int maxLineLength_) :
containsCaret(false),
edgeColumn(0),
bracePreviousStyles{},
- hotspot(0,0),
widthLine(wrapWidthInfinite),
lines(1),
wrapIndent(0) {
@@ -377,6 +377,14 @@ constexpr size_t AlignUp(size_t value, size_t alignment) noexcept {
constexpr size_t alignmentLLC = 20;
+constexpr bool GraphicASCII(char ch) noexcept {
+ return ch >= ' ' && ch <= '~';
+}
+
+bool AllGraphicASCII(std::string_view text) noexcept {
+ return std::all_of(text.cbegin(), text.cend(), GraphicASCII);
+}
+
}
@@ -533,8 +541,10 @@ std::shared_ptr<LineLayout> LineLayoutCache::Retrieve(Sci::Line lineNumber, Sci:
return std::make_shared<LineLayout>(lineNumber, maxChars);
}
+namespace {
+
// Simply pack the (maximum 4) character bytes into an int
-static unsigned int KeyFromString(std::string_view charBytes) noexcept {
+constexpr unsigned int KeyFromString(std::string_view charBytes) noexcept {
PLATFORM_ASSERT(charBytes.length() <= 4);
unsigned int k=0;
for (size_t i=0; i < charBytes.length(); i++) {
@@ -545,14 +555,21 @@ static unsigned int KeyFromString(std::string_view charBytes) noexcept {
return k;
}
+constexpr unsigned int representationKeyCrLf = KeyFromString("\r\n");
+
+}
+
void SpecialRepresentations::SetRepresentation(std::string_view charBytes, std::string_view value) {
if ((charBytes.length() <= 4) && (value.length() <= Representation::maxLength)) {
const unsigned int key = KeyFromString(charBytes);
- MapRepresentation::iterator it = mapReprs.find(key);
+ const MapRepresentation::iterator it = mapReprs.find(key);
if (it == mapReprs.end()) {
// New entry so increment for first byte
const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
startByteHasReprs[ucStart]++;
+ if (key == representationKeyCrLf) {
+ crlf = true;
+ }
}
mapReprs[key] = Representation(value);
}
@@ -561,7 +578,7 @@ void SpecialRepresentations::SetRepresentation(std::string_view charBytes, std::
void SpecialRepresentations::SetRepresentationAppearance(std::string_view charBytes, RepresentationAppearance appearance) {
if (charBytes.length() <= 4) {
const unsigned int key = KeyFromString(charBytes);
- MapRepresentation::iterator it = mapReprs.find(key);
+ const MapRepresentation::iterator it = mapReprs.find(key);
if (it == mapReprs.end()) {
// Not present so fail
return;
@@ -573,7 +590,7 @@ void SpecialRepresentations::SetRepresentationAppearance(std::string_view charBy
void SpecialRepresentations::SetRepresentationColour(std::string_view charBytes, ColourRGBA colour) {
if (charBytes.length() <= 4) {
const unsigned int key = KeyFromString(charBytes);
- MapRepresentation::iterator it = mapReprs.find(key);
+ const MapRepresentation::iterator it = mapReprs.find(key);
if (it == mapReprs.end()) {
// Not present so fail
return;
@@ -585,24 +602,33 @@ void SpecialRepresentations::SetRepresentationColour(std::string_view charBytes,
void SpecialRepresentations::ClearRepresentation(std::string_view charBytes) {
if (charBytes.length() <= 4) {
- MapRepresentation::iterator it = mapReprs.find(KeyFromString(charBytes));
+ const unsigned int key = KeyFromString(charBytes);
+ const MapRepresentation::iterator it = mapReprs.find(key);
if (it != mapReprs.end()) {
mapReprs.erase(it);
const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
startByteHasReprs[ucStart]--;
+ if (key == representationKeyCrLf) {
+ crlf = false;
+ }
}
}
}
+const Representation *SpecialRepresentations::GetRepresentation(std::string_view charBytes) const {
+ const MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes));
+ if (it != mapReprs.end()) {
+ return &(it->second);
+ }
+ return nullptr;
+}
+
const Representation *SpecialRepresentations::RepresentationFromCharacter(std::string_view charBytes) const {
if (charBytes.length() <= 4) {
const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
if (!startByteHasReprs[ucStart])
return nullptr;
- MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes));
- if (it != mapReprs.end()) {
- return &(it->second);
- }
+ return GetRepresentation(charBytes);
}
return nullptr;
}
@@ -612,14 +638,15 @@ bool SpecialRepresentations::Contains(std::string_view charBytes) const {
const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
if (!startByteHasReprs[ucStart])
return false;
- MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes));
+ const MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes));
return it != mapReprs.end();
}
void SpecialRepresentations::Clear() {
mapReprs.clear();
constexpr short none = 0;
std::fill(startByteHasReprs, std::end(startByteHasReprs), none);
+ crlf = false;
}
void BreakFinder::Insert(Sci::Position val) {
@@ -694,16 +721,23 @@ TextSegment BreakFinder::Next() {
const int prev = nextBreak;
while (nextBreak < lineRange.end) {
int charWidth = 1;
- if (encodingFamily == EncodingFamily::unicode)
- charWidth = UTF8DrawBytes(reinterpret_cast<unsigned char *>(&ll->chars[nextBreak]),
- static_cast<int>(lineRange.end - nextBreak));
- else if (encodingFamily == EncodingFamily::dbcs)
- charWidth = pdoc->DBCSDrawBytes(
- std::string_view(&ll->chars[nextBreak], lineRange.end - nextBreak));
- // Special case \r\n line ends if there is a representation
- if (preprs->Contains("\r\n") && ll->chars[nextBreak] == '\r' && ll->chars[nextBreak + 1] == '\n')
- charWidth = 2;
- const Representation *repr = preprs->RepresentationFromCharacter(std::string_view(&ll->chars[nextBreak], charWidth));
+ const char * const chars = &ll->chars[nextBreak];
+ const unsigned char ch = chars[0];
+ if (!UTF8IsAscii(ch) && encodingFamily != EncodingFamily::eightBit) {
+ if (encodingFamily == EncodingFamily::unicode) {
+ charWidth = UTF8DrawBytes(reinterpret_cast<const unsigned char *>(chars), static_cast<int>(lineRange.end - nextBreak));
+ } else {
+ charWidth = pdoc->DBCSDrawBytes(std::string_view(chars, lineRange.end - nextBreak));
+ }
+ }
+ const Representation *repr = nullptr;
+ if (preprs->MayContain(ch)) {
+ // Special case \r\n line ends if there is a representation
+ if (ch == '\r' && preprs->ContainsCrLf() && chars[1] == '\n') {
+ charWidth = 2;
+ }
+ repr = preprs->GetRepresentation(std::string_view(chars, charWidth));
+ }
if (((nextBreak > 0) && (ll->styles[nextBreak] != ll->styles[nextBreak - 1])) ||
repr ||
(nextBreak == saeNext)) {
@@ -768,10 +802,10 @@ PositionCacheEntry::PositionCacheEntry(const PositionCacheEntry &other) :
}
void PositionCacheEntry::Set(unsigned int styleNumber_, std::string_view sv,
- const XYPOSITION *positions_, unsigned int clock_) {
+ const XYPOSITION *positions_, uint16_t clock_) {
Clear();
- styleNumber = styleNumber_;
- len = static_cast<unsigned int>(sv.length());
+ styleNumber = static_cast<uint16_t>(styleNumber_);
+ len = static_cast<uint16_t>(sv.length());
clock = clock_;
if (sv.data() && positions_) {
positions = std::make_unique<XYPOSITION[]>(len + (len / sizeof(XYPOSITION)) + 1);
@@ -848,7 +882,17 @@ size_t PositionCache::GetSize() const noexcept {
void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, unsigned int styleNumber,
std::string_view sv, XYPOSITION *positions) {
- allClear = false;
+ const Style &style = vstyle.styles[styleNumber];
+ if (style.monospaceASCII) {
+ if (AllGraphicASCII(sv)) {
+ const XYPOSITION monospaceCharacterWidth = style.monospaceCharacterWidth;
+ for (size_t i = 0; i < sv.length(); i++) {
+ positions[i] = monospaceCharacterWidth * (i+1);
+ }
+ return;
+ }
+ }
+
size_t probe = pces.size(); // Out of bounds
if ((!pces.empty()) && (sv.length() < 30)) {
// Only store short strings in the cache so it doesn't churn with
@@ -869,7 +913,8 @@ void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, uns
probe = probe2;
}
}
- const Font *fontStyle = vstyle.styles[styleNumber].font.get();
+
+ const Font *fontStyle = style.font.get();
surface->MeasureWidths(fontStyle, sv, positions);
if (probe < pces.size()) {
// Store into cache
@@ -882,6 +927,7 @@ void PositionCache::MeasureWidths(Surface *surface, const ViewStyle &vstyle, uns
}
clock = 2;
}
+ allClear = false;
pces[probe].Set(styleNumber, sv, positions, clock);
}
}
Modified: scintilla/src/PositionCache.h
21 lines changed, 13 insertions(+), 8 deletions(-)
===================================================================
@@ -79,9 +79,6 @@ class LineLayout {
std::unique_ptr<BidiData> bidiData;
- // Hotspot support
- Range hotspot;
-
// Wrapped line support
int widthLine;
int lines;
@@ -175,9 +172,9 @@ class LineLayoutCache {
};
class PositionCacheEntry {
- unsigned int styleNumber:8;
- unsigned int len:8;
- unsigned int clock:16;
+ uint16_t styleNumber;
+ uint16_t len;
+ uint16_t clock;
std::unique_ptr<XYPOSITION []> positions;
public:
PositionCacheEntry() noexcept;
@@ -188,7 +185,7 @@ class PositionCacheEntry {
void operator=(const PositionCacheEntry &) = delete;
void operator=(PositionCacheEntry &&) = delete;
~PositionCacheEntry();
- void Set(unsigned int styleNumber_, std::string_view sv, const XYPOSITION *positions_, unsigned int clock_);
+ void Set(unsigned int styleNumber_, std::string_view sv, const XYPOSITION *positions_, uint16_t clock_);
void Clear() noexcept;
bool Retrieve(unsigned int styleNumber_, std::string_view sv, XYPOSITION *positions_) const noexcept;
static size_t Hash(unsigned int styleNumber_, std::string_view sv) noexcept;
@@ -212,13 +209,21 @@ typedef std::map<unsigned int, Representation> MapRepresentation;
class SpecialRepresentations {
MapRepresentation mapReprs;
short startByteHasReprs[0x100] {};
+ bool crlf = false;
public:
void SetRepresentation(std::string_view charBytes, std::string_view value);
void SetRepresentationAppearance(std::string_view charBytes, RepresentationAppearance appearance);
void SetRepresentationColour(std::string_view charBytes, ColourRGBA colour);
void ClearRepresentation(std::string_view charBytes);
+ const Representation *GetRepresentation(std::string_view charBytes) const;
const Representation *RepresentationFromCharacter(std::string_view charBytes) const;
bool Contains(std::string_view charBytes) const;
+ bool ContainsCrLf() const noexcept {
+ return crlf;
+ }
+ bool MayContain(unsigned char ch) const noexcept {
+ return startByteHasReprs[ch] != 0;
+ }
void Clear();
};
@@ -268,7 +273,7 @@ class BreakFinder {
class PositionCache {
std::vector<PositionCacheEntry> pces;
- unsigned int clock;
+ uint16_t clock;
bool allClear;
public:
PositionCache();
Modified: scintilla/src/RESearch.cxx
4 lines changed, 0 insertions(+), 4 deletions(-)
===================================================================
@@ -260,10 +260,6 @@ RESearch::RESearch(CharClassify *charClassTable) {
Clear();
}
-RESearch::~RESearch() {
- Clear();
-}
-
void RESearch::Clear() noexcept {
for (int i = 0; i < MAXTAG; i++) {
pat[i].clear();
Modified: scintilla/src/RESearch.h
1 lines changed, 0 insertions(+), 1 deletions(-)
===================================================================
@@ -23,7 +23,6 @@ class RESearch {
public:
explicit RESearch(CharClassify *charClassTable);
// No dynamic allocation so default copy constructor and assignment operator are OK.
- ~RESearch();
void Clear() noexcept;
void GrabMatches(const CharacterIndexer &ci);
const char *Compile(const char *pattern, Sci::Position length, bool caseSensitive, bool posix) noexcept;
Modified: scintilla/src/ScintillaBase.cxx
34 lines changed, 3 insertions(+), 31 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
#include <cstddef>
#include <cstdlib>
+#include <cstdint>
#include <cassert>
#include <cstring>
@@ -550,13 +551,8 @@ namespace Scintilla::Internal {
class LexState : public LexInterface {
public:
explicit LexState(Document *pdoc_) noexcept;
- void SetInstance(ILexer5 *instance_);
- // Deleted so LexState objects can not be copied.
- LexState(const LexState &) = delete;
- LexState(LexState &&) = delete;
- LexState &operator=(const LexState &) = delete;
- LexState &operator=(LexState &&) = delete;
- ~LexState() override;
+
+ // LexInterface deleted the standard operators and defined the virtual destructor so don't need to here.
const char *DescribeWordListSets();
void SetWordList(int n, const char *wl);
@@ -592,30 +588,6 @@ class LexState : public LexInterface {
LexState::LexState(Document *pdoc_) noexcept : LexInterface(pdoc_) {
}
-LexState::~LexState() {
- if (instance) {
- try {
- instance->Release();
- } catch (...) {
- // ILexer5::Release must not throw, ignore if it does.
- }
- instance = nullptr;
- }
-}
-
-void LexState::SetInstance(ILexer5 *instance_) {
- if (instance) {
- try {
- instance->Release();
- } catch (...) {
- // ILexer5::Release must not throw, ignore if it does.
- }
- instance = nullptr;
- }
- instance = instance_;
- pdoc->LexerChanged();
-}
-
LexState *ScintillaBase::DocumentLexState() {
if (!pdoc->GetLexInterface()) {
pdoc->SetLexInterface(std::make_unique<LexState>(pdoc));
Modified: scintilla/src/Selection.cxx
3 lines changed, 0 insertions(+), 3 deletions(-)
===================================================================
@@ -194,9 +194,6 @@ Selection::Selection() : mainRange(0), moveExtends(false), tentativeMai@@ Diff output truncated at 100000 characters. @@
--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
More information about the Commits
mailing list