Update to scintilla 5.5.7 & Lexilla 5.4.5

Release 5.5.7 (https://www.scintilla.org/scintilla557.zip)

Released 8 June 2025

1. Add SCI_SCROLLVERTICAL method to restore view position and maintain it while performing line wrapping.
2. Add SC_UNDO_SELECTION_HISTORY_SCROLL flag to SCI_SETUNDOSELECTIONHISTORY which controls whether undo and redo restore vertical scroll position.
3. Tweak SC_MARK_BAR to be slightly wider by using next higher whole pixel instead of next lower for margin width / 3.
4. Scale images in autocompletion lists with SCI_AUTOCSETIMAGESCALE to match high DPI screens. Initially only on GTK and Qt.
5. Fix wrapping bug for UTF-8 where \r\n could wrap between the characters. Notepad++ Pull Request #16373.
6. Fix crash during painting when scroll bars changed. Bug #2481.
7. On GTK, reset vertical scroll bar synchronously in SCI_SETDOCPOINTER to fix bug where scroll position not restored in non-wrap mode. Bug #2416.
8. On GTK, fix IME problem when tentative composition interfered with delete surrounding. Feature #1476.
9. On GTK, update IME cursor position inside retrieve surrounding to better position candidate window. Feature #1488.

Release 5.4.5 (https://www.scintilla.org/lexilla545.zip)

Released 8 June 2025

1. Dart: Add error state SCE_DART_STRINGEOL for unterminated string. Pull request #315.
2. Makefile: Add a keyword list to makefile lexer to highlight GNU Make directives like 'ifdef' and 'vpath' as SCE_MAKE_PREPROCESSOR since these are similar to NMAKE directives like '!IFDEF'.
3. Nix: Add error state SCE_NIX_STRINGEOL for unterminated string. Pull request #315.
4. TOML: Add error state SCE_TOML_STRINGEOL for unterminated string. Pull request #315.
5. Zig: Add error state SCE_ZIG_STRINGEOL for unterminated string. Pull request #315.

Close #16649
This commit is contained in:
Christian Grasser 2025-06-09 11:37:58 +02:00 committed by Don Ho
parent 5b26ef1ca8
commit e85c354135
117 changed files with 1348 additions and 876 deletions

View File

@ -27,12 +27,12 @@ directory conventionally called "lexilla".
To use GCC, run lexilla/src/makefile:
make
To use Clang, run lexilla/test/makefile:
To use Clang, run lexilla/src/makefile:
make CLANG=1
On macOS, CLANG is set automatically so this can just be
make
To use MSVC, run lexilla/test/lexilla.mak:
To use MSVC, run lexilla/src/lexilla.mak:
nmake -f lexilla.mak
To build a debugging version of the library, add DEBUG=1 to the command:

View File

@ -171,7 +171,6 @@ constParameterPointer:lexilla/lexers/LexTCMD.cxx
invalidscanf:lexilla/lexers/LexTCMD.cxx
constParameterReference:lexilla/lexers/LexTeX.cxx
variableScope:lexilla/lexers/LexTeX.cxx
constVariableReference:lexilla/lexers/LexTroff.cxx
knownConditionTrueFalse:lexilla/lexers/LexVB.cxx
constParameterReference:lexilla/lexers/LexVerilog.cxx
variableScope:lexilla/lexers/LexVerilog.cxx

View File

@ -9,7 +9,7 @@
<meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
<meta name="Description"
content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
<meta name="Date.Modified" content="20250402" />
<meta name="Date.Modified" content="20250608" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
.logo {
@ -62,8 +62,8 @@
<font color="#FFCC99" size="4"> A library of language lexers for use with Scintilla</font>
</td>
<td width="40%" align="right">
<font color="#FFCC99" size="3">Release version 5.4.4<br />
Site last modified April 2 2025</font>
<font color="#FFCC99" size="3">Release version 5.4.5<br />
Site last modified June 8 2025</font>
</td>
<td width="20%">
&nbsp;
@ -78,11 +78,11 @@
</tr>
</table>
<ul id="versionlist">
<li>Version 5.4.4 fixes a problem when building for ARM654 on Windows.</li>
<li>Version 5.4.5 improves Dart, Makefile, Nix, TOML, and Zig.</li>
<li>Version 5.4.4 fixes a problem when building for ARM64 on Windows.</li>
<li>Version 5.4.3 improves C++, Modula 3, Pascal, Python, and Ruby.</li>
<li>Version 5.4.2 adds Nix lexer. Improves JavaScript, PHP, Rust, TOML, and Zig.</li>
<li>Version 5.4.1 adds Dart, troff, and Zig lexers. Improves C++, F#, HTML, and Smalltalk.</li>
<li>Version 5.4.0 adds a TOML lexer.</li>
</ul>
<ul id="menu">
<li id="remote1"><a href="https://www.scintilla.org/SciTEImage.html">Screenshot</a></li>

View File

@ -26,9 +26,9 @@
<table bgcolor="#CCCCCC" width="100%" cellspacing="0" cellpadding="8" border="0">
<tr>
<td>
<font size="4"> <a href="https://www.scintilla.org/lexilla544.zip">
<font size="4"> <a href="https://www.scintilla.org/lexilla545.zip">
Windows</a>&nbsp;&nbsp;
<a href="https://www.scintilla.org/lexilla544.tgz">
<a href="https://www.scintilla.org/lexilla545.tgz">
GTK/Linux</a>&nbsp;&nbsp;
</font>
</td>
@ -42,7 +42,7 @@
containing very few restrictions.
</p>
<h3>
Release 5.4.4
Release 5.4.5
</h3>
<h4>
Source Code
@ -50,8 +50,8 @@
The source code package contains all of the source code for Lexilla but no binary
executable code and is available in
<ul>
<li><a href="https://www.scintilla.org/lexilla544.zip">zip format</a> (1.4M) commonly used on Windows</li>
<li><a href="https://www.scintilla.org/lexilla544.tgz">tgz format</a> (1.0M) commonly used on Linux and compatible operating systems</li>
<li><a href="https://www.scintilla.org/lexilla545.zip">zip format</a> (1.4M) commonly used on Windows</li>
<li><a href="https://www.scintilla.org/lexilla545.tgz">tgz format</a> (1.0M) commonly used on Linux and compatible operating systems</li>
</ul>
Instructions for building on both Windows and Linux are included in the readme file.
<h4>

View File

@ -594,6 +594,34 @@
</tr>
</table>
<h2 id="Releases">Releases</h2>
<h3>
<a href="https://www.scintilla.org/lexilla545.zip">Release 5.4.5</a>
</h3>
<ul>
<li>
Released 8 June 2025.
</li>
<li>
Dart: Add error state SCE_DART_STRINGEOL for unterminated string.
<a href="https://github.com/ScintillaOrg/lexilla/pull/315">Pull request #315</a>.
</li>
<li>
Makefile: Add a keyword list to makefile lexer to highlight GNU Make directives like 'ifdef' and 'vpath' as
SCE_MAKE_PREPROCESSOR since these are similar to NMAKE directives like '!IFDEF'.
</li>
<li>
Nix: Add error state SCE_NIX_STRINGEOL for unterminated string.
<a href="https://github.com/ScintillaOrg/lexilla/pull/315">Pull request #315</a>.
</li>
<li>
TOML: Add error state SCE_TOML_STRINGEOL for unterminated string.
<a href="https://github.com/ScintillaOrg/lexilla/pull/315">Pull request #315</a>.
</li>
<li>
Zig: Add error state SCE_ZIG_STRINGEOL for unterminated string.
<a href="https://github.com/ScintillaOrg/lexilla/pull/315">Pull request #315</a>.
</li>
</ul>
<h3>
<a href="https://www.scintilla.org/lexilla544.zip">Release 5.4.4</a>
</h3>

View File

@ -2349,6 +2349,7 @@ val SCE_TOML_TRIPLE_STRING_SQ=11
val SCE_TOML_TRIPLE_STRING_DQ=12
val SCE_TOML_ESCAPECHAR=13
val SCE_TOML_DATETIME=14
val SCE_TOML_STRINGEOL=15
# Lexical states for SCLEX_TROFF
lex troff=SCLEX_TROFF SCE_TROFF_
val SCE_TROFF_DEFAULT=0
@ -2408,6 +2409,7 @@ val SCE_DART_KW_PRIMARY=23
val SCE_DART_KW_SECONDARY=24
val SCE_DART_KW_TERTIARY=25
val SCE_DART_KW_TYPE=26
val SCE_DART_STRINGEOL=27
# Lexical states for SCLEX_ZIG
lex Zig=SCLEX_ZIG SCE_ZIG_
val SCE_ZIG_DEFAULT=0
@ -2428,6 +2430,7 @@ val SCE_ZIG_KW_SECONDARY=14
val SCE_ZIG_KW_TERTIARY=15
val SCE_ZIG_KW_TYPE=16
val SCE_ZIG_IDENTIFIER_STRING=17
val SCE_ZIG_STRINGEOL=18
# Lexical states for SCLEX_NIX
lex Nix=SCLEX_NIX SCE_NIX_
val SCE_NIX_DEFAULT=0
@ -2446,3 +2449,4 @@ val SCE_NIX_KEYWORD1=12
val SCE_NIX_KEYWORD2=13
val SCE_NIX_KEYWORD3=14
val SCE_NIX_KEYWORD4=15
val SCE_NIX_STRINGEOL=16

View File

@ -2098,6 +2098,7 @@
#define SCE_TOML_TRIPLE_STRING_DQ 12
#define SCE_TOML_ESCAPECHAR 13
#define SCE_TOML_DATETIME 14
#define SCE_TOML_STRINGEOL 15
#define SCE_TROFF_DEFAULT 0
#define SCE_TROFF_REQUEST 1
#define SCE_TROFF_COMMAND 2
@ -2153,6 +2154,7 @@
#define SCE_DART_KW_SECONDARY 24
#define SCE_DART_KW_TERTIARY 25
#define SCE_DART_KW_TYPE 26
#define SCE_DART_STRINGEOL 27
#define SCE_ZIG_DEFAULT 0
#define SCE_ZIG_COMMENTLINE 1
#define SCE_ZIG_COMMENTLINEDOC 2
@ -2171,6 +2173,7 @@
#define SCE_ZIG_KW_TERTIARY 15
#define SCE_ZIG_KW_TYPE 16
#define SCE_ZIG_IDENTIFIER_STRING 17
#define SCE_ZIG_STRINGEOL 18
#define SCE_NIX_DEFAULT 0
#define SCE_NIX_COMMENTLINE 1
#define SCE_NIX_COMMENTBLOCK 2
@ -2187,6 +2190,7 @@
#define SCE_NIX_KEYWORD2 13
#define SCE_NIX_KEYWORD3 14
#define SCE_NIX_KEYWORD4 15
#define SCE_NIX_STRINGEOL 16
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */

View File

@ -12,7 +12,6 @@
#include <cstdlib>
#include <cassert>
#include <cstring>
#include <cctype>
#include <cstdio>
#include <cstdarg>
@ -40,26 +39,19 @@ using namespace Lexilla;
namespace {
bool IsAWordChar(const int ch) noexcept {
return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
ch == '_' || ch == '?');
return IsAlphaNumeric(ch) || ch == '.' || ch == '_' || ch == '?';
}
bool IsAWordStart(const int ch) noexcept {
return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' ||
ch == '%' || ch == '@' || ch == '$' || ch == '?');
return IsAlphaNumeric(ch) || ch == '_' || ch == '.' ||
ch == '%' || ch == '@' || ch == '$' || ch == '?';
}
bool IsAsmOperator(const int ch) noexcept {
if ((ch < 0x80) && (isalnum(ch)))
if (IsAlphaNumeric(ch))
return false;
// '.' left out as it is used to make up numbers
if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
ch == '(' || ch == ')' || ch == '=' || ch == '^' ||
ch == '[' || ch == ']' || ch == '<' || ch == '&' ||
ch == '>' || ch == ',' || ch == '|' || ch == '~' ||
ch == '%' || ch == ':')
return true;
return false;
return AnyOf(ch, '*', '/', '-', '+', '(', ')', '=', '^', '[', ']', '<', '&', '>', ',', '|', '~', '%', ':');
}
constexpr bool IsStreamCommentStyle(int style) noexcept {
@ -71,26 +63,17 @@ constexpr bool IsStreamCommentStyle(int style) noexcept {
// Options used for LexerAsm
struct OptionsAsm {
std::string delimiter;
bool fold;
bool foldSyntaxBased;
bool foldCommentMultiline;
bool foldCommentExplicit;
bool fold = false;
bool foldSyntaxBased = true;
bool foldCommentMultiline = false;
bool foldCommentExplicit = false;
std::string foldExplicitStart;
std::string foldExplicitEnd;
bool foldExplicitAnywhere;
bool foldCompact;
bool foldExplicitAnywhere = false;
bool foldCompact = true;
std::string commentChar;
OptionsAsm() {
delimiter = "";
fold = false;
foldSyntaxBased = true;
foldCommentMultiline = false;
foldCommentExplicit = false;
foldExplicitStart = "";
foldExplicitEnd = "";
foldExplicitAnywhere = false;
foldCompact = true;
commentChar = "";
[[nodiscard]] char Delimiter() const noexcept {
return delimiter.empty() ? '~' : delimiter[0];
}
};
@ -153,12 +136,11 @@ class LexerAsm : public DefaultLexer {
WordList directives4foldend;
OptionsAsm options;
OptionSetAsm osAsm;
int commentChar;
char commentChar;
public:
LexerAsm(const char *languageName_, int language_, int commentChar_) : DefaultLexer(languageName_, language_) {
commentChar = commentChar_;
}
virtual ~LexerAsm() {
LexerAsm(const char *languageName_, int language_, char commentChar_) :
DefaultLexer(languageName_, language_),
commentChar(commentChar_) {
}
void SCI_METHOD Release() override {
delete this;
@ -166,27 +148,27 @@ public:
int SCI_METHOD Version() const override {
return lvRelease5;
}
const char * SCI_METHOD PropertyNames() override {
const char *SCI_METHOD PropertyNames() override {
return osAsm.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) override {
return osAsm.PropertyType(name);
}
const char * SCI_METHOD DescribeProperty(const char *name) override {
const char *SCI_METHOD DescribeProperty(const char *name) override {
return osAsm.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char * SCI_METHOD PropertyGet(const char *key) override {
const char *SCI_METHOD PropertyGet(const char *key) override {
return osAsm.PropertyGet(key);
}
const char * SCI_METHOD DescribeWordListSets() override {
const char *SCI_METHOD DescribeWordListSets() override {
return osAsm.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
void SCI_METHOD Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
void * SCI_METHOD PrivateCall(int, void *) override {
void *SCI_METHOD PrivateCall(int, void *) override {
return nullptr;
}
@ -233,6 +215,8 @@ Sci_Position SCI_METHOD LexerAsm::WordListSet(int n, const char *wl) {
case 7:
wordListN = &directives4foldend;
break;
default:
break;
}
Sci_Position firstModification = -1;
if (wordListN) {
@ -255,8 +239,7 @@ void SCI_METHOD LexerAsm::Lex(Sci_PositionU startPos, Sci_Position length, int i
StyleContext sc(startPos, length, initStyle, styler);
for (; sc.More(); sc.Forward())
{
for (; sc.More(); sc.Forward()) {
if (sc.atLineStart) {
switch (sc.state) {
@ -285,16 +268,21 @@ void SCI_METHOD LexerAsm::Lex(Sci_PositionU startPos, Sci_Position length, int i
}
// Determine if the current state should terminate.
if (sc.state == SCE_ASM_OPERATOR) {
switch (sc.state) {
case SCE_ASM_OPERATOR:
if (!IsAsmOperator(sc.ch)) {
sc.SetState(SCE_ASM_DEFAULT);
sc.SetState(SCE_ASM_DEFAULT);
}
} else if (sc.state == SCE_ASM_NUMBER) {
break;
case SCE_ASM_NUMBER:
if (!IsAWordChar(sc.ch)) {
sc.SetState(SCE_ASM_DEFAULT);
}
} else if (sc.state == SCE_ASM_IDENTIFIER) {
if (!IsAWordChar(sc.ch) ) {
break;
case SCE_ASM_IDENTIFIER:
if (!IsAWordChar(sc.ch)) {
char s[100];
sc.GetCurrentLowered(s, sizeof(s));
bool IsDirective = false;
@ -315,24 +303,26 @@ void SCI_METHOD LexerAsm::Lex(Sci_PositionU startPos, Sci_Position length, int i
}
sc.SetState(SCE_ASM_DEFAULT);
if (IsDirective && !strcmp(s, "comment")) {
const char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0];
while (IsASpaceOrTab(sc.ch) && !sc.atLineEnd) {
sc.ForwardSetState(SCE_ASM_DEFAULT);
}
if (sc.ch == delimiter) {
if (sc.ch == options.Delimiter()) {
sc.SetState(SCE_ASM_COMMENTDIRECTIVE);
}
}
}
} else if (sc.state == SCE_ASM_COMMENTDIRECTIVE) {
const char delimiter = options.delimiter.empty() ? '~' : options.delimiter.c_str()[0];
if (sc.ch == delimiter) {
break;
case SCE_ASM_COMMENTDIRECTIVE:
if (sc.ch == options.Delimiter()) {
while (!sc.MatchLineEnd()) {
sc.Forward();
}
sc.SetState(SCE_ASM_DEFAULT);
}
} else if (sc.state == SCE_ASM_STRING) {
break;
case SCE_ASM_STRING:
if (sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
sc.Forward();
@ -343,7 +333,9 @@ void SCI_METHOD LexerAsm::Lex(Sci_PositionU startPos, Sci_Position length, int i
sc.ChangeState(SCE_ASM_STRINGEOL);
sc.ForwardSetState(SCE_ASM_DEFAULT);
}
} else if (sc.state == SCE_ASM_CHARACTER) {
break;
case SCE_ASM_CHARACTER:
if (sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
sc.Forward();
@ -354,13 +346,17 @@ void SCI_METHOD LexerAsm::Lex(Sci_PositionU startPos, Sci_Position length, int i
sc.ChangeState(SCE_ASM_STRINGEOL);
sc.ForwardSetState(SCE_ASM_DEFAULT);
}
break;
default:
break;
}
// Determine if a new state should be entered.
if (sc.state == SCE_ASM_DEFAULT) {
if (sc.ch == commentCharacter) {
sc.SetState(SCE_ASM_COMMENT);
} else if (IsASCII(sc.ch) && (isdigit(sc.ch) || (sc.ch == '.' && IsASCII(sc.chNext) && isdigit(sc.chNext)))) {
} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
sc.SetState(SCE_ASM_NUMBER);
} else if (IsAWordStart(sc.ch)) {
sc.SetState(SCE_ASM_IDENTIFIER);
@ -381,32 +377,32 @@ void SCI_METHOD LexerAsm::Lex(Sci_PositionU startPos, Sci_Position length, int i
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "else".
void SCI_METHOD LexerAsm::Fold(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
void SCI_METHOD LexerAsm::Fold(Sci_PositionU startPos_, Sci_Position length, int initStyle, IDocument *pAccess) {
if (!options.fold)
return;
LexAccessor styler(pAccess);
const Sci_PositionU endPos = startPos + length;
const Sci_Position startPos = static_cast<Sci_Position>(startPos_);
const Sci_Position endPos = startPos + length;
int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos);
int levelCurrent = SC_FOLDLEVELBASE;
if (lineCurrent > 0)
levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
levelCurrent = FoldLevelStart(styler.LevelAt(lineCurrent-1));
int levelNext = levelCurrent;
char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos);
int styleNext = styler.StyleIndexAt(startPos);
int style = initStyle;
char word[100]{};
int wordlen = 0;
std::string word;
const bool userDefinedFoldMarkers = !options.foldExplicitStart.empty() && !options.foldExplicitEnd.empty();
for (Sci_PositionU i = startPos; i < endPos; i++) {
for (Sci_Position i = startPos; i < endPos; i++) {
const char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
const int stylePrev = style;
style = styleNext;
styleNext = styler.StyleAt(i + 1);
styleNext = styler.StyleIndexAt(i + 1);
const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (options.foldCommentMultiline && IsStreamCommentStyle(style)) {
if (!IsStreamCommentStyle(stylePrev)) {
@ -419,10 +415,10 @@ void SCI_METHOD LexerAsm::Fold(Sci_PositionU startPos, Sci_Position length, int
if (options.foldCommentExplicit && ((style == SCE_ASM_COMMENT) || options.foldExplicitAnywhere)) {
if (userDefinedFoldMarkers) {
if (styler.Match(i, options.foldExplicitStart.c_str())) {
levelNext++;
levelNext++;
} else if (styler.Match(i, options.foldExplicitEnd.c_str())) {
levelNext--;
}
levelNext--;
}
} else {
if (ch == ';') {
if (chNext == '{') {
@ -431,41 +427,30 @@ void SCI_METHOD LexerAsm::Fold(Sci_PositionU startPos, Sci_Position length, int
levelNext--;
}
}
}
}
if (options.foldSyntaxBased && (style == SCE_ASM_DIRECTIVE)) {
word[wordlen++] = MakeLowerCase(ch);
if (wordlen == 100) { // prevent overflow
word[0] = '\0';
wordlen = 1;
}
}
if (options.foldSyntaxBased && (style == SCE_ASM_DIRECTIVE)) {
word.push_back(MakeLowerCase(ch));
if (styleNext != SCE_ASM_DIRECTIVE) { // reading directive ready
word[wordlen] = '\0';
wordlen = 0;
if (directives4foldstart.InList(word)) {
levelNext++;
} else if (directives4foldend.InList(word)){
} else if (directives4foldend.InList(word)) {
levelNext--;
}
word.clear();
}
}
if (!IsASpace(ch))
visibleChars++;
if (atEOL || (i == endPos-1)) {
const int levelUse = levelCurrent;
int lev = levelUse | levelNext << 16;
if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
const int lev = FoldLevelForCurrentNext(levelCurrent, levelNext) |
FoldLevelFlags(levelCurrent, levelNext, visibleChars == 0 && options.foldCompact);
styler.SetLevelIfDifferent(lineCurrent, lev);
lineCurrent++;
levelCurrent = levelNext;
if (atEOL && (i == static_cast<Sci_PositionU>(styler.Length() - 1))) {
if (atEOL && (i == (styler.Length() - 1))) {
// There is an empty line at end of file so give it same level and empty
styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG);
styler.SetLevel(lineCurrent, FoldLevelForCurrent(levelCurrent) | SC_FOLDLEVELWHITEFLAG);
}
visibleChars = 0;
}

View File

@ -1268,14 +1268,9 @@ void SCI_METHOD LexerBash::Fold(Sci_PositionU startPos_, Sci_Position length, in
}
if (atEOL) {
int lev = levelPrev;
if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if ((levelCurrent > levelPrev) && (visibleChars > 0))
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
const int lev = levelPrev |
FoldLevelFlags(levelPrev, levelCurrent, visibleChars == 0 && options.foldCompact, visibleChars > 0);
styler.SetLevelIfDifferent(lineCurrent, lev);
lineCurrent++;
levelPrev = levelCurrent;
visibleChars = 0;

View File

@ -121,7 +121,7 @@ struct BracketPair {
BracketPair FindBracketPair(Tokens &tokens) {
const Tokens::iterator itBracket = std::find(tokens.begin(), tokens.end(), "(");
if (itBracket != tokens.end()) {
size_t nest = 0;
ptrdiff_t nest = 0;
for (Tokens::iterator itTok = itBracket; itTok != tokens.end(); ++itTok) {
if (*itTok == "(") {
nest++;
@ -1502,7 +1502,7 @@ void SCI_METHOD LexerCPP::Fold(Sci_PositionU startPos, Sci_Position length, int
Sci_Position lineCurrent = styler.GetLine(startPos);
int levelCurrent = SC_FOLDLEVELBASE;
if (lineCurrent > 0)
levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
levelCurrent = FoldLevelStart(styler.LevelAt(lineCurrent-1));
Sci_PositionU lineStartNext = styler.LineStart(lineCurrent+1);
int levelMinCurrent = levelCurrent;
int levelNext = levelCurrent;
@ -1583,21 +1583,16 @@ void SCI_METHOD LexerCPP::Fold(Sci_PositionU startPos, Sci_Position length, int
) {
levelUse = levelMinCurrent;
}
int lev = levelUse | levelNext << 16;
if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
const int lev = FoldLevelForCurrentNext(levelUse, levelNext) |
FoldLevelFlags(levelUse, levelNext, visibleChars == 0 && options.foldCompact);
styler.SetLevelIfDifferent(lineCurrent, lev);
lineCurrent++;
lineStartNext = styler.LineStart(lineCurrent+1);
levelCurrent = levelNext;
levelMinCurrent = levelCurrent;
if (atEOL && (i == static_cast<Sci_PositionU>(styler.Length()-1))) {
// There is an empty line at end of file so give it same level and empty
styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG);
styler.SetLevel(lineCurrent, FoldLevelForCurrent(levelCurrent) | SC_FOLDLEVELWHITEFLAG);
}
visibleChars = 0;
inLineComment = false;
@ -1825,7 +1820,7 @@ Tokens LexerCPP::Tokenize(const std::string &expr) const {
word += *cp;
cp++;
}
tokens.push_back(word);
tokens.push_back(std::move(word));
}
return tokens;
}

View File

@ -204,6 +204,7 @@ LexicalClass lexicalClasses[] = {
24, "SCE_DART_KW_SECONDARY", "identifier", "Secondary keywords",
25, "SCE_DART_KW_TERTIARY", "identifier", "Tertiary keywords",
26, "SCE_DART_KW_TYPE", "identifier", "Global types",
27, "SCE_DART_STRINGEOL", "error literal string", "End of line where string is not closed",
};
class LexerDart : public DefaultLexer {
@ -342,6 +343,10 @@ void LexerDart::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
int chPrevNonWhite = 0;
EscapeSequence escSeq;
if (initStyle == SCE_DART_STRINGEOL) {
initStyle = SCE_DART_DEFAULT;
}
if (startPos != 0) {
// backtrack to the line where interpolation starts
BacktrackToStart(styler, DartLineStateMaskInterpolation, startPos, lengthDoc, initStyle);
@ -457,6 +462,8 @@ void LexerDart::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
case SCE_DART_TRIPLE_RAWSTRING_DQ:
if (sc.atLineStart && !IsTripleString(sc.state)) {
sc.SetState(SCE_DART_DEFAULT);
} else if (sc.atLineEnd && !IsTripleString(sc.state)) {
sc.ChangeState(SCE_DART_STRINGEOL);
} else if (sc.ch == '\\' && !IsRaw(sc.state)) {
if (escSeq.resetEscapeState(sc.state, sc.chNext)) {
sc.SetState(SCE_DART_ESCAPECHAR);
@ -489,6 +496,12 @@ void LexerDart::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyl
}
break;
case SCE_DART_STRINGEOL:
if (sc.atLineStart) {
sc.SetState(SCE_DART_DEFAULT);
}
break;
case SCE_DART_ESCAPECHAR:
if (escSeq.atEscapeEnd(sc.ch)) {
if (escSeq.brace && sc.ch == '}') {

View File

@ -168,7 +168,8 @@ void LexerEDIFACT::Lex(Sci_PositionU startPos, Sci_Position length, int, IDocume
{
posCurrent = ForwardPastWhitespace(pAccess, posCurrent, posFinish);
// Mark whitespace as default
styler.ColourTo(posCurrent - 1, SCE_EDI_DEFAULT);
if (posCurrent > 0)
styler.ColourTo(posCurrent - 1, SCE_EDI_DEFAULT);
if (posCurrent >= posFinish)
break;

View File

@ -617,16 +617,9 @@ void LexerLua::Fold(Sci_PositionU startPos_, Sci_Position length, int initStyle,
}
if (atEOL) {
int lev = levelPrev;
if (visibleChars == 0 && foldCompact) {
lev |= SC_FOLDLEVELWHITEFLAG;
}
if ((levelCurrent > levelPrev) && (visibleChars > 0)) {
lev |= SC_FOLDLEVELHEADERFLAG;
}
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
const int lev = levelPrev |
FoldLevelFlags(levelPrev, levelCurrent, visibleChars == 0 && foldCompact, visibleChars > 0);
styler.SetLevelIfDifferent(lineCurrent, lev);
lineCurrent++;
levelPrev = levelCurrent;
visibleChars = 0;

View File

@ -14,6 +14,7 @@
#include <string>
#include <string_view>
#include <map>
#include "ILexer.h"
#include "Scintilla.h"
@ -25,19 +26,110 @@
#include "StyleContext.h"
#include "CharacterSet.h"
#include "LexerModule.h"
#include "OptionSet.h"
#include "DefaultLexer.h"
using namespace Scintilla;
using namespace Lexilla;
static inline bool AtEOL(Accessor &styler, Sci_PositionU i) {
namespace {
// Options used for LexerMakeFile
struct OptionsMake {
};
const char *const makeWordListDescription[] = {
"Directives",
nullptr
};
struct OptionSetMake : public OptionSet<OptionsMake> {
OptionSetMake() {
DefineWordListSets(makeWordListDescription);
}
};
const LexicalClass lexicalClasses[] = {
// Lexer makefile SCLEX_MAKEFILE SCE_MAKE_
0, "SCE_MAKE_DEFAULT", "default", "White space",
1, "SCE_MAKE_COMMENT", "comment", "Comment",
2, "SCE_MAKE_PREPROCESSOR", "preprocessor", "Preprocessor",
3, "SCE_MAKE_IDENTIFIER", "identifier", "Identifiers",
4, "SCE_MAKE_OPERATOR", "operator", "Operator",
5, "SCE_MAKE_TARGET", "identifier", "Identifiers",
9, "SCE_MAKE_IDEOL", "error identifier", "Incomplete identifier reference",
};
bool AtEOL(Accessor &styler, Sci_PositionU i) {
return (styler[i] == '\n') ||
((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
}
static void ColouriseMakeLine(
const std::string &lineBuffer,
Sci_PositionU startLine,
Sci_PositionU endPos,
Accessor &styler) {
class LexerMakeFile : public DefaultLexer {
WordList directives;
OptionsMake options;
OptionSetMake osMake;
public:
LexerMakeFile() :
DefaultLexer("makefile", SCLEX_MAKEFILE, lexicalClasses, std::size(lexicalClasses)) {
}
const char *SCI_METHOD PropertyNames() override {
return osMake.PropertyNames();
}
int SCI_METHOD PropertyType(const char *name) override {
return osMake.PropertyType(name);
}
const char *SCI_METHOD DescribeProperty(const char *name) override {
return osMake.DescribeProperty(name);
}
Sci_Position SCI_METHOD PropertySet(const char *key, const char *val) override;
const char *SCI_METHOD PropertyGet(const char *key) override {
return osMake.PropertyGet(key);
}
const char *SCI_METHOD DescribeWordListSets() override {
return osMake.DescribeWordListSets();
}
Sci_Position SCI_METHOD WordListSet(int n, const char *wl) override;
void ColouriseMakeLine(std::string_view lineBuffer,
Sci_PositionU startLine, Sci_PositionU endPos, Accessor &styler);
void SCI_METHOD Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) override;
static ILexer5 *LexerFactoryMakeFile() {
return new LexerMakeFile();
}
};
Sci_Position SCI_METHOD LexerMakeFile::PropertySet(const char *key, const char *val) {
if (osMake.PropertySet(&options, key, val)) {
return 0;
}
return -1;
}
Sci_Position SCI_METHOD LexerMakeFile::WordListSet(int n, const char *wl) {
WordList *wordListN = nullptr;
switch (n) {
case 0:
wordListN = &directives;
break;
default:
break;
}
Sci_Position firstModification = -1;
if (wordListN && wordListN->Set(wl)) {
firstModification = 0;
}
return firstModification;
}
void LexerMakeFile::ColouriseMakeLine(
const std::string_view lineBuffer,
Sci_PositionU startLine,
Sci_PositionU endPos,
Accessor &styler) {
const Sci_PositionU lengthLine = lineBuffer.length();
Sci_PositionU i = 0;
@ -46,9 +138,7 @@ static void ColouriseMakeLine(
bool bSpecial = false;
// check for a tab character in column 0 indicating a command
bool bCommand = false;
if ((lengthLine > 0) && (lineBuffer[0] == '\t'))
bCommand = true;
const bool bCommand = StartsWith(lineBuffer, '\t');
// Skip initial spaces
while ((i < lengthLine) && isspacechar(lineBuffer[i])) {
@ -63,10 +153,22 @@ static void ColouriseMakeLine(
styler.ColourTo(endPos, SCE_MAKE_PREPROCESSOR);
return;
}
if (IsUpperOrLowerCase(lineBuffer[i]) &&
(lineBuffer.find_first_of(":=") == std::string::npos)) {
const std::string_view firstWord(lineBuffer.substr(i));
size_t endWord = 0;
while ((endWord < firstWord.length()) && IsUpperOrLowerCase(firstWord[endWord])) {
endWord++;
}
if (directives.InList(firstWord.substr(0, endWord))) {
styler.ColourTo(startLine + i + endWord - 1, SCE_MAKE_PREPROCESSOR);
i += endWord;
}
}
}
int varCount = 0;
while (i < lengthLine) {
if (((i + 1) < lengthLine) && (lineBuffer[i] == '$' && lineBuffer[i + 1] == '(')) {
if (lineBuffer.substr(i, 2) == "$(") {
styler.ColourTo(startLine + i - 1, state);
state = SCE_MAKE_IDENTIFIER;
varCount++;
@ -78,32 +180,22 @@ static void ColouriseMakeLine(
}
// skip identifier and target styling if this is a command line
if (!bSpecial && !bCommand) {
if (lineBuffer[i] == ':') {
if (((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=')) {
// it's a ':=', so style as an identifier
if (lastNonSpace >= 0)
styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
styler.ColourTo(startLine + i + 1, SCE_MAKE_OPERATOR);
} else {
// We should check that no colouring was made since the beginning of the line,
// to avoid colouring stuff like /OUT:file
if (lastNonSpace >= 0)
styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_TARGET);
styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
}
bSpecial = true; // Only react to the first ':' of the line
state = SCE_MAKE_DEFAULT;
} else if (lineBuffer[i] == '=') {
if (lastNonSpace >= 0)
styler.ColourTo(startLine + lastNonSpace, SCE_MAKE_IDENTIFIER);
styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
styler.ColourTo(startLine + i, SCE_MAKE_OPERATOR);
bSpecial = true; // Only react to the first '=' of the line
state = SCE_MAKE_DEFAULT;
if (!bSpecial && !bCommand && AnyOf(lineBuffer[i], ':', '=')) {
// Three cases:
// : target
// := immediate assignment
// = lazy assignment
const bool colon = lineBuffer[i] == ':';
const bool immediate = colon && ((i + 1) < lengthLine) && (lineBuffer[i + 1] == '=');
const Sci_PositionU lengthOperator = immediate ? 1 : 0;
if (lastNonSpace >= 0) {
const int attribute = (colon && !immediate) ? SCE_MAKE_TARGET : SCE_MAKE_IDENTIFIER;
styler.ColourTo(startLine + lastNonSpace, attribute);
}
styler.ColourTo(startLine + i - 1, SCE_MAKE_DEFAULT);
styler.ColourTo(startLine + i + lengthOperator, SCE_MAKE_OPERATOR);
bSpecial = true; // Only react to the first ':' or '=' of the line
state = SCE_MAKE_DEFAULT;
}
if (!isspacechar(lineBuffer[i])) {
lastNonSpace = i;
@ -117,7 +209,8 @@ static void ColouriseMakeLine(
}
}
static void ColouriseMakeDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], Accessor &styler) {
void LexerMakeFile::Lex(Sci_PositionU startPos, Sci_Position length, int /* initStyle */, IDocument *pAccess) {
Accessor styler(pAccess, nullptr);
std::string lineBuffer;
styler.StartAt(startPos);
styler.StartSegment(startPos);
@ -134,10 +227,9 @@ static void ColouriseMakeDoc(Sci_PositionU startPos, Sci_Position length, int, W
if (!lineBuffer.empty()) { // Last line does not have ending characters
ColouriseMakeLine(lineBuffer, startLine, startPos + length - 1, styler);
}
styler.Flush();
}
static const char *const emptyWordListDesc[] = {
nullptr
};
}
extern const LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", nullptr, emptyWordListDesc);
extern const LexerModule lmMake(SCLEX_MAKEFILE, LexerMakeFile::LexerFactoryMakeFile, "makefile", makeWordListDescription);

View File

@ -43,10 +43,10 @@ static void ColouriseMaximaDoc(Sci_PositionU startPos, Sci_Position length, int
styler.StartAt(startPos);
Sci_PositionU lengthDoc = startPos + length;
Sci_Position lengthDoc = startPos + length;
styler.StartSegment(startPos);
Sci_PositionU i = startPos;
Sci_Position i = startPos;
// If we are in the middle of a comment we go back to its start before highlighting
if(lastStyle == SCE_MAXIMA_COMMENT)
@ -201,7 +201,7 @@ static void ColouriseMaximaDoc(Sci_PositionU startPos, Sci_Position length, int
// All other keywords are functions if they are followed
// by an opening parenthesis
char nextNonwhitespace = ' ';
for (Sci_PositionU o = i + 1; o < lengthDoc; o++)
for (Sci_Position o = i + 1; o < lengthDoc; o++)
{
nextNonwhitespace = styler.SafeGetCharAt(o);
if(!IsASCII(nextNonwhitespace) || !isspacechar(nextNonwhitespace))

View File

@ -150,6 +150,7 @@ LexicalClass lexicalClasses[] = {
13, "SCE_NIX_KEYWORD2", "identifier", "Keywords 2",
14, "SCE_NIX_KEYWORD3", "identifier", "Keywords 3",
15, "SCE_NIX_KEYWORD4", "identifier", "Keywords 4",
16, "SCE_NIX_STRINGEOL", "error literal string", "End of line where string is not closed",
};
class LexerNix : public DefaultLexer {
@ -266,6 +267,10 @@ void LexerNix::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle
std::vector<InterpolatingState> interpolatingStack;
if (initStyle == SCE_NIX_STRINGEOL) {
initStyle = SCE_NIX_DEFAULT;
}
if (startPos != 0) {
// backtrack to the line where interpolation starts
BacktrackToStart(styler, NixLineStateMaskInterpolation, startPos, lengthDoc, initStyle);
@ -323,6 +328,8 @@ void LexerNix::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle
case SCE_NIX_STRING:
if (sc.atLineStart) {
sc.SetState(SCE_NIX_DEFAULT);
} else if (sc.atLineEnd) {
sc.ChangeState(SCE_NIX_STRINGEOL);
} else if (sc.ch == '\\' && AnyOf(sc.chNext, '"', '\\', 'n', 'r', 't', '$')) {
sc.SetState(SCE_NIX_STRING);
sc.ChangeState(SCE_NIX_ESCAPECHAR);
@ -339,6 +346,12 @@ void LexerNix::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle
}
break;
case SCE_NIX_STRINGEOL:
if (sc.atLineStart) {
sc.SetState(SCE_NIX_DEFAULT);
}
break;
case SCE_NIX_PATH:
if (sc.atLineStart) {
sc.SetState(SCE_NIX_DEFAULT);

View File

@ -1742,7 +1742,7 @@ void SCI_METHOD LexerPerl::Fold(Sci_PositionU startPos, Sci_Position length, int
int levelPrev = SC_FOLDLEVELBASE;
if (lineCurrent > 0)
levelPrev = styler.LevelAt(lineCurrent - 1) >> 16;
levelPrev = FoldLevelStart(styler.LevelAt(lineCurrent - 1));
int levelCurrent = levelPrev;
char chNext = styler[startPos];
char chPrev = styler.SafeGetCharAt(startPos - 1);
@ -1875,14 +1875,9 @@ void SCI_METHOD LexerPerl::Fold(Sci_PositionU startPos, Sci_Position length, int
levelCurrent = SC_FOLDLEVELBASE + 1;
isPackageLine = false;
}
lev |= levelCurrent << 16;
if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if ((levelCurrent > levelPrev) && (visibleChars > 0))
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
lev |= levelCurrent << FoldLevelShift;
lev |= FoldLevelFlags(levelPrev, levelCurrent, visibleChars == 0 && options.foldCompact, visibleChars > 0);
styler.SetLevelIfDifferent(lineCurrent, lev);
lineCurrent++;
levelPrev = levelCurrent;
visibleChars = 0;
@ -1892,7 +1887,7 @@ void SCI_METHOD LexerPerl::Fold(Sci_PositionU startPos, Sci_Position length, int
chPrev = ch;
}
// Fill in the real level of the next line, keeping the current flags as they will be filled in later
int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
const int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
styler.SetLevel(lineCurrent, levelPrev | flagsNext);
}

View File

@ -409,7 +409,6 @@ public:
explicit LexerPython() :
DefaultLexer("python", SCLEX_PYTHON, lexicalClasses, std::size(lexicalClasses)) {
}
~LexerPython() override = default;
void SCI_METHOD Release() override {
delete this;
}
@ -534,11 +533,7 @@ void LexerPython::ProcessLineEnd(StyleContext &sc, std::vector<SingleFStringExpS
}
if (!fstringStateStack.empty()) {
std::pair<Sci_Position, std::vector<SingleFStringExpState> > val;
val.first = sc.currentLine;
val.second = fstringStateStack;
ftripleStateAtEol.insert(val);
ftripleStateAtEol.insert({sc.currentLine, fstringStateStack});
}
if ((sc.state == SCE_P_DEFAULT)

View File

@ -1424,7 +1424,7 @@ void SCI_METHOD LexerRaku::Lex(Sci_PositionU startPos, Sci_Position length, int
}
const int state = sc.state;
sc.Forward();
char ch_delim = 0;
int ch_delim = 0;
if (setSpecialVar.Contains(sc.ch)
&& !setWord.Contains(sc.chNext)) { // Process Special Var
ch_delim = -1;
@ -1532,7 +1532,7 @@ void SCI_METHOD LexerRaku::Fold(Sci_PositionU startPos, Sci_Position length, int
// init char and style variables
char chNext = styler[startPos];
int stylePrev = styler.StyleAt(startPos - 1);
int stylePrev = startPos > 0 ? styler.StyleAt(startPos - 1) : 0;
int styleNext = styler.StyleAt(startPos);
int styleNextStartLine = styler.StyleAt(lineStartNext);
int visibleChars = 0;

View File

@ -489,7 +489,7 @@ void InterpolateVariable(LexAccessor &styler, int state, Sci_Position &i, char &
styler.ColourTo(pos, SCE_RB_OPERATOR);
state = SCE_RB_GLOBAL;
pos += 2;
unsigned len = 0;
int len = 0;
if (chNext == '$') {
if (chNext2 == '-') {
++pos;

View File

@ -671,7 +671,7 @@ void SCI_METHOD LexerSQL::Fold(Sci_PositionU startPos, Sci_Position length, int
}
lineCurrent = styler.GetLine(startPos);
if (lineCurrent > 0)
levelCurrent = styler.LevelAt(lineCurrent - 1) >> 16;
levelCurrent = FoldLevelStart(styler.LevelAt(lineCurrent - 1));
}
// And because folding ends at ';', keep going until we find one
// Otherwise if create ... view ... as is split over multiple
@ -947,15 +947,9 @@ void SCI_METHOD LexerSQL::Fold(Sci_PositionU startPos, Sci_Position length, int
}
}
if (atEOL) {
const int levelUse = levelCurrent;
int lev = levelUse | levelNext << 16;
if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG;
if (lev != styler.LevelAt(lineCurrent)) {
styler.SetLevel(lineCurrent, lev);
}
const int lev = FoldLevelForCurrentNext(levelCurrent, levelNext) |
FoldLevelFlags(levelCurrent, levelNext, visibleChars == 0 && options.foldCompact);
styler.SetLevelIfDifferent(lineCurrent, lev);
lineCurrent++;
levelCurrent = levelNext;
visibleChars = 0;

View File

@ -163,6 +163,10 @@ void ColouriseTOMLDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initSt
TOMLKeyState keyState = TOMLKeyState::Unquoted;
EscapeSequence escSeq;
if (initStyle == SCE_TOML_STRINGEOL) {
initStyle = SCE_TOML_DEFAULT;
}
StyleContext sc(startPos, lengthDoc, initStyle, styler);
if (sc.currentLine > 0) {
const int lineState = styler.GetLineState(sc.currentLine - 1);
@ -274,6 +278,8 @@ void ColouriseTOMLDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initSt
case SCE_TOML_TRIPLE_STRING_DQ:
if (sc.atLineStart && !IsTripleString(sc.state)) {
sc.SetState(SCE_TOML_DEFAULT);
} else if (sc.atLineEnd && !IsTripleString(sc.state)) {
sc.ChangeState(SCE_TOML_STRINGEOL);
} else if (sc.ch == '\\' && IsDoubleQuoted(sc.state)) {
if (escSeq.resetEscapeState(sc.state, sc.chNext)) {
sc.SetState(SCE_TOML_ESCAPECHAR);
@ -293,6 +299,12 @@ void ColouriseTOMLDoc(Sci_PositionU startPos, Sci_Position lengthDoc, int initSt
}
break;
case SCE_TOML_STRINGEOL:
if (sc.atLineStart) {
sc.SetState(SCE_TOML_DEFAULT);
}
break;
case SCE_TOML_ESCAPECHAR:
if (escSeq.atEscapeEnd(sc.ch)) {
sc.SetState(escSeq.outerState);

View File

@ -163,6 +163,7 @@ LexicalClass lexicalClasses[] = {
15, "SCE_ZIG_KW_TERTIARY", "identifier", "Tertiary keywords",
16, "SCE_ZIG_KW_TYPE", "identifier", "Global types",
17, "SCE_ZIG_IDENTIFIER_STRING", "identifier", "Identifier using @\"\" syntax",
18, "SCE_ZIG_STRINGEOL", "error literal string", "End of line where string is not closed",
};
class LexerZig : public DefaultLexer {
@ -262,6 +263,10 @@ void LexerZig::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle
int lineState = 0;
EscapeSequence escSeq;
if (initStyle == SCE_ZIG_STRINGEOL) {
initStyle = SCE_ZIG_DEFAULT;
}
StyleContext sc(startPos, lengthDoc, initStyle, styler);
while (sc.More()) {
@ -311,6 +316,8 @@ void LexerZig::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle
case SCE_ZIG_IDENTIFIER_STRING:
if (sc.atLineStart) {
sc.SetState(SCE_ZIG_DEFAULT);
} else if (sc.atLineEnd && sc.state != SCE_ZIG_MULTISTRING) {
sc.ChangeState(SCE_ZIG_STRINGEOL);
} else if (sc.ch == '\\' && sc.state != SCE_ZIG_MULTISTRING) {
escSeq.resetEscapeState(sc.state, sc.chNext);
sc.SetState(SCE_ZIG_ESCAPECHAR);
@ -326,6 +333,12 @@ void LexerZig::Lex(Sci_PositionU startPos, Sci_Position lengthDoc, int initStyle
}
break;
case SCE_ZIG_STRINGEOL:
if (sc.atLineStart) {
sc.SetState(SCE_ZIG_DEFAULT);
}
break;
case SCE_ZIG_ESCAPECHAR:
if (escSeq.atEscapeEnd(sc.ch)) {
if (escSeq.brace && sc.ch == '}') {

View File

@ -58,9 +58,8 @@ int CompareNCaseInsensitive(const char *a, const char *b, size_t len) noexcept {
}
if (len == 0)
return 0;
else
// Either *a or *b is nul
return *a - *b;
// Either *a or *b is nul
return *a - *b;
}
}

View File

@ -190,6 +190,10 @@ int CompareCaseInsensitive(const char *a, const char *b) noexcept;
bool EqualCaseInsensitive(std::string_view a, std::string_view b) noexcept;
int CompareNCaseInsensitive(const char *a, const char *b, size_t len) noexcept;
constexpr bool StartsWith(std::string_view s, char start) noexcept {
return !s.empty() && (s.front() == start);
}
}
#endif

View File

@ -139,3 +139,6 @@ int SCI_METHOD DefaultLexer::GetIdentifier() {
return language;
}
const char *SCI_METHOD DefaultLexer::PropertyGet(const char * /* key */) {
return nullptr;
}

View File

@ -50,6 +50,7 @@ public:
// ILexer5 methods
const char * SCI_METHOD GetName() override;
int SCI_METHOD GetIdentifier() override;
const char *SCI_METHOD PropertyGet(const char *key) override;
};
}

View File

@ -11,6 +11,7 @@
#include <algorithm>
#include "ILexer.h"
#include "Scintilla.h"
#include "LexAccessor.h"
#include "CharacterSet.h"
@ -73,4 +74,21 @@ std::string LexAccessor::GetRangeLowered(Sci_PositionU startPos_, Sci_PositionU
return s;
}
void LexAccessor::SetLevelIfDifferent(Sci_Position line, int level) {
if (level != pAccess->GetLevel(line)) {
pAccess->SetLevel(line, level);
}
}
int FoldLevelFlags(int levelLine, int levelNext, bool white, bool headerPermitted) noexcept {
int flags = 0;
if (white) {
flags |= SC_FOLDLEVELWHITEFLAG;
}
if ((levelLine < levelNext) && (headerPermitted)) {
flags |= SC_FOLDLEVELHEADERFLAG;
}
return flags;
}
}

View File

@ -205,6 +205,8 @@ public:
void SetLevel(Sci_Position line, int level) {
pAccess->SetLevel(line, level);
}
// Avoids some overhead when level same as before
void SetLevelIfDifferent(Sci_Position line, int level);
void IndicatorFill(Sci_Position start, Sci_Position end, int indicator, int value) {
pAccess->DecorationSetCurrentIndicator(indicator);
pAccess->DecorationFillRange(start, value, end - start);
@ -222,6 +224,21 @@ struct LexicalClass {
const char *description;
};
// Fold level setting
constexpr int FoldLevelShift = 16;
constexpr int FoldLevelStart(int levelPrevious) noexcept {
return levelPrevious >> FoldLevelShift;
}
constexpr int FoldLevelForCurrentNext(int levelCurrent, int levelNext) noexcept {
return levelCurrent | levelNext << FoldLevelShift;
}
// Where lexer uses current/next but only has one value, commonly at end of range
constexpr int FoldLevelForCurrent(int levelCurrent) noexcept {
return FoldLevelForCurrentNext(levelCurrent, levelCurrent);
}
int FoldLevelFlags(int levelLine, int levelNext, bool white, bool headerPermitted=true) noexcept;
}
#endif

View File

@ -43,7 +43,7 @@ public:
void Set(Sci_Position position, T value) {
Delete(position);
if (states.empty() || (value != states[states.size()-1].value)) {
states.push_back(State(position, value));
states.emplace_back(position, value);
}
}
T ValueAt(Sci_Position position) {

View File

@ -191,8 +191,29 @@ bool WordList::InList(const char *s) const noexcept {
/** convenience overload so can easily call with std::string.
*/
bool WordList::InList(const std::string &s) const noexcept {
return InList(s.c_str());
bool WordList::InList(std::string_view sv) const noexcept {
if (!words || sv.empty())
return false;
const char first = sv[0];
const unsigned char firstChar = first;
if (int j = starts[firstChar]; j >= 0) {
const std::string_view after = sv.substr(1);
for (; words[j][0] == first; j++) {
if (std::string_view(words[j] + 1) == after) {
return true;
}
}
}
if (int j = starts[static_cast<unsigned int>('^')]; j >= 0) {
for (; words[j][0] == '^';j++) {
// Use rfind with 0 position to act like C++20 starts_with for C++17
if (sv.rfind(words[j] + 1, 0) == 0) {
return true;
}
}
}
return false;
}
/** similar to InList, but word s can be a substring of keyword.

View File

@ -33,7 +33,7 @@ public:
void Clear() noexcept;
bool Set(const char *s, bool lowerCase=false);
bool InList(const char *s) const noexcept;
bool InList(const std::string &s) const noexcept;
bool InList(std::string_view sv) const noexcept;
bool InListAbbreviated(const char *s, const char marker) const noexcept;
bool InListAbridged(const char *s, const char marker) const noexcept;
const char *WordAt(int n) const noexcept;

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>5.4.4</string>
<string>5.4.5</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>

View File

@ -876,7 +876,7 @@
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 5.4.4;
CURRENT_PROJECT_VERSION = 5.4.5;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 4F446KW87E;
DYLIB_COMPATIBILITY_VERSION = 1;
@ -904,7 +904,7 @@
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 5.4.4;
CURRENT_PROJECT_VERSION = 5.4.5;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 4F446KW87E;
DYLIB_COMPATIBILITY_VERSION = 1;

View File

@ -4,8 +4,8 @@
#include <windows.h>
#define VERSION_LEXILLA "5.4.4"
#define VERSION_WORDS 5, 4, 4, 0
#define VERSION_LEXILLA "5.4.5"
#define VERSION_WORDS 5, 4, 5, 0
VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_WORDS

View File

@ -41,6 +41,7 @@ $(DIR_O)/LexAccessor.o: \
../lexlib/LexAccessor.cxx \
../../scintilla/include/ILexer.h \
../../scintilla/include/Sci_Position.h \
../../scintilla/include/Scintilla.h \
../lexlib/LexAccessor.h \
../lexlib/CharacterSet.h
$(DIR_O)/LexerBase.o: \
@ -897,7 +898,9 @@ $(DIR_O)/LexMake.o: \
../lexlib/Accessor.h \
../lexlib/StyleContext.h \
../lexlib/CharacterSet.h \
../lexlib/LexerModule.h
../lexlib/LexerModule.h \
../lexlib/OptionSet.h \
../lexlib/DefaultLexer.h
$(DIR_O)/LexMarkdown.o: \
../lexers/LexMarkdown.cxx \
../../scintilla/include/ILexer.h \

View File

@ -41,6 +41,7 @@ $(DIR_O)/LexAccessor.obj: \
../lexlib/LexAccessor.cxx \
../../scintilla/include/ILexer.h \
../../scintilla/include/Sci_Position.h \
../../scintilla/include/Scintilla.h \
../lexlib/LexAccessor.h \
../lexlib/CharacterSet.h
$(DIR_O)/LexerBase.obj: \
@ -897,7 +898,9 @@ $(DIR_O)/LexMake.obj: \
../lexlib/Accessor.h \
../lexlib/StyleContext.h \
../lexlib/CharacterSet.h \
../lexlib/LexerModule.h
../lexlib/LexerModule.h \
../lexlib/OptionSet.h \
../lexlib/DefaultLexer.h
$(DIR_O)/LexMarkdown.obj: \
../lexers/LexMarkdown.cxx \
../../scintilla/include/ILexer.h \

View File

@ -49,4 +49,9 @@ movq
comment ~ A multiple-line
comment directive~
; test for folding from segment to ends
data segment
hw db "HW!"
data ends
;end

View File

@ -1,53 +1,58 @@
0 400 0 ; Enumerate all styles: 0 to 15 except for 11(comment block) which is not yet implemented.
0 400 0 ; This is not a viable source file, it just illustrates the different states in isolation.
0 400 0
0 400 0 ; comment=1
0 400 0 ; Comment
0 400 0
0 400 0 ; whitespace=0
0 400 0 ; w
0 400 0
0 400 0 ; number=2
0 400 0 11
0 400 0
0 400 0 ; string=3
0 400 0 "String"
0 400 0
0 400 0 ; operator=4
0 400 0 +
0 400 0
0 400 0 ; identifier=5
0 400 0 identifier
0 400 0
0 400 0 ; CPU instruction=6
0 400 0 add
0 400 0
0 400 0 ; math Instruction=7
0 400 0 fadd
0 400 0
0 400 0 ; register=8
0 400 0 ECX
0 400 0
0 400 0 ; directive=9
0 400 0 section
0 400 0
0 400 0 ; directive operand=10
0 400 0 rel
0 400 0
0 400 0 ; comment block=11 is for future expansion
0 400 0
0 400 0 ; character=12
0 400 0 'character'
0 400 0
0 400 0 ; string EOL=13
0 400 0 "no line end
0 400 0
0 400 0 ; extended instruction=14
0 400 0 movq
0 400 0
0 400 0 ; comment directive=15
0 400 0 comment ~ A multiple-line
0 400 0 comment directive~
0 400 0
0 400 0 ;end
0 400 0
0 400 400 ; Enumerate all styles: 0 to 15 except for 11(comment block) which is not yet implemented.
0 400 400 ; This is not a viable source file, it just illustrates the different states in isolation.
1 400 400
0 400 400 ; comment=1
0 400 400 ; Comment
1 400 400
0 400 400 ; whitespace=0
0 400 400 ; w
1 400 400
0 400 400 ; number=2
0 400 400 11
1 400 400
0 400 400 ; string=3
0 400 400 "String"
1 400 400
0 400 400 ; operator=4
0 400 400 +
1 400 400
0 400 400 ; identifier=5
0 400 400 identifier
1 400 400
0 400 400 ; CPU instruction=6
0 400 400 add
1 400 400
0 400 400 ; math Instruction=7
0 400 400 fadd
1 400 400
0 400 400 ; register=8
0 400 400 ECX
1 400 400
0 400 400 ; directive=9
0 400 400 section
1 400 400
0 400 400 ; directive operand=10
0 400 400 rel
1 400 400
0 400 400 ; comment block=11 is for future expansion
1 400 400
0 400 400 ; character=12
0 400 400 'character'
1 400 400
0 400 400 ; string EOL=13
0 400 400 "no line end
1 400 400
0 400 400 ; extended instruction=14
0 400 400 movq
1 400 400
0 400 400 ; comment directive=15
0 400 400 comment ~ A multiple-line
0 400 400 comment directive~
1 400 400
0 400 400 ; test for folding from segment to ends
2 400 401 + data segment
0 401 401 | hw db "HW!"
0 401 400 | data ends
1 400 400
0 400 400 ;end
1 400 400

View File

@ -49,4 +49,9 @@
{0} {9}comment{0} {15}~ A multiple-line
comment directive~{0}
{1}; test for folding from segment to ends
{5}data{0} {9}segment{0}
{5}hw{0} {9}db{0} {3}"HW!"{0}
{5}data{0} {9}ends{0}
{1};end

View File

@ -3,7 +3,10 @@ lexer.*.asm=asm
keywords.*.asm=add sub xor mov lea call
keywords2.*.asm=fadd
keywords3.*.asm=rsp rax rcx rdx r8 r9 ecx
keywords4.*.asm=db section alignb resq resqdb global extern equ .bss .text .data start comment
keywords4.*.asm=db section segment ends alignb resq resqdb global extern equ .bss .text .data start comment
keywords5.*.asm=qword rel
keywords6.*.asm=movd movq
keywords7.*.asm=segment
keywords8.*.asm=ends
fold=1

View File

@ -332,3 +332,8 @@ var s3 = """multi-line
${x}
strings
""";
var s1 = 'Unterminated string;
var s2 = "Unterminated string;
var s3 = r'Unterminated raw string;
var s4 = r'Unterminated raw string;

View File

@ -332,4 +332,9 @@
0 401 401 | ${x}
0 401 401 | strings
0 401 400 | """;
0 400 400
0 400 400 var s1 = 'Unterminated string;
0 400 400 var s2 = "Unterminated string;
0 400 400 var s3 = r'Unterminated raw string;
0 400 400 var s4 = r'Unterminated raw string;
0 400 0

View File

@ -332,3 +332,8 @@ strings
{17}${{14}x{17}}{8}
strings
"""{16};{0}
{23}var{0} {14}s1{0} {16}={0} {27}'Unterminated string;
{23}var{0} {14}s2{0} {16}={0} {27}"Unterminated string;
{23}var{0} {14}s3{0} {16}={0} {27}r'Unterminated raw string;
{23}var{0} {14}s4{0} {16}={0} {27}r'Unterminated raw string;

View File

@ -1 +1,2 @@
lexer.*.mak=makefile
keywords.*.mak=ifdef

View File

@ -7,10 +7,17 @@
# 'LD' identifier=3, '=' operator=4, 'link' default=0
LD=link
# '!IFDEF DEBUG' preprocessor=2
# '!IFDEF DEBUG' NMAKE preprocessor=2
!IFDEF DEBUG
# 'ifdef DEBUG' GNI make directive default=0
ifdef DEBUG
# '$(' ID EOL=9
X=$(
# Recipe with variable reference $(CXX)
cake.o: cake.cxx
$(CXX) -c $< -o $@
# End of file

View File

@ -7,11 +7,18 @@
0 400 0 # 'LD' identifier=3, '=' operator=4, 'link' default=0
0 400 0 LD=link
0 400 0
0 400 0 # '!IFDEF DEBUG' preprocessor=2
0 400 0 # '!IFDEF DEBUG' NMAKE preprocessor=2
0 400 0 !IFDEF DEBUG
0 400 0
0 400 0 # 'ifdef DEBUG' GNI make directive default=0
0 400 0 ifdef DEBUG
0 400 0
0 400 0 # '$(' ID EOL=9
0 400 0 X=$(
0 400 0
0 400 0 # Recipe with variable reference $(CXX)
0 400 0 cake.o: cake.cxx
0 400 0 $(CXX) -c $< -o $@
0 400 0
0 400 0 # End of file
0 400 0

View File

@ -7,10 +7,17 @@
{1}# 'LD' identifier=3, '=' operator=4, 'link' default=0
{3}LD{4}={0}link
{1}# '!IFDEF DEBUG' preprocessor=2
{1}# '!IFDEF DEBUG' NMAKE preprocessor=2
{2}!IFDEF DEBUG
{0}
{1}# 'ifdef DEBUG' GNI make directive default=0
{2}ifdef{0} DEBUG
{1}# '$(' ID EOL=9
{3}X{4}={9}$(
{0}
{1}# Recipe with variable reference $(CXX)
{5}cake.o{4}:{0} cake.cxx
{3}$(CXX){0} -c $< -o $@
{1}# End of file

View File

@ -347,3 +347,6 @@ stdenv.mkDerivation rec {
'';
}
message = "unterminated string;
message2 = "unterminated string;

View File

@ -347,4 +347,7 @@
0 402 401 | '';
0 401 401 |
0 401 400 | }
0 400 400
0 400 400 message = "unterminated string;
0 400 400 message2 = "unterminated string;
0 400 0

View File

@ -347,3 +347,6 @@ string
''{7};{0}
{7}}{0}
{10}message{0} {7}={0} {16}"unterminated string;
{10}message2{0} {7}={0} {16}"unterminated string;

View File

@ -189,3 +189,5 @@ points = [ { x = 1, y = 2, z = 3 },
~~~~ = true # invalid character in key
invalid # invalid, missing value
key = identifier # also invalid, identifier must be one of true, false, inf, nan
key = "unterminated string
key = 'other unterminated string

View File

@ -189,4 +189,6 @@
0 401 0 | ~~~~ = true # invalid character in key
0 401 0 | invalid # invalid, missing value
0 401 0 | key = identifier # also invalid, identifier must be one of true, false, inf, nan
0 401 0 | key = "unterminated string
0 401 0 | key = 'other unterminated string
0 401 0 |

View File

@ -189,3 +189,5 @@ trimmed in raw strings.
{7}~~~~ = true {1}# invalid character in key
{6}invalid{0} {1}# invalid, missing value
{6}key{0} {8}={0} {2}identifier{0} {1}# also invalid, identifier must be one of true, false, inf, nan
{6}key{0} {8}={0} {15}"unterminated string
{6}key{0} {8}={0} {15}'other unterminated string

View File

@ -288,3 +288,7 @@ const Color = enum {
@"really red",
};
const color: Color = .@"really red";
const s1 = "Unterminated string
const s2 = 'Unterminated character
const s3 = @"Unterminated identifier string

View File

@ -288,4 +288,8 @@
0 401 401 | @"really red",
0 401 400 | };
0 400 400 const color: Color = .@"really red";
0 400 400
0 400 400 const s1 = "Unterminated string
0 400 400 const s2 = 'Unterminated character
0 400 400 const s3 = @"Unterminated identifier string
0 400 0

View File

@ -288,3 +288,7 @@
{17}@"really red"{5},{0}
{5}};{0}
{13}const{0} {10}color{5}:{0} {10}Color{0} {5}={0} {5}.{17}@"really red"{5};{0}
{13}const{0} {10}s1{0} {5}={0} {18}"Unterminated string
{13}const{0} {10}s2{0} {5}={0} {18}'Unterminated character
{13}const{0} {10}s3{0} {5}={0} {18}@"Unterminated identifier string

View File

@ -44,6 +44,24 @@ TEST_CASE("WordList") {
REQUIRE(!wl.InList(sClass));
}
SECTION("StringViewInList") {
wl.Set("else struct i ^gtk");
std::string_view svStruct = "struct";
REQUIRE(wl.InList(svStruct));
std::string_view svClass = "class";
REQUIRE(!wl.InList(svClass));
// Test single characters
std::string_view svI = "i";
REQUIRE(wl.InList(svI));
std::string_view svA = "a";
REQUIRE(!wl.InList(svA));
// Test prefix
std::string_view svPrefix = "gtk_prefix";
REQUIRE(wl.InList(svPrefix));
}
SECTION("InListUnicode") {
// "cheese" in English
// "kase" ('k', 'a with diaeresis', 's', 'e') in German

View File

@ -1 +1 @@
544
545

View File

@ -1115,6 +1115,14 @@ int ScintillaCall::AutoCGetStyle() {
return static_cast<int>(Call(Message::AutoCGetStyle));
}
void ScintillaCall::AutoCSetImageScale(int scalePercent) {
Call(Message::AutoCSetImageScale, scalePercent);
}
int ScintillaCall::AutoCGetImageScale() {
return static_cast<int>(Call(Message::AutoCGetImageScale));
}
void ScintillaCall::SetIndent(int indentSize) {
Call(Message::SetIndent, indentSize);
}
@ -1367,6 +1375,10 @@ void ScintillaCall::LineScroll(Position columns, Line lines) {
Call(Message::LineScroll, columns, lines);
}
void ScintillaCall::ScrollVertical(Line docLine, Line subLine) {
Call(Message::ScrollVertical, docLine, subLine);
}
void ScintillaCall::ScrollCaret() {
Call(Message::ScrollCaret);
}

View File

@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>5.5.6</string>
<string>5.5.7</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>

View File

@ -586,7 +586,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 5.5.6;
CURRENT_PROJECT_VERSION = 5.5.7;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -650,7 +650,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 5.5.6;
CURRENT_PROJECT_VERSION = 5.5.7;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
@ -682,7 +682,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5.5.6;
CURRENT_PROJECT_VERSION = 5.5.7;
DEAD_CODE_STRIPPING = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
@ -717,7 +717,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5.5.6;
CURRENT_PROJECT_VERSION = 5.5.7;
DEAD_CODE_STRIPPING = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";

View File

@ -1951,6 +1951,7 @@ void ScintillaCocoa::ScrollText(Sci::Line) {
* Modifies the vertical scroll position to make the current top line show up as such.
*/
void ScintillaCocoa::SetVerticalScrollPos() {
Editor::SetVerticalScrollPos();
NSScrollView *scrollView = ScrollContainer();
if (scrollView) {
NSClipView *clipView = scrollView.contentView;

View File

@ -130,7 +130,7 @@
<h1>Scintilla Documentation</h1>
<p>Last edited 29 March 2025 NH</p>
<p>Last edited 29 May 2025 NH</p>
<p style="background:#90F0C0">Scintilla 5 has moved the lexers from Scintilla into a new
<a href="Lexilla.html">Lexilla</a> project.<br />
@ -151,6 +151,8 @@
discussion of folding</a>.<br />
<a class="jump" href="https://github.com/geany/geany/files/5204338/Scintilla-var.aq-Tutorial.pdf">
Beginner's Guide to lexing and folding</a>.<br />
<a class="jump" href="https://www.youtube.com/watch?v=M07iGUA07rY">
Video on writing a lexer with wxStyledTextCtrl</a>.<br />
The <a class="jump" href="SciCoding.html">coding style</a> used in Scintilla and SciTE is
worth following if you want to contribute code to Scintilla but is not compulsory.</p>
@ -1324,6 +1326,35 @@ struct Sci_TextRangeFull {
This is most commonly desired in conjunction with virtual space but is an independent
setting so works without virtual space.</p>
<table class="standard" summary="Virtual space options">
<tbody valign="top">
<tr>
<th align="left"><code>SCVS_NONE</code></th>
<td>0</td>
<td>The default: no virtual space.</td>
</tr>
<tr>
<th align="left"><code>SCVS_RECTANGULARSELECTION</code></th>
<td>1</td>
<td>Virtual space is enabled for rectangular selections.</td>
</tr>
<tr>
<th align="left"><code>SCVS_USERACCESSIBLE</code></th>
<td>2</td>
<td>Virtual space is enabled for user actions such as right arrow key or clicking beyond line end.</td>
</tr>
<tr>
<th align="left"><code>SCVS_NOWRAPLINESTART</code></th>
<td>4</td>
<td>Left arrow does not wrap to the previous line.</td>
</tr>
</tbody>
</table>
<p>
<b id="SCI_SETRECTANGULARSELECTIONMODIFIER">SCI_SETRECTANGULARSELECTIONMODIFIER(int modifier)</b><br />
<b id="SCI_GETRECTANGULARSELECTIONMODIFIER">SCI_GETRECTANGULARSELECTIONMODIFIER &rarr; int</b><br />
@ -2054,6 +2085,14 @@ struct Sci_TextToFindFull {
<td>Restore selection for each undo and redo.</td>
</tr>
<tr>
<th align="left"><code>SC_UNDO_SELECTION_HISTORY_SCROLL</code></th>
<td>2</td>
<td>Restore vertical scroll position. Has no effect without <code>SC_UNDO_SELECTION_HISTORY_ENABLED</code>.</td>
</tr>
</tbody>
</table>
@ -2358,6 +2397,7 @@ struct Sci_TextToFindFull {
<a class="message" href="#SCI_GETFIRSTVISIBLELINE">SCI_GETFIRSTVISIBLELINE &rarr; line</a><br />
<a class="message" href="#SCI_SETXOFFSET">SCI_SETXOFFSET(int xOffset)</a><br />
<a class="message" href="#SCI_GETXOFFSET">SCI_GETXOFFSET &rarr; int</a><br />
<a class="message" href="#SCI_SCROLLVERTICAL">SCI_SCROLLVERTICAL(line docLine, line subLine)</a><br />
<a class="message" href="#SCI_LINESCROLL">SCI_LINESCROLL(position columns, line lines)</a><br />
<a class="message" href="#SCI_SCROLLCARET">SCI_SCROLLCARET</a><br />
<a class="message" href="#SCI_SCROLLRANGE">SCI_SCROLLRANGE(position secondary, position primary)</a><br />
@ -2391,6 +2431,26 @@ struct Sci_TextToFindFull {
view. A value of 0 is the normal position with the first text column visible at the left of the
view.</p>
<p><b id="SCI_SCROLLVERTICAL">SCI_SCROLLVERTICAL(line docLine, line subLine)</b><br />
Sets the vertical scroll position to be the display line for the
<code class="parameter">subLine</code> of the <code class="parameter">docLine</code>, similar to<br>
<code>SCI_SETFIRSTVISIBLELINE(SCI_VISIBLEFROMDOCLINE(docLine) + subLine)</code>.</p>
<p>The <code class="parameter">subLine</code> is capped to the maximum number of sublines
for that document line which may change because of styling and wrapping. It is ignored when line
wrapping is off.</p>
<p>If line wrapping is on, then that
<code class="parameter">docLine</code>/<code class="parameter">subLine</code>
is remembered and reapplied as lines are wrapped.
This ensures that when wrapping is completed, which may take some time, the line at the top of the view is that
requested by the application and the view range is stable during the wrapping process.
It is forgotten once the document is fully wrapped or the user
performs scrolling manually such as by dragging the scroll bar.</p>
<p>This method is a good way for applications to restore the user's positional context when re-selecting a
document as it is robust to changes in window width and styles.</p>
<p><b id="SCI_LINESCROLL">SCI_LINESCROLL(position columns, line lines)</b><br />
This will attempt to scroll the display by the number of columns and lines that you specify.
Positive line values increase the line number at the top of the screen (i.e. they move the text
@ -3631,7 +3691,7 @@ struct Sci_TextToFindFull {
<td>&check;</td>
<td>&check;</td></tr>
<tr>
<th align="left"><code>SC_CHARSET_GREEK</code></td>
<th align="left"><code>SC_CHARSET_GREEK</code></th>
<td>161</td>
<td>&check;</td>
<td></td>
@ -4539,8 +4599,8 @@ struct Sci_TextToFindFull {
<p>Using a margin number outside the valid range has no
effect. By default, margin 0 is set to display line numbers, but is given a width of 0, so it
is hidden. Margin 1 is set to display non-folding symbols and is given a width of 16 pixels, so
it is visible. Margin 2 is set to display the folding symbols, but is given a width of 0, so it
is hidden. Of course, you can set the margins to be whatever you wish.</p>
it is visible. Margin 2 is a symbol margin that is given a width of 0, so it is hidden.
Of course, you can set the margins to be whatever you wish.</p>
<p>Styled text margins used to show revision and blame information:</p>
<p><img src="styledmargin.png" alt="Styled text margins used to show revision and blame information" /></p>
@ -5221,7 +5281,7 @@ struct Sci_TextToFindFull {
</tr>
</tbody>
</table>
<p></p>
<br />
<table class="standard" summary="IME interaction">
<caption>IME interaction support</caption>
@ -6475,6 +6535,8 @@ struct Sci_TextToFindFull {
<a class="message" href="#SCI_AUTOCGETMAXWIDTH">SCI_AUTOCGETMAXWIDTH &rarr; int</a><br />
<a class="message" href="#SCI_AUTOCSETSTYLE">SCI_AUTOCSETSTYLE(int style)</a><br />
<a class="message" href="#SCI_AUTOCGETSTYLE">SCI_AUTOCGETSTYLE &rarr; int</a><br />
<a class="message" href="#SCI_AUTOCSETIMAGESCALE">SCI_AUTOCSETIMAGESCALE(int scale)</a><br />
<a class="message" href="#SCI_AUTOCGETIMAGESCALE">SCI_AUTOCGETIMAGESCALE &rarr; int</a><br />
<a class="element" href="#SC_ELEMENT_LIST">SC_ELEMENT_LIST : colouralpha</a><br />
<a class="element" href="#SC_ELEMENT_LIST_BACK">SC_ELEMENT_LIST_BACK : colouralpha</a><br />
<a class="element" href="#SC_ELEMENT_LIST_SELECTED">SC_ELEMENT_LIST_SELECTED : colouralpha</a><br />
@ -6706,6 +6768,16 @@ struct Sci_TextToFindFull {
result as the argument to <code>SCI_AUTOCSETSTYLE</code> and <code>SCI_STYLESETFONT</code> and others.
</p>
<p>
<b id="SCI_AUTOCSETIMAGESCALE">SCI_AUTOCSETIMAGESCALE(int scalePercent)</b><br />
<b id="SCI_AUTOCGETIMAGESCALE">SCI_AUTOCGETIMAGESCALE &rarr; int</b><br />
Get or set the scale factor in percent for <em>all</em> autocompletion list images. This is useful on macOS with
a retina display where each display unit is 2 pixels: use a factor of 200 so that each image pixel is displayed using a screen pixel.
The default scale, 100, will stretch each image pixel to cover 4 screen pixels on a retina display.
</p>
<p>This is currently only implemented for the Qt and GTK platforms.</p>
<p>
<b id="SC_ELEMENT_LIST">SC_ELEMENT_LIST : colouralpha</b><br />
<b id="SC_ELEMENT_LIST_BACK">SC_ELEMENT_LIST_BACK : colouralpha</b><br />

View File

@ -26,9 +26,9 @@
<table bgcolor="#CCCCCC" width="100%" cellspacing="0" cellpadding="8" border="0">
<tr>
<td>
<font size="4"> <a href="https://www.scintilla.org/scintilla556.zip">
<font size="4"> <a href="https://www.scintilla.org/scintilla557.zip">
Windows</a>&nbsp;&nbsp;
<a href="https://www.scintilla.org/scintilla556.tgz">
<a href="https://www.scintilla.org/scintilla557.tgz">
GTK/Linux</a>&nbsp;&nbsp;
</font>
</td>
@ -42,7 +42,7 @@
containing very few restrictions.
</p>
<h3>
Release 5.5.6
Release 5.5.7
</h3>
<h4>
Source Code
@ -50,8 +50,8 @@
The source code package contains all of the source code for Scintilla but no binary
executable code and is available in
<ul>
<li><a href="https://www.scintilla.org/scintilla556.zip">zip format</a> (1.8M) commonly used on Windows</li>
<li><a href="https://www.scintilla.org/scintilla556.tgz">tgz format</a> (1.7M) commonly used on Linux and compatible operating systems</li>
<li><a href="https://www.scintilla.org/scintilla557.zip">zip format</a> (1.8M) commonly used on Windows</li>
<li><a href="https://www.scintilla.org/scintilla557.tgz">tgz format</a> (1.7M) commonly used on Linux and compatible operating systems</li>
</ul>
Instructions for building on both Windows and Linux are included in the readme file.
<h4>

View File

@ -593,6 +593,49 @@
</tr>
</table>
<h2 id="Releases">Releases</h2>
<h3>
<a href="https://www.scintilla.org/scintilla557.zip">Release 5.5.7</a>
</h3>
<ul>
<li>
Released 8 June 2025.
</li>
<li>
Add SCI_SCROLLVERTICAL method to restore view position and maintain it while performing line wrapping.
</li>
<li>
Add SC_UNDO_SELECTION_HISTORY_SCROLL flag to SCI_SETUNDOSELECTIONHISTORY which controls
whether undo and redo restore vertical scroll position.
</li>
<li>
Tweak SC_MARK_BAR to be slightly wider by using next higher whole pixel instead of next lower for margin width / 3.
</li>
<li>
Scale images in autocompletion lists with SCI_AUTOCSETIMAGESCALE to match high DPI screens.
Initially only on GTK and Qt.
</li>
<li>
Fix wrapping bug for UTF-8 where \r\n could wrap between the characters.
<a href="https://github.com/notepad-plus-plus/notepad-plus-plus/pull/16373">Notepad++ Pull Request #16373</a>.
</li>
<li>
Fix crash during painting when scroll bars changed.
<a href="https://sourceforge.net/p/scintilla/bugs/2481/">Bug #2481</a>.
</li>
<li>
On GTK, reset vertical scroll bar synchronously in SCI_SETDOCPOINTER to fix bug where
scroll position not restored in non-wrap mode.
<a href="https://sourceforge.net/p/scintilla/bugs/2416/">Bug #2416</a>.
</li>
<li>
On GTK, fix IME problem when tentative composition interfered with delete surrounding.
<a href="https://sourceforge.net/p/scintilla/feature-requests/1476/">Feature #1476</a>.
</li>
<li>
On GTK, update IME cursor position inside retrieve surrounding to better position candidate window.
<a href="https://sourceforge.net/p/scintilla/feature-requests/1488/">Feature #1488</a>.
</li>
</ul>
<h3>
<a href="https://www.scintilla.org/scintilla556.zip">Release 5.5.6</a>
</h3>

View File

@ -9,7 +9,7 @@
<meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
<meta name="Description"
content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
<meta name="Date.Modified" content="20250402" />
<meta name="Date.Modified" content="20250608" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
.logo {
@ -61,8 +61,8 @@
GTK, and macOS</font>
</td>
<td width="40%" align="right">
<font color="#FFCC99" size="3"> Release version 5.5.6<br />
Site last modified April 2 2025</font>
<font color="#FFCC99" size="3"> Release version 5.5.7<br />
Site last modified June 8 2025</font>
</td>
<td width="20%">
&nbsp;
@ -77,11 +77,11 @@
</tr>
</table>
<ul id="versionlist">
<li>Version 5.5.7 can prevent storing scroll position in undo selection history and adds a wrap-aware SCI_SCROLLVERTICAL API.</li>
<li>Version 5.5.6 improves DBCS and autocompletion drawing on Win32 and improves dwell, encoding and text clipping on Qt.</li>
<li>Version 5.5.5 can remember selection with undo and redo. Update to use DirectWrite 1.1.</li>
<li>Version 5.5.4 fixes wrapping of removed lines and edge cases for moving lines. On GTK, middle click can be repeated with one value.</li>
<li>Version 5.5.3 fixes horizontal scrolling with a touchpad on Win32.</li>
<li>Version 5.5.2 adds multiple selection copy with separator, a font stretch setting, and access to whether an undo sequence is active.</li>
</ul>
<ul id="menu">
<li id="remote1"><a href="https://www.scintilla.org/SciTEImage.html">Screenshot</a></li>

View File

@ -27,6 +27,9 @@
#if defined(GDK_WINDOWING_WAYLAND)
#include <gdk/gdkwayland.h>
#endif
#if GTK_CHECK_VERSION(3, 10, 0)
#include <cairo/cairo-gobject.h>
#endif
#include "ScintillaTypes.h"
#include "ScintillaMessages.h"
@ -1432,6 +1435,7 @@ class ListBoxX : public ListBox {
#if GTK_CHECK_VERSION(3,0,0)
std::unique_ptr<GtkCssProvider, GObjectReleaser> cssProvider;
#endif
float imageScale;
public:
IListBoxDelegate *delegate;
@ -1439,7 +1443,7 @@ public:
pixhash(nullptr), pixbuf_renderer(nullptr),
renderer(nullptr),
desiredVisibleRows(5), maxItemCharacters(0),
aveCharWidth(1),
aveCharWidth(1), imageScale(1.0),
delegate(nullptr) {
}
// Deleted so ListBoxX objects can not be copied.
@ -1673,7 +1677,13 @@ void ListBoxX::Create(Window &parent, int, Point, int, bool, Technology) {
/* Tree and its model */
GtkListStore *store =
gtk_list_store_new(N_COLUMNS, GDK_TYPE_PIXBUF, G_TYPE_STRING);
gtk_list_store_new(N_COLUMNS,
#if GTK_CHECK_VERSION(3, 10, 0)
CAIRO_GOBJECT_TYPE_SURFACE,
#else
GDK_TYPE_PIXBUF,
#endif
G_TYPE_STRING);
list = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store));
g_signal_connect(G_OBJECT(list), "style-set", G_CALLBACK(StyleSet), nullptr);
@ -1701,7 +1711,13 @@ void ListBoxX::Create(Window &parent, int, Point, int, bool, Technology) {
gtk_cell_renderer_set_fixed_size(pixbuf_renderer, 0, -1);
gtk_tree_view_column_pack_start(column, pixbuf_renderer, FALSE);
gtk_tree_view_column_add_attribute(column, pixbuf_renderer,
"pixbuf", PIXBUF_COLUMN);
#if GTK_CHECK_VERSION(3, 10, 0)
"surface",
#else
"pixbuf",
#endif
PIXBUF_COLUMN);
renderer = gtk_cell_renderer_text_new();
gtk_cell_renderer_text_set_fixed_height_from_font(GTK_CELL_RENDERER_TEXT(renderer), 1);
@ -1915,11 +1931,20 @@ void ListBoxX::Append(char *s, int type) {
if (nullptr == list_image->pixbuf)
init_pixmap(list_image);
if (list_image->pixbuf) {
#if GTK_CHECK_VERSION(3, 10, 0)
cairo_surface_t *surface = gdk_cairo_surface_create_from_pixbuf(list_image->pixbuf, imageScale, nullptr);
gtk_list_store_set(GTK_LIST_STORE(store), &iter,
PIXBUF_COLUMN, surface,
TEXT_COLUMN, s, -1);
const gint pixbuf_width = gdk_pixbuf_get_width(list_image->pixbuf) / imageScale;
#else
gtk_list_store_set(GTK_LIST_STORE(store), &iter,
PIXBUF_COLUMN, list_image->pixbuf,
TEXT_COLUMN, s, -1);
const gint pixbuf_width = gdk_pixbuf_get_width(list_image->pixbuf);
#endif
gint renderer_height, renderer_width;
gtk_cell_renderer_get_fixed_size(pixbuf_renderer,
&renderer_width, &renderer_height);
@ -2125,7 +2150,8 @@ void ListBoxX::SetList(const char *listText, char separator, char typesep) {
}
}
void ListBoxX::SetOptions(ListOptions) {
void ListBoxX::SetOptions(ListOptions options_) {
imageScale = options_.imageScale;
}
Menu::Menu() noexcept : mid(nullptr) {}

View File

@ -1102,6 +1102,7 @@ void ScintillaGTK::ScrollText(Sci::Line linesToMove) {
}
void ScintillaGTK::SetVerticalScrollPos() {
Editor::SetVerticalScrollPos();
DwellEnd(true);
gtk_adjustment_set_value(GTK_ADJUSTMENT(adjustmentv), static_cast<gdouble>(topLine));
}
@ -2375,29 +2376,6 @@ bool ScintillaGTK::KoreanIME() {
return lastNonCommonScript == G_UNICODE_SCRIPT_HANGUL;
}
void ScintillaGTK::MoveImeCarets(Sci::Position pos) {
// Move carets relatively by bytes
for (size_t r=0; r<sel.Count(); r++) {
const Sci::Position positionInsert = sel.Range(r).Start().Position();
sel.Range(r) = SelectionRange(positionInsert + pos);
}
}
void ScintillaGTK::DrawImeIndicator(int indicator, Sci::Position len) {
// Emulate the visual style of IME characters with indicators.
// Draw an indicator on the character before caret by the character bytes of len
// so it should be called after InsertCharacter().
// It does not affect caret positions.
if (indicator < 8 || indicator > INDICATOR_MAX) {
return;
}
pdoc->DecorationSetCurrentIndicator(indicator);
for (size_t r=0; r<sel.Count(); r++) {
const Sci::Position positionInsert = sel.Range(r).Start().Position();
pdoc->DecorationFillRange(positionInsert - len, 1, len);
}
}
namespace {
std::vector<int> MapImeIndicators(PangoAttrList *attrs, const char *u8Str) {
@ -2624,24 +2602,16 @@ bool ScintillaGTK::RetrieveSurroundingThis(GtkIMContext *context) {
const Sci::Position startByte = pdoc->LineStart(line);
const Sci::Position endByte = pdoc->LineEnd(line);
std::string utf8Text;
gint cursorIndex; // index of the cursor inside utf8Text, in bytes
const char *charSetBuffer;
std::string utf8Text = UTF8FromEncoded(RangeText(startByte, endByte));
gint cursorIndex = UTF8FromEncoded(RangeText(startByte, pos)).length();
if (IsUnicodeMode() || ! *(charSetBuffer = CharacterSetID())) {
utf8Text = RangeText(startByte, endByte);
cursorIndex = pos - startByte;
if (pdoc->TentativeActive()) {
// Prepare one line feed with no preedit under PreeditChangedInlineThis();
} else {
// Need to convert
std::string tmpbuf = RangeText(startByte, pos);
utf8Text = ConvertText(&tmpbuf[0], tmpbuf.length(), "UTF-8", charSetBuffer, false);
cursorIndex = utf8Text.length();
if (endByte > pos) {
tmpbuf = RangeText(pos, endByte);
utf8Text += ConvertText(&tmpbuf[0], tmpbuf.length(), "UTF-8", charSetBuffer, false);
}
// reconvert key triggers CandidateBox to show up
// when quick phrase input on fcitx (or maybe accented input on mac)
SetCandidateWindowPos();
}
gtk_im_context_set_surrounding(context, &utf8Text[0], utf8Text.length(), cursorIndex);
return true;
@ -2657,6 +2627,10 @@ gboolean ScintillaGTK::RetrieveSurrounding(GtkIMContext *context, ScintillaGTK *
bool ScintillaGTK::DeleteSurroundingThis(GtkIMContext *, gint characterOffset, gint characterCount) {
try {
if (pdoc->TentativeActive()) {
// First remove composition text so that correct surrounding text is deleted.
pdoc->TentativeUndo();
}
const Sci::Position startByte = pdoc->GetRelativePosition(CurrentPosition(), characterOffset);
if (startByte == INVALID_POSITION)
return false;
@ -3120,6 +3094,8 @@ void ScintillaGTK::SetDocPointer(Document *document) {
Editor::SetDocPointer(document);
ChangeScrollBars();
if (sciAccessible) {
// the accessible needs have the old Document, but also the new one active
sciAccessible->ChangeDocument(oldDoc, pdoc);

View File

@ -243,8 +243,6 @@ private:
bool DeleteSurroundingThis(GtkIMContext *context, gint characterOffset, gint characterCount);
static gboolean DeleteSurrounding(GtkIMContext *context, gint characterOffset, gint characterCount,
ScintillaGTK *sciThis);
void MoveImeCarets(Sci::Position pos);
void DrawImeIndicator(int indicator, Sci::Position len);
void SetCandidateWindowPos();
static void StyleSetText(GtkWidget *widget, GtkStyle *previous, void *);

View File

@ -478,6 +478,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SCI_AUTOCGETMAXHEIGHT 2211
#define SCI_AUTOCSETSTYLE 2109
#define SCI_AUTOCGETSTYLE 2120
#define SCI_AUTOCSETIMAGESCALE 2815
#define SCI_AUTOCGETIMAGESCALE 2816
#define SCI_SETINDENT 2122
#define SCI_GETINDENT 2123
#define SCI_SETUSETABS 2124
@ -541,6 +543,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SCI_GETCHANGEHISTORY 2781
#define SC_UNDO_SELECTION_HISTORY_DISABLED 0
#define SC_UNDO_SELECTION_HISTORY_ENABLED 1
#define SC_UNDO_SELECTION_HISTORY_SCROLL 2
#define SCI_SETUNDOSELECTIONHISTORY 2782
#define SCI_GETUNDOSELECTIONHISTORY 2783
#define SCI_SETSELECTIONSERIALIZED 2784
@ -567,6 +570,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SCI_LINEFROMPOSITION 2166
#define SCI_POSITIONFROMLINE 2167
#define SCI_LINESCROLL 2168
#define SCI_SCROLLVERTICAL 2817
#define SCI_SCROLLCARET 2169
#define SCI_SCROLLRANGE 2569
#define SCI_REPLACESEL 2170

View File

@ -1174,6 +1174,12 @@ set void AutoCSetStyle=2109(int style,)
# Get the style number used for auto-completion and user lists fonts.
get int AutoCGetStyle=2120(,)
# Set the scale factor in percent for auto-completion list images.
set void AutoCSetImageScale=2815(int scalePercent,)
# Get the scale factor in percent for auto-completion list images.
get int AutoCGetImageScale=2816(,)
# Set the number of spaces used for one level of indentation.
set void SetIndent=2122(int indentSize,)
@ -1337,6 +1343,7 @@ get ChangeHistoryOption GetChangeHistory=2781(,)
enu UndoSelectionHistoryOption=SC_UNDO_SELECTION_HISTORY_
val SC_UNDO_SELECTION_HISTORY_DISABLED=0
val SC_UNDO_SELECTION_HISTORY_ENABLED=1
val SC_UNDO_SELECTION_HISTORY_SCROLL=2
# Enable or disable undo selection history.
set void SetUndoSelectionHistory=2782(UndoSelectionHistoryOption undoSelectionHistory,)
@ -1415,6 +1422,9 @@ fun position PositionFromLine=2167(line line,)
# Scroll horizontally and vertically.
fun void LineScroll=2168(position columns, line lines)
# Scroll vertically with allowance for wrapping.
fun void ScrollVertical=2817(line docLine, line subLine)
# Ensure the caret is visible.
fun void ScrollCaret=2169(,)
@ -1565,7 +1575,7 @@ fun void CallTipCancel=2201(,)
fun bool CallTipActive=2202(,)
# Retrieve the position where the caret was before displaying the call tip.
fun position CallTipPosStart=2203(,)
get position CallTipPosStart=2203(,)
# Set the start position in order to change when backspacing removes the calltip.
set void CallTipSetPosStart=2214(position posStart,)

View File

@ -324,6 +324,8 @@ public:
int AutoCGetMaxHeight();
void AutoCSetStyle(int style);
int AutoCGetStyle();
void AutoCSetImageScale(int scalePercent);
int AutoCGetImageScale();
void SetIndent(int indentSize);
int Indent();
void SetUseTabs(bool useTabs);
@ -387,6 +389,7 @@ public:
Line LineFromPosition(Position pos);
Position PositionFromLine(Line line);
void LineScroll(Position columns, Line lines);
void ScrollVertical(Line docLine, Line subLine);
void ScrollCaret();
void ScrollRange(Position secondary, Position primary);
void ReplaceSel(const char *text);

View File

@ -249,6 +249,8 @@ enum class Message {
AutoCGetMaxHeight = 2211,
AutoCSetStyle = 2109,
AutoCGetStyle = 2120,
AutoCSetImageScale = 2815,
AutoCGetImageScale = 2816,
SetIndent = 2122,
GetIndent = 2123,
SetUseTabs = 2124,
@ -309,6 +311,7 @@ enum class Message {
LineFromPosition = 2166,
PositionFromLine = 2167,
LineScroll = 2168,
ScrollVertical = 2817,
ScrollCaret = 2169,
ScrollRange = 2569,
ReplaceSel = 2170,

View File

@ -303,6 +303,7 @@ enum class ChangeHistoryOption {
enum class UndoSelectionHistoryOption {
Disabled = 0,
Enabled = 1,
Scroll = 2,
};
enum class FoldLevel {

View File

@ -13,7 +13,7 @@ TEMPLATE = lib
CONFIG += lib_bundle
CONFIG += c++1z
VERSION = 5.5.6
VERSION = 5.5.7
SOURCES += \
ScintillaEdit.cpp \

View File

@ -40,6 +40,7 @@
#include <QTextLayout>
#include <QTextLine>
#include <QLibrary>
#include <QtMath>
using namespace Scintilla;
@ -994,6 +995,7 @@ private:
bool unicodeMode{false};
int visibleRows{5};
QMap<int,QPixmap> images;
float imageScale{1.0};
};
ListBoxImpl::ListBoxImpl() noexcept = default;
@ -1034,10 +1036,11 @@ void ListBoxImpl::Create(Window &parent,
int maxIconWidth = 0;
int maxIconHeight = 0;
foreach (QPixmap im, images) {
if (maxIconWidth < im.width())
maxIconWidth = im.width();
if (maxIconHeight < im.height())
maxIconHeight = im.height();
im.setDevicePixelRatio(imageScale);
if (maxIconWidth < im.width() / im.devicePixelRatio())
maxIconWidth = im.width() / im.devicePixelRatio();
if (maxIconHeight < im.height() / im.devicePixelRatio())
maxIconHeight = im.height() / im.devicePixelRatio();
}
list->setIconSize(QSize(maxIconWidth, maxIconHeight));
@ -1085,8 +1088,8 @@ int ListBoxImpl::CaretFromEdge()
ListWidget *list = GetWidget();
int maxIconWidth = 0;
foreach (QPixmap im, images) {
if (maxIconWidth < im.width())
maxIconWidth = im.width();
if (maxIconWidth < im.width() / im.devicePixelRatio())
maxIconWidth = im.width() / im.devicePixelRatio();
}
int extra;
@ -1165,9 +1168,9 @@ void ListBoxImpl::RegisterQPixmapImage(int type, const QPixmap& pm)
ListWidget *list = GetWidget();
if (list) {
QSize iconSize = list->iconSize();
if (pm.width() > iconSize.width() || pm.height() > iconSize.height())
list->setIconSize(QSize(qMax(pm.width(), iconSize.width()),
qMax(pm.height(), iconSize.height())));
if (pm.width() / pm.devicePixelRatio() > iconSize.width() || pm.height() / pm.devicePixelRatio() > iconSize.height())
list->setIconSize(QSize(qMax(qFloor(pm.width() / pm.devicePixelRatio()), iconSize.width()),
qMax(qFloor(pm.height() / pm.devicePixelRatio()), iconSize.height())));
}
}
@ -1226,8 +1229,9 @@ void ListBoxImpl::SetList(const char *list, char separator, char typesep)
Append(startword, numword?atoi(numword + 1):-1);
}
}
void ListBoxImpl::SetOptions(ListOptions)
void ListBoxImpl::SetOptions(ListOptions options_)
{
imageScale = options_.imageScale;
}
ListWidget *ListBoxImpl::GetWidget() const noexcept
{

View File

@ -21,11 +21,6 @@
#include <QScrollBar>
#include <QTextFormat>
constexpr int IndicatorInput = static_cast<int>(Scintilla::IndicatorNumbers::Ime);
constexpr int IndicatorTarget = IndicatorInput + 1;
constexpr int IndicatorConverted = IndicatorInput + 2;
constexpr int IndicatorUnknown = IndicatorInput + 3;
// Q_WS_MAC and Q_WS_X11 aren't defined in Qt5
#if QT_VERSION >= QT_VERSION_CHECK(5, 0, 0)
#ifdef Q_OS_MAC
@ -458,31 +453,6 @@ bool ScintillaEditBase::IsHangul(const QChar qchar)
HangulJamoExtendedA || HangulJamoExtendedB;
}
void ScintillaEditBase::MoveImeCarets(Scintilla::Position offset)
{
// Move carets relatively by bytes
for (size_t r=0; r < sqt->sel.Count(); r++) {
const Sci::Position positionInsert = sqt->sel.Range(r).Start().Position();
sqt->sel.Range(r) = SelectionRange(positionInsert + offset);
}
}
void ScintillaEditBase::DrawImeIndicator(int indicator, int len)
{
// Emulate the visual style of IME characters with indicators.
// Draw an indicator on the character before caret by the character bytes of len
// so it should be called after InsertCharacter().
// It does not affect caret positions.
if (indicator < INDICATOR_CONTAINER || indicator > INDICATOR_MAX) {
return;
}
sqt->pdoc->DecorationSetCurrentIndicator(indicator);
for (size_t r=0; r< sqt-> sel.Count(); r++) {
const Sci::Position positionInsert = sqt->sel.Range(r).Start().Position();
sqt->pdoc->DecorationFillRange(positionInsert - len, 1, len);
}
}
namespace {
int GetImeCaretPos(QInputMethodEvent *event)
@ -613,7 +583,7 @@ void ScintillaEditBase::inputMethodEvent(QInputMethodEvent *event)
sqt->InsertCharacter(std::string_view(oneChar.data(), oneCharLen), CharacterSource::TentativeInput);
DrawImeIndicator(imeIndicator[i], oneCharLen);
sqt->DrawImeIndicator(imeIndicator[i], oneCharLen);
i += ucWidth;
}
@ -622,13 +592,13 @@ void ScintillaEditBase::inputMethodEvent(QInputMethodEvent *event)
const int imeEndToImeCaretU16 = imeCaretPos - preeditStrLen;
const Sci::Position imeCaretPosDoc = sqt->pdoc->GetRelativePositionUTF16(sqt->CurrentPosition(), imeEndToImeCaretU16);
MoveImeCarets(- sqt->CurrentPosition() + imeCaretPosDoc);
sqt->MoveImeCarets(- sqt->CurrentPosition() + imeCaretPosDoc);
if (IsHangul(preeditStr.at(0))) {
#ifndef Q_OS_WIN
if (imeCaretPos > 0) {
int oneCharBefore = sqt->pdoc->GetRelativePosition(sqt->CurrentPosition(), -1);
MoveImeCarets(- sqt->CurrentPosition() + oneCharBefore);
sqt->MoveImeCarets(- sqt->CurrentPosition() + oneCharBefore);
}
#endif
sqt->view.imeCaretBlockOverride = true;

View File

@ -162,8 +162,6 @@ private:
int wheelDelta;
static bool IsHangul(const QChar qchar);
void MoveImeCarets(Scintilla::Position offset);
void DrawImeIndicator(int indicator, int len);
static Scintilla::KeyMod ModifiersOfKeyboard();
};

View File

@ -13,7 +13,7 @@ TEMPLATE = lib
CONFIG += lib_bundle
CONFIG += c++1z
VERSION = 5.5.6
VERSION = 5.5.7
SOURCES += \
PlatQt.cpp \

View File

@ -280,6 +280,7 @@ void ScintillaQt::ScrollText(Sci::Line linesToMove)
void ScintillaQt::SetVerticalScrollPos()
{
Editor::SetVerticalScrollPos();
scrollArea->verticalScrollBar()->setValue(topLine);
emit verticalScrolled(topLine);
}

View File

@ -2,6 +2,8 @@
// All platform headers should be included before Scintilla headers
// and each of these groups are then divided into directory groups.
// Qt platform layer not handled as it doesn't define a strong ordering of headers.
// Base of the repository relative to this file
//base:..
@ -16,8 +18,6 @@
//source:cocoa/*.mm
//source:cocoa/*.h
//source:test/unit/*.cxx
//source:lexilla/src/*.cxx
//source:lexilla/test/*.cxx
// C standard library
#include <stddef.h>
@ -71,6 +71,7 @@
#include <gdk/gdkkeysyms.h>
#include <gdk/gdkwayland.h>
#include <gtk/gtk-a11y.h>
#include <cairo/cairo-gobject.h>
// Windows headers
#include <windows.h>

View File

@ -41,6 +41,7 @@ AutoComplete::AutoComplete() :
ignoreCase(false),
chooseSingle(false),
options(AutoCompleteOption::Normal),
imageScale(1.0),
posStart(0),
startLen(0),
cancelAtStartPos(true),

View File

@ -25,6 +25,7 @@ public:
bool ignoreCase;
bool chooseSingle;
AutoCompleteOption options;
float imageScale;
std::unique_ptr<ListBox> lb;
Sci::Position posStart;
Sci::Position startLen;

View File

@ -95,9 +95,8 @@ int CallTip::NextTabPos(int x) const noexcept {
x -= insetX; // position relative to text
x = (x + tabSize) / tabSize; // tab "number"
return tabSize*x + insetX; // position of next tab
} else {
return x + 1; // arbitrary
}
return x + 1; // arbitrary
}
namespace {

View File

@ -4072,6 +4072,10 @@ namespace {
enum class OtherID { oidNone, oidStart, oidContinue };
// Silence 'magic' number warning as these character values are not used in multiple places.
// NOLINTBEGIN(*-magic-numbers)
// Some characters are treated as valid for identifiers even
// though most characters from their category are not.
// Values copied from http://www.unicode.org/Public/9.0.0/ucd/PropList.txt
@ -4161,6 +4165,8 @@ bool OmitXidContinue(int character) noexcept {
}
}
// NOLINTEND(*-magic-numbers)
}
// UAX #31 defines ID_Start as

View File

@ -65,6 +65,7 @@ public:
Sci::Line LinesInDoc() const noexcept override;
Sci::Line LinesDisplayed() const noexcept override;
Sci::Line DisplayFromDoc(Sci::Line lineDoc) const noexcept override;
Sci::Line DisplayFromDocSub(Sci::Line lineDoc, Sci::Line lineSub) const noexcept override;
Sci::Line DisplayLastFromDoc(Sci::Line lineDoc) const noexcept override;
Sci::Line DocFromDisplay(Sci::Line lineDisplay) const noexcept override;
@ -183,6 +184,12 @@ Sci::Line ContractionState<LINE>::DisplayFromDoc(Sci::Line lineDoc) const noexce
}
}
template <typename LINE>
Sci::Line ContractionState<LINE>::DisplayFromDocSub(Sci::Line lineDoc, Sci::Line lineSub) const noexcept {
return DisplayFromDoc(lineDoc) +
std::min(lineSub, static_cast<Sci::Line>(GetHeight(lineDoc) - 1));
}
template <typename LINE>
Sci::Line ContractionState<LINE>::DisplayLastFromDoc(Sci::Line lineDoc) const noexcept {
return DisplayFromDoc(lineDoc) + GetHeight(lineDoc) - 1;

View File

@ -21,6 +21,7 @@ public:
virtual Sci::Line LinesInDoc() const noexcept=0;
virtual Sci::Line LinesDisplayed() const noexcept=0;
virtual Sci::Line DisplayFromDoc(Sci::Line lineDoc) const noexcept=0;
virtual Sci::Line DisplayFromDocSub(Sci::Line lineDoc, Sci::Line lineSub) const noexcept=0;
virtual Sci::Line DisplayLastFromDoc(Sci::Line lineDoc) const noexcept=0;
virtual Sci::Line DocFromDisplay(Sci::Line lineDisplay) const noexcept=0;

View File

@ -16,6 +16,12 @@ using namespace Scintilla::Internal;
namespace Scintilla::Internal {
// Silence 'magic' number use since the set of DBCS lead and trail bytes differ
// between encodings and would require many constant declarations that would just
// obscure the behaviour.
// NOLINTBEGIN(*-magic-numbers)
bool DBCSIsLeadByte(int codePage, char ch) noexcept {
// Byte ranges found in Wikipedia articles with relevant search strings in each case
const unsigned char uch = ch;
@ -91,6 +97,8 @@ bool IsDBCSValidSingleByte(int codePage, int ch) noexcept {
}
}
// NOLINTEND(*-magic-numbers)
using CodePageToFoldMap = std::map<int, FoldMap>;
CodePageToFoldMap cpToFoldMap;

View File

@ -28,14 +28,12 @@ bool DBCSIsLeadByte(int codePage, char ch) noexcept;
bool DBCSIsTrailByte(int codePage, char ch) noexcept;
bool IsDBCSValidSingleByte(int codePage, int ch) noexcept;
// Calculate a number from a DBCS byte pair that can be used to index into an array or map.
// Calculate a number from a DBCS byte pair that can be used to index into an array or map.
// Should only be called with genuine DBCS character pairs which means that ch1 has top bit set.
constexpr uint16_t DBCSIndex(char ch1, char ch2) noexcept {
constexpr unsigned int highStart = 0x80U;
constexpr unsigned int byteMultiply = 0x100U;
const unsigned char uch1 = ch1;
const unsigned char uch1 = ch1 & 0x7F;
const unsigned char uch2 = ch2;
return ((uch1 - highStart) * byteMultiply) + uch2;
return (uch1 << 8) | uch2;
}
struct DBCSPair {

View File

@ -120,7 +120,7 @@ void ActionDuration::AddSample(size_t numberActions, double durationOfActions) n
// Most recent value contributes 25% to smoothed value.
constexpr double alpha = 0.25;
const double durationOne = durationOfActions / numberActions;
const double durationOne = durationOfActions / static_cast<double>(numberActions);
duration = std::clamp(alpha * durationOne + (1.0 - alpha) * duration,
minDuration, maxDuration);
}
@ -260,8 +260,7 @@ LineAnnotation *Document::EOLAnnotations() const noexcept {
LineEndType Document::LineEndTypesSupported() const {
if ((CpUtf8 == dbcsCodePage) && pli)
return pli->LineEndTypesSupported();
else
return LineEndType::Default;
return LineEndType::Default;
}
bool Document::SetDBCSCodePage(int dbcsCodePage_) {
@ -272,9 +271,8 @@ bool Document::SetDBCSCodePage(int dbcsCodePage_) {
cb.SetUTF8Substance(CpUtf8 == dbcsCodePage);
ModifiedAt(0); // Need to restyle whole document
return true;
} else {
return false;
}
return false;
}
bool Document::SetLineEndTypesAllowed(LineEndType lineEndBitSet_) {
@ -285,12 +283,9 @@ bool Document::SetLineEndTypesAllowed(LineEndType lineEndBitSet_) {
ModifiedAt(0);
cb.SetLineEndTypes(lineEndBitSetActive);
return true;
} else {
return false;
}
} else {
return false;
}
return false;
}
void Document::SetSavePoint() {
@ -453,9 +448,8 @@ int Document::AddMark(Sci::Line line, int markerNum) {
const DocModification mh(ModificationFlags::ChangeMarker, LineStart(line), 0, 0, nullptr, line);
NotifyModified(mh);
return prev;
} else {
return -1;
}
return -1;
}
void Document::AddMarkSet(Sci::Line line, int valueSet) {
@ -632,14 +626,14 @@ constexpr bool IsSubordinate(FoldLevel levelStart, FoldLevel levelTry) noexcept
Sci::Line Document::GetLastChild(Sci::Line lineParent, std::optional<FoldLevel> level, Sci::Line lastLine) {
const FoldLevel levelStart = LevelNumberPart(level ? *level : GetFoldLevel(lineParent));
const Sci::Line maxLine = LinesTotal();
const Sci::Line lookLastLine = (lastLine != -1) ? std::min(LinesTotal() - 1, lastLine) : -1;
const Sci::Line maxLine = LinesTotal() - 1;
const Sci::Line lookLastLine = (lastLine != -1) ? std::min(maxLine, lastLine) : maxLine;
Sci::Line lineMaxSubord = lineParent;
while (lineMaxSubord < maxLine - 1) {
while (lineMaxSubord < maxLine) {
EnsureStyledTo(LineStart(lineMaxSubord + 2));
if (!IsSubordinate(levelStart, GetFoldLevel(lineMaxSubord + 1)))
break;
if ((lookLastLine != -1) && (lineMaxSubord >= lookLastLine) && !LevelIsWhitespace(GetFoldLevel(lineMaxSubord)))
if ((lineMaxSubord >= lookLastLine) && !LevelIsWhitespace(GetFoldLevel(lineMaxSubord)))
break;
lineMaxSubord++;
}
@ -763,15 +757,13 @@ int Document::LenChar(Sci::Position pos) const noexcept {
if (utf8status & UTF8MaskInvalid) {
// Treat as invalid and use up just one byte
return 1;
} else {
return utf8status & UTF8MaskWidth;
}
return utf8status & UTF8MaskWidth;
}
if (IsDBCSLeadByteNoExcept(leadByte) && IsDBCSTrailByteNoExcept(cb.CharAt(pos + 1))) {
return 2;
} else {
if (IsDBCSLeadByteNoExcept(leadByte) && IsDBCSTrailByteNoExcept(cb.CharAt(pos + 1))) {
return 2;
} else {
return 1;
}
return 1;
}
}
@ -785,21 +777,20 @@ bool Document::InGoodUTF8(Sci::Position pos, Sci::Position &start, Sci::Position
const int widthCharBytes = UTF8BytesOfLead[leadByte];
if (widthCharBytes == 1) {
return false;
} else {
const int trailBytes = widthCharBytes - 1;
const Sci::Position len = pos - start;
if (len > trailBytes)
// pos too far from lead
return false;
unsigned char charBytes[UTF8MaxBytes] = {leadByte,0,0,0};
for (Sci::Position b=1; b<widthCharBytes && ((start+b) < cb.Length()); b++)
charBytes[b] = cb.CharAt(start+b);
const int utf8status = UTF8Classify(charBytes, widthCharBytes);
if (utf8status & UTF8MaskInvalid)
return false;
end = start + widthCharBytes;
return true;
}
const int trailBytes = widthCharBytes - 1;
const Sci::Position len = pos - start;
if (len > trailBytes)
// pos too far from lead
return false;
unsigned char charBytes[UTF8MaxBytes] = {leadByte,0,0,0};
for (Sci::Position b=1; b<widthCharBytes && ((start+b) < cb.Length()); b++)
charBytes[b] = cb.CharAt(start+b);
const int utf8status = UTF8Classify(charBytes, widthCharBytes);
if (utf8status & UTF8MaskInvalid)
return false;
end = start + widthCharBytes;
return true;
}
// Normalise a position so that it is not part way through a multi-byte character.
@ -958,10 +949,9 @@ bool Document::NextCharacter(Sci::Position &pos, int moveDir) const noexcept {
Sci::Position posNext = NextPosition(pos, moveDir);
if (posNext == pos) {
return false;
} else {
pos = posNext;
return true;
}
pos = posNext;
return true;
}
CharacterExtracted Document::CharacterAfter(Sci::Position position) const noexcept {
@ -1109,6 +1099,12 @@ bool SCI_METHOD Document::IsDBCSLeadByte(char ch) const {
return IsDBCSLeadByteNoExcept(ch);
}
// Silence 'magic' number use since the set of DBCS lead and trail bytes differ
// between encodings and would require many constant declarations that would just
// obscure the behaviour.
// NOLINTBEGIN(*-magic-numbers)
bool Document::IsDBCSLeadByteNoExcept(char ch) const noexcept {
// Used inside core Scintilla
// Byte ranges found in Wikipedia articles with relevant search strings in each case
@ -1192,6 +1188,8 @@ unsigned char Document::DBCSMinTrailByte() const noexcept {
}
}
// NOLINTEND(*-magic-numbers)
int Document::DBCSDrawBytes(std::string_view text) const noexcept {
if (text.length() <= 1) {
return static_cast<int>(text.length());
@ -1218,7 +1216,8 @@ void DiscardEndFragment(std::string_view &text) noexcept {
text.remove_suffix(1);
} else if (UTF8IsTrailByte(text.back())) {
// go back to the start of last character.
const size_t maxTrail = std::max<size_t>(UTF8MaxBytes - 1, text.length());
constexpr int UTF8MaxTrail = UTF8MaxBytes - 1;
const size_t maxTrail = std::max<size_t>(UTF8MaxTrail, text.length());
size_t trail = 1;
while (trail < maxTrail && UTF8IsTrailByte(text[text.length() - trail])) {
trail++;
@ -1307,7 +1306,7 @@ std::string CreateIndentation(Sci::Position indent, int tabSize, bool insertSpac
bool Scintilla::Internal::DiscardLastCombinedCharacter(std::string_view &text) noexcept {
// Handle the simple common case where a base character may be followed by
// accents and similar marks by discarding until start of base character.
//
//
// From Grapheme_Cluster_Boundaries
// combining character sequence = ccs-base? ccs-extend+
// ccs-base := [\p{L}\p{N}\p{P}\p{S}\p{Zs}]
@ -1405,10 +1404,9 @@ size_t Document::SafeSegment(std::string_view text) const noexcept {
EncodingFamily Document::CodePageFamily() const noexcept {
if (CpUtf8 == dbcsCodePage)
return EncodingFamily::unicode;
else if (dbcsCodePage)
if (dbcsCodePage)
return EncodingFamily::dbcs;
else
return EncodingFamily::eightBit;
return EncodingFamily::eightBit;
}
void Document::ModifiedAt(Sci::Position pos) noexcept {
@ -1448,37 +1446,36 @@ bool Document::DeleteChars(Sci::Position pos, Sci::Position len) {
CheckReadOnly();
if (enteredModification != 0) {
return false;
} else {
enteredModification++;
if (!cb.IsReadOnly()) {
if (cb.IsCollectingUndo() && cb.CanRedo()) {
// Abandoning some undo actions so truncate any later selections
TruncateUndoComments(cb.UndoCurrent());
}
NotifyModified(
DocModification(
ModificationFlags::BeforeDelete | ModificationFlags::User,
pos, len,
0, nullptr));
const Sci::Line prevLinesTotal = LinesTotal();
const bool startSavePoint = cb.IsSavePoint();
bool startSequence = false;
const char *text = cb.DeleteChars(pos, len, startSequence);
if (startSavePoint && cb.IsCollectingUndo())
NotifySavePoint(false);
if ((pos < LengthNoExcept()) || (pos == 0))
ModifiedAt(pos);
else
ModifiedAt(pos-1);
NotifyModified(
DocModification(
ModificationFlags::DeleteText | ModificationFlags::User |
(startSequence?ModificationFlags::StartAction:ModificationFlags::None),
pos, len,
LinesTotal() - prevLinesTotal, text));
}
enteredModification--;
}
enteredModification++;
if (!cb.IsReadOnly()) {
if (cb.IsCollectingUndo() && cb.CanRedo()) {
// Abandoning some undo actions so truncate any later selections
TruncateUndoComments(cb.UndoCurrent());
}
NotifyModified(
DocModification(
ModificationFlags::BeforeDelete | ModificationFlags::User,
pos, len,
0, nullptr));
const Sci::Line prevLinesTotal = LinesTotal();
const bool startSavePoint = cb.IsSavePoint();
bool startSequence = false;
const char *text = cb.DeleteChars(pos, len, startSequence);
if (startSavePoint && cb.IsCollectingUndo())
NotifySavePoint(false);
if ((pos < LengthNoExcept()) || (pos == 0))
ModifiedAt(pos);
else
ModifiedAt(pos-1);
NotifyModified(
DocModification(
ModificationFlags::DeleteText | ModificationFlags::User |
(startSequence?ModificationFlags::StartAction:ModificationFlags::None),
pos, len,
LinesTotal() - prevLinesTotal, text));
}
enteredModification--;
return !cb.IsReadOnly();
}
@ -2512,10 +2509,10 @@ Sci::Position Document::FindText(Sci::Position minPos, Sci::Position maxPos, con
}
const char *Document::SubstituteByPosition(const char *text, Sci::Position *length) {
if (regex)
if (regex) {
return regex->SubstituteByPosition(this, text, length);
else
return nullptr;
}
return nullptr;
}
LineCharacterIndexType Document::LineCharacterIndex() const noexcept {
@ -2565,46 +2562,44 @@ void SCI_METHOD Document::StartStyling(Sci_Position position) {
bool SCI_METHOD Document::SetStyleFor(Sci_Position length, char style) {
if (enteredStyling != 0) {
return false;
} else {
enteredStyling++;
const Sci::Position prevEndStyled = endStyled;
if (cb.SetStyleFor(endStyled, length, style)) {
const DocModification mh(ModificationFlags::ChangeStyle | ModificationFlags::User,
prevEndStyled, length);
NotifyModified(mh);
}
endStyled += length;
enteredStyling--;
return true;
}
enteredStyling++;
const Sci::Position prevEndStyled = endStyled;
if (cb.SetStyleFor(endStyled, length, style)) {
const DocModification mh(ModificationFlags::ChangeStyle | ModificationFlags::User,
prevEndStyled, length);
NotifyModified(mh);
}
endStyled += length;
enteredStyling--;
return true;
}
bool SCI_METHOD Document::SetStyles(Sci_Position length, const char *styles) {
if (enteredStyling != 0) {
return false;
} else {
enteredStyling++;
bool didChange = false;
Sci::Position startMod = 0;
Sci::Position endMod = 0;
for (int iPos = 0; iPos < length; iPos++, endStyled++) {
PLATFORM_ASSERT(endStyled < Length());
if (cb.SetStyleAt(endStyled, styles[iPos])) {
if (!didChange) {
startMod = endStyled;
}
didChange = true;
endMod = endStyled;
}
}
if (didChange) {
const DocModification mh(ModificationFlags::ChangeStyle | ModificationFlags::User,
startMod, endMod - startMod + 1);
NotifyModified(mh);
}
enteredStyling--;
return true;
}
enteredStyling++;
bool didChange = false;
Sci::Position startMod = 0;
Sci::Position endMod = 0;
for (int iPos = 0; iPos < length; iPos++, endStyled++) {
PLATFORM_ASSERT(endStyled < Length());
if (cb.SetStyleAt(endStyled, styles[iPos])) {
if (!didChange) {
startMod = endStyled;
}
didChange = true;
endMod = endStyled;
}
}
if (didChange) {
const DocModification mh(ModificationFlags::ChangeStyle | ModificationFlags::User,
startMod, endMod - startMod + 1);
NotifyModified(mh);
}
enteredStyling--;
return true;
}
void Document::EnsureStyledTo(Sci::Position pos) {
@ -2640,7 +2635,7 @@ void Document::SetLexInterface(std::unique_ptr<LexInterface> pLexInterface) noex
void Document::SetViewState(void *view, ViewStateShared pVSS) {
if (pVSS) {
viewData[view] = pVSS;
viewData[view] = std::move(pVSS);
} else {
viewData.erase(view);
}
@ -3027,7 +3022,7 @@ Sci::Position Document::BraceMatch(Sci::Position position, Sci::Position /*maxRe
// Avoid using MovePositionOutsideChar to check DBCS trail byte
unsigned char maxSafeChar = 0xff;
if (dbcsCodePage != 0 && dbcsCodePage != CpUtf8) {
maxSafeChar = DBCSMinTrailByte() - 1;
maxSafeChar = std::max<unsigned char>(DBCSMinTrailByte(), 1) - 1;
}
while ((position >= 0) && (position < LengthNoExcept())) {
@ -3115,10 +3110,10 @@ public:
}
[[nodiscard]] char CharAt(Sci::Position index) const noexcept override {
if (index < 0 || index >= end)
if (index < 0 || index >= end) {
return 0;
else
return pdoc->CharAt(index);
}
return pdoc->CharAt(index);
}
[[nodiscard]] Sci::Position MovePositionOutsideChar(Sci::Position pos, Sci::Position moveDir) const noexcept override {
return pdoc->MovePositionOutsideChar(pos, moveDir, false);

View File

@ -173,7 +173,7 @@ public:
};
// Base class for view state that can be held and transferred without understanding the contents.
// Declared here but real implementation subclass declared in EditModel
// Declared here but real implementation subclass declared in EditModel
struct ViewState {
ViewState() noexcept = default;
// Deleted so ViewState objects can not be copied

View File

@ -172,7 +172,7 @@ int EditModel::GetMark(Sci::Line line) const {
}
void EditModel::EnsureModelState() {
if (!modelState && (undoSelectionHistoryOption == UndoSelectionHistoryOption::Enabled)) {
if (!modelState && (undoSelectionHistoryOption != UndoSelectionHistoryOption::Disabled)) {
if (ViewStateShared vss = pdoc->GetViewState(this)) {
modelState = std::dynamic_pointer_cast<ModelState>(vss);
} else {

View File

@ -277,7 +277,7 @@ void EditView::DropGraphics() noexcept {
}
void EditView::RefreshPixMaps(Surface *surfaceWindow, const ViewStyle &vsDraw) {
if (!pixmapIndentGuide) {
if (!(pixmapIndentGuide && pixmapIndentGuideHighlight)) {
// 1 extra pixel in height so can handle odd/even positions and so produce a continuous line
pixmapIndentGuide = surfaceWindow->AllocatePixMap(1, vsDraw.lineHeight + 1);
pixmapIndentGuideHighlight = surfaceWindow->AllocatePixMap(1, vsDraw.lineHeight + 1);
@ -670,8 +670,8 @@ Point EditView::LocationFromPosition(Surface *surface, const EditModel &model, S
pt.y = static_cast<XYPOSITION>(subLine*vs.lineHeight);
}
}
pt.y += (lineVisible - topLine) * vs.lineHeight;
pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
pt.y += static_cast<XYPOSITION>((lineVisible - topLine) * vs.lineHeight);
pt.x += pos.VirtualSpaceWidth(vs.styles[ll->EndLineStyle()].spaceWidth);
}
return pt;
}
@ -958,7 +958,7 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
XYPOSITION virtualSpace = 0;
if (lastSubLine) {
const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
virtualSpace = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line)) * spaceWidth;
virtualSpace = static_cast<XYPOSITION>(model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line))) * spaceWidth;
}
const XYPOSITION xEol = ll->positions[lineEnd] - subLineStart;
@ -977,9 +977,9 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
if (!portion.Empty()) {
const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] -
subLineStart+portion.start.VirtualSpace() * spaceWidth;
subLineStart + portion.start.VirtualSpaceWidth(spaceWidth);
rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] -
subLineStart+portion.end.VirtualSpace() * spaceWidth;
subLineStart + portion.end.VirtualSpaceWidth(spaceWidth);
rcSegment.left = (rcSegment.left > rcLine.left) ? rcSegment.left : rcLine.left;
rcSegment.right = (rcSegment.right < rcLine.right) ? rcSegment.right : rcLine.right;
surface->FillRectangleAligned(rcSegment, Fill(
@ -1149,8 +1149,8 @@ void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, con
}
const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
const XYPOSITION virtualSpace = model.sel.VirtualSpaceFor(
model.pdoc->LineEnd(line)) * spaceWidth;
const XYPOSITION virtualSpace = static_cast<XYPOSITION>(model.sel.VirtualSpaceFor(
model.pdoc->LineEnd(line))) * spaceWidth;
rcSegment.left = xStart + ll->positions[ll->numCharsInLine] - subLineStart + virtualSpace + vsDraw.aveCharWidth;
rcSegment.right = rcSegment.left + static_cast<XYPOSITION>(widthFoldDisplayText);
@ -1267,8 +1267,8 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c
leftBoxSpace + rightBoxSpace);
const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
const XYPOSITION virtualSpace = model.sel.VirtualSpaceFor(
model.pdoc->LineEnd(line)) * spaceWidth;
const XYPOSITION virtualSpace = static_cast<XYPOSITION>(model.sel.VirtualSpaceFor(
model.pdoc->LineEnd(line))) * spaceWidth;
rcSegment.left = xStart +
ll->positions[ll->numCharsInLine] - subLineStart
+ virtualSpace + vsDraw.aveCharWidth;
@ -1518,7 +1518,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
}
const int offset = static_cast<int>(posCaret.Position() - posLineStart);
const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
const XYPOSITION virtualOffset = posCaret.VirtualSpace() * spaceWidth;
const XYPOSITION virtualOffset = posCaret.VirtualSpaceWidth(spaceWidth);
if (ll->InLine(offset, subLine) && offset <= ll->numCharsBeforeEOL) {
XYPOSITION xposCaret = ll->positions[offset] + virtualOffset - ll->positions[ll->LineStart(subLine)];
if (model.BidirectionalEnabled() && (posCaret.VirtualSpace() == 0)) {
@ -1785,7 +1785,9 @@ void DrawTranslucentSelection(Surface *surface, const EditModel &model, const Vi
const ColourRGBA selectionBack = SelectionBackground(
model, vsDraw, model.sel.RangeType(r));
const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
const Interval intervalVirtual{ portion.start.VirtualSpace() * spaceWidth, portion.end.VirtualSpace() * spaceWidth };
const Interval intervalVirtual{
portion.start.VirtualSpaceWidth(spaceWidth),
portion.end.VirtualSpaceWidth(spaceWidth) };
if (model.BidirectionalEnabled()) {
const SelectionSegment portionInSubLine = portionInLine.Subtract(lineRange.start);

View File

@ -202,6 +202,8 @@ Editor::Editor() : durationWrapOneByte(0.000001, 0.00000001, 0.00001) {
recordingMacro = false;
foldAutomatic = AutomaticFold::None;
insideWrapScroll = false;
convertPastes = true;
SetRepresentations();
@ -267,7 +269,7 @@ PointDocument Editor::DocumentPointFromView(Point ptView) const {
ptDocument.y += ptOrigin.y;
} else {
ptDocument.x += xOffset;
ptDocument.y += topLine * vs.lineHeight;
ptDocument.y += static_cast<double>(topLine * vs.lineHeight);
}
return ptDocument;
}
@ -275,8 +277,7 @@ PointDocument Editor::DocumentPointFromView(Point ptView) const {
Sci::Line Editor::TopLineOfMain() const noexcept {
if (HasMarginWindow())
return 0;
else
return topLine;
return topLine;
}
Point Editor::ClientSize() const {
@ -310,8 +311,7 @@ Sci::Line Editor::LinesToScroll() const {
const Sci::Line retVal = LinesOnScreen() - 1;
if (retVal < 1)
return 1;
else
return retVal;
return retVal;
}
Sci::Line Editor::MaxScrollPos() const {
@ -325,9 +325,8 @@ Sci::Line Editor::MaxScrollPos() const {
}
if (retVal < 0) {
return 0;
} else {
return retVal;
}
return retVal;
}
SelectionPosition Editor::ClampPositionIntoDocument(SelectionPosition sp) const {
@ -626,7 +625,7 @@ void Editor::InvalidateWholeSelection() {
/* For Line selection - the anchor and caret are always
at the beginning and end of the region lines. */
SelectionRange Editor::LineSelectionRange(SelectionPosition currentPos_, SelectionPosition anchor_) const {
SelectionRange Editor::LineSelectionRange(SelectionPosition currentPos_, SelectionPosition anchor_) const noexcept {
if (currentPos_ > anchor_) {
anchor_ = SelectionPosition(pdoc->LineStartPosition(anchor_.Position()));
currentPos_ = SelectionPosition(pdoc->LineEndPosition(currentPos_.Position()));
@ -743,9 +742,9 @@ void Editor::MultipleSelectAdd(AddNumber addNumber) {
// Common case is that the selection is completely within the target but
// may also have overlap at start or end.
if (rangeMainSelection.end < rangeTarget.end)
searchRanges.push_back(Range(rangeMainSelection.end, rangeTarget.end));
searchRanges.emplace_back(rangeMainSelection.end, rangeTarget.end);
if (rangeTarget.start < rangeMainSelection.start)
searchRanges.push_back(Range(rangeTarget.start, rangeMainSelection.start));
searchRanges.emplace_back(rangeTarget.start, rangeMainSelection.start);
} else {
// No overlap
searchRanges.push_back(rangeTarget);
@ -903,18 +902,17 @@ SelectionPosition Editor::MovePositionSoVisible(SelectionPosition pos, int moveD
const Sci::Line lineDoc = pdoc->SciLineFromPosition(pos.Position());
if (pcs->GetVisible(lineDoc)) {
return pos;
}
Sci::Line lineDisplay = pcs->DisplayFromDoc(lineDoc);
if (moveDir > 0) {
// lineDisplay is already line before fold as lines in fold use display line of line after fold
lineDisplay = std::clamp<Sci::Line>(lineDisplay, 0, pcs->LinesDisplayed());
return SelectionPosition(
pdoc->LineStart(pcs->DocFromDisplay(lineDisplay)));
} else {
Sci::Line lineDisplay = pcs->DisplayFromDoc(lineDoc);
if (moveDir > 0) {
// lineDisplay is already line before fold as lines in fold use display line of line after fold
lineDisplay = std::clamp<Sci::Line>(lineDisplay, 0, pcs->LinesDisplayed());
return SelectionPosition(
pdoc->LineStart(pcs->DocFromDisplay(lineDisplay)));
} else {
lineDisplay = std::clamp<Sci::Line>(lineDisplay - 1, 0, pcs->LinesDisplayed());
return SelectionPosition(
pdoc->LineEnd(pcs->DocFromDisplay(lineDisplay)));
}
lineDisplay = std::clamp<Sci::Line>(lineDisplay - 1, 0, pcs->LinesDisplayed());
return SelectionPosition(
pdoc->LineEnd(pcs->DocFromDisplay(lineDisplay)));
}
}
@ -1113,9 +1111,9 @@ void Editor::MoveCaretInsideView(bool ensureVisible) {
false, false, UserVirtualSpace()),
Selection::SelTypes::none, ensureVisible);
} else if ((pt.y + vs.lineHeight - 1) > rcClient.bottom) {
const ptrdiff_t yOfLastLineFullyDisplayed = static_cast<ptrdiff_t>(rcClient.top) + (LinesOnScreen() - 1) * vs.lineHeight;
const ptrdiff_t yOfLastLineFullyDisplayed = static_cast<ptrdiff_t>(rcClient.top) + ((LinesOnScreen() - 1) * vs.lineHeight);
MovePositionTo(SPositionFromLocation(
Point::FromInts(lastXChosen - xOffset, static_cast<int>(rcClient.top + yOfLastLineFullyDisplayed)),
Point::FromInts(lastXChosen - xOffset, static_cast<int>(rcClient.top + static_cast<XYPOSITION>(yOfLastLineFullyDisplayed))),
false, false, UserVirtualSpace()),
Selection::SelTypes::none, ensureVisible);
}
@ -1543,7 +1541,7 @@ bool Editor::WrapBlock(Surface *surface, Sci::Line lineToWrap, Sci::Line lineToW
std::vector<int> linesAfterWrap(linesBeingWrapped);
size_t threads = std::min<size_t>({ linesBeingWrapped, view.maxLayoutThreads });
size_t threads = std::min<size_t>(linesBeingWrapped, view.maxLayoutThreads);
if (!surface->SupportsFeature(Supports::ThreadSafeMeasureWidths)) {
threads = 1;
}
@ -1607,7 +1605,7 @@ bool Editor::WrapBlock(Surface *surface, Sci::Line lineToWrap, Sci::Line lineToW
// Multiply duration by number of threads to produce (near) equivalence to duration if single threaded
const double durationShortLines = epWrapping.Duration(true);
const double durationShortLinesThreads = durationShortLines * threads;
const double durationShortLinesThreads = durationShortLines * static_cast<double>(threads);
// Wrap all the long lines in the main thread.
// LayoutLine may then multi-thread over segments in each line.
@ -1683,8 +1681,15 @@ bool Editor::WrapLines(WrapScope ws) {
// Decide where to start wrapping
Sci::Line lineToWrap = wrapPending.start;
Sci::Line lineToWrapEnd = std::min(wrapPending.end, pdoc->LinesTotal());
const Sci::Line lineDocTop = pcs->DocFromDisplay(topLine);
const Sci::Line subLineTop = topLine - pcs->DisplayFromDoc(lineDocTop);
LineDocSub lineScrollTo;
if (scrollToAfterWrap) {
lineScrollTo = scrollToAfterWrap.value();
} else {
const Sci::Line subLineTop = topLine - pcs->DisplayFromDoc(lineDocTop);
lineScrollTo = { lineDocTop, subLineTop };
}
if (ws == WrapScope::wsVisible) {
lineToWrap = std::clamp(lineDocTop-5, wrapPending.start, pdoc->LinesTotal());
// Priority wrap to just after visible area.
@ -1735,21 +1740,23 @@ bool Editor::WrapLines(WrapScope ws) {
wrapOccurred = WrapBlock(surface, lineToWrap, lineToWrapEnd);
goodTopLine = pcs->DisplayFromDoc(lineDocTop) + std::min(
subLineTop, static_cast<Sci::Line>(pcs->GetHeight(lineDocTop)-1));
goodTopLine = pcs->DisplayFromDocSub(lineScrollTo.lineDoc, lineScrollTo.subLine);
}
}
// If wrapping is done, bring it to resting position
if (wrapPending.start >= lineEndNeedWrap) {
wrapPending.Reset();
scrollToAfterWrap.reset();
}
}
if (wrapOccurred) {
insideWrapScroll = true;
SetScrollBars();
SetTopLine(std::clamp<Sci::Line>(goodTopLine, 0, MaxScrollPos()));
SetVerticalScrollPos();
insideWrapScroll = false;
}
return wrapOccurred;
@ -1850,15 +1857,11 @@ void Editor::PaintSelMargin(Surface *surfaceWindow, const PRectangle &rc) {
void Editor::RefreshPixMaps(Surface *surfaceWindow) {
view.RefreshPixMaps(surfaceWindow, vs);
marginView.RefreshPixMaps(surfaceWindow, vs);
if (view.bufferedDraw) {
if (view.bufferedDraw && !(view.pixmapLine && marginView.pixmapSelMargin)) {
const PRectangle rcClient = GetClientRectangle();
if (!view.pixmapLine) {
view.pixmapLine = surfaceWindow->AllocatePixMap(static_cast<int>(rcClient.Width()), vs.lineHeight);
}
if (!marginView.pixmapSelMargin) {
marginView.pixmapSelMargin = surfaceWindow->AllocatePixMap(vs.fixedColumnWidth,
static_cast<int>(rcClient.Height()));
}
view.pixmapLine = surfaceWindow->AllocatePixMap(static_cast<int>(rcClient.Width()), vs.lineHeight);
marginView.pixmapSelMargin = surfaceWindow->AllocatePixMap(vs.fixedColumnWidth,
static_cast<int>(rcClient.Height()));
}
}
@ -1872,7 +1875,6 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
RefreshStyleData();
if (paintState == PaintState::abandoned)
return; // Scroll bars may have changed so need redraw
RefreshPixMaps(surfaceWindow);
paintAbandonedByStyling = false;
@ -1884,7 +1886,6 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
if (NotifyUpdateUI()) {
RefreshStyleData();
RefreshPixMaps(surfaceWindow);
}
// Wrap the visible lines if needed.
@ -1894,9 +1895,10 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
if (AbandonPaint()) {
return;
}
RefreshPixMaps(surfaceWindow); // In case pixmaps invalidated by scrollbar change
}
RefreshPixMaps(surfaceWindow);
if (!marginView.pixmapSelPattern->Initialised()) {
// When Direct2D is used, pixmap creation may fail with D2DERR_RECREATE_TARGET so
// abandon this paint to avoid further failures.
@ -1990,8 +1992,13 @@ long Editor::TextWidth(uptr_t style, const char *text) {
AutoSurface surface(this);
if (surface) {
return std::lround(surface->WidthText(vs.styles[style].font.get(), text));
} else {
return 1;
}
return 1;
}
void Editor::SetVerticalScrollPos() {
if (!insideWrapScroll) {
scrollToAfterWrap.reset();
}
}
@ -2047,11 +2054,10 @@ Sci::Position Editor::RealizeVirtualSpace(Sci::Position position, Sci::Position
const Sci::Position indent = pdoc->GetLineIndentPosition(line);
if (indent == position) {
return pdoc->SetLineIndentation(line, pdoc->GetLineIndentation(line) + virtualSpace);
} else {
const std::string spaceText(virtualSpace, ' ');
const Sci::Position lengthInserted = pdoc->InsertString(position, spaceText);
position += lengthInserted;
}
const std::string spaceText(virtualSpace, ' ');
const Sci::Position lengthInserted = pdoc->InsertString(position, spaceText);
position += lengthInserted;
}
return position;
}
@ -2409,12 +2415,14 @@ void Editor::SelectAll() {
void Editor::RestoreSelection(Sci::Position newPos, UndoRedo history) {
EnsureModelState();
if ((undoSelectionHistoryOption == UndoSelectionHistoryOption::Enabled) && modelState) {
if (FlagSet(undoSelectionHistoryOption, UndoSelectionHistoryOption::Enabled) && modelState) {
// Undo wants the element after the current as it just undid it
const int index = pdoc->UndoCurrent() + (history == UndoRedo::undo ? 1 : 0);
const SelectionWithScroll selAndLine = modelState->SelectionFromStack(index, history);
if (!selAndLine.selection.empty()) {
ScrollTo(selAndLine.topLine);
if (FlagSet(undoSelectionHistoryOption, UndoSelectionHistoryOption::Scroll)) {
ScrollTo(selAndLine.topLine);
}
sel = Selection(selAndLine.selection);
if (sel.IsRectangular()) {
const size_t mainForRectangular = sel.Main();
@ -2654,9 +2662,8 @@ bool Editor::NotifyMarginClick(Point pt, KeyMod modifiers) {
scn.margin = marginClicked;
NotifyParent(scn);
return true;
} else {
return false;
}
return false;
}
bool Editor::NotifyMarginRightClick(Point pt, KeyMod modifiers) {
@ -2670,9 +2677,8 @@ bool Editor::NotifyMarginRightClick(Point pt, KeyMod modifiers) {
scn.margin = marginRightClicked;
NotifyParent(scn);
return true;
} else {
return false;
}
return false;
}
void Editor::NotifyNeedShown(Sci::Position pos, Sci::Position len) {
@ -2746,12 +2752,10 @@ constexpr Sci::Position MovePositionForDeletion(Sci::Position position, Sci::Pos
const Sci::Position endDeletion = startDeletion + length;
if (position > endDeletion) {
return position - length;
} else {
return startDeletion;
}
} else {
return position;
return startDeletion;
}
return position;
}
}
@ -2799,7 +2803,7 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) {
view.llc.Invalidate(LineLayout::ValidLevel::checkTextAndStyle);
}
} else {
if ((undoSelectionHistoryOption == UndoSelectionHistoryOption::Enabled) &&
if (FlagSet(undoSelectionHistoryOption, UndoSelectionHistoryOption::Enabled) &&
FlagSet(mh.modificationType, ModificationFlags::User)) {
if (FlagSet(mh.modificationType, ModificationFlags::BeforeInsert | ModificationFlags::BeforeDelete)) {
RememberSelectionForUndo(pdoc->UndoCurrent());
@ -3366,7 +3370,7 @@ SelectionPosition Editor::PositionUpOrDown(SelectionPosition spStart, int direct
// There is an equivalent case when moving down which skips
// over a line.
Point ptNew = LocationFromPosition(posNew.Position());
while ((posNew.Position() > spStart.Position()) && (ptNew.y > newY)) {
while ((posNew.Position() > spStart.Position()) && (ptNew.y > static_cast<XYPOSITION>(newY))) {
posNew.Add(-1);
posNew.SetVirtualSpace(0);
ptNew = LocationFromPosition(posNew.Position());
@ -3452,9 +3456,8 @@ Sci::Position Editor::StartEndDisplayLine(Sci::Position pos, bool start) {
const Sci::Position posRet = view.StartEndDisplayLine(surface, *this, pos, start, vs);
if (posRet == Sci::invalidPosition) {
return pos;
} else {
return posRet;
}
return posRet;
}
namespace {
@ -3564,19 +3567,19 @@ Sci::Position Editor::HomeWrapPosition(Sci::Position position) {
Sci::Position Editor::VCHomeDisplayPosition(Sci::Position position) {
const Sci::Position homePos = pdoc->VCHomePosition(position);
const Sci::Position viewLineStart = StartEndDisplayLine(position, true);
if (viewLineStart > homePos)
if (viewLineStart > homePos) {
return viewLineStart;
else
return homePos;
}
return homePos;
}
Sci::Position Editor::VCHomeWrapPosition(Sci::Position position) {
const Sci::Position homePos = pdoc->VCHomePosition(position);
const Sci::Position viewLineStart = StartEndDisplayLine(position, true);
if ((viewLineStart < position) && (viewLineStart > homePos))
if ((viewLineStart < position) && (viewLineStart > homePos)) {
return viewLineStart;
else
return homePos;
}
return homePos;
}
Sci::Position Editor::LineEndWrapPosition(Sci::Position position) {
@ -3585,8 +3588,7 @@ Sci::Position Editor::LineEndWrapPosition(Sci::Position position) {
if (endPos > realEndPos // if moved past visible EOLs
|| position >= endPos) // if at end of display line already
return realEndPos;
else
return endPos;
return endPos;
}
SelectionPosition Editor::PositionMove(Message iMessage, SelectionPosition spCaret) {
@ -4144,11 +4146,10 @@ int Editor::KeyDownWithModifiers(Keys key, KeyMod modifiers, bool *consumed) {
if (consumed)
*consumed = true;
return static_cast<int>(WndProc(msg, 0, 0));
} else {
if (consumed)
*consumed = false;
return KeyDefault(key, modifiers);
}
if (consumed)
*consumed = false;
return KeyDefault(key, modifiers);
}
void Editor::Indent(bool forwards, bool lineIndent) {
@ -4175,7 +4176,7 @@ void Editor::Indent(bool forwards, bool lineIndent) {
sel.Range(r) = SelectionRange(caretPosition + lengthInserted);
} else {
int numSpaces = (pdoc->tabInChars) -
(pdoc->GetColumn(caretPosition) % (pdoc->tabInChars));
static_cast<int>((pdoc->GetColumn(caretPosition) % (pdoc->tabInChars)));
if (numSpaces < 1)
numSpaces = pdoc->tabInChars;
const std::string spaceText(numSpaces, ' ');
@ -4426,7 +4427,7 @@ std::string Editor::RangeText(Sci::Position start, Sci::Position end) const {
pdoc->GetCharRange(ret.data(), start, len);
return ret;
}
return std::string();
return {};
}
bool Editor::CopyLineRange(SelectionText *ss, bool allowProtected) {
@ -4440,9 +4441,8 @@ bool Editor::CopyLineRange(SelectionText *ss, bool allowProtected) {
ss->Copy(text, pdoc->dbcsCodePage,
vs.styles[StyleDefault].characterSet, false, true);
return true;
} else {
return false;
}
return false;
}
void Editor::CopySelectionRange(SelectionText *ss, bool allowLineCopy) {
@ -4629,7 +4629,7 @@ bool Editor::PointInSelection(Point pt) {
}
ptrdiff_t Editor::SelectionFromPoint(Point pt) {
// Prioritize checking inside non-empty selections since each character will be inside only 1
// Prioritize checking inside non-empty selections since each character will be inside only 1
const SelectionPosition posChar = SPositionFromLocation(pt, true, true);
for (size_t r = 0; r < sel.Count(); r++) {
if (sel.Range(r).ContainsCharacter(posChar)) {
@ -4659,9 +4659,8 @@ bool Editor::PointInSelMargin(Point pt) const {
const Point ptOrigin = GetVisibleOriginInMain();
rcSelMargin.Move(0, -ptOrigin.y);
return rcSelMargin.ContainsWholePixel(pt);
} else {
return false;
}
return false;
}
Window::Cursor Editor::GetMarginCursor(Point pt) const noexcept {
@ -4911,10 +4910,9 @@ void Editor::ButtonDownWithModifiers(Point pt, unsigned int curTime, KeyMod modi
DropSelection(selectionPart);
// Completed: don't want any more processing of this click
return;
} else {
// Switch to just the click position
SetSelection(newPos, newPos);
}
// Switch to just the click position
SetSelection(newPos, newPos);
}
if (!sel.Range(selectionPart).Empty()) {
inDragDrop = DragDrop::initial;
@ -5348,10 +5346,10 @@ Sci::Position Editor::PositionAfterArea(PRectangle rcArea) const {
// This often means that the line after a modification is restyled which helps
// detect multiline comment additions and heals single line comments
const Sci::Line lineAfter = TopLineOfMain() + static_cast<Sci::Line>(rcArea.bottom - 1) / vs.lineHeight + 1;
if (lineAfter < pcs->LinesDisplayed())
if (lineAfter < pcs->LinesDisplayed()) {
return pdoc->LineStart(pcs->DocFromDisplay(lineAfter) + 1);
else
return pdoc->Length();
}
return pdoc->Length();
}
// Style to a position within the view. If this causes a change at end of last line then
@ -5454,9 +5452,8 @@ int Editor::SupportsFeature(Supports feature) {
bool Editor::PaintContains(PRectangle rc) {
if (rc.Empty()) {
return true;
} else {
return rcPaint.Contains(rc);
}
return rcPaint.Contains(rc);
}
bool Editor::PaintContainsMargin() {
@ -5560,6 +5557,8 @@ void Editor::SetDocPointer(Document *document) {
SetRepresentations();
scrollToAfterWrap.reset();
// Reset the contraction state to fully shown.
pcs->Clear();
pcs->InsertLines(0, pdoc->LinesTotal() - 1);
@ -5699,7 +5698,7 @@ void Editor::FoldExpand(Sci::Line line, FoldAction action, FoldLevel level) {
Redraw();
}
Sci::Line Editor::ContractedFoldNext(Sci::Line lineStart) const {
Sci::Line Editor::ContractedFoldNext(Sci::Line lineStart) const noexcept {
for (Sci::Line line = lineStart; line<pdoc->LinesTotal();) {
if (!pcs->GetExpanded(line) && LevelIsHeader(pdoc->GetFoldLevel(line)))
return line;
@ -5950,8 +5949,7 @@ bool Editor::IsUnicodeMode() const noexcept {
int Editor::CodePage() const noexcept {
if (pdoc)
return pdoc->dbcsCodePage;
else
return 0;
return 0;
}
std::unique_ptr<Surface> Editor::CreateMeasurementSurface() const {
@ -5981,9 +5979,8 @@ Sci::Line Editor::WrapCount(Sci::Line line) {
if (surface && ll) {
view.LayoutLine(*this, surface, vs, ll.get(), wrapWidth);
return ll->lines;
} else {
return 1;
}
return 1;
}
void Editor::AddStyledText(const char *buffer, Sci::Position appendLength) {
@ -6571,6 +6568,15 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
HorizontalScrollTo(xOffset + static_cast<int>(static_cast<int>(wParam) * vs.spaceWidth));
return 1;
case Message::ScrollVertical:
if (Wrapping()) {
scrollToAfterWrap = { LineFromUPtr(wParam), lParam };
} else {
scrollToAfterWrap.reset();
}
ScrollTo(pcs->DisplayFromDocSub(LineFromUPtr(wParam), lParam));
break;
case Message::SetXOffset:
xOffset = static_cast<int>(wParam);
ContainerNeedsUpdate(Update::HScroll);
@ -7487,7 +7493,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
break;
case Message::MarkerSetStrokeWidth:
if (wParam <= MarkerMax)
vs.markers[wParam].strokeWidth = lParam / 100.0f;
vs.markers[wParam].strokeWidth = static_cast<XYPOSITION>(lParam) / 100.0f;
InvalidateStyleData();
RedrawSelMargin();
break;
@ -8181,7 +8187,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::IndicSetStrokeWidth:
if (wParam <= IndicatorMax && lParam >= 0 && lParam <= 1000) {
vs.indicators[wParam].strokeWidth = lParam / 100.0f;
vs.indicators[wParam].strokeWidth = static_cast<XYPOSITION>(lParam) / 100.0;
InvalidateStyleRedraw();
}
break;
@ -8452,7 +8458,8 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
doc->Allocate(PositionFromUPtr(wParam));
doc->SetUndoCollection(false);
pcs = ContractionStateCreate(pdoc->IsLarge());
return reinterpret_cast<sptr_t>(static_cast<ILoader *>(doc));
ILoader *loader = doc;
return reinterpret_cast<sptr_t>(loader);
}
case Message::SetModEventMask:

View File

@ -283,6 +283,12 @@ protected: // ScintillaBase subclass needs access to much of Editor
// Wrapping support
WrapPending wrapPending;
ActionDuration durationWrapOneByte;
bool insideWrapScroll;
struct LineDocSub {
Scintilla::Line lineDoc = 0;
Scintilla::Line subLine = 0;
};
std::optional<LineDocSub> scrollToAfterWrap;
bool convertPastes;
@ -346,7 +352,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
void ThinRectangularRange();
void InvalidateSelection(SelectionRange newMain, bool invalidateWholeSelection=false);
void InvalidateWholeSelection();
SelectionRange LineSelectionRange(SelectionPosition currentPos_, SelectionPosition anchor_) const;
SelectionRange LineSelectionRange(SelectionPosition currentPos_, SelectionPosition anchor_) const noexcept;
void SetSelection(SelectionPosition currentPos_, SelectionPosition anchor_);
void SetSelection(Sci::Position currentPos_, Sci::Position anchor_);
void SetSelection(SelectionPosition currentPos_);
@ -417,7 +423,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
Sci::Position FormatRange(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam);
long TextWidth(Scintilla::uptr_t style, const char *text);
virtual void SetVerticalScrollPos() = 0;
virtual void SetVerticalScrollPos();
virtual void SetHorizontalScrollPos() = 0;
virtual bool ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) = 0;
virtual void ReconfigureScrollBars();
@ -593,7 +599,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
void SetFoldExpanded(Sci::Line lineDoc, bool expanded);
void FoldLine(Sci::Line line, Scintilla::FoldAction action);
void FoldExpand(Sci::Line line, Scintilla::FoldAction action, Scintilla::FoldLevel level);
Sci::Line ContractedFoldNext(Sci::Line lineStart) const;
Sci::Line ContractedFoldNext(Sci::Line lineStart) const noexcept;
void EnsureLineVisible(Sci::Line lineDoc, bool enforcePolicy);
void FoldChanged(Sci::Line line, Scintilla::FoldLevel levelNow, Scintilla::FoldLevel levelPrev);
void NeedShown(Sci::Position pos, Sci::Position len);

View File

@ -196,7 +196,7 @@ void LineMarker::DrawFoldingMark(Surface *surface, const PRectangle &rcWhole, Fo
// To centre +/-, odd strokeWidth -> odd symbol width, even -> even
const XYPOSITION widthSymbol =
((std::lround(minDimension * pixelDivisions) % 2) == (std::lround(widthStroke * pixelDivisions) % 2)) ?
minDimension : minDimension - 1.0f / pixelDivisions;
minDimension : minDimension - (1.0 / static_cast<XYPOSITION>(pixelDivisions));
const Point centre = PixelAlign(rcWhole.Centre(), pixelDivisions);
@ -464,11 +464,13 @@ void LineMarker::Draw(Surface *surface, const PRectangle &rcWhole, const Font *f
break;
case MarkerSymbol::DotDotDot: {
XYPOSITION right = static_cast<XYPOSITION>(centreX - 6);
// 3 2x2 dots with 3 pixels between, margin must be 12 wide to show all
constexpr XYPOSITION pitchDots = 5.0;
XYPOSITION xBlob = std::floor(centreX - (pitchDots + 1));
for (int b = 0; b < 3; b++) {
const PRectangle rcBlob(right, rc.bottom - 4, right + 2, rc.bottom - 2);
const PRectangle rcBlob(xBlob, rc.bottom - 4, xBlob + 2, rc.bottom - 2);
surface->FillRectangle(rcBlob, fore);
right += 5.0f;
xBlob += pitchDots;
}
}
break;
@ -516,26 +518,28 @@ void LineMarker::Draw(Surface *surface, const PRectangle &rcWhole, const Font *f
break;
case MarkerSymbol::Bar: {
// Hide cap by continuing a bit.
constexpr XYPOSITION continueLength = 5.0;
PRectangle rcBar = rcWhole;
const XYPOSITION widthBar = std::floor(rcWhole.Width() / 3.0);
const XYPOSITION widthBar = std::ceil(rcWhole.Width() / 3.0);
rcBar.left = centreX - std::floor(widthBar / 2.0);
rcBar.right = rcBar.left + widthBar;
surface->SetClip(rcWhole);
surface->SetClip(rcWhole); // Hide continued caps
switch (part) {
case LineMarker::FoldPart::headWithTail:
surface->RectangleDraw(rcBar, FillStroke(back, fore, strokeWidth));
break;
case LineMarker::FoldPart::head:
rcBar.bottom += 5;
rcBar.bottom += continueLength;
surface->RectangleDraw(rcBar, FillStroke(back, fore, strokeWidth));
break;
case LineMarker::FoldPart::tail:
rcBar.top -= 5;
rcBar.top -= continueLength;
surface->RectangleDraw(rcBar, FillStroke(back, fore, strokeWidth));
break;
case LineMarker::FoldPart::body:
rcBar.top -= 5;
rcBar.bottom += 5;
rcBar.top -= continueLength;
rcBar.bottom += continueLength;
surface->RectangleDraw(rcBar, FillStroke(back, fore, strokeWidth));
break;
default:

View File

@ -124,7 +124,7 @@ void MarginView::DropGraphics() noexcept {
}
void MarginView::RefreshPixMaps(Surface *surfaceWindow, const ViewStyle &vsDraw) {
if (!pixmapSelPattern) {
if (!(pixmapSelPattern && pixmapSelPatternOffset1)) {
constexpr int patternSize = 8;
pixmapSelPattern = surfaceWindow->AllocatePixMap(patternSize, patternSize);
pixmapSelPatternOffset1 = surfaceWindow->AllocatePixMap(patternSize, patternSize);
@ -278,7 +278,7 @@ void MarginView::PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcOn
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;
XYPOSITION yposScreen = static_cast<XYPOSITION>(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.

Some files were not shown because too many files have changed in this diff Show More