[geany/geany] fb7ab2: Update to Scintilla 5.1.4 and Lexilla 5.1.3
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: fb7ab270d9e20b2d39f1d14b9a45c6967e691a84
https://github.com/geany/geany/commit/fb7ab270d9e20b2d39f1d14b9a45c6967e691a84
Log Message:
-----------
Update to Scintilla 5.1.4 and Lexilla 5.1.3
Scintilla:
- On GTK, fix primary selection paste within same instance. Bug #2287.
- On GTK, fix potential crash when closing Scintilla instances due to releasing global settings object.
Lexilla:
- Various Rust fixes
Modified Paths:
--------------
scintilla/gtk/PlatGTK.cxx
scintilla/gtk/ScintillaGTK.cxx
scintilla/gtk/ScintillaGTK.h
scintilla/include/Scintilla.h
scintilla/include/Scintilla.iface
scintilla/include/ScintillaCall.h
scintilla/include/ScintillaTypes.h
scintilla/lexilla/lexers/LexPython.cxx
scintilla/lexilla/lexers/LexRust.cxx
scintilla/lexilla/lexlib/Accessor.h
scintilla/lexilla/lexlib/LexerBase.cxx
scintilla/lexilla/lexlib/WordList.cxx
scintilla/lexilla/version.txt
scintilla/src/CellBuffer.cxx
scintilla/src/CharClassify.cxx
scintilla/src/CharacterType.h
scintilla/src/ContractionState.cxx
scintilla/src/Document.cxx
scintilla/src/Document.h
scintilla/src/EditView.cxx
scintilla/src/Editor.cxx
scintilla/src/KeyMap.cxx
scintilla/src/MarginView.cxx
scintilla/src/MarginView.h
scintilla/src/PerLine.cxx
scintilla/src/PositionCache.cxx
scintilla/src/PositionCache.h
scintilla/src/ViewStyle.cxx
scintilla/src/ViewStyle.h
scintilla/src/XPM.cxx
scintilla/src/XPM.h
scintilla/version.txt
Modified: scintilla/gtk/PlatGTK.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -114,7 +114,7 @@ class FontHandle : public Font {
FontHandle(FontHandle &&) = delete;
FontHandle &operator=(const FontHandle &) = delete;
FontHandle &operator=(FontHandle &&) = delete;
- ~FontHandle() {
+ ~FontHandle() override {
if (pfd)
pango_font_description_free(pfd);
pfd = nullptr;
Modified: scintilla/gtk/ScintillaGTK.cxx
26 lines changed, 13 insertions(+), 13 deletions(-)
===================================================================
@@ -282,9 +282,6 @@ ScintillaGTK::~ScintillaGTK() {
if (settingsHandlerId) {
g_signal_handler_disconnect(settings, settingsHandlerId);
}
- if (settings) {
- g_object_unref(settings);
- }
}
void ScintillaGTK::RealizeThis(GtkWidget *widget) {
@@ -1303,7 +1300,7 @@ struct CaseMapper {
}
std::string ScintillaGTK::CaseMapString(const std::string &s, CaseMapping caseMapping) {
- if ((s.size() == 0) || (caseMapping == CaseMapping::same))
+ if (s.empty() || (caseMapping == CaseMapping::same))
return s;
if (IsUnicodeMode()) {
@@ -1566,20 +1563,26 @@ void ScintillaGTK::GetGtkSelectionText(GtkSelectionData *selectionData, Selectio
void ScintillaGTK::InsertSelection(GtkClipboard *clipBoard, GtkSelectionData *selectionData) {
const gint length = gtk_selection_data_get_length(selectionData);
+ const GdkAtom selection = gtk_selection_data_get_selection(selectionData);
if (length >= 0) {
- GdkAtom selection = gtk_selection_data_get_selection(selectionData);
SelectionText selText;
GetGtkSelectionText(selectionData, selText);
UndoGroup ug(pdoc);
if (selection == GDK_SELECTION_CLIPBOARD) {
ClearSelection(multiPasteMode == MultiPaste::Each);
}
+ if (selection == GDK_SELECTION_PRIMARY) {
+ SetSelection(posPrimary, posPrimary);
+ }
InsertPasteShape(selText.Data(), selText.Length(),
selText.rectangular ? PasteShape::rectangular : PasteShape::stream);
EnsureCaretVisible();
} else {
+ if (selection == GDK_SELECTION_PRIMARY) {
+ SetSelection(posPrimary, posPrimary);
+ }
GdkAtom target = gtk_selection_data_get_target(selectionData);
if (target == atomUTF8) {
// In case data is actually only stored as text/plain;charset=utf-8 not UTF8_STRING
@@ -1653,7 +1656,7 @@ void ScintillaGTK::GetSelection(GtkSelectionData *selection_data, guint info, Se
std::unique_ptr<SelectionText> newline_normalized;
{
std::string tmpstr = Document::TransformLineEnds(text->Data(), text->Length(), EndOfLine::Lf);
- newline_normalized.reset(new SelectionText());
+ newline_normalized = std::make_unique<SelectionText>();
newline_normalized->Copy(tmpstr, CpUtf8, CharacterSet::Ansi, text->rectangular, false);
text = newline_normalized.get();
}
@@ -1880,12 +1883,11 @@ gint ScintillaGTK::PressThis(GdkEventButton *event) {
ButtonDownWithModifiers(pt, event->time, ModifierFlags(shift, ctrl, alt, meta));
} else if (event->button == 2) {
// Grab the primary selection if it exists
- const SelectionPosition pos = SPositionFromLocation(pt, false, false, UserVirtualSpace());
+ posPrimary = SPositionFromLocation(pt, false, false, UserVirtualSpace());
if (OwnPrimarySelection() && primary.Empty())
CopySelectionRange(&primary);
sel.Clear();
- SetSelection(pos, pos);
RequestSelection(GDK_SELECTION_PRIMARY);
} else if (event->button == 3) {
if (!PointInSelection(pt))
@@ -2449,7 +2451,7 @@ std::vector<int> MapImeIndicators(PangoAttrList *attrs, const char *u8Str) {
void ScintillaGTK::SetCandidateWindowPos() {
// Composition box accompanies candidate box.
const Point pt = PointMainCaret();
- GdkRectangle imeBox = {0}; // No need to set width
+ GdkRectangle imeBox {};
imeBox.x = static_cast<gint>(pt.x);
imeBox.y = static_cast<gint>(pt.y + std::max(4, vs.lineHeight/4));
// prevent overlapping with current line
@@ -3011,7 +3013,7 @@ gboolean ScintillaGTK::IdleCallback(gpointer pSci) {
// Idler will be automatically stopped, if there is nothing
// to do while idle.
const bool ret = sciThis->Idle();
- if (ret == false) {
+ if (!ret) {
// FIXME: This will remove the idler from GTK, we don't want to
// remove it as it is removed automatically when this function
// returns false (although, it should be harmless).
@@ -3047,9 +3049,7 @@ void ScintillaGTK::SetDocPointer(Document *document) {
sciAccessible = ScintillaGTKAccessible::FromAccessible(accessible);
if (sciAccessible && pdoc) {
oldDoc = pdoc;
- if (oldDoc) {
- oldDoc->AddRef();
- }
+ oldDoc->AddRef();
}
}
Modified: scintilla/gtk/ScintillaGTK.h
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -34,6 +34,7 @@ class ScintillaGTK : public ScintillaBase {
int horizontalScrollBarHeight;
SelectionText primary;
+ SelectionPosition posPrimary;
GdkEvent *evbtn;
guint buttonMouse;
@@ -92,7 +93,7 @@ class ScintillaGTK : public ScintillaBase {
ScintillaGTK(ScintillaGTK &&) = delete;
ScintillaGTK &operator=(const ScintillaGTK &) = delete;
ScintillaGTK &operator=(ScintillaGTK &&) = delete;
- virtual ~ScintillaGTK();
+ ~ScintillaGTK() override;
static ScintillaGTK *FromWidget(GtkWidget *widget) noexcept;
static void ClassInit(OBJECT_CLASS *object_class, GtkWidgetClass *widget_class, GtkContainerClass *container_class);
private:
Modified: scintilla/include/Scintilla.h
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -907,6 +907,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define CARETSTYLE_BLOCK 2
#define CARETSTYLE_OVERSTRIKE_BAR 0
#define CARETSTYLE_OVERSTRIKE_BLOCK 0x10
+#define CARETSTYLE_CURSES 0x20
#define CARETSTYLE_INS_MASK 0xF
#define CARETSTYLE_BLOCK_AFTER 0x100
#define SCI_SETCARETSTYLE 2512
Modified: scintilla/include/Scintilla.iface
3 lines changed, 2 insertions(+), 1 deletions(-)
===================================================================
@@ -2489,6 +2489,7 @@ val CARETSTYLE_LINE=1
val CARETSTYLE_BLOCK=2
val CARETSTYLE_OVERSTRIKE_BAR=0
val CARETSTYLE_OVERSTRIKE_BLOCK=0x10
+val CARETSTYLE_CURSES=0x20
val CARETSTYLE_INS_MASK=0xF
val CARETSTYLE_BLOCK_AFTER=0x100
@@ -3127,7 +3128,7 @@ fun int DescribeKeyWordSets=4017(, stringresult descriptions)
# Bit set of LineEndType enumertion for which line ends beyond the standard
# LF, CR, and CRLF are supported by the lexer.
-get int GetLineEndTypesSupported=4018(,)
+get LineEndType GetLineEndTypesSupported=4018(,)
# Allocate a set of sub styles for a particular base style, returning start of range
fun int AllocateSubStyles=4020(int styleBase, int numberStyles)
Modified: scintilla/include/ScintillaCall.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -854,7 +854,7 @@ class ScintillaCall {
std::string DescribeProperty(const char *name);
int DescribeKeyWordSets(char *descriptions);
std::string DescribeKeyWordSets();
- int LineEndTypesSupported();
+ Scintilla::LineEndType LineEndTypesSupported();
int AllocateSubStyles(int styleBase, int numberStyles);
int SubStylesStart(int styleBase);
int SubStylesLength(int styleBase);
Modified: scintilla/include/ScintillaTypes.h
1 lines changed, 1 insertions(+), 0 deletions(-)
===================================================================
@@ -439,6 +439,7 @@ enum class CaretStyle {
Block = 2,
OverstrikeBar = 0,
OverstrikeBlock = 0x10,
+ Curses = 0x20,
InsMask = 0xF,
BlockAfter = 0x100,
};
Modified: scintilla/lexilla/lexers/LexPython.cxx
21 lines changed, 11 insertions(+), 10 deletions(-)
===================================================================
@@ -71,7 +71,7 @@ bool IsPyComment(Accessor &styler, Sci_Position pos, Sci_Position len) {
return len > 0 && styler[pos] == '#';
}
-bool IsPyStringTypeChar(int ch, literalsAllowed allowed) noexcept {
+constexpr bool IsPyStringTypeChar(int ch, literalsAllowed allowed) noexcept {
return
((allowed & litB) && (ch == 'b' || ch == 'B')) ||
((allowed & litU) && (ch == 'u' || ch == 'U')) ||
@@ -93,17 +93,17 @@ bool IsPyStringStart(int ch, int chNext, int chNext2, literalsAllowed allowed) n
return false;
}
-bool IsPyFStringState(int st) noexcept {
+constexpr bool IsPyFStringState(int st) noexcept {
return ((st == SCE_P_FCHARACTER) || (st == SCE_P_FSTRING) ||
(st == SCE_P_FTRIPLE) || (st == SCE_P_FTRIPLEDOUBLE));
}
-bool IsPySingleQuoteStringState(int st) noexcept {
+constexpr bool IsPySingleQuoteStringState(int st) noexcept {
return ((st == SCE_P_CHARACTER) || (st == SCE_P_STRING) ||
(st == SCE_P_FCHARACTER) || (st == SCE_P_FSTRING));
}
-bool IsPyTripleQuoteStringState(int st) noexcept {
+constexpr bool IsPyTripleQuoteStringState(int st) noexcept {
return ((st == SCE_P_TRIPLE) || (st == SCE_P_TRIPLEDOUBLE) ||
(st == SCE_P_FTRIPLE) || (st == SCE_P_FTRIPLEDOUBLE));
}
@@ -232,7 +232,7 @@ struct OptionsPython {
bool foldCompact;
bool unicodeIdentifiers;
- OptionsPython() {
+ OptionsPython() noexcept {
whingeLevel = 0;
base2or8Literals = true;
stringsU = true;
@@ -436,6 +436,8 @@ Sci_Position SCI_METHOD LexerPython::WordListSet(int n, const char *wl) {
case 1:
wordListN = &keywords2;
break;
+ default:
+ break;
}
Sci_Position firstModification = -1;
if (wordListN) {
@@ -635,7 +637,7 @@ void SCI_METHOD LexerPython::Lex(Sci_PositionU startPos, Sci_Position length, in
style = SCE_P_WORD2;
}
} else {
- int subStyle = classifierIdentifiers.ValueFor(s);
+ const int subStyle = classifierIdentifiers.ValueFor(s);
if (subStyle >= 0) {
style = subStyle;
}
@@ -895,8 +897,8 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
const int style = styler.StyleAt(lookAtPos) & 31;
quote = options.foldQuotes && IsPyTripleQuoteStringState(style);
}
- const int quote_start = (quote && !prevQuote);
- const int quote_continue = (quote && prevQuote);
+ const bool quote_start = (quote && !prevQuote);
+ const bool quote_continue = (quote && prevQuote);
if (!quote || !prevQuote)
indentCurrentLevel = indentCurrent & SC_FOLDLEVELNUMBERMASK;
if (quote)
@@ -921,8 +923,7 @@ void SCI_METHOD LexerPython::Fold(Sci_PositionU startPos, Sci_Position length, i
int minCommentLevel = indentCurrentLevel;
while (!quote &&
(lineNext < docLines) &&
- ((indentNext & SC_FOLDLEVELWHITEFLAG) ||
- (lineNext <= docLines && IsCommentLine(lineNext, styler)))) {
+ ((indentNext & SC_FOLDLEVELWHITEFLAG) || (IsCommentLine(lineNext, styler)))) {
if (IsCommentLine(lineNext, styler) && indentNext < minCommentLevel) {
minCommentLevel = indentNext;
Modified: scintilla/lexilla/lexers/LexRust.cxx
12 lines changed, 5 insertions(+), 7 deletions(-)
===================================================================
@@ -286,6 +286,8 @@ static void ScanNumber(Accessor& styler, Sci_Position& pos) {
pos += 2;
} else if (c == '6' && n == '4') {
pos += 2;
+ } else if (styler.Match(pos, "128")) {
+ pos += 3;
} else if (styler.Match(pos, "size")) {
pos += 4;
} else {
@@ -524,7 +526,7 @@ static void ResumeBlockComment(Accessor &styler, Sci_Position& pos, Sci_Position
level++;
}
}
- else {
+ else if (pos < max) {
pos++;
}
if (pos >= max) {
@@ -557,12 +559,8 @@ static void ResumeLineComment(Accessor &styler, Sci_Position& pos, Sci_Position
maybe_doc_comment = true;
}
- while (pos < max && c != '\n') {
- if (pos == styler.LineEnd(styler.GetLine(pos)))
- styler.SetLineState(styler.GetLine(pos), 0);
- pos++;
- c = styler.SafeGetCharAt(pos, '\0');
- }
+ pos = styler.LineEnd(styler.GetLine(pos));
+ styler.SetLineState(styler.GetLine(pos), SCE_RUST_DEFAULT);
if (state == DocComment || (state == UnknownComment && maybe_doc_comment))
styler.ColourTo(pos - 1, SCE_RUST_COMMENTLINEDOC);
Modified: scintilla/lexilla/lexlib/Accessor.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -23,7 +23,7 @@ class Accessor : public LexAccessor {
PropSetSimple *pprops;
Accessor(Scintilla::IDocument *pAccess_, PropSetSimple *pprops_);
int GetPropertyInt(std::string_view key, int defaultValue=0) const;
- int IndentAmount(Sci_Position line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = 0);
+ int IndentAmount(Sci_Position line, int *flags, PFNIsCommentLeader pfnIsCommentLeader = nullptr);
};
}
Modified: scintilla/lexilla/lexlib/LexerBase.cxx
6 lines changed, 3 insertions(+), 3 deletions(-)
===================================================================
@@ -31,15 +31,15 @@ LexerBase::LexerBase(const LexicalClass *lexClasses_, size_t nClasses_) :
lexClasses(lexClasses_), nClasses(nClasses_) {
for (int wl = 0; wl < numWordLists; wl++)
keyWordLists[wl] = new WordList;
- keyWordLists[numWordLists] = 0;
+ keyWordLists[numWordLists] = nullptr;
}
LexerBase::~LexerBase() {
for (int wl = 0; wl < numWordLists; wl++) {
delete keyWordLists[wl];
- keyWordLists[wl] = 0;
+ keyWordLists[wl] = nullptr;
}
- keyWordLists[numWordLists] = 0;
+ keyWordLists[numWordLists] = nullptr;
}
void SCI_METHOD LexerBase::Release() {
Modified: scintilla/lexilla/lexlib/WordList.cxx
8 lines changed, 4 insertions(+), 4 deletions(-)
===================================================================
@@ -80,7 +80,7 @@ WordList::~WordList() {
}
WordList::operator bool() const noexcept {
- return len ? true : false;
+ return len != 0;
}
bool WordList::operator!=(const WordList &other) const noexcept {
@@ -144,7 +144,7 @@ bool WordList::Set(const char *s) {
* so '^GTK_' matches 'GTK_X', 'GTK_MAJOR_VERSION', and 'GTK_'.
*/
bool WordList::InList(const char *s) const noexcept {
- if (0 == words)
+ if (!words)
return false;
const unsigned char firstChar = s[0];
int j = starts[firstChar];
@@ -186,7 +186,7 @@ bool WordList::InList(const char *s) const noexcept {
* The marker is ~ in this case.
*/
bool WordList::InListAbbreviated(const char *s, const char marker) const noexcept {
- if (0 == words)
+ if (!words)
return false;
const unsigned char firstChar = s[0];
int j = starts[firstChar];
@@ -240,7 +240,7 @@ bool WordList::InListAbbreviated(const char *s, const char marker) const noexcep
* No multiple markers check is done and wont work.
*/
bool WordList::InListAbridged(const char *s, const char marker) const noexcept {
- if (0 == words)
+ if (!words)
return false;
const unsigned char firstChar = s[0];
int j = starts[firstChar];
Modified: scintilla/lexilla/version.txt
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1 +1 @@
-512
+513
Modified: scintilla/src/CellBuffer.cxx
4 lines changed, 2 insertions(+), 2 deletions(-)
===================================================================
@@ -37,7 +37,7 @@ struct CountWidths {
// from the Base Multilingual Plane and those from other planes.
Sci::Position countBasePlane;
Sci::Position countOtherPlanes;
- CountWidths(Sci::Position countBasePlane_=0, Sci::Position countOtherPlanes_=0) noexcept :
+ explicit CountWidths(Sci::Position countBasePlane_=0, Sci::Position countOtherPlanes_=0) noexcept :
countBasePlane(countBasePlane_),
countOtherPlanes(countOtherPlanes_) {
}
@@ -1286,7 +1286,7 @@ void CellBuffer::EndUndoAction() {
}
void CellBuffer::AddUndoAction(Sci::Position token, bool mayCoalesce) {
- bool startSequence;
+ bool startSequence = false;
uh.AppendAction(ActionType::container, token, nullptr, 0, startSequence, mayCoalesce);
}
Modified: scintilla/src/CharClassify.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -24,7 +24,7 @@ void CharClassify::SetDefaultCharClasses(bool includeWordClass) {
for (int ch = 0; ch < maxChar; ch++) {
if (ch == '\r' || ch == '\n')
charClass[ch] = CharacterClass::newLine;
- else if (ch < 0x20 || ch == ' ')
+ else if (IsControl(ch) || ch == ' ')
charClass[ch] = CharacterClass::space;
else if (includeWordClass && (ch >= 0x80 || IsAlphaNumeric(ch) || ch == '_'))
charClass[ch] = CharacterClass::word;
Modified: scintilla/src/CharacterType.h
84 lines changed, 57 insertions(+), 27 deletions(-)
===================================================================
@@ -12,14 +12,33 @@ namespace Scintilla::Internal {
// Functions for classifying characters
+/**
+ * Check if a character is a space.
+ * This is ASCII specific but is safe with chars >= 0x80.
+ */
constexpr bool IsASpace(int ch) noexcept {
return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
}
-constexpr bool IsASpaceOrTab(int ch) noexcept {
+constexpr bool IsSpaceOrTab(int ch) noexcept {
return (ch == ' ') || (ch == '\t');
}
+constexpr bool IsControl(int ch) noexcept {
+ return ((ch >= 0) && (ch <= 0x1F)) || (ch == 0x7F);
+}
+
+constexpr bool IsEOLCharacter(int ch) noexcept {
+ return ch == '\r' || ch == '\n';
+}
+
+constexpr bool IsBreakSpace(int ch) noexcept {
+ // used for text breaking, treat C0 control character as space.
+ // by default C0 control character is handled as special representation,
+ // so not appears in normal text. 0x7F DEL is omitted to simplify the code.
+ return ch >= 0 && ch <= ' ';
+}
+
constexpr bool IsADigit(int ch) noexcept {
return (ch >= '0') && (ch <= '9');
}
@@ -57,33 +76,44 @@ constexpr bool IsAlphaNumeric(int ch) noexcept {
((ch >= 'A') && (ch <= 'Z'));
}
-/**
- * Check if a character is a space.
- * This is ASCII specific but is safe with chars >= 0x80.
- */
-constexpr bool isspacechar(int ch) noexcept {
- return (ch == ' ') || ((ch >= 0x09) && (ch <= 0x0d));
-}
-
-constexpr bool iswordchar(int ch) noexcept {
- return IsAlphaNumeric(ch) || ch == '.' || ch == '_';
-}
-
-constexpr bool iswordstart(int ch) noexcept {
- return IsAlphaNumeric(ch) || ch == '_';
-}
-
-constexpr bool isoperator(int ch) noexcept {
- if (IsAlphaNumeric(ch))
- return false;
- if (ch == '%' || ch == '^' || ch == '&' || ch == '*' ||
- ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
- ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
- ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
- ch == '<' || ch == '>' || ch == ',' || ch == '/' ||
- ch == '?' || ch == '!' || ch == '.' || ch == '~')
+constexpr bool IsPunctuation(int ch) noexcept {
+ switch (ch) {
+ case '!':
+ case '"':
+ case '#':
+ case '$':
+ case '%':
+ case '&':
+ case '\'':
+ case '(':
+ case ')':
+ case '*':
+ case '+':
+ case ',':
+ case '-':
+ case '.':
+ case '/':
+ case ':':
+ case ';':
+ case '<':
+ case '=':
+ case '>':
+ case '?':
+ case '@':
+ case '[':
+ case '\\':
+ case ']':
+ case '^':
+ case '_':
+ case '`':
+ case '{':
+ case '|':
+ case '}':
+ case '~':
return true;
- return false;
+ default:
+ return false;
+ }
}
// Simple case functions for ASCII supersets.
Modified: scintilla/src/ContractionState.cxx
4 lines changed, 1 insertions(+), 3 deletions(-)
===================================================================
@@ -95,9 +95,7 @@ ContractionState<LINE>::ContractionState() noexcept : linesInDocument(1) {
}
template <typename LINE>
-ContractionState<LINE>::~ContractionState() {
- Clear();
-}
+ContractionState<LINE>::~ContractionState() = default;
template <typename LINE>
void ContractionState<LINE>::EnsureData() {
Modified: scintilla/src/Document.cxx
188 lines changed, 82 insertions(+), 106 deletions(-)
===================================================================
@@ -1127,53 +1127,74 @@ bool Document::IsDBCSDualByteAt(Sci::Position pos) const noexcept {
&& IsDBCSTrailByteNoExcept(cb.CharAt(pos + 1));
}
-static constexpr bool IsSpaceOrTab(int ch) noexcept {
- return ch == ' ' || ch == '\t';
-}
-
-// Need to break text into segments near lengthSegment but taking into
-// account the encoding to not break inside a UTF-8 or DBCS character
-// and also trying to avoid breaking inside a pair of combining characters.
+// Need to break text into segments near end but taking into account the
+// encoding to not break inside a UTF-8 or DBCS character and also trying
+// to avoid breaking inside a pair of combining characters, or inside
+// ligatures.
+// TODO: implement grapheme cluster boundaries,
+// see https://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries.
+//
// The segment length must always be long enough (more than 4 bytes)
// so that there will be at least one whole character to make a segment.
// For UTF-8, text must consist only of valid whole characters.
// In preference order from best to worst:
-// 1) Break after space
-// 2) Break before punctuation
-// 3) Break after whole character
-
-int Document::SafeSegment(const char *text, int length, int lengthSegment) const noexcept {
- if (length <= lengthSegment)
- return length;
- int lastSpaceBreak = -1;
- int lastPunctuationBreak = -1;
- int lastEncodingAllowedBreak = 0;
- for (int j=0; j < lengthSegment;) {
- const unsigned char ch = text[j];
- if (j > 0) {
- if (IsSpaceOrTab(text[j - 1]) && !IsSpaceOrTab(text[j])) {
- lastSpaceBreak = j;
+// 1) Break before or after spaces or controls
+// 2) Break at word and punctuation boundary for better kerning and ligature support
+// 3) Break after whole character, this may break combining characters
+
+size_t Document::SafeSegment(std::string_view text) const noexcept {
+ // check space first as most written language use spaces.
+ for (std::string_view::iterator it = text.end() - 1; it != text.begin(); --it) {
+ if (IsBreakSpace(*it)) {
+ return it - text.begin();
+ }
+ }
+
+ if (!dbcsCodePage || dbcsCodePage == CpUtf8) {
+ // backward iterate for UTF-8 and single byte encoding to find word and punctuation boundary.
+ std::string_view::iterator it = text.end() - 1;
+ const bool punctuation = IsPunctuation(*it);
+ do {
+ --it;
+ if (punctuation != IsPunctuation(*it)) {
+ return it - text.begin() + 1;
}
- if (ch < 'A') {
- lastPunctuationBreak = j;
+ } while (it != text.begin());
+
+ it = text.end() - 1;
+ if (dbcsCodePage) {
+ // for UTF-8 go back to the start of last character.
+ for (int trail = 0; trail < UTF8MaxBytes - 1 && UTF8IsTrailByte(*it); trail++) {
+ --it;
}
}
- lastEncodingAllowedBreak = j;
+ return it - text.begin();
+ }
- if (dbcsCodePage == CpUtf8) {
- j += UTF8BytesOfLead[ch];
- } else if (dbcsCodePage) {
- j += IsDBCSLeadByteNoExcept(ch) ? 2 : 1;
- } else {
- j++;
+ {
+ // forward iterate for DBCS to find word and punctuation boundary.
+ size_t lastPunctuationBreak = 0;
+ size_t lastEncodingAllowedBreak = 0;
+ CharacterClass ccPrev = CharacterClass::space;
+ for (size_t j = 0; j < text.length();) {
+ const unsigned char ch = text[j];
+ lastEncodingAllowedBreak = j++;
+
+ CharacterClass cc = CharacterClass::word;
+ if (UTF8IsAscii(ch)) {
+ if (IsPunctuation(ch)) {
+ cc = CharacterClass::punctuation;
+ }
+ } else {
+ j += IsDBCSLeadByteNoExcept(ch);
+ }
+ if (cc != ccPrev) {
+ ccPrev = cc;
+ lastPunctuationBreak = lastEncodingAllowedBreak;
+ }
}
+ return lastPunctuationBreak ? lastPunctuationBreak : lastEncodingAllowedBreak;
}
- if (lastSpaceBreak >= 0) {
- return lastSpaceBreak;
- } else if (lastPunctuationBreak >= 0) {
- return lastPunctuationBreak;
- }
- return lastEncodingAllowedBreak;
}
EncodingFamily Document::CodePageFamily() const noexcept {
@@ -1218,7 +1239,7 @@ bool Document::DeleteChars(Sci::Position pos, Sci::Position len) {
DocModification(
ModificationFlags::BeforeDelete | ModificationFlags::User,
pos, len,
- 0, 0));
+ 0, nullptr));
const Sci::Line prevLinesTotal = LinesTotal();
const bool startSavePoint = cb.IsSavePoint();
bool startSequence = false;
@@ -2419,7 +2440,7 @@ Sci::Line Document::GetMaxLineState() const noexcept {
void SCI_METHOD Document::ChangeLexerState(Sci_Position start, Sci_Position end) {
const DocModification mh(ModificationFlags::LexerState, start,
- end-start, 0, 0, 0);
+ end-start, 0, nullptr, 0);
NotifyModified(mh);
}
@@ -2432,20 +2453,20 @@ StyledText Document::MarginStyledText(Sci::Line line) const noexcept {
void Document::MarginSetText(Sci::Line line, const char *text) {
Margins()->SetText(line, text);
const DocModification mh(ModificationFlags::ChangeMargin, LineStart(line),
- 0, 0, 0, line);
+ 0, 0, nullptr, line);
NotifyModified(mh);
}
void Document::MarginSetStyle(Sci::Line line, int style) {
Margins()->SetStyle(line, style);
NotifyModified(DocModification(ModificationFlags::ChangeMargin, LineStart(line),
- 0, 0, 0, line));
+ 0, 0, nullptr, line));
}
void Document::MarginSetStyles(Sci::Line line, const unsigned char *styles) {
Margins()->SetStyles(line, styles);
NotifyModified(DocModification(ModificationFlags::ChangeMargin, LineStart(line),
- 0, 0, 0, line));
+ 0, 0, nullptr, line));
}
void Document::MarginClearAll() {
@@ -2468,7 +2489,7 @@ void Document::AnnotationSetText(Sci::Line line, const char *text) {
Annotations()->SetText(line, text);
const int linesAfter = AnnotationLines(line);
DocModification mh(ModificationFlags::ChangeAnnotation, LineStart(line),
- 0, 0, 0, line);
+ 0, 0, nullptr, line);
mh.annotationLinesAdded = linesAfter - linesBefore;
NotifyModified(mh);
}
@@ -2478,7 +2499,7 @@ void Document::AnnotationSetStyle(Sci::Line line, int style) {
if (line >= 0 && line < LinesTotal()) {
Annotations()->SetStyle(line, style);
const DocModification mh(ModificationFlags::ChangeAnnotation, LineStart(line),
- 0, 0, 0, line);
+ 0, 0, nullptr, line);
NotifyModified(mh);
}
}
@@ -2511,7 +2532,7 @@ void Document::EOLAnnotationSetText(Sci::Line line, const char *text) {
if (line >= 0 && line < LinesTotal()) {
EOLAnnotations()->SetText(line, text);
const DocModification mh(ModificationFlags::ChangeEOLAnnotation, LineStart(line),
- 0, 0, 0, line);
+ 0, 0, nullptr, line);
NotifyModified(mh);
}
}
@@ -2520,7 +2541,7 @@ void Document::EOLAnnotationSetStyle(Sci::Line line, int style) {
if (line >= 0 && line < LinesTotal()) {
EOLAnnotations()->SetStyle(line, style);
const DocModification mh(ModificationFlags::ChangeEOLAnnotation, LineStart(line),
- 0, 0, 0, line);
+ 0, 0, nullptr, line);
NotifyModified(mh);
}
}
@@ -2600,49 +2621,8 @@ void Document::NotifyModified(DocModification mh) {
}
}
-// Used for word part navigation.
-static bool IsASCIIPunctuationCharacter(unsigned int ch) noexcept {
- switch (ch) {
- case '!':
- case '"':
- case '#':
- case '$':
- case '%':
- case '&':
- case '\'':
- case '(':
- case ')':
- case '*':
- case '+':
- case ',':
- case '-':
- case '.':
- case '/':
- case ':':
- case ';':
- case '<':
- case '=':
- case '>':
- case '?':
- case '@':
- case '[':
- case '\\':
- case ']':
- case '^':
- case '_':
- case '`':
- case '{':
- case '|':
- case '}':
- case '~':
- return true;
- default:
- return false;
- }
-}
-
bool Document::IsWordPartSeparator(unsigned int ch) const {
- return (WordCharacterClass(ch) == CharacterClass::word) && IsASCIIPunctuationCharacter(ch);
+ return (WordCharacterClass(ch) == CharacterClass::word) && IsPunctuation(ch);
}
Sci::Position Document::WordPartLeft(Sci::Position pos) const {
@@ -2672,15 +2652,15 @@ Sci::Position Document::WordPartLeft(Sci::Position pos) const {
pos -= CharacterBefore(pos).widthBytes;
if (!IsADigit(CharacterAfter(pos).character))
pos += CharacterAfter(pos).widthBytes;
- } else if (IsASCIIPunctuationCharacter(ceStart.character)) {
- while (pos > 0 && IsASCIIPunctuationCharacter(CharacterAfter(pos).character))
+ } else if (IsPunctuation(ceStart.character)) {
+ while (pos > 0 && IsPunctuation(CharacterAfter(pos).character))
pos -= CharacterBefore(pos).widthBytes;
- if (!IsASCIIPunctuationCharacter(CharacterAfter(pos).character))
+ if (!IsPunctuation(CharacterAfter(pos).character))
pos += CharacterAfter(pos).widthBytes;
- } else if (isspacechar(ceStart.character)) {
- while (pos > 0 && isspacechar(CharacterAfter(pos).character))
+ } else if (IsASpace(ceStart.character)) {
+ while (pos > 0 && IsASpace(CharacterAfter(pos).character))
pos -= CharacterBefore(pos).widthBytes;
- if (!isspacechar(CharacterAfter(pos).character))
+ if (!IsASpace(CharacterAfter(pos).character))
pos += CharacterAfter(pos).widthBytes;
} else if (!IsASCII(ceStart.character)) {
while (pos > 0 && !IsASCII(CharacterAfter(pos).character))
@@ -2723,30 +2703,26 @@ Sci::Position Document::WordPartRight(Sci::Position pos) const {
} else if (IsADigit(ceStart.character)) {
while (pos < length && IsADigit(CharacterAfter(pos).character))
pos += CharacterAfter(pos).widthBytes;
- } else if (IsASCIIPunctuationCharacter(ceStart.character)) {
- while (pos < length && IsASCIIPunctuationCharacter(CharacterAfter(pos).character))
+ } else if (IsPunctuation(ceStart.character)) {
+ while (pos < length && IsPunctuation(CharacterAfter(pos).character))
pos += CharacterAfter(pos).widthBytes;
- } else if (isspacechar(ceStart.character)) {
- while (pos < length && isspacechar(CharacterAfter(pos).character))
+ } else if (IsASpace(ceStart.character)) {
+ while (pos < length && IsASpace(CharacterAfter(pos).character))
pos += CharacterAfter(pos).widthBytes;
} else {
pos += CharacterAfter(pos).widthBytes;
}
return pos;
}
-static constexpr bool IsLineEndChar(char c) noexcept {
- return (c == '\n' || c == '\r');
-}
-
Sci::Position Document::ExtendStyleRange(Sci::Position pos, int delta, bool singleLine) noexcept {
- const int sStart = cb.StyleAt(pos);
+ const char sStart = cb.StyleAt(pos);
if (delta < 0) {
- while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))))
+ while (pos > 0 && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsEOLCharacter(cb.CharAt(pos))))
pos--;
pos++;
} else {
- while (pos < (LengthNoExcept()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsLineEndChar(cb.CharAt(pos))))
+ while (pos < (LengthNoExcept()) && (cb.StyleAt(pos) == sStart) && (!singleLine || !IsEOLCharacter(cb.CharAt(pos))))
pos++;
}
return pos;
@@ -2986,7 +2962,7 @@ class UTF8Iterator {
typedef wchar_t* pointer;
typedef wchar_t& reference;
- UTF8Iterator(const Document *doc_=nullptr, Sci::Position position_=0) noexcept :
+ explicit UTF8Iterator(const Document *doc_=nullptr, Sci::Position position_=0) noexcept :
doc(doc_), position(position_), characterIndex(0), lenBytes(0), lenCharacters(0), buffered{} {
buffered[0] = 0;
buffered[1] = 0;
Modified: scintilla/src/Document.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -352,7 +352,7 @@ class Document : PerLine, public Scintilla::IDocument, public Scintilla::ILoader
bool IsDBCSTrailByteNoExcept(char ch) const noexcept;
int DBCSDrawBytes(std::string_view text) const noexcept;
bool IsDBCSDualByteAt(Sci::Position pos) const noexcept;
- int SafeSegment(const char *text, int length, int lengthSegment) const noexcept;
+ size_t SafeSegment(std::string_view text) const noexcept;
EncodingFamily CodePageFamily() const noexcept;
// Gateways to modifying document
Modified: scintilla/src/EditView.cxx
107 lines changed, 66 insertions(+), 41 deletions(-)
===================================================================
@@ -368,12 +368,6 @@ inline char CaseForce(Style::CaseForce caseForce, char chDoc, char chPrevious) n
}
}
-constexpr bool IsControlCharacter(int ch) noexcept {
- // iscntrl returns true for lots of chars > 127 which are displayable,
- // currently only check C0 control characters.
- return (ch >= 0 && ch < ' ') || (ch == 127);
-}
-
bool ViewIsASCII(std::string_view text) {
return std::all_of(text.cbegin(), text.cend(), IsASCII);
}
@@ -470,7 +464,7 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
ll->positions[0] = 0;
bool lastSegItalics = false;
- BreakFinder bfLayout(ll, nullptr, Range(0, numCharsInLine), posLineStart, 0, false, model.pdoc, &model.reprs, nullptr);
+ BreakFinder bfLayout(ll, nullptr, Range(0, numCharsInLine), posLineStart, 0, BreakFinder::BreakFor::Text, model.pdoc, &model.reprs, nullptr);
while (bfLayout.More()) {
const TextSegment ts = bfLayout.Next();
@@ -570,46 +564,55 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
ll->wrapIndent = vstyle.aveCharWidth; // Indent to show start visual
ll->lines = 0;
// Calculate line start positions based upon width.
- Sci::Position lastGoodBreak = 0;
Sci::Position lastLineStart = 0;
- XYACCUMULATOR startOffset = 0;
+ XYACCUMULATOR startOffset = width;
Sci::Position p = 0;
- while (p < ll->numCharsInLine) {
- if ((ll->positions[p + 1] - startOffset) >= width) {
+ const Wrap wrapState = vstyle.wrap.state;
+ const Sci::Position numCharsInLine = ll->numCharsInLine;
+ while (p < numCharsInLine) {
+ while (p < numCharsInLine && ll->positions[p + 1] < startOffset) {
+ p++;
+ }
+ if (p < numCharsInLine) {
+ // backtrack to find lastGoodBreak
+ Sci::Position lastGoodBreak = p;
+ if (p > 0) {
+ lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) - posLineStart;
+ }
+ if (wrapState != Wrap::Char) {
+ Sci::Position pos = lastGoodBreak;
+ while (pos > lastLineStart) {
+ // style boundary and space
+ if (wrapState != Wrap::WhiteSpace && (ll->styles[pos - 1] != ll->styles[pos])) {
+ break;
+ }
+ if (IsBreakSpace(ll->chars[pos - 1]) && !IsBreakSpace(ll->chars[pos])) {
+ break;
+ }
+ pos = model.pdoc->MovePositionOutsideChar(pos + posLineStart - 1, -1) - posLineStart;
+ }
+ if (pos > lastLineStart) {
+ lastGoodBreak = pos;
+ }
+ }
if (lastGoodBreak == lastLineStart) {
// Try moving to start of last character
if (p > 0) {
- lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1)
- - posLineStart;
+ lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1) - posLineStart;
}
if (lastGoodBreak == lastLineStart) {
// Ensure at least one character on line.
- lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1)
- - posLineStart;
+ lastGoodBreak = model.pdoc->MovePositionOutsideChar(lastGoodBreak + posLineStart + 1, 1) - posLineStart;
}
}
lastLineStart = lastGoodBreak;
ll->lines++;
- ll->SetLineStart(ll->lines, static_cast<int>(lastGoodBreak));
- startOffset = ll->positions[lastGoodBreak];
+ ll->SetLineStart(ll->lines, static_cast<int>(lastLineStart));
+ startOffset = ll->positions[lastLineStart];
// take into account the space for start wrap mark and indent
- startOffset -= ll->wrapIndent;
- p = lastGoodBreak + 1;
- continue;
- }
- if (p > 0) {
- if (vstyle.wrap.state == Wrap::Char) {
- lastGoodBreak = model.pdoc->MovePositionOutsideChar(p + posLineStart, -1)
- - posLineStart;
- p = model.pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
- continue;
- } else if ((vstyle.wrap.state == Wrap::Word) && (ll->styles[p] != ll->styles[p - 1])) {
- lastGoodBreak = p;
- } else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) {
- lastGoodBreak = p;
- }
+ startOffset += width - ll->wrapIndent;
+ p = lastLineStart + 1;
}
- p++;
}
ll->lines++;
}
@@ -1636,7 +1639,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
}
const bool caretBlinkState = (model.caret.active && model.caret.on) || (!additionalCaretsBlink && !mainCaret);
const bool caretVisibleState = additionalCaretsVisible || mainCaret;
- if ((xposCaret >= 0) && vsDraw.IsCaretVisible() &&
+ if ((xposCaret >= 0) && vsDraw.IsCaretVisible(mainCaret) &&
(drawDrag || (caretBlinkState && caretVisibleState))) {
bool canDrawBlockCaret = true;
bool drawBlockCaret = false;
@@ -1660,7 +1663,8 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
if (xposCaret > 0)
caretWidthOffset = 0.51f; // Move back so overlaps both character cells.
xposCaret += xStart;
- const ViewStyle::CaretShape caretShape = drawDrag ? ViewStyle::CaretShape::line : vsDraw.CaretShapeForMode(model.inOverstrike);
+ const ViewStyle::CaretShape caretShape = drawDrag ? ViewStyle::CaretShape::line :
+ vsDraw.CaretShapeForMode(model.inOverstrike, mainCaret);
if (drawDrag) {
/* Dragging text, use a line caret */
rcCaret.left = std::round(xposCaret - caretWidthOffset);
@@ -1673,7 +1677,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
} else if ((caretShape == ViewStyle::CaretShape::block) || imeCaretBlockOverride) {
/* Block caret */
rcCaret.left = xposCaret;
- if (canDrawBlockCaret && !(IsControlCharacter(ll->chars[offset]))) {
+ if (canDrawBlockCaret && !(IsControl(ll->chars[offset]))) {
drawBlockCaret = true;
rcCaret.right = xposCaret + widthOverstrikeCaret;
} else {
@@ -1733,6 +1737,21 @@ static void DrawWrapIndentAndMarker(Surface *surface, const ViewStyle &vsDraw, c
}
}
+// On the curses platform, the terminal is drawing its own caret, so if the caret is within
+// the main selection, do not draw the selection at that position.
+// Use iDoc from DrawBackground and DrawForeground here because TextSegment has been adjusted
+// such that, if the caret is inside the main selection, the beginning or end of that selection
+// is at the end of a text segment.
+// This function should only be called if iDoc is within the main selection.
+static InSelection CharacterInCursesSelection(Sci::Position iDoc, const EditModel &model, const ViewStyle &vsDraw) {
+ const SelectionPosition &posCaret = model.sel.RangeMain().caret;
+ const bool caretAtStart = posCaret < model.sel.RangeMain().anchor && posCaret.Position() == iDoc;
+ const bool caretAtEnd = posCaret > model.sel.RangeMain().anchor &&
+ vsDraw.DrawCaretInsideSelection(false, false) &&
+ model.pdoc->MovePositionOutsideChar(posCaret.Position() - 1, -1) == iDoc;
+ return (caretAtStart || caretAtEnd) ? InSelection::inNone : InSelection::inMain;
+}
+
void EditView::DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
PRectangle rcLine, Range lineRange, Sci::Position posLineStart, int xStart,
int subLine, std::optional<ColourRGBA> background) const {
@@ -1743,7 +1762,8 @@ void EditView::DrawBackground(Surface *surface, const EditModel &model, const Vi
// Does not take margin into account but not significant
const XYPOSITION xStartVisible = static_cast<XYPOSITION>(subLineStart-xStart);
- BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, selBackDrawn, model.pdoc, &model.reprs, nullptr);
+ const BreakFinder::BreakFor breakFor = selBackDrawn ? BreakFinder::BreakFor::Selection : BreakFinder::BreakFor::Text;
+ BreakFinder bfBack(ll, &model.sel, lineRange, posLineStart, xStartVisible, breakFor, model.pdoc, &model.reprs, &vsDraw);
const bool drawWhitespaceBackground = vsDraw.WhitespaceBackgroundDrawn() && !background;
@@ -1766,7 +1786,9 @@ void EditView::DrawBackground(Surface *surface, const EditModel &model, const Vi
if (rcSegment.right > rcLine.right)
rcSegment.right = rcLine.right;
- const InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc);
+ InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc);
+ if (FlagSet(vsDraw.caret.style, CaretStyle::Curses) && (inSelection == InSelection::inMain))
+ inSelection = CharacterInCursesSelection(iDoc, model, vsDraw);
const bool inHotspot = model.hotspot.Valid() && model.hotspot.ContainsCharacter(iDoc);
ColourRGBA textBack = TextBackground(model, vsDraw, ll, background, inSelection,
inHotspot, ll->styles[i], i);
@@ -1959,8 +1981,9 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
const XYPOSITION xStartVisible = static_cast<XYPOSITION>(subLineStart-xStart);
// Foreground drawing loop
- BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible,
- (((phasesDraw == PhasesDraw::One) && selBackDrawn) || vsDraw.SelectionTextDrawn()), model.pdoc, &model.reprs, &vsDraw);
+ const BreakFinder::BreakFor breakFor = (((phasesDraw == PhasesDraw::One) && selBackDrawn) || vsDraw.SelectionTextDrawn())
+ ? BreakFinder::BreakFor::ForegroundAndSelection : BreakFinder::BreakFor::Foreground;
+ BreakFinder bfFore(ll, &model.sel, lineRange, posLineStart, xStartVisible, breakFor, model.pdoc, &model.reprs, &vsDraw);
while (bfFore.More()) {
@@ -2010,7 +2033,9 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
}
}
}
- const InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc);
+ InSelection inSelection = hideSelection ? InSelection::inNone : model.sel.CharacterInSelection(iDoc);
+ if (FlagSet(vsDraw.caret.style, CaretStyle::Curses) && (inSelection == InSelection::inMain))
+ inSelection = CharacterInCursesSelection(iDoc, model, vsDraw);
const std::optional<ColourRGBA> selectionFore = SelectionForeground(model, vsDraw, inSelection);
if (selectionFore) {
textFore = *selectionFore;
Modified: scintilla/src/Editor.cxx
12 lines changed, 6 insertions(+), 6 deletions(-)
===================================================================
@@ -772,9 +772,9 @@ void Editor::MultipleSelectAdd(AddNumber addNumber) {
searchRanges.push_back(rangeTarget);
}
- for (std::vector<Range>::const_iterator it = searchRanges.begin(); it != searchRanges.end(); ++it) {
- Sci::Position searchStart = it->start;
- const Sci::Position searchEnd = it->end;
+ for (const Range range : searchRanges) {
+ Sci::Position searchStart = range.start;
+ const Sci::Position searchEnd = range.end;
for (;;) {
Sci::Position lengthFound = selectedText.length();
const Sci::Position pos = pdoc->FindText(searchStart, searchEnd,
@@ -2193,10 +2193,10 @@ void Editor::PasteRectangular(SelectionPosition pos, const char *ptr, Sci::Posit
sel.RangeMain().caret = RealizeVirtualSpace(sel.RangeMain().caret);
const int xInsert = XFromPosition(sel.RangeMain().caret);
bool prevCr = false;
- while ((len > 0) && IsEOLChar(ptr[len-1]))
+ while ((len > 0) && IsEOLCharacter(ptr[len-1]))
len--;
for (Sci::Position i = 0; i < len; i++) {
- if (IsEOLChar(ptr[i])) {
+ if (IsEOLCharacter(ptr[i])) {
if ((ptr[i] == '\r') || (!prevCr))
line++;
if (line >= pdoc->LinesTotal()) {
@@ -7592,7 +7592,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
return vs.ElementColour(Element::Caret)->OpaqueRGB();
case Message::SetCaretStyle:
- if (static_cast<CaretStyle>(wParam) <= (CaretStyle::Block | CaretStyle::OverstrikeBlock | CaretStyle::BlockAfter))
+ if (static_cast<CaretStyle>(wParam) <= (CaretStyle::Block | CaretStyle::OverstrikeBlock | CaretStyle::Curses | CaretStyle::BlockAfter))
vs.caret.style = static_cast<CaretStyle>(wParam);
else
/* Default to the line caret */
Modified: scintilla/src/KeyMap.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -67,7 +67,7 @@ const std::map<KeyModifiers, Message> &KeyMap::GetKeyMap() const noexcept {
namespace {
-constexpr Keys Key(char ch) {
+constexpr Keys Key(char ch) noexcept {
return static_cast<Keys>(ch);
}
Modified: scintilla/src/MarginView.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -87,7 +87,7 @@ void DrawWrapMarker(Surface *surface, PRectangle rcPlace,
XYPOSITION yBase;
int yDir;
XYPOSITION halfWidth;
- Point At(XYPOSITION xRelative, XYPOSITION yRelative) noexcept {
+ Point At(XYPOSITION xRelative, XYPOSITION yRelative) const noexcept {
return Point(xBase + xDir * xRelative + halfWidth, yBase + yDir * yRelative + halfWidth);
}
};
Modified: scintilla/src/MarginView.h
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -36,7 +36,7 @@ class MarginView {
void DropGraphics() noexcept;
void RefreshPixMaps(Surface *surfaceWindow, const ViewStyle &vsDraw);
- void PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcMargin, const MarginStyle &marginStyle,
+ void PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcOneMargin, 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/PerLine.cxx
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -102,7 +102,7 @@ void LineMarkers::Init() {
void LineMarkers::InsertLine(Sci::Line line) {
if (markers.Length()) {
- markers.Insert(line, 0);
+ markers.Insert(line, nullptr);
}
}
Modified: scintilla/src/PositionCache.cxx
98 lines changed, 55 insertions(+), 43 deletions(-)
===================================================================
@@ -31,6 +31,7 @@
#include "Geometry.h"
#include "Platform.h"
+#include "CharacterType.h"
#include "CharacterCategoryMap.h"
#include "Position.h"
#include "UniqueString.h"
@@ -547,10 +548,8 @@ namespace {
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++) {
- k = k * 0x100;
- const unsigned char uc = charBytes[i];
- k += uc;
+ for (const unsigned char uc : charBytes) {
+ k = k * 0x100 + uc;
}
return k;
}
@@ -562,16 +561,18 @@ 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);
- const MapRepresentation::iterator it = mapReprs.find(key);
- if (it == mapReprs.end()) {
+ const bool inserted = mapReprs.insert_or_assign(key, Representation(value)).second;
+ if (inserted) {
// New entry so increment for first byte
const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
startByteHasReprs[ucStart]++;
+ if (key > maxKey) {
+ maxKey = key;
+ }
if (key == representationKeyCrLf) {
crlf = true;
}
}
- mapReprs[key] = Representation(value);
}
}
@@ -608,6 +609,9 @@ void SpecialRepresentations::ClearRepresentation(std::string_view charBytes) {
mapReprs.erase(it);
const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
startByteHasReprs[ucStart]--;
+ if (key == maxKey && startByteHasReprs[ucStart] == 0) {
+ maxKey = mapReprs.empty() ? 0 : mapReprs.crbegin()->first;
+ }
if (key == representationKeyCrLf) {
crlf = false;
}
@@ -616,7 +620,11 @@ void SpecialRepresentations::ClearRepresentation(std::string_view charBytes) {
}
const Representation *SpecialRepresentations::GetRepresentation(std::string_view charBytes) const {
- const MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes));
+ const unsigned int key = KeyFromString(charBytes);
+ if (key > maxKey) {
+ return nullptr;
+ }
+ const MapRepresentation::const_iterator it = mapReprs.find(key);
if (it != mapReprs.end()) {
return &(it->second);
}
@@ -633,19 +641,11 @@ const Representation *SpecialRepresentations::RepresentationFromCharacter(std::s
return nullptr;
}
-bool SpecialRepresentations::Contains(std::string_view charBytes) const {
- PLATFORM_ASSERT(charBytes.length() <= 4);
- const unsigned char ucStart = charBytes.empty() ? 0 : charBytes[0];
- if (!startByteHasReprs[ucStart])
- return false;
- const MapRepresentation::const_iterator it = mapReprs.find(KeyFromString(charBytes));
- return it != mapReprs.end();
-}
-
void SpecialRepresentations::Clear() {
mapReprs.clear();
- constexpr short none = 0;
+ constexpr unsigned short none = 0;
std::fill(startByteHasReprs, std::end(startByteHasReprs), none);
+ maxKey = 0;
crlf = false;
}
@@ -662,7 +662,7 @@ void BreakFinder::Insert(Sci::Position val) {
}
BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lineRange_, Sci::Position posLineStart_,
- XYPOSITION xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw) :
+ XYPOSITION xStart, BreakFor breakFor, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw) :
ll(ll_),
lineRange(lineRange_),
posLineStart(posLineStart_),
@@ -683,7 +683,7 @@ BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lin
nextBreak--;
}
- if (breakForSelection) {
+ if (FlagSet(breakFor, BreakFor::Selection)) {
const SelectionPosition posStart(posLineStart);
const SelectionPosition posEnd(posLineStart + lineRange.end);
const SelectionSegment segmentLine(posStart, posEnd);
@@ -696,8 +696,23 @@ BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lin
Insert(portion.end.Position() - posLineStart);
}
}
+ // On the curses platform, the terminal is drawing its own caret, so add breaks around the
+ // caret in the main selection in order to help prevent the selection from being drawn in
+ // the caret's cell.
+ if (FlagSet(pvsDraw->caret.style, CaretStyle::Curses) && !psel->RangeMain().Empty()) {
+ const Sci::Position caretPos = psel->RangeMain().caret.Position();
+ const Sci::Position anchorPos = psel->RangeMain().anchor.Position();
+ if (caretPos < anchorPos) {
+ const Sci::Position nextPos = pdoc->MovePositionOutsideChar(caretPos + 1, 1);
+ Insert(nextPos - posLineStart);
+ } else if (caretPos > anchorPos && pvsDraw->DrawCaretInsideSelection(false, false)) {
+ const Sci::Position prevPos = pdoc->MovePositionOutsideChar(caretPos - 1, -1);
+ if (prevPos > anchorPos)
+ Insert(prevPos - posLineStart);
+ }
+ }
}
- if (pvsDraw && pvsDraw->indicatorsSetFore) {
+ if (FlagSet(breakFor, BreakFor::Foreground) && pvsDraw->indicatorsSetFore) {
for (const IDecoration *deco : pdoc->decorations->View()) {
if (pvsDraw->indicators[deco->Indicator()].OverridesTextFore()) {
Sci::Position startPos = deco->EndRun(posLineStart);
@@ -713,12 +728,12 @@ BreakFinder::BreakFinder(const LineLayout *ll_, const Selection *psel, Range lin
saeNext = (!selAndEdge.empty()) ? selAndEdge[0] : -1;
}
-BreakFinder::~BreakFinder() {
-}
+BreakFinder::~BreakFinder() noexcept = default;
TextSegment BreakFinder::Next() {
- if (subBreak == -1) {
+ if (subBreak < 0) {
const int prev = nextBreak;
+ const Representation *repr = nullptr;
while (nextBreak < lineRange.end) {
int charWidth = 1;
const char * const chars = &ll->chars[nextBreak];
@@ -730,7 +745,7 @@ TextSegment BreakFinder::Next() {
charWidth = pdoc->DBCSDrawBytes(std::string_view(chars, lineRange.end - nextBreak));
}
}
- const Representation *repr = nullptr;
+ 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') {
@@ -752,35 +767,32 @@ TextSegment BreakFinder::Next() {
} else {
repr = nullptr; // Optimize -> should remember repr
}
- if ((nextBreak - prev) < lengthStartSubdivision) {
- return TextSegment(prev, nextBreak - prev, repr);
- } else {
- break;
- }
+ break;
}
}
nextBreak += charWidth;
}
- if ((nextBreak - prev) < lengthStartSubdivision) {
- return TextSegment(prev, nextBreak - prev);
+
+ const int lengthSegment = nextBreak - prev;
+ if (lengthSegment < lengthStartSubdivision) {
+ return TextSegment(prev, lengthSegment, repr);
}
subBreak = prev;
}
+
// Splitting up a long run from prev to nextBreak in lots of approximately lengthEachSubdivision.
- // For very long runs add extra breaks after spaces or if no spaces before low punctuation.
const int startSegment = subBreak;
- if ((nextBreak - subBreak) <= lengthEachSubdivision) {
- subBreak = -1;
- return TextSegment(startSegment, nextBreak - startSegment);
+ const int remaining = nextBreak - startSegment;
+ int lengthSegment = remaining;
+ if (lengthSegment > lengthEachSubdivision) {
+ lengthSegment = static_cast<int>(pdoc->SafeSegment(std::string_view(&ll->chars[startSegment], lengthEachSubdivision)));
+ }
+ if (lengthSegment < remaining) {
+ subBreak += lengthSegment;
} else {
- subBreak += pdoc->SafeSegment(&ll->chars[subBreak], nextBreak-subBreak, lengthEachSubdivision);
- if (subBreak >= nextBreak) {
- subBreak = -1;
- return TextSegment(startSegment, nextBreak - startSegment);
- } else {
- return TextSegment(startSegment, subBreak - startSegment);
- }
+ subBreak = -1;
}
+ return TextSegment(startSegment, lengthSegment);
}
bool BreakFinder::More() const noexcept {
Modified: scintilla/src/PositionCache.h
24 lines changed, 11 insertions(+), 13 deletions(-)
===================================================================
@@ -10,14 +10,6 @@
namespace Scintilla::Internal {
-inline constexpr bool IsEOLChar(int ch) noexcept {
- return (ch == '\r') || (ch == '\n');
-}
-
-inline constexpr bool IsSpaceOrTab(int ch) noexcept {
- return ch == ' ' || ch == '\t';
-}
-
/**
* A point in document space.
* Uses double for sufficient resolution in large (>20,000,000 line) documents.
@@ -208,7 +200,8 @@ typedef std::map<unsigned int, Representation> MapRepresentation;
class SpecialRepresentations {
MapRepresentation mapReprs;
- short startByteHasReprs[0x100] {};
+ unsigned short startByteHasReprs[0x100] {};
+ unsigned int maxKey = 0;
bool crlf = false;
public:
void SetRepresentation(std::string_view charBytes, std::string_view value);
@@ -217,7 +210,6 @@ class SpecialRepresentations {
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;
}
@@ -250,7 +242,7 @@ class BreakFinder {
int saeNext;
int subBreak;
const Document *pdoc;
- EncodingFamily encodingFamily;
+ const EncodingFamily encodingFamily;
const SpecialRepresentations *preprs;
void Insert(Sci::Position val);
public:
@@ -259,14 +251,20 @@ class BreakFinder {
enum { lengthStartSubdivision = 300 };
// Try to make each subdivided run lengthEachSubdivision or shorter.
enum { lengthEachSubdivision = 100 };
+ enum class BreakFor {
+ Text = 0,
+ Selection = 1,
+ Foreground = 2,
+ ForegroundAndSelection = 3,
+ };
BreakFinder(const LineLayout *ll_, const Selection *psel, Range lineRange_, Sci::Position posLineStart_,
- XYPOSITION xStart, bool breakForSelection, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw);
+ XYPOSITION xStart, BreakFor breakFor, const Document *pdoc_, const SpecialRepresentations *preprs_, const ViewStyle *pvsDraw);
// Deleted so BreakFinder objects can not be copied.
BreakFinder(const BreakFinder &) = delete;
BreakFinder(BreakFinder &&) = delete;
void operator=(const BreakFinder &) = delete;
void operator=(BreakFinder &&) = delete;
- ~BreakFinder();
+ ~BreakFinder() noexcept;
TextSegment Next();
bool More() const noexcept;
};
Modified: scintilla/src/ViewStyle.cxx
32 lines changed, 13 insertions(+), 19 deletions(-)
===================================================================
@@ -136,8 +136,6 @@ ViewStyle::ViewStyle(size_t stylesSize_) :
Element::SelectionBack,
Element::SelectionInactiveBack,
});
- selection.layer = Layer::Base;
- selection.eolFilled = false;
foldmarginColour.reset();
foldmarginHighlightColour.reset();
@@ -155,15 +153,9 @@ ViewStyle::ViewStyle(size_t stylesSize_) :
Element::Caret,
Element::CaretAdditional,
});
- caret.style = CaretStyle::Line;
- caret.width = 1;
elementColours.erase(Element::CaretLineBack);
elementAllowsTranslucent.insert(Element::CaretLineBack);
- caretLine.alwaysShow = false;
- caretLine.subLine = false;
- caretLine.layer = Layer::Base;
- caretLine.frame = 0;
someStylesProtected = false;
someStylesForceCase = false;
@@ -210,12 +202,6 @@ ViewStyle::ViewStyle(size_t stylesSize_) :
ctrlCharPadding = 3; // +3 For a blank on front and rounded edge each side
lastSegItalicsOffset = 2;
- wrap.state = Wrap::None;
- wrap.visualFlags = WrapVisualFlag::None;
- wrap.visualFlagsLocation = WrapVisualLocation::Default;
- wrap.visualStartIndent = 0;
- wrap.indentMode = WrapIndentMode::Fixed;
-
localeName = localeNameDefault;
}
@@ -661,26 +647,34 @@ bool ViewStyle::SetWrapIndentMode(WrapIndentMode wrapIndentMode_) noexcept {
bool ViewStyle::IsBlockCaretStyle() const noexcept {
return ((caret.style & CaretStyle::InsMask) == CaretStyle::Block) ||
- FlagSet(caret.style, CaretStyle::OverstrikeBlock);
+ FlagSet(caret.style, CaretStyle::OverstrikeBlock) ||
+ FlagSet(caret.style, CaretStyle::Curses);
}
-bool ViewStyle::IsCaretVisible() const noexcept {
- return caret.width > 0 && caret.style != CaretStyle::Invisible;
+bool ViewStyle::IsCaretVisible(bool isMainSelection) const noexcept {
+ return caret.width > 0 &&
+ ((caret.style & CaretStyle::InsMask) != CaretStyle::Invisible ||
+ (FlagSet(caret.style, CaretStyle::Curses) && !isMainSelection)); // only draw additional selections in curses mode
}
bool ViewStyle::DrawCaretInsideSelection(bool inOverstrike, bool imeCaretBlockOverride) const noexcept {
if (FlagSet(caret.style, CaretStyle::BlockAfter))
return false;
return ((caret.style & CaretStyle::InsMask) == CaretStyle::Block) ||
(inOverstrike && FlagSet(caret.style, CaretStyle::OverstrikeBlock)) ||
- imeCaretBlockOverride;
+ imeCaretBlockOverride ||
+ FlagSet(caret.style, CaretStyle::Curses);
}
-ViewStyle::CaretShape ViewStyle::CaretShapeForMode(bool inOverstrike) const noexcept {
+ViewStyle::CaretShape ViewStyle::CaretShapeForMode(bool inOverstrike, bool isMainSelection) const noexcept {
if (inOverstrike) {
return (FlagSet(caret.style, CaretStyle::OverstrikeBlock)) ? CaretShape::block : CaretShape::bar;
}
+ if (FlagSet(caret.style, CaretStyle::Curses) && !isMainSelection) {
+ return CaretShape::block;
+ }
+
const CaretStyle caretStyle = caret.style & CaretStyle::InsMask;
return (caretStyle <= CaretStyle::Block) ? static_cast<CaretShape>(caretStyle) : CaretShape::line;
}
Modified: scintilla/src/ViewStyle.h
38 lines changed, 19 insertions(+), 19 deletions(-)
===================================================================
@@ -47,40 +47,40 @@ inline std::optional<ColourRGBA> OptionalColour(Scintilla::uptr_t wParam, Scinti
struct SelectionAppearance {
// Whether to draw on base layer or over text
- Scintilla::Layer layer;
+ Scintilla::Layer layer = Layer::Base;
// Draw selection past line end characters up to right border
- bool eolFilled;
+ bool eolFilled = false;
};
struct CaretLineAppearance {
// Whether to draw on base layer or over text
- Scintilla::Layer layer;
+ Scintilla::Layer layer = Layer::Base;
// Also show when non-focused
- bool alwaysShow;
+ bool alwaysShow = false;
// highlight sub line instead of whole line
- bool subLine;
+ bool subLine = false;
// Non-0: draw a rectangle around line instead of filling line. Value is pixel width of frame
- int frame;
+ int frame = 0;
};
struct CaretAppearance {
// Line, block, over-strike bar ...
- Scintilla::CaretStyle style;
+ Scintilla::CaretStyle style = CaretStyle::Line;
// Width in pixels
- int width;
+ int width = 1;
};
struct WrapAppearance {
// No wrapping, word, character, whitespace appearance
- Scintilla::Wrap state;
+ Scintilla::Wrap state = Wrap::None;
// Show indication of wrap at line end, line start, or in margin
- Scintilla::WrapVisualFlag visualFlags;
+ Scintilla::WrapVisualFlag visualFlags = WrapVisualFlag::None;
// Show indication near margin or near text
- Scintilla::WrapVisualLocation visualFlagsLocation;
+ Scintilla::WrapVisualLocation visualFlagsLocation = WrapVisualLocation::Default;
// How much indentation to show wrapping
- int visualStartIndent;
- // WrapIndentMode::Fixed, _SAME, _INDENT, _DEEPINDENT
- Scintilla::WrapIndentMode indentMode;
+ int visualStartIndent = 0;
+ // WrapIndentMode::Fixed, Same, Indent, DeepIndent
+ Scintilla::WrapIndentMode indentMode = WrapIndentMode::Fixed;
};
struct EdgeProperties {
@@ -137,10 +137,10 @@ class ViewStyle {
/// Margins are ordered: Line Numbers, Selection Margin, Spacing Margin
int leftMarginWidth; ///< Spacing margin on left of text
int rightMarginWidth; ///< Spacing margin on right of text
- int maskInLine; ///< Mask for markers to be put into text because there is nowhere for them to go in margin
- int maskDrawInText; ///< Mask for markers that always draw in text
+ int maskInLine = 0; ///< Mask for markers to be put into text because there is nowhere for them to go in margin
+ int maskDrawInText = 0; ///< Mask for markers that always draw in text
std::vector<MarginStyle> ms;
- int fixedColumnWidth; ///< Total width of margins
+ int fixedColumnWidth = 0; ///< Total width of margins
bool marginInside; ///< true: margin included in text view, false: separate views
int textStart; ///< Starting x position of text within the view
int zoomLevel;
@@ -235,9 +235,9 @@ class ViewStyle {
enum class CaretShape { invisible, line, block, bar };
bool IsBlockCaretStyle() const noexcept;
- bool IsCaretVisible() const noexcept;
+ bool IsCaretVisible(bool isMainSelection) const noexcept;
bool DrawCaretInsideSelection(bool inOverstrike, bool imeCaretBlockOverride) const noexcept;
- CaretShape CaretShapeForMode(bool inOverstrike) const noexcept;
+ CaretShape CaretShapeForMode(bool inOverstrike, bool isMainSelection) const noexcept;
private:
void AllocStyles(size_t sizeNew);
Modified: scintilla/src/XPM.cxx
29 lines changed, 10 insertions(+), 19 deletions(-)
===================================================================
@@ -7,6 +7,7 @@
#include <cstdlib>
#include <cstring>
+#include <climits>
#include <stdexcept>
#include <string_view>
@@ -92,17 +93,14 @@ XPM::XPM(const char *const *linesForm) {
Init(linesForm);
}
-XPM::~XPM() {
-}
-
void XPM::Init(const char *textForm) {
// Test done is two parts to avoid possibility of overstepping the memory
// if memcmp implemented strangely. Must be 4 bytes at least at destination.
if ((0 == memcmp(textForm, "/* X", 4)) && (0 == memcmp(textForm, "/* XPM */", 9))) {
// Build the lines form out of the text form
std::vector<const char *> linesForm = LinesFormFromTextForm(textForm);
if (!linesForm.empty()) {
- Init(&linesForm[0]);
+ Init(linesForm.data());
}
} else {
// It is really in line form
@@ -146,7 +144,7 @@ void XPM::Init(const char *const *linesForm) {
colourCodeTable[static_cast<unsigned char>(code)] = colour;
}
- for (int y=0; y<height; y++) {
+ for (ptrdiff_t y=0; y<height; y++) {
const char *lform = linesForm[y+nColours+1];
const size_t len = MeasureLength(lform);
for (size_t x = 0; x<len; x++)
@@ -241,19 +239,16 @@ RGBAImage::RGBAImage(const XPM &xpm) {
}
}
-RGBAImage::~RGBAImage() {
-}
-
int RGBAImage::CountBytes() const noexcept {
return width * height * 4;
}
const unsigned char *RGBAImage::Pixels() const noexcept {
- return &pixelBytes[0];
+ return pixelBytes.data();
}
void RGBAImage::SetPixel(int x, int y, ColourRGBA colour) noexcept {
- unsigned char *pixel = &pixelBytes[0] + (y * width + x) * 4;
+ unsigned char *pixel = pixelBytes.data() + (y * width + x) * 4;
// RGBA
pixel[0] = colour.GetRed();
pixel[1] = colour.GetGreen();
@@ -267,9 +262,9 @@ void RGBAImage::BGRAFromRGBA(unsigned char *pixelsBGRA, const unsigned char *pix
for (size_t i = 0; i < count; i++) {
const unsigned char alpha = pixelsRGBA[3];
// Input is RGBA, output is BGRA with premultiplied alpha
- pixelsBGRA[2] = pixelsRGBA[0] * alpha / 255;
- pixelsBGRA[1] = pixelsRGBA[1] * alpha / 255;
- pixelsBGRA[0] = pixelsRGBA[2] * alpha / 255;
+ pixelsBGRA[2] = pixelsRGBA[0] * alpha / UCHAR_MAX;
+ pixelsBGRA[1] = pixelsRGBA[1] * alpha / UCHAR_MAX;
+ pixelsBGRA[0] = pixelsRGBA[2] * alpha / UCHAR_MAX;
pixelsBGRA[3] = alpha;
pixelsRGBA += bytesPerPixel;
pixelsBGRA += bytesPerPixel;
@@ -279,10 +274,6 @@ void RGBAImage::BGRAFromRGBA(unsigned char *pixelsBGRA, const unsigned char *pix
RGBAImageSet::RGBAImageSet() : height(-1), width(-1) {
}
-RGBAImageSet::~RGBAImageSet() {
- Clear();
-}
-
/// Remove all images.
void RGBAImageSet::Clear() noexcept {
images.clear();
@@ -307,7 +298,7 @@ RGBAImage *RGBAImageSet::Get(int ident) {
}
/// Give the largest height of the set.
-int RGBAImageSet::GetHeight() const {
+int RGBAImageSet::GetHeight() const noexcept {
if (height < 0) {
for (const std::pair<const int, std::unique_ptr<RGBAImage>> &image : images) {
if (height < image.second->GetHeight()) {
@@ -319,7 +310,7 @@ int RGBAImageSet::GetHeight() const {
}
/// Give the largest width of the set.
-int RGBAImageSet::GetWidth() const {
+int RGBAImageSet::GetWidth() const noexcept {
if (width < 0) {
for (const std::pair<const int, std::unique_ptr<RGBAImage>> &image : images) {
if (width < image.second->GetWidth()) {
Modified: scintilla/src/XPM.h
20 lines changed, 2 insertions(+), 18 deletions(-)
===================================================================
@@ -25,11 +25,6 @@ class XPM {
public:
explicit XPM(const char *textForm);
explicit XPM(const char *const *linesForm);
- XPM(const XPM &) = default;
- XPM(XPM &&) noexcept = default;
- XPM &operator=(const XPM &) = default;
- XPM &operator=(XPM &&) noexcept = default;
- ~XPM();
void Init(const char *textForm);
void Init(const char *const *linesForm);
/// Decompose image into runs and use FillRectangle for each run
@@ -53,11 +48,6 @@ class RGBAImage {
static constexpr size_t bytesPerPixel = 4;
RGBAImage(int width_, int height_, float scale_, const unsigned char *pixels_);
explicit RGBAImage(const XPM &xpm);
- RGBAImage(const RGBAImage &) = default;
- RGBAImage(RGBAImage &&) noexcept = default;
- RGBAImage &operator=(const RGBAImage &) = default;
- RGBAImage &operator=(RGBAImage &&) noexcept = default;
- virtual ~RGBAImage();
int GetHeight() const noexcept { return height; }
int GetWidth() const noexcept { return width; }
float GetScale() const noexcept { return scale; }
@@ -79,22 +69,16 @@ class RGBAImageSet {
mutable int width; ///< Memorize largest width of the set.
public:
RGBAImageSet();
- // Deleted so RGBAImageSet objects can not be copied.
- RGBAImageSet(const RGBAImageSet &) = delete;
- RGBAImageSet(RGBAImageSet &&) = delete;
- RGBAImageSet &operator=(const RGBAImageSet &) = delete;
- RGBAImageSet &operator=(RGBAImageSet &&) = delete;
- ~RGBAImageSet();
/// Remove all images.
void Clear() noexcept;
/// Add an image.
void AddImage(int ident, std::unique_ptr<RGBAImage> image);
/// Get image by id.
RGBAImage *Get(int ident);
/// Give the largest height of the set.
- int GetHeight() const;
+ int GetHeight() const noexcept;
/// Give the largest width of the set.
- int GetWidth() const;
+ int GetWidth() const noexcept;
};
}
Modified: scintilla/version.txt
2 lines changed, 1 insertions(+), 1 deletions(-)
===================================================================
@@ -1 +1 @@
-513
+514
--------------
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