Update to scintilla 5.3.1 and lexilla 5.2.0

Close #12327
This commit is contained in:
Christian Grasser 2022-10-12 20:45:40 +02:00 committed by Don Ho
parent 22489a1311
commit b502266e8d
78 changed files with 1152 additions and 290 deletions

View File

@ -43,6 +43,7 @@
**.pl text **.pl text
**.p6 text **.p6 text
**.ps1 text **.ps1 text
**.r text
**.rb text **.rb text
**.rs text **.rs text
**.sql text **.sql text

View File

@ -17,10 +17,12 @@ noExplicitConstructor
// code legibility. // code legibility.
passedByValue passedByValue
// This could be fixed but it should be rewritten to use string_view which doesn't have resize
uselessCallsSubstr:lexilla/lexers/LexCPP.cxx
// Suppress most lexer warnings since the lexers are maintained by others // Suppress most lexer warnings since the lexers are maintained by others
redundantCondition:lexilla/lexers/LexA68k.cxx redundantCondition:lexilla/lexers/LexA68k.cxx
constParameter:lexilla/lexers/LexAbaqus.cxx constParameter:lexilla/lexers/LexAbaqus.cxx
unusedStructMember:lexilla/lexers/LexAsciidoc.cxx
constParameterCallback:lexilla/lexers/LexAsn1.cxx constParameterCallback:lexilla/lexers/LexAsn1.cxx
knownConditionTrueFalse:lexilla/lexers/LexAU3.cxx knownConditionTrueFalse:lexilla/lexers/LexAU3.cxx
shadowVariable:lexilla/lexers/LexAU3.cxx shadowVariable:lexilla/lexers/LexAU3.cxx
@ -43,6 +45,7 @@ knownConditionTrueFalse:lexilla/lexers/LexEiffel.cxx
variableScope:lexilla/lexers/LexErlang.cxx variableScope:lexilla/lexers/LexErlang.cxx
knownConditionTrueFalse:lexilla/lexers/LexEScript.cxx knownConditionTrueFalse:lexilla/lexers/LexEScript.cxx
constParameter:lexilla/lexers/LexFortran.cxx constParameter:lexilla/lexers/LexFortran.cxx
redundantContinue:lexilla/lexers/LexFortran.cxx
redundantCondition:lexilla/lexers/LexFSharp.cxx redundantCondition:lexilla/lexers/LexFSharp.cxx
knownConditionTrueFalse:lexilla/lexers/LexFSharp.cxx knownConditionTrueFalse:lexilla/lexers/LexFSharp.cxx
constParameter:lexilla/lexers/LexGDScript.cxx constParameter:lexilla/lexers/LexGDScript.cxx
@ -102,12 +105,16 @@ knownConditionTrueFalse:lexilla/lexers/LexTxt2tags.cxx
knownConditionTrueFalse:lexilla/lexers/LexVB.cxx knownConditionTrueFalse:lexilla/lexers/LexVB.cxx
constParameter:lexilla/lexers/LexVerilog.cxx constParameter:lexilla/lexers/LexVerilog.cxx
variableScope:lexilla/lexers/LexVerilog.cxx variableScope:lexilla/lexers/LexVerilog.cxx
badBitmaskCheck:lexilla/lexers/LexVerilog.cxx
uselessCallsSubstr:lexilla/lexers/LexVerilog.cxx
constParameter:lexilla/lexers/LexVHDL.cxx constParameter:lexilla/lexers/LexVHDL.cxx
shadowVariable:lexilla/lexers/LexVHDL.cxx shadowVariable:lexilla/lexers/LexVHDL.cxx
unreadVariable:lexilla/lexers/LexVHDL.cxx unreadVariable:lexilla/lexers/LexVHDL.cxx
variableScope:lexilla/lexers/LexVHDL.cxx variableScope:lexilla/lexers/LexVHDL.cxx
unreadVariable:lexilla/lexers/LexVisualProlog.cxx unreadVariable:lexilla/lexers/LexVisualProlog.cxx
unreadVariable:lexilla/lexers/LexX12.cxx unreadVariable:lexilla/lexers/LexX12.cxx
constVariable:lexilla/lexers/LexX12.cxx
uselessCallsSubstr:lexilla/lexers/LexX12.cxx
constParameter:lexilla/lexers/LexYAML.cxx constParameter:lexilla/lexers/LexYAML.cxx
knownConditionTrueFalse:lexilla/lexers/LexYAML.cxx knownConditionTrueFalse:lexilla/lexers/LexYAML.cxx
@ -136,7 +143,6 @@ constVariable:lexilla/lexers/LexModula.cxx
constVariable:lexilla/lexers/LexOpal.cxx constVariable:lexilla/lexers/LexOpal.cxx
constVariable:lexilla/lexers/LexPS.cxx constVariable:lexilla/lexers/LexPS.cxx
constVariable:lexilla/lexers/LexPascal.cxx constVariable:lexilla/lexers/LexPascal.cxx
constVariable:lexilla/lexers/LexR.cxx
constVariable:lexilla/lexers/LexRebol.cxx constVariable:lexilla/lexers/LexRebol.cxx
constVariable:lexilla/lexers/LexRuby.cxx constVariable:lexilla/lexers/LexRuby.cxx
constVariable:lexilla/lexers/LexSorcus.cxx constVariable:lexilla/lexers/LexSorcus.cxx

View File

@ -9,7 +9,7 @@
<meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" /> <meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
<meta name="Description" <meta name="Description"
content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." /> content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
<meta name="Date.Modified" content="20220827" /> <meta name="Date.Modified" content="20221012" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css"> <style type="text/css">
.logo { .logo {
@ -61,8 +61,8 @@
<font color="#FFCC99" size="4"> A library of language lexers for use with Scintilla</font> <font color="#FFCC99" size="4"> A library of language lexers for use with Scintilla</font>
</td> </td>
<td width="40%" align="right"> <td width="40%" align="right">
<font color="#FFCC99" size="3">Release version 5.1.9<br /> <font color="#FFCC99" size="3">Release version 5.2.0<br />
Site last modified August 27 2022</font> Site last modified October 12 2022</font>
</td> </td>
<td width="20%"> <td width="20%">
&nbsp; &nbsp;
@ -77,12 +77,12 @@
</tr> </tr>
</table> </table>
<ul id="versionlist"> <ul id="versionlist">
<li>Version 5.2.0 improves PowerShell and R.</li>
<li>Version 5.1.9 improves Julia and Properties.</li> <li>Version 5.1.9 improves Julia and Properties.</li>
<li>Version 5.1.8 improves F#, MS SQL, PowerShell, and Visual Prolog.</li> <li>Version 5.1.8 improves F#, MS SQL, PowerShell, and Visual Prolog.</li>
<li>Version 5.1.7 improves CMake, HTML, Matlab, Raku, Ruby, and VHDL.</li> <li>Version 5.1.7 improves CMake, HTML, Matlab, Raku, Ruby, and VHDL.</li>
<li>Version 5.1.6 improves Markdown and Ruby.</li> <li>Version 5.1.6 improves Markdown and Ruby.</li>
<li>Version 5.1.5 improves Bash, Batch, F#, HTML, Inno Setup, and Python.</li> <li>Version 5.1.5 improves Bash, Batch, F#, HTML, Inno Setup, and Python.</li>
<li>Version 5.1.4 adds lexers for AsciiDoc and GDScript.</li>
</ul> </ul>
<ul id="menu"> <ul id="menu">
<li id="remote1"><a href="https://www.scintilla.org/SciTEImage.html">Screenshot</a></li> <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"> <table bgcolor="#CCCCCC" width="100%" cellspacing="0" cellpadding="8" border="0">
<tr> <tr>
<td> <td>
<font size="4"> <a href="https://www.scintilla.org/lexilla519.zip"> <font size="4"> <a href="https://www.scintilla.org/lexilla520.zip">
Windows</a>&nbsp;&nbsp; Windows</a>&nbsp;&nbsp;
<a href="https://www.scintilla.org/lexilla519.tgz"> <a href="https://www.scintilla.org/lexilla520.tgz">
GTK/Linux</a>&nbsp;&nbsp; GTK/Linux</a>&nbsp;&nbsp;
</font> </font>
</td> </td>
@ -42,7 +42,7 @@
containing very few restrictions. containing very few restrictions.
</p> </p>
<h3> <h3>
Release 5.1.9 Release 5.2.0
</h3> </h3>
<h4> <h4>
Source Code Source Code
@ -50,8 +50,8 @@
The source code package contains all of the source code for Lexilla but no binary The source code package contains all of the source code for Lexilla but no binary
executable code and is available in executable code and is available in
<ul> <ul>
<li><a href="https://www.scintilla.org/lexilla519.zip">zip format</a> (1.1M) commonly used on Windows</li> <li><a href="https://www.scintilla.org/lexilla520.zip">zip format</a> (1.2M) commonly used on Windows</li>
<li><a href="https://www.scintilla.org/lexilla519.tgz">tgz format</a> (0.9M) commonly used on Linux and compatible operating systems</li> <li><a href="https://www.scintilla.org/lexilla520.tgz">tgz format</a> (0.9M) commonly used on Linux and compatible operating systems</li>
</ul> </ul>
Instructions for building on both Windows and Linux are included in the readme file. Instructions for building on both Windows and Linux are included in the readme file.
<h4> <h4>

View File

@ -585,6 +585,43 @@
</tr> </tr>
</table> </table>
<h2>Releases</h2> <h2>Releases</h2>
<h3>
<a href="https://www.scintilla.org/lexilla520.zip">Release 5.2.0</a>
</h3>
<ul>
<li>
Released 12 October 2022.
</li>
<li>
PowerShell: End comment before \r carriage return so \r and \n in same
SCE_POWERSHELL_DEFAULT style.
<a href="https://github.com/ScintillaOrg/lexilla/pull/99">Pull request #99</a>.
</li>
<li>
PowerShell: Fix character truncation bug that lead to 'ġ' styled as an operator since its low 8 bits
are equal to '!'.
</li>
<li>
R: Support hexadecimal, float exponent and number suffix.
<a href="https://github.com/ScintillaOrg/lexilla/issues/101">Issue #101</a>.
</li>
<li>
R: Highlight backticks.
<a href="https://github.com/ScintillaOrg/lexilla/pull/102">Pull request #102</a>.
</li>
<li>
R: Highlight raw strings.
<a href="https://github.com/ScintillaOrg/lexilla/issues/100">Issue #100</a>.
</li>
<li>
R: Optionally highlight escape sequences in strings.
<a href="https://github.com/ScintillaOrg/lexilla/issues/100">Issue #100</a>.
</li>
<li>
Fix early truncation from LexAccessor::GetRange and LexAccessor::GetRangeLowered.
<a href="https://github.com/ScintillaOrg/lexilla/issues/17">Issue #17</a>.
</li>
</ul>
<h3> <h3>
<a href="https://www.scintilla.org/lexilla519.zip">Release 5.1.9</a> <a href="https://www.scintilla.org/lexilla519.zip">Release 5.1.9</a>
</h3> </h3>

View File

@ -1569,6 +1569,10 @@ val SCE_R_OPERATOR=8
val SCE_R_IDENTIFIER=9 val SCE_R_IDENTIFIER=9
val SCE_R_INFIX=10 val SCE_R_INFIX=10
val SCE_R_INFIXEOL=11 val SCE_R_INFIXEOL=11
val SCE_R_BACKTICKS=12
val SCE_R_RAWSTRING=13
val SCE_R_RAWSTRING2=14
val SCE_R_ESCAPESEQUENCE=15
# Lexical state for SCLEX_MAGIK # Lexical state for SCLEX_MAGIK
lex MagikSF=SCLEX_MAGIK SCE_MAGIK_ lex MagikSF=SCLEX_MAGIK SCE_MAGIK_
val SCE_MAGIK_DEFAULT=0 val SCE_MAGIK_DEFAULT=0

View File

@ -1522,6 +1522,10 @@
#define SCE_R_IDENTIFIER 9 #define SCE_R_IDENTIFIER 9
#define SCE_R_INFIX 10 #define SCE_R_INFIX 10
#define SCE_R_INFIXEOL 11 #define SCE_R_INFIXEOL 11
#define SCE_R_BACKTICKS 12
#define SCE_R_RAWSTRING 13
#define SCE_R_RAWSTRING2 14
#define SCE_R_ESCAPESEQUENCE 15
#define SCE_MAGIK_DEFAULT 0 #define SCE_MAGIK_DEFAULT 0
#define SCE_MAGIK_COMMENT 1 #define SCE_MAGIK_COMMENT 1
#define SCE_MAGIK_HYPER_COMMENT 16 #define SCE_MAGIK_HYPER_COMMENT 16

View File

@ -169,7 +169,7 @@ class EscapeSequence {
int digitsLeft = 0; int digitsLeft = 0;
public: public:
EscapeSequence() = default; EscapeSequence() = default;
void resetEscapeState(int nextChar) { void resetEscapeState(int nextChar) noexcept {
digitsLeft = 0; digitsLeft = 0;
escapeSetValid = &setNoneNumeric; escapeSetValid = &setNoneNumeric;
if (nextChar == 'U') { if (nextChar == 'U') {
@ -186,7 +186,7 @@ public:
escapeSetValid = &setOctDigits; escapeSetValid = &setOctDigits;
} }
} }
bool atEscapeEnd(int currChar) const { bool atEscapeEnd(int currChar) const noexcept {
return (digitsLeft <= 0) || !escapeSetValid->Contains(currChar); return (digitsLeft <= 0) || !escapeSetValid->Contains(currChar);
} }
void consumeDigit() noexcept { void consumeDigit() noexcept {
@ -314,9 +314,8 @@ public:
LinePPState ForLine(Sci_Position line) const noexcept { LinePPState ForLine(Sci_Position line) const noexcept {
if ((line > 0) && (vlls.size() > static_cast<size_t>(line))) { if ((line > 0) && (vlls.size() > static_cast<size_t>(line))) {
return vlls[line]; return vlls[line];
} else {
return LinePPState();
} }
return {};
} }
void Add(Sci_Position line, LinePPState lls) { void Add(Sci_Position line, LinePPState lls) {
vlls.resize(line+1); vlls.resize(line+1);
@ -728,6 +727,8 @@ Sci_Position SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) {
case 5: case 5:
wordListN = &markerList; wordListN = &markerList;
break; break;
default:
break;
} }
Sci_Position firstModification = -1; Sci_Position firstModification = -1;
if (wordListN) { if (wordListN) {
@ -1427,7 +1428,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
if (options.updatePreprocessor && preproc.IsActive()) { if (options.updatePreprocessor && preproc.IsActive()) {
const std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, false); const std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, false);
Tokens tokens = Tokenize(restOfLine); Tokens tokens = Tokenize(restOfLine);
if (tokens.size() >= 1) { if (!tokens.empty()) {
const std::string key = tokens[0]; const std::string key = tokens[0];
preprocessorDefinitions.erase(key); preprocessorDefinitions.erase(key);
ppDefineHistory.push_back(PPDefinition(lineCurrent, key, "", true)); ppDefineHistory.push_back(PPDefinition(lineCurrent, key, "", true));
@ -1813,7 +1814,7 @@ bool LexerCPP::EvaluateExpression(const std::string &expr, const SymbolTable &pr
// "0" or "" -> false else true // "0" or "" -> false else true
const bool isFalse = tokens.empty() || const bool isFalse = tokens.empty() ||
((tokens.size() == 1) && ((tokens[0] == "") || tokens[0] == "0")); ((tokens.size() == 1) && (tokens[0].empty() || tokens[0] == "0"));
return !isFalse; return !isFalse;
} }

View File

@ -29,19 +29,19 @@
using namespace Lexilla; using namespace Lexilla;
// Extended to accept accented characters // Extended to accept accented characters
static inline bool IsAWordChar(int ch) { static inline bool IsAWordChar(int ch) noexcept {
return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_'; return ch >= 0x80 || isalnum(ch) || ch == '-' || ch == '_';
} }
static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
WordList *keywordlists[], Accessor &styler) { WordList *keywordlists[], Accessor &styler) {
WordList &keywords = *keywordlists[0]; const WordList &keywords = *keywordlists[0];
WordList &keywords2 = *keywordlists[1]; const WordList &keywords2 = *keywordlists[1];
WordList &keywords3 = *keywordlists[2]; const WordList &keywords3 = *keywordlists[2];
WordList &keywords4 = *keywordlists[3]; const WordList &keywords4 = *keywordlists[3];
WordList &keywords5 = *keywordlists[4]; const WordList &keywords5 = *keywordlists[4];
WordList &keywords6 = *keywordlists[5]; const WordList &keywords6 = *keywordlists[5];
styler.StartAt(startPos); styler.StartAt(startPos);
@ -50,7 +50,7 @@ static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length,
for (; sc.More(); sc.Forward()) { for (; sc.More(); sc.Forward()) {
if (sc.state == SCE_POWERSHELL_COMMENT) { if (sc.state == SCE_POWERSHELL_COMMENT) {
if (sc.atLineEnd) { if (sc.MatchLineEnd()) {
sc.SetState(SCE_POWERSHELL_DEFAULT); sc.SetState(SCE_POWERSHELL_DEFAULT);
} }
} else if (sc.state == SCE_POWERSHELL_COMMENTSTREAM) { } else if (sc.state == SCE_POWERSHELL_COMMENTSTREAM) {
@ -107,7 +107,7 @@ static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length,
sc.SetState(SCE_POWERSHELL_DEFAULT); sc.SetState(SCE_POWERSHELL_DEFAULT);
} }
} else if (sc.state == SCE_POWERSHELL_OPERATOR) { } else if (sc.state == SCE_POWERSHELL_OPERATOR) {
if (!isoperator(static_cast<char>(sc.ch))) { if (!isoperator(sc.ch)) {
sc.SetState(SCE_POWERSHELL_DEFAULT); sc.SetState(SCE_POWERSHELL_DEFAULT);
} }
} else if (sc.state == SCE_POWERSHELL_IDENTIFIER) { } else if (sc.state == SCE_POWERSHELL_IDENTIFIER) {
@ -148,7 +148,7 @@ static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length,
sc.SetState(SCE_POWERSHELL_VARIABLE); sc.SetState(SCE_POWERSHELL_VARIABLE);
} else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
sc.SetState(SCE_POWERSHELL_NUMBER); sc.SetState(SCE_POWERSHELL_NUMBER);
} else if (isoperator(static_cast<char>(sc.ch))) { } else if (isoperator(sc.ch)) {
sc.SetState(SCE_POWERSHELL_OPERATOR); sc.SetState(SCE_POWERSHELL_OPERATOR);
} else if (IsAWordChar(sc.ch)) { } else if (IsAWordChar(sc.ch)) {
sc.SetState(SCE_POWERSHELL_IDENTIFIER); sc.SetState(SCE_POWERSHELL_IDENTIFIER);
@ -165,10 +165,10 @@ static void ColourisePowerShellDoc(Sci_PositionU startPos, Sci_Position length,
// and to make it possible to fiddle the current level for "} else {". // and to make it possible to fiddle the current level for "} else {".
static void FoldPowerShellDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, static void FoldPowerShellDoc(Sci_PositionU startPos, Sci_Position length, int initStyle,
WordList *[], Accessor &styler) { WordList *[], Accessor &styler) {
bool foldComment = styler.GetPropertyInt("fold.comment") != 0; const bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; const bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
Sci_PositionU endPos = startPos + length; const Sci_PositionU endPos = startPos + length;
int visibleChars = 0; int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos); Sci_Position lineCurrent = styler.GetLine(startPos);
int levelCurrent = SC_FOLDLEVELBASE; int levelCurrent = SC_FOLDLEVELBASE;
@ -180,12 +180,12 @@ static void FoldPowerShellDoc(Sci_PositionU startPos, Sci_Position length, int i
int styleNext = styler.StyleAt(startPos); int styleNext = styler.StyleAt(startPos);
int style = initStyle; int style = initStyle;
for (Sci_PositionU i = startPos; i < endPos; i++) { for (Sci_PositionU i = startPos; i < endPos; i++) {
char ch = chNext; const char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1); chNext = styler.SafeGetCharAt(i + 1);
int stylePrev = style; const int stylePrev = style;
style = styleNext; style = styleNext;
styleNext = styler.StyleAt(i + 1); styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (style == SCE_POWERSHELL_OPERATOR) { if (style == SCE_POWERSHELL_OPERATOR) {
if (ch == '{') { if (ch == '{') {
// Measure the minimum before a '{' to allow // Measure the minimum before a '{' to allow

View File

@ -6,12 +6,8 @@
// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org> // Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed. // The License.txt file describes the conditions under which this software may be distributed.
#include <stdlib.h> #include <cassert>
#include <string.h> #include <cctype>
#include <stdio.h>
#include <stdarg.h>
#include <assert.h>
#include <ctype.h>
#include <string> #include <string>
#include <string_view> #include <string_view>
@ -29,17 +25,17 @@
using namespace Lexilla; using namespace Lexilla;
static inline bool IsAWordChar(const int ch) { namespace {
inline bool IsAWordChar(int ch) noexcept {
return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_'); return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
} }
static inline bool IsAWordStart(const int ch) { inline bool IsAWordStart(int ch) noexcept {
return (ch < 0x80) && (isalnum(ch) || ch == '_'); return (ch < 0x80) && (isalnum(ch) || ch == '_');
} }
static inline bool IsAnOperator(const int ch) { constexpr bool IsAnOperator(int ch) noexcept {
if (IsASCII(ch) && isalnum(ch))
return false;
// '.' left out as it is used to make up numbers // '.' left out as it is used to make up numbers
if (ch == '-' || ch == '+' || ch == '!' || ch == '~' || if (ch == '-' || ch == '+' || ch == '!' || ch == '~' ||
ch == '?' || ch == ':' || ch == '*' || ch == '/' || ch == '?' || ch == ':' || ch == '*' || ch == '/' ||
@ -51,36 +47,103 @@ static inline bool IsAnOperator(const int ch) {
return false; return false;
} }
static void ColouriseRDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[], constexpr bool IsOctalOrHex(int ch, bool hex) noexcept {
return IsAnOctalDigit(ch) || (hex && IsAHeXDigit(ch));
}
// https://search.r-project.org/R/refmans/base/html/Quotes.html
struct EscapeSequence {
int outerState = SCE_R_DEFAULT;
int digitsLeft = 0;
bool hex = false;
bool brace = false;
// highlight any character as escape sequence, unrecognized escape sequence is syntax error.
void resetEscapeState(int state, int chNext) noexcept {
outerState = state;
digitsLeft = 1;
hex = true;
brace = false;
if (chNext == 'x') {
digitsLeft = 3;
} else if (chNext == 'u') {
digitsLeft = 5;
} else if (chNext == 'U') {
digitsLeft = 9;
} else if (IsAnOctalDigit(chNext)) {
digitsLeft = 3;
hex = false;
}
}
bool atEscapeEnd(int ch) noexcept {
--digitsLeft;
return digitsLeft <= 0 || !IsOctalOrHex(ch, hex);
}
};
int CheckRawString(LexAccessor &styler, Sci_Position pos, int &dashCount) {
dashCount = 0;
while (true) {
const char ch = styler.SafeGetCharAt(pos++);
switch (ch) {
case '-':
++dashCount;
break;
case '(':
return ')';
case '[':
return ']';
case '{':
return '}';
default:
dashCount = 0;
return 0;
}
}
}
void ColouriseRDoc(Sci_PositionU startPos, Sci_Position length, int initStyle, WordList *keywordlists[],
Accessor &styler) { Accessor &styler) {
WordList &keywords = *keywordlists[0]; const WordList &keywords = *keywordlists[0];
WordList &keywords2 = *keywordlists[1]; const WordList &keywords2 = *keywordlists[1];
WordList &keywords3 = *keywordlists[2]; const WordList &keywords3 = *keywordlists[2];
// state for raw string
int matchingDelimiter = 0;
// Do not leak onto next line int dashCount = 0;
if (initStyle == SCE_R_INFIXEOL)
initStyle = SCE_R_DEFAULT;
// property lexer.r.escape.sequence
// Set to 1 to enable highlighting of escape sequences in strings.
const bool escapeSequence = styler.GetPropertyInt("lexer.r.escape.sequence", 0) != 0;
EscapeSequence escapeSeq;
StyleContext sc(startPos, length, initStyle, styler); StyleContext sc(startPos, length, initStyle, styler);
if (sc.currentLine > 0) {
const int lineState = styler.GetLineState(sc.currentLine - 1);
matchingDelimiter = lineState & 0xff;
dashCount = lineState >> 8;
}
for (; sc.More(); sc.Forward()) { for (; sc.More(); sc.Forward()) {
if (sc.atLineStart && (sc.state == SCE_R_STRING)) {
// Prevent SCE_R_STRINGEOL from leaking back to previous line
sc.SetState(SCE_R_STRING);
}
// Determine if the current state should terminate. // Determine if the current state should terminate.
if (sc.state == SCE_R_OPERATOR) { switch (sc.state) {
case SCE_R_OPERATOR:
sc.SetState(SCE_R_DEFAULT); sc.SetState(SCE_R_DEFAULT);
} else if (sc.state == SCE_R_NUMBER) { break;
if (!IsADigit(sc.ch) && !(sc.ch == '.' && IsADigit(sc.chNext))) {
case SCE_R_NUMBER:
// https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Literal-constants
if (AnyOf(sc.ch, 'e', 'E', 'p', 'P') && (IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-')) {
sc.Forward(); // exponent part
} else if (!(IsAHeXDigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)))) {
if (AnyOf(sc.ch, 'L', 'i')) {
sc.Forward(); // integer and complex qualifier
}
sc.SetState(SCE_R_DEFAULT); sc.SetState(SCE_R_DEFAULT);
} }
} else if (sc.state == SCE_R_IDENTIFIER) { break;
case SCE_R_IDENTIFIER:
if (!IsAWordChar(sc.ch)) { if (!IsAWordChar(sc.ch)) {
char s[100]; char s[100];
sc.GetCurrent(s, sizeof(s)); sc.GetCurrent(s, sizeof(s));
@ -93,53 +156,122 @@ static void ColouriseRDoc(Sci_PositionU startPos, Sci_Position length, int initS
} }
sc.SetState(SCE_R_DEFAULT); sc.SetState(SCE_R_DEFAULT);
} }
} else if (sc.state == SCE_R_COMMENT) { break;
if (sc.ch == '\r' || sc.ch == '\n') {
case SCE_R_COMMENT:
if (sc.MatchLineEnd()) {
sc.SetState(SCE_R_DEFAULT); sc.SetState(SCE_R_DEFAULT);
} }
} else if (sc.state == SCE_R_STRING) { break;
case SCE_R_STRING:
case SCE_R_STRING2:
case SCE_R_BACKTICKS:
if (sc.ch == '\\') { if (sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { if (escapeSequence) {
escapeSeq.resetEscapeState(sc.state, sc.chNext);
sc.SetState(SCE_R_ESCAPESEQUENCE);
sc.Forward(); sc.Forward();
if (sc.chNext == '{' && AnyOf(sc.ch, 'u', 'U')) {
escapeSeq.brace = true;
sc.Forward();
} else if (sc.MatchLineEnd()) {
// don't highlight line ending as escape sequence:
// escapeSeq.outerState is lost when editing on next line.
sc.SetState(escapeSeq.outerState);
}
} else {
sc.Forward(); // Skip all characters after the backslash
} }
} else if (sc.ch == '\"') { } else if ((sc.state == SCE_R_STRING && sc.ch == '\"')
|| (sc.state == SCE_R_STRING2 && sc.ch == '\'')
|| (sc.state == SCE_R_BACKTICKS && sc.ch == '`')) {
sc.ForwardSetState(SCE_R_DEFAULT); sc.ForwardSetState(SCE_R_DEFAULT);
} }
} else if (sc.state == SCE_R_INFIX) { break;
case SCE_R_ESCAPESEQUENCE:
if (escapeSeq.atEscapeEnd(sc.ch)) {
if (escapeSeq.brace && sc.ch == '}') {
sc.Forward();
}
sc.SetState(escapeSeq.outerState);
continue;
}
break;
case SCE_R_RAWSTRING:
case SCE_R_RAWSTRING2:
while (sc.ch == matchingDelimiter) {
sc.Forward();
int count = dashCount;
while (count != 0 && sc.ch == '-') {
--count;
sc.Forward();
}
if (count == 0 && sc.ch == ((sc.state == SCE_R_RAWSTRING) ? '\"' : '\'')) {
matchingDelimiter = 0;
dashCount = 0;
sc.ForwardSetState(SCE_R_DEFAULT);
break;
}
}
break;
case SCE_R_INFIX:
if (sc.ch == '%') { if (sc.ch == '%') {
sc.ForwardSetState(SCE_R_DEFAULT); sc.ForwardSetState(SCE_R_DEFAULT);
} else if (sc.atLineEnd) { } else if (sc.atLineEnd) {
sc.ChangeState(SCE_R_INFIXEOL); sc.ChangeState(SCE_R_INFIXEOL);
sc.ForwardSetState(SCE_R_DEFAULT);
} }
}else if (sc.state == SCE_R_STRING2) { break;
if (sc.ch == '\\') {
if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') { case SCE_R_INFIXEOL:
sc.Forward(); if (sc.atLineStart) {
} sc.SetState(SCE_R_DEFAULT);
} else if (sc.ch == '\'') {
sc.ForwardSetState(SCE_R_DEFAULT);
} }
break;
} }
// Determine if a new state should be entered. // Determine if a new state should be entered.
if (sc.state == SCE_R_DEFAULT) { if (sc.state == SCE_R_DEFAULT) {
if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) { if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
sc.SetState(SCE_R_NUMBER); sc.SetState(SCE_R_NUMBER);
if (sc.ch == '0' && AnyOf(sc.chNext, 'x', 'X')) {
sc.Forward();
}
} else if (AnyOf(sc.ch, 'r', 'R') && AnyOf(sc.chNext, '\"', '\'')) {
const int chNext = sc.chNext;
matchingDelimiter = CheckRawString(styler, sc.currentPos + 2, dashCount);
if (matchingDelimiter) {
sc.SetState((chNext == '\"') ? SCE_R_RAWSTRING : SCE_R_RAWSTRING2);
sc.Forward(dashCount + 2);
} else {
// syntax error
sc.SetState(SCE_R_IDENTIFIER);
sc.ForwardSetState((chNext == '\"') ? SCE_R_STRING : SCE_R_STRING2);
}
} else if (IsAWordStart(sc.ch) ) { } else if (IsAWordStart(sc.ch) ) {
sc.SetState(SCE_R_IDENTIFIER); sc.SetState(SCE_R_IDENTIFIER);
} else if (sc.Match('#')) { } else if (sc.Match('#')) {
sc.SetState(SCE_R_COMMENT); sc.SetState(SCE_R_COMMENT);
} else if (sc.ch == '\"') { } else if (sc.ch == '\"') {
sc.SetState(SCE_R_STRING); sc.SetState(SCE_R_STRING);
} else if (sc.ch == '%') { } else if (sc.ch == '%') {
sc.SetState(SCE_R_INFIX); sc.SetState(SCE_R_INFIX);
} else if (sc.ch == '\'') { } else if (sc.ch == '\'') {
sc.SetState(SCE_R_STRING2); sc.SetState(SCE_R_STRING2);
} else if (sc.ch == '`') {
sc.SetState(SCE_R_BACKTICKS);
} else if (IsAnOperator(sc.ch)) { } else if (IsAnOperator(sc.ch)) {
sc.SetState(SCE_R_OPERATOR); sc.SetState(SCE_R_OPERATOR);
} }
} }
if (sc.atLineEnd) {
const int lineState = matchingDelimiter | (dashCount << 8);
styler.SetLineState(sc.currentLine, lineState);
}
} }
sc.Complete(); sc.Complete();
} }
@ -147,11 +279,11 @@ static void ColouriseRDoc(Sci_PositionU startPos, Sci_Position length, int initS
// Store both the current line's fold level and the next lines in the // Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment // level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {". // and to make it possible to fiddle the current level for "} else {".
static void FoldRDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[], void FoldRDoc(Sci_PositionU startPos, Sci_Position length, int, WordList *[],
Accessor &styler) { Accessor &styler) {
bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0; const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0; const bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
Sci_PositionU endPos = startPos + length; const Sci_PositionU endPos = startPos + length;
int visibleChars = 0; int visibleChars = 0;
Sci_Position lineCurrent = styler.GetLine(startPos); Sci_Position lineCurrent = styler.GetLine(startPos);
int levelCurrent = SC_FOLDLEVELBASE; int levelCurrent = SC_FOLDLEVELBASE;
@ -162,11 +294,11 @@ static void FoldRDoc(Sci_PositionU startPos, Sci_Position length, int, WordList
char chNext = styler[startPos]; char chNext = styler[startPos];
int styleNext = styler.StyleAt(startPos); int styleNext = styler.StyleAt(startPos);
for (Sci_PositionU i = startPos; i < endPos; i++) { for (Sci_PositionU i = startPos; i < endPos; i++) {
char ch = chNext; const char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1); chNext = styler.SafeGetCharAt(i + 1);
int style = styleNext; const int style = styleNext;
styleNext = styler.StyleAt(i + 1); styleNext = styler.StyleAt(i + 1);
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n'); const bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
if (style == SCE_R_OPERATOR) { if (style == SCE_R_OPERATOR) {
if (ch == '{') { if (ch == '{') {
// Measure the minimum before a '{' to allow // Measure the minimum before a '{' to allow
@ -203,15 +335,15 @@ static void FoldRDoc(Sci_PositionU startPos, Sci_Position length, int, WordList
} }
static const char * const RWordLists[] = { const char * const RWordLists[] = {
"Language Keywords", "Language Keywords",
"Base / Default package function", "Base / Default package function",
"Other Package Functions", "Other Package Functions",
"Unused", "Unused",
"Unused", "Unused",
0, nullptr,
}; };
}
LexerModule lmR(SCLEX_R, ColouriseRDoc, "r", FoldRDoc, RWordLists); LexerModule lmR(SCLEX_R, ColouriseRDoc, "r", FoldRDoc, RWordLists);

View File

@ -93,6 +93,16 @@ constexpr bool IsADigit(int ch) noexcept {
return (ch >= '0') && (ch <= '9'); return (ch >= '0') && (ch <= '9');
} }
constexpr bool IsAHeXDigit(int ch) noexcept {
return (ch >= '0' && ch <= '9')
|| (ch >= 'A' && ch <= 'F')
|| (ch >= 'a' && ch <= 'f');
}
constexpr bool IsAnOctalDigit(int ch) noexcept {
return ch >= '0' && ch <= '7';
}
constexpr bool IsADigit(int ch, int base) noexcept { constexpr bool IsADigit(int ch, int base) noexcept {
if (base <= 10) { if (base <= 10) {
return (ch >= '0') && (ch < '0' + base); return (ch >= '0') && (ch < '0' + base);

View File

@ -58,7 +58,7 @@ std::string LexAccessor::GetRange(Sci_PositionU startPos_, Sci_PositionU endPos_
assert(startPos_ < endPos_); assert(startPos_ < endPos_);
const Sci_PositionU len = endPos_ - startPos_; const Sci_PositionU len = endPos_ - startPos_;
std::string s(len, '\0'); std::string s(len, '\0');
GetRange(startPos_, endPos_, s.data(), len); GetRange(startPos_, endPos_, s.data(), len + 1);
return s; return s;
} }
@ -66,7 +66,7 @@ std::string LexAccessor::GetRangeLowered(Sci_PositionU startPos_, Sci_PositionU
assert(startPos_ < endPos_); assert(startPos_ < endPos_);
const Sci_PositionU len = endPos_ - startPos_; const Sci_PositionU len = endPos_ - startPos_;
std::string s(len, '\0'); std::string s(len, '\0');
GetRangeLowered(startPos_, endPos_, s.data(), len); GetRangeLowered(startPos_, endPos_, s.data(), len + 1);
return s; return s;
} }

View File

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

View File

@ -851,7 +851,7 @@
buildSettings = { buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 5.1.9; CURRENT_PROJECT_VERSION = 5.2.0;
DEVELOPMENT_TEAM = 4F446KW87E; DEVELOPMENT_TEAM = 4F446KW87E;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1; DYLIB_CURRENT_VERSION = 1;
@ -877,7 +877,7 @@
buildSettings = { buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 5.1.9; CURRENT_PROJECT_VERSION = 5.2.0;
DEVELOPMENT_TEAM = 4F446KW87E; DEVELOPMENT_TEAM = 4F446KW87E;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1; DYLIB_CURRENT_VERSION = 1;

View File

@ -4,8 +4,8 @@
#include <windows.h> #include <windows.h>
#define VERSION_LEXILLA "5.1.9" #define VERSION_LEXILLA "5.2.0"
#define VERSION_WORDS 5, 1, 9, 0 #define VERSION_WORDS 5, 2, 0, 0
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_WORDS FILEVERSION VERSION_WORDS

View File

@ -0,0 +1,62 @@
# Enumerate all styles: 0 to 16
# line comment = 1
# more comment
# whitespace = 0
# spaces
# string = 2
"a string"
# character = 3
'c'
# number = 4
123
# variable = 5
$variable
# operator = 6
();
# identifier = 7
identifier
# keyword = 8
break
;
# cmdlet = 9
Write-Output "test output"
# alias = 10
chdir C:\Temp\
# function = 11
Get-Verb -Group Security
# user-defined keyword = 12
lexilla
# multi-line comment = 13
<#
multi-line comment
#>
# here string = 14
@"
here string double
"@
# here string single quote = 15
@'
here string single
'@
# comment keyword = 16
<#
.synopsis
End of file.
#>

View File

@ -0,0 +1,63 @@
0 400 400 # Enumerate all styles: 0 to 16
1 400 400
0 400 400 # line comment = 1
0 400 400 # more comment
1 400 400
0 400 400 # whitespace = 0
0 400 400 # spaces
1 400 400
0 400 400 # string = 2
0 400 400 "a string"
1 400 400
0 400 400 # character = 3
0 400 400 'c'
1 400 400
0 400 400 # number = 4
0 400 400 123
1 400 400
0 400 400 # variable = 5
0 400 400 $variable
1 400 400
0 400 400 # operator = 6
0 400 400 ();
1 400 400
0 400 400 # identifier = 7
0 400 400 identifier
1 400 400
0 400 400 # keyword = 8
0 400 400 break
0 400 400 ;
1 400 400
0 400 400 # cmdlet = 9
0 400 400 Write-Output "test output"
1 400 400
0 400 400 # alias = 10
0 400 400 chdir C:\Temp\
1 400 400
0 400 400 # function = 11
0 400 400 Get-Verb -Group Security
1 400 400
0 400 400 # user-defined keyword = 12
0 400 400 lexilla
1 400 400
0 400 400 # multi-line comment = 13
0 400 400 <#
0 400 400 multi-line comment
0 400 400 #>
1 400 400
0 400 400 # here string = 14
0 400 400 @"
0 400 400 here string double
0 400 400 "@
1 400 400
0 400 400 # here string single quote = 15
0 400 400 @'
0 400 400 here string single
0 400 400 '@
1 400 400
0 400 400 # comment keyword = 16
0 400 400 <#
0 400 400 .synopsis
0 400 400 End of file.
0 400 400 #>
0 400 0

View File

@ -0,0 +1,62 @@
{1}# Enumerate all styles: 0 to 16{0}
{1}# line comment = 1{0}
{1}# more comment{0}
{1}# whitespace = 0{0}
{1}# spaces{0}
{1}# string = 2{0}
{2}"a string"{0}
{1}# character = 3{0}
{3}'c'{0}
{1}# number = 4{0}
{4}123{0}
{1}# variable = 5{0}
{5}$variable{0}
{1}# operator = 6{0}
{6}();{0}
{1}# identifier = 7{0}
{7}identifier{0}
{1}# keyword = 8{0}
{8}break{0}
{6};{0}
{1}# cmdlet = 9{0}
{9}Write-Output{0} {2}"test output"{0}
{1}# alias = 10{0}
{10}chdir{0} {7}C{6}:{0}\{7}Temp{0}\
{1}# function = 11{0}
{11}Get-Verb{0} {6}-{7}Group{0} {7}Security{0}
{1}# user-defined keyword = 12{0}
{12}lexilla{0}
{1}# multi-line comment = 13{0}
{13}<#
multi-line comment
#>{0}
{1}# here string = 14{0}
{14}@"
here string double
"@{0}
{1}# here string single quote = 15{0}
{15}@'
here string single
'@{0}
{1}# comment keyword = 16{0}
{13}<#
{16}.synopsis{13}
End of file.
#>{0}

View File

@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
# Show problem with character value truncation causing U+0121 'ġ' (LATIN SMALL LETTER G WITH DOT ABOVE)
# to be styled as an operator as static_cast<char>(0x121) = 0x21 == '!' which is an operator
# Isolate
ġ
# Continuing from operator
(ġ)

View File

@ -0,0 +1,10 @@
0 400 400 # -*- coding: utf-8 -*-
0 400 400 # Show problem with character value truncation causing U+0121 'ġ' (LATIN SMALL LETTER G WITH DOT ABOVE)
0 400 400 # to be styled as an operator as static_cast<char>(0x121) = 0x21 == '!' which is an operator
1 400 400
0 400 400 # Isolate
0 400 400 ġ
1 400 400
0 400 400 # Continuing from operator
0 400 400 (ġ)
0 400 0

View File

@ -0,0 +1,9 @@
{1}# -*- coding: utf-8 -*-{0}
{1}# Show problem with character value truncation causing U+0121 'ġ' (LATIN SMALL LETTER G WITH DOT ABOVE){0}
{1}# to be styled as an operator as static_cast<char>(0x121) = 0x21 == '!' which is an operator{0}
{1}# Isolate{0}
{7}ġ{0}
{1}# Continuing from operator{0}
{6}({7}ġ{6}){0}

View File

@ -0,0 +1 @@
# End comment before \r carriage return.

View File

@ -0,0 +1,2 @@
0 400 400 # End comment before \r carriage return.
0 400 0

View File

@ -0,0 +1 @@
{1}# End comment before \r carriage return.{0}

View File

@ -1,7 +1,9 @@
lexer.*.ps1=powershell lexer.*.ps1=powershell
fold=1 fold=1
keywords.*.ps1=if else in local keywords.*.ps1=break if else in local
keywords2.*.ps1=write-host write-output keywords2.*.ps1=write-host write-output
keywords3.*.ps1=cd chdir cat keywords3.*.ps1=cd chdir cat
keywords4.*.ps1=mkdir prompt keywords4.*.ps1=mkdir prompt get-verb
keywords5.*.ps1=lexilla
keywords6.*.ps1=synopsis

View File

@ -0,0 +1,10 @@
# ugly code to demonstrate multiline string.
`Hello
World` <- function(x, y, z) {
print(x);
print(y);
print(z);
}
`Hello\nWorld`("Hello\nMoon!", "Hello
Venus", 'Hello\
Mars');

View File

@ -0,0 +1,11 @@
0 400 400 # ugly code to demonstrate multiline string.
0 400 400 `Hello
2 400 401 + World` <- function(x, y, z) {
0 401 401 | print(x);
0 401 401 | print(y);
0 401 401 | print(z);
0 401 400 | }
0 400 400 `Hello\nWorld`("Hello\nMoon!", "Hello
0 400 400 Venus", 'Hello\
0 400 400 Mars');
0 400 0

View File

@ -0,0 +1,10 @@
{1}# ugly code to demonstrate multiline string.{0}
{12}`Hello
World`{0} {8}<-{0} {9}function{8}({9}x{0}, {9}y{0}, {9}z{8}){0} {8}{{0}
{9}print{8}({9}x{8}){0};
{9}print{8}({9}y{8}){0};
{9}print{8}({9}z{8}){0};
{8}}{0}
{12}`Hello\nWorld`{8}({6}"Hello\nMoon!"{0}, {6}"Hello
Venus"{0}, {7}'Hello\
Mars'{8}){0};

View File

@ -0,0 +1,48 @@
# https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Reserved-words
if
# base keyword (3)
abbreviate
# other keyword (4)
acme
# infix operator
# https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Special-operators
%x%
# https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Literal-constants
# Valid integer constants
1L, 0x10L, 1000000L, 1e6L
# Valid numeric constants
1 10 0.1 .2 1e-7 1.2e+7
1.1L, 1e-3L, 0x1.1p-2
# Valid complex constants
2i 4.1i 1e-2i
# https://search.r-project.org/R/refmans/base/html/Quotes.html
# single quotes
'"It\'s alive!", he screamed.'
# double quotes
"\"It's alive!\", he screamed."
# escape sequence
"\n0\r1\t2\b3\a4\f5\\6\'7\"8\`9"
"\1230\x121\u12342\U000123453\u{1234}4\U{00012345}5\
6\ 7"
# Backticks
d$`1st column`
# double quoted raw string
r"---(\1--)-)---"
# single quoted raw string
R'---(\1--)-)---'
# infix EOL (11)
%a
#back to comment

View File

@ -0,0 +1,49 @@
0 400 400 # https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Reserved-words
0 400 400 if
1 400 400
0 400 400 # base keyword (3)
0 400 400 abbreviate
1 400 400
0 400 400 # other keyword (4)
0 400 400 acme
1 400 400
0 400 400 # infix operator
0 400 400 # https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Special-operators
0 400 400 %x%
1 400 400
0 400 400 # https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Literal-constants
0 400 400 # Valid integer constants
0 400 400 1L, 0x10L, 1000000L, 1e6L
1 400 400
0 400 400 # Valid numeric constants
0 400 400 1 10 0.1 .2 1e-7 1.2e+7
0 400 400 1.1L, 1e-3L, 0x1.1p-2
1 400 400
0 400 400 # Valid complex constants
0 400 400 2i 4.1i 1e-2i
1 400 400
0 400 400 # https://search.r-project.org/R/refmans/base/html/Quotes.html
0 400 400 # single quotes
0 400 400 '"It\'s alive!", he screamed.'
1 400 400
0 400 400 # double quotes
0 400 400 "\"It's alive!\", he screamed."
1 400 400
0 400 400 # escape sequence
0 400 400 "\n0\r1\t2\b3\a4\f5\\6\'7\"8\`9"
0 400 400 "\1230\x121\u12342\U000123453\u{1234}4\U{00012345}5\
0 400 400 6\ 7"
1 400 400
0 400 400 # Backticks
0 400 400 d$`1st column`
1 400 400
0 400 400 # double quoted raw string
0 400 400 r"---(\1--)-)---"
1 400 400
0 400 400 # single quoted raw string
0 400 400 R'---(\1--)-)---'
1 400 400
0 400 400 # infix EOL (11)
0 400 400 %a
0 400 400 #back to comment
0 400 0

View File

@ -0,0 +1,48 @@
{1}# https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Reserved-words{0}
{2}if{0}
{1}# base keyword (3){0}
{3}abbreviate{0}
{1}# other keyword (4){0}
{4}acme{0}
{1}# infix operator{0}
{1}# https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Special-operators{0}
{10}%x%{0}
{1}# https://cran.r-project.org/doc/manuals/r-release/R-lang.html#Literal-constants{0}
{1}# Valid integer constants{0}
{5}1L{0}, {5}0x10L{0}, {5}1000000L{0}, {5}1e6L{0}
{1}# Valid numeric constants{0}
{5}1{0} {5}10{0} {5}0.1{0} {5}.2{0} {5}1e-7{0} {5}1.2e+7{0}
{5}1.1L{0}, {5}1e-3L{0}, {5}0x1.1p-2{0}
{1}# Valid complex constants{0}
{5}2i{0} {5}4.1i{0} {5}1e-2i{0}
{1}# https://search.r-project.org/R/refmans/base/html/Quotes.html{0}
{1}# single quotes{0}
{7}'"It{15}\'{7}s alive!", he screamed.'{0}
{1}# double quotes{0}
{6}"{15}\"{6}It's alive!{15}\"{6}, he screamed."{0}
{1}# escape sequence{0}
{6}"{15}\n{6}0{15}\r{6}1{15}\t{6}2{15}\b{6}3{15}\a{6}4{15}\f{6}5{15}\\{6}6{15}\'{6}7{15}\"{6}8{15}\`{6}9"{0}
{6}"{15}\123{6}0{15}\x12{6}1{15}\u1234{6}2{15}\U00012345{6}3{15}\u{1234}{6}4{15}\U{00012345}{6}5{15}\{6}
6{15}\ {6}7"{0}
{1}# Backticks{0}
{9}d{8}${12}`1st column`{0}
{1}# double quoted raw string{0}
{13}r"---(\1--)-)---"{0}
{1}# single quoted raw string{0}
{14}R'---(\1--)-)---'{0}
{1}# infix EOL (11){0}
{11}%a
{1}#back to comment{0}

View File

@ -0,0 +1,9 @@
lexer.*.r=r
keywords.*.r=if
keywords2.*.r=abbreviate
keywords3.*.r=acme
fold=1
fold.compact=1
match AllStyles.r
lexer.r.escape.sequence=1

View File

@ -1 +1 @@
519 520

4
scintilla/.editorconfig Normal file
View File

@ -0,0 +1,4 @@
root = true
[**]
indent_style = tab

View File

@ -647,6 +647,18 @@ bool ScintillaCall::StyleGetCheckMonospaced(int style) {
return Call(Message::StyleGetCheckMonospaced, style); return Call(Message::StyleGetCheckMonospaced, style);
} }
void ScintillaCall::StyleSetInvisibleRepresentation(int style, const char *representation) {
CallString(Message::StyleSetInvisibleRepresentation, style, representation);
}
int ScintillaCall::StyleGetInvisibleRepresentation(int style, char *representation) {
return static_cast<int>(CallPointer(Message::StyleGetInvisibleRepresentation, style, representation));
}
std::string ScintillaCall::StyleGetInvisibleRepresentation(int style) {
return CallReturnString(Message::StyleGetInvisibleRepresentation, style);
}
void ScintillaCall::SetElementColour(Scintilla::Element element, ColourAlpha colourElement) { void ScintillaCall::SetElementColour(Scintilla::Element element, ColourAlpha colourElement) {
Call(Message::SetElementColour, static_cast<uintptr_t>(element), colourElement); Call(Message::SetElementColour, static_cast<uintptr_t>(element), colourElement);
} }

View File

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

View File

@ -573,7 +573,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 5.3.0; CURRENT_PROJECT_VERSION = 5.3.1;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES; ENABLE_TESTABILITY = YES;
@ -635,7 +635,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 5.3.0; CURRENT_PROJECT_VERSION = 5.3.1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO; ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -665,7 +665,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5.3.0; CURRENT_PROJECT_VERSION = 5.3.1;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
@ -699,7 +699,7 @@
CODE_SIGN_IDENTITY = "-"; CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual; CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 5.3.0; CURRENT_PROJECT_VERSION = 5.3.1;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View File

@ -129,7 +129,7 @@
<h1>Scintilla Documentation</h1> <h1>Scintilla Documentation</h1>
<p>Last edited 26 August 2022 NH</p> <p>Last edited 1 October 2022 NH</p>
<p style="background:#90F0C0">Scintilla 5 has moved the lexers from Scintilla into a new <p style="background:#90F0C0">Scintilla 5 has moved the lexers from Scintilla into a new
<a href="Lexilla.html">Lexilla</a> project.<br /> <a href="Lexilla.html">Lexilla</a> project.<br />
@ -1338,11 +1338,17 @@ struct Sci_TextToFindFull {
<p>Scintilla can display document changes (modified, saved, ...) in the margin or in the text.</p> <p>Scintilla can display document changes (modified, saved, ...) in the margin or in the text.</p>
<p>The main states are original text that has not been modified, modified, and modified then saved.
As it is possible to undo to before the save point, there are additional states for reverted from save and
reverted back to original from save.
The reverted states are different to the saved document on disk so some applications may want to
display these states just like the main modified state.</p>
<p><img src="ChangeHistory.png" alt="Change history markers and indicators." /></p> <p><img src="ChangeHistory.png" alt="Change history markers and indicators." /></p>
<p>The image shows the default visuals which can be altered by the application. <p>The image shows the default visuals which can be altered by the application.
In the text, inserted characters appear with coloured underlines and points where characters were deleted are shown with small triangles. In the text, inserted characters appear with coloured underlines and points where characters were deleted are shown with small triangles.
The margin shows a block indicating the overall state of the line, prioritising the more consequential modified states. The margin shows a block indicating the overall state of the line, prioritizing the more consequential modified states.
The states are The states are
modified (<span style="color:#FF8000">orange</span>), modified (<span style="color:#FF8000">orange</span>),
saved (<span style="color:#00A000">green</span>), saved (<span style="color:#00A000">green</span>),
@ -1353,6 +1359,9 @@ struct Sci_TextToFindFull {
<p>This feature uses a moderate amount of memory proportional to the amount of modifications made. <p>This feature uses a moderate amount of memory proportional to the amount of modifications made.
On huge documents, this could be significant so could be disabled when it would cause excessive memory use.</p> On huge documents, this could be significant so could be disabled when it would cause excessive memory use.</p>
<p>If the applications wants to display a simplified set of visuals without differentiating between modifications
that have been reverted then assign the same attributes to multiple markers and indicators.</p>
<code><a class="message" href="#SCI_SETCHANGEHISTORY">SCI_SETCHANGEHISTORY(int changeHistory)</a><br /> <code><a class="message" href="#SCI_SETCHANGEHISTORY">SCI_SETCHANGEHISTORY(int changeHistory)</a><br />
<a class="message" href="#SCI_GETCHANGEHISTORY">SCI_GETCHANGEHISTORY &rarr; int</a><br /> <a class="message" href="#SCI_GETCHANGEHISTORY">SCI_GETCHANGEHISTORY &rarr; int</a><br />
</code> </code>
@ -1414,8 +1423,8 @@ struct Sci_TextToFindFull {
<td>21</td> <td>21</td>
<td>A change was made to this line and saved but then reverted to its original state. <td>A change was made to this line and saved but then reverted to its original state.</td>
This line is different to its state on disk.</td> <td>This line is different to its state on disk.</td>
</tr> </tr>
<tr> <tr>
@ -1423,7 +1432,8 @@ struct Sci_TextToFindFull {
<td>22</td> <td>22</td>
<td>This line was modified and saved. This line is the same as its state on disk.</td> <td>This line was modified and saved.</td>
<td>This line is the same as its state on disk.</td>
</tr> </tr>
<tr> <tr>
@ -1431,7 +1441,8 @@ struct Sci_TextToFindFull {
<td>23</td> <td>23</td>
<td>This line was modified but not yet saved. This line is different to its state on disk.</td> <td>This line was modified but not yet saved.</td>
<td>This line is different to its state on disk.</td>
</tr> </tr>
<tr> <tr>
@ -1439,8 +1450,8 @@ struct Sci_TextToFindFull {
<td>24</td> <td>24</td>
<td>A change was made to this line and saved but then reverted but not to its original state. <td>A change was made to this line and saved but then reverted but not to its original state.</td>
This line is different to its state on disk.</td> <td>This line is different to its state on disk.</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -1452,50 +1463,54 @@ struct Sci_TextToFindFull {
<tr> <tr>
<th align="left"><code>INDICATOR_HISTORY_REVERTED_TO_ORIGIN_INSERTION</code></th> <th align="left"><code>INDICATOR_HISTORY_REVERTED_TO_ORIGIN_INSERTION</code></th>
<td>36</td> <td>36</td>
<td>Text was deleted and saved but then reverted to its original state. <td>Text was deleted and saved but then reverted to its original state.</td>
This text is not present on disk.</td> <td>This text has not been saved to disk.</td>
</tr> </tr>
<tr> <tr>
<th align="left"><code>INDICATOR_HISTORY_REVERTED_TO_ORIGIN_DELETION</code></th> <th align="left"><code>INDICATOR_HISTORY_REVERTED_TO_ORIGIN_DELETION</code></th>
<td>37</td> <td>37</td>
<td>Text was inserted and saved but then reverted to its original state. <td>Text was inserted and saved but then reverted to its original state.</td>
This range is different to its state on disk.</td> <td>There is text on disk that is missing.</td>
</tr> </tr>
<tr> <tr>
<th align="left"><code>INDICATOR_HISTORY_SAVED_INSERTION</code></th> <th align="left"><code>INDICATOR_HISTORY_SAVED_INSERTION</code></th>
<td>38</td> <td>38</td>
<td>Text was inserted and saved. This text is the same as on disk.</td> <td>Text was inserted and saved.</td>
<td>This text is the same as on disk.</td>
</tr> </tr>
<tr> <tr>
<th align="left"><code>INDICATOR_HISTORY_SAVED_DELETION</code></th> <th align="left"><code>INDICATOR_HISTORY_SAVED_DELETION</code></th>
<td>39</td> <td>39</td>
<td>Text was deleted and saved. This range is the same as on disk.</td> <td>Text was deleted and saved.</td>
<td>This range is the same as on disk.</td>
</tr> </tr>
<tr> <tr>
<th align="left"><code>INDICATOR_HISTORY_MODIFIED_INSERTION</code></th> <th align="left"><code>INDICATOR_HISTORY_MODIFIED_INSERTION</code></th>
<td>40</td> <td>40</td>
<td>Text was inserted but not yet saved. This text is not present on disk.</td> <td>Text was inserted but not yet saved.</td>
<td>This text has not been saved to disk.</td>
</tr> </tr>
<tr> <tr>
<th align="left"><code>INDICATOR_HISTORY_MODIFIED_DELETION</code></th> <th align="left"><code>INDICATOR_HISTORY_MODIFIED_DELETION</code></th>
<td>41</td> <td>41</td>
<td>Text was deleted but not yet saved. This range is different to its state on disk.</td> <td>Text was deleted but not yet saved.</td>
<td>There is text on disk that is missing.</td>
</tr> </tr>
<tr> <tr>
<th align="left"><code>INDICATOR_HISTORY_REVERTED_TO_MODIFIED_INSERTION</code></th> <th align="left"><code>INDICATOR_HISTORY_REVERTED_TO_MODIFIED_INSERTION</code></th>
<td>42</td> <td>42</td>
<td>Text was deleted and saved but then reverted but not to its original state. <td>Text was deleted and saved but then reverted but not to its original state.</td>
This text is not present on disk.</td> <td>This text has not been saved to disk.</td>
</tr> </tr>
<tr> <tr>
<th align="left"><code>INDICATOR_HISTORY_REVERTED_TO_MODIFIED_DELETION</code></th> <th align="left"><code>INDICATOR_HISTORY_REVERTED_TO_MODIFIED_DELETION</code></th>
<td>43</td> <td>43</td>
<td>Text was inserted and saved but then reverted but not to its original state. <td>Text was inserted and saved but then reverted but not to its original state.</td>
This range is different to its state on disk.</td> <td>There is text on disk that is missing.</td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
@ -3233,6 +3248,8 @@ struct Sci_TextToFindFull {
<a class="message" href="#SCI_STYLESETCHECKMONOSPACED">SCI_STYLESETCHECKMONOSPACED(int style, bool <a class="message" href="#SCI_STYLESETCHECKMONOSPACED">SCI_STYLESETCHECKMONOSPACED(int style, bool
checkMonospaced)</a><br /> checkMonospaced)</a><br />
<a class="message" href="#SCI_STYLEGETCHECKMONOSPACED">SCI_STYLEGETCHECKMONOSPACED(int style) &rarr; bool</a><br /> <a class="message" href="#SCI_STYLEGETCHECKMONOSPACED">SCI_STYLEGETCHECKMONOSPACED(int style) &rarr; bool</a><br />
<a class="message" href="#SCI_STYLESETINVISIBLEREPRESENTATION">SCI_STYLESETINVISIBLEREPRESENTATION(int style, const char *representation)</a><br />
<a class="message" href="#SCI_STYLEGETINVISIBLEREPRESENTATION">SCI_STYLEGETINVISIBLEREPRESENTATION(int style, char *representation NUL-terminated) &rarr; int</a><br />
<a class="message" href="#SCI_SETFONTLOCALE">SCI_SETFONTLOCALE(&lt;unused&gt;, const char *localeName)</a><br /> <a class="message" href="#SCI_SETFONTLOCALE">SCI_SETFONTLOCALE(&lt;unused&gt;, const char *localeName)</a><br />
<a class="message" href="#SCI_GETFONTLOCALE">SCI_GETFONTLOCALE(&lt;unused&gt;, char *localeName) &rarr; int</a><br /> <a class="message" href="#SCI_GETFONTLOCALE">SCI_GETFONTLOCALE(&lt;unused&gt;, char *localeName) &rarr; int</a><br />
</code> </code>
@ -3499,6 +3516,15 @@ struct Sci_TextToFindFull {
Applications may apply the 'check monospaced' attribute just to fonts known to be monospaced or on all fonts, leaving it to Scintilla to Applications may apply the 'check monospaced' attribute just to fonts known to be monospaced or on all fonts, leaving it to Scintilla to
reject fonts that are proportional.</p> reject fonts that are proportional.</p>
<p><b id="SCI_STYLESETINVISIBLEREPRESENTATION">SCI_STYLESETINVISIBLEREPRESENTATION(int style, const char *representation)</b><br />
<b id="SCI_STYLEGETINVISIBLEREPRESENTATION">SCI_STYLEGETINVISIBLEREPRESENTATION(int style, char *representation NUL-terminated) &rarr; int</b><br />
When a style is made invisible with <a class="seealso" href="#SCI_STYLESETVISIBLE">SCI_STYLESETVISIBLE</a>, text is difficult to edit as
the cursor can be at both sides of the invisible text segment. With these messages invisible text segements can be made visible with a single
UTF8 characater giving the user an indication if the cursor is left or right of the invisible text. The character is displayed using the current style.</p>
<p>The <code>representation</code> parameter is a zero terminated string holding the one character used to represent the invisible text segment. Only the first character
is used, the character is decoded as UTF-8.</p>
<p><b id="SCI_SETFONTLOCALE">SCI_SETFONTLOCALE(&lt;unused&gt;, const char *localeName)</b><br /> <p><b id="SCI_SETFONTLOCALE">SCI_SETFONTLOCALE(&lt;unused&gt;, const char *localeName)</b><br />
<b id="SCI_GETFONTLOCALE">SCI_GETFONTLOCALE(&lt;unused&gt;, char *localeName NUL-terminated) &rarr; int</b><br /> <b id="SCI_GETFONTLOCALE">SCI_GETFONTLOCALE(&lt;unused&gt;, char *localeName NUL-terminated) &rarr; int</b><br />
These messages set the locale used for font selection with language-dependent glyphs. These messages set the locale used for font selection with language-dependent glyphs.
@ -5160,8 +5186,11 @@ struct Sci_TextToFindFull {
(<code>SC_MARK_</code>*) or you can use characters. By default, all 32 markers are set to (<code>SC_MARK_</code>*) or you can use characters. By default, all 32 markers are set to
<code>SC_MARK_CIRCLE</code> with a black foreground and a white background.</p> <code>SC_MARK_CIRCLE</code> with a black foreground and a white background.</p>
<p>The markers are drawn in the order of their numbers, so higher numbered markers appear on <p>The markers are drawn in the order of their numbers (except for <code>SC_MARK_BAR</code>), so higher
top of lower numbered ones. Markers try to move with their text by tracking where the start of numbered markers appear on top of lower numbered ones.
<code>SC_MARK_BAR</code> markers are drawn first so they are underneath as they often cover
multiple lines for change history and other markers mark individual lines.
Markers try to move with their text by tracking where the start of
their line moves. When a line is deleted, its markers are combined, by an <code>OR</code> their line moves. When a line is deleted, its markers are combined, by an <code>OR</code>
operation, with the markers of the next line.</p> operation, with the markers of the next line.</p>
<code><a class="message" href="#SCI_MARKERDEFINE">SCI_MARKERDEFINE(int markerNumber, int <code><a class="message" href="#SCI_MARKERDEFINE">SCI_MARKERDEFINE(int markerNumber, int

View File

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

View File

@ -571,9 +571,67 @@
<td>Christian Schmitz</td> <td>Christian Schmitz</td>
<td>Michael Berlenz</td> <td>Michael Berlenz</td>
<td>Jacky Yang</td> <td>Jacky Yang</td>
</tr><tr>
<td>Reinhard Nißl</td>
<td>Ferdinand Oeinck</td>
</tr> </tr>
</table> </table>
<h2>Releases</h2> <h2>Releases</h2>
<h3>
<a href="https://www.scintilla.org/scintilla531.zip">Release 5.3.1</a>
</h3>
<ul>
<li>
Released 12 October 2022.
</li>
<li>
Added SCI_STYLESETINVISIBLEREPRESENTATION to make it easier to edit around invisible text.
This also allows representing long lexemes with a single character to provide a summarized view.
<a href="https://sourceforge.net/p/scintilla/feature-requests/1453/">Feature #1453</a>.
</li>
<li>
Removed NotifyLexerChanged notification from DocWatcher.
This is a private interface but could be used by independent platform layers
and was exposed by ScintillaDocument in the Qt implementation of ScintillaEdit.
</li>
<li>
Draw lines more consistently in SC_PHASES_TWO and SC_PHASES_ONE modes by
clipping drawing to just the line rectangle.
This stops drawing some extreme ascenders, descenders and portions of indicators which
may appear and then disappear depending on which lines were drawn.
</li>
<li>
Draw SC_MARK_BAR markers underneath other markers
as they often cover multiple lines for change history and other markers mark individual lines.
</li>
<li>
Enlarge point and point top indicators and scale to be larger with larger text.
</li>
<li>
Suppress change history background line shading when printing.
<a href="https://sourceforge.net/p/scintilla/bugs/2358/">Bug #2358</a>.
</li>
<li>
Make SCI_LINESCROLL more accurate when width of space not integer.
<a href="https://sourceforge.net/p/scintilla/bugs/2357/">Bug #2357</a>.
</li>
<li>
On Win32 implement horizontal scrolling mouse wheel.
<a href="https://sourceforge.net/p/scintilla/feature-requests/1450/">Feature #1450</a>.
</li>
<li>
On Win32 implement horizontal scrolling with Shift + mouse wheel.
<a href="https://sourceforge.net/p/scintilla/feature-requests/749/">Feature #749</a>,
<a href="https://sourceforge.net/p/scintilla/feature-requests/1451/">Feature #1451</a>.
</li>
<li>
On Win32 ensure page and step clicks on horizontal scroll bar do not overshoot document width.
</li>
<li>
On GTK, fix bug where there were too many or too few lines when wrapping.
<a href="https://sourceforge.net/p/scintilla/bugs/2349/">Bug #2349</a>.
</li>
</ul>
<h3> <h3>
<a href="https://www.scintilla.org/scintilla530.zip">Release 5.3.0</a> <a href="https://www.scintilla.org/scintilla530.zip">Release 5.3.0</a>
</h3> </h3>

View File

@ -9,7 +9,7 @@
<meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" /> <meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
<meta name="Description" <meta name="Description"
content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." /> content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
<meta name="Date.Modified" content="20220827" /> <meta name="Date.Modified" content="20221012" />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css"> <style type="text/css">
#versionlist { #versionlist {
@ -56,8 +56,8 @@
GTK, and macOS</font> GTK, and macOS</font>
</td> </td>
<td width="40%" align="right"> <td width="40%" align="right">
<font color="#FFCC99" size="3"> Release version 5.3.0<br /> <font color="#FFCC99" size="3"> Release version 5.3.1<br />
Site last modified August 27 2022</font> Site last modified October 12 2022</font>
</td> </td>
<td width="20%"> <td width="20%">
&nbsp; &nbsp;
@ -72,12 +72,11 @@
</tr> </tr>
</table> </table>
<ul id="versionlist"> <ul id="versionlist">
<li>Version 5.3.1 can represent invisible text with a character to simplify editing and provide summarized views.</li>
<li>Version 5.3.0 adds change history.</li> <li>Version 5.3.0 adds change history.</li>
<li>Version 5.2.4 fixes failures on GTK with multi-threaded layout.</li> <li>Version 5.2.4 fixes failures on GTK with multi-threaded layout.</li>
<li>Version 5.2.3 adds 64-bit safe APIs and fixes scrollbar on GTK with Xorg.</li> <li>Version 5.2.3 adds 64-bit safe APIs and fixes scrollbar on GTK with Xorg.</li>
<li>Version 5.2.2 on GTK, scroll horizontally with Shift + Scroll Wheel.</li> <li>Version 5.2.2 on GTK, scroll horizontally with Shift + Scroll Wheel.</li>
<li>Version 5.2.1 fixes leaks on GTK.</li>
<li>Version 5.2.0 adds multithreaded layout to significantly improve performance for very wide lines.</li>
</ul> </ul>
<ul id="menu"> <ul id="menu">
<li id="remote1"><a href="https://www.scintilla.org/SciTEImage.html">Screenshot</a></li> <li id="remote1"><a href="https://www.scintilla.org/SciTEImage.html">Screenshot</a></li>

View File

@ -1786,6 +1786,12 @@ void ScintillaGTK::Resize(int width, int height) {
} }
if (IS_WIDGET_MAPPED(PWidget(wMain))) { if (IS_WIDGET_MAPPED(PWidget(wMain))) {
ChangeSize(); ChangeSize();
} else {
const PRectangle rcTextArea = GetTextRectangle();
if (wrapWidth != rcTextArea.Width()) {
wrapWidth = rcTextArea.Width();
NeedWrapping();
}
} }
alloc.x = 0; alloc.x = 0;

View File

@ -280,6 +280,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SCI_STYLESETHOTSPOT 2409 #define SCI_STYLESETHOTSPOT 2409
#define SCI_STYLESETCHECKMONOSPACED 2254 #define SCI_STYLESETCHECKMONOSPACED 2254
#define SCI_STYLEGETCHECKMONOSPACED 2255 #define SCI_STYLEGETCHECKMONOSPACED 2255
#define SCI_STYLESETINVISIBLEREPRESENTATION 2256
#define SCI_STYLEGETINVISIBLEREPRESENTATION 2257
#define SC_ELEMENT_LIST 0 #define SC_ELEMENT_LIST 0
#define SC_ELEMENT_LIST_BACK 1 #define SC_ELEMENT_LIST_BACK 1
#define SC_ELEMENT_LIST_SELECTED 2 #define SC_ELEMENT_LIST_SELECTED 2

View File

@ -694,6 +694,12 @@ set void StyleSetCheckMonospaced=2254(int style, bool checkMonospaced)
# Get whether a style may be monospaced. # Get whether a style may be monospaced.
get bool StyleGetCheckMonospaced=2255(int style,) get bool StyleGetCheckMonospaced=2255(int style,)
# Set the invisible representation for a style.
set void StyleSetInvisibleRepresentation=2256(int style, string representation)
# Get the invisible representation for a style.
get int StyleGetInvisibleRepresentation=2257(int style, stringresult representation)
enu Element=SC_ELEMENT_ enu Element=SC_ELEMENT_
val SC_ELEMENT_LIST=0 val SC_ELEMENT_LIST=0
val SC_ELEMENT_LIST_BACK=1 val SC_ELEMENT_LIST_BACK=1

View File

@ -200,6 +200,9 @@ public:
void StyleSetHotSpot(int style, bool hotspot); void StyleSetHotSpot(int style, bool hotspot);
void StyleSetCheckMonospaced(int style, bool checkMonospaced); void StyleSetCheckMonospaced(int style, bool checkMonospaced);
bool StyleGetCheckMonospaced(int style); bool StyleGetCheckMonospaced(int style);
void StyleSetInvisibleRepresentation(int style, const char *representation);
int StyleGetInvisibleRepresentation(int style, char *representation);
std::string StyleGetInvisibleRepresentation(int style);
void SetElementColour(Scintilla::Element element, ColourAlpha colourElement); void SetElementColour(Scintilla::Element element, ColourAlpha colourElement);
ColourAlpha ElementColour(Scintilla::Element element); ColourAlpha ElementColour(Scintilla::Element element);
void ResetElementColour(Scintilla::Element element); void ResetElementColour(Scintilla::Element element);

View File

@ -136,6 +136,8 @@ enum class Message {
StyleSetHotSpot = 2409, StyleSetHotSpot = 2409,
StyleSetCheckMonospaced = 2254, StyleSetCheckMonospaced = 2254,
StyleGetCheckMonospaced = 2255, StyleGetCheckMonospaced = 2255,
StyleSetInvisibleRepresentation = 2256,
StyleGetInvisibleRepresentation = 2257,
SetElementColour = 2753, SetElementColour = 2753,
GetElementColour = 2754, GetElementColour = 2754,
ResetElementColour = 2755, ResetElementColour = 2755,

View File

@ -54,7 +54,6 @@ public:
void NotifyModified(Document *doc, DocModification mh, void *userData) override; void NotifyModified(Document *doc, DocModification mh, void *userData) override;
void NotifyDeleted(Document *doc, void *userData) noexcept override; void NotifyDeleted(Document *doc, void *userData) noexcept override;
void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endPos) override; void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endPos) override;
void NotifyLexerChanged(Document *doc, void *userData) override;
void NotifyErrorOccurred(Document *doc, void *userData, Status status) override; void NotifyErrorOccurred(Document *doc, void *userData, Status status) override;
}; };
@ -85,10 +84,6 @@ void WatcherHelper::NotifyStyleNeeded(Document *, void *, Sci::Position endPos)
emit owner->style_needed(endPos); emit owner->style_needed(endPos);
} }
void WatcherHelper::NotifyLexerChanged(Document *, void *) {
emit owner->lexer_changed();
}
void WatcherHelper::NotifyErrorOccurred(Document *, void *, Status status) { void WatcherHelper::NotifyErrorOccurred(Document *, void *, Status status) {
emit owner->error_occurred(static_cast<int>(status)); emit owner->error_occurred(static_cast<int>(status));
} }

View File

@ -82,7 +82,6 @@ signals:
void modified(int position, int modification_type, const QByteArray &text, int length, void modified(int position, int modification_type, const QByteArray &text, int length,
int linesAdded, int line, int foldLevelNow, int foldLevelPrev); int linesAdded, int line, int foldLevelNow, int foldLevelPrev);
void style_needed(int pos); void style_needed(int pos);
void lexer_changed();
void error_occurred(int status); void error_occurred(int status);
friend class ::WatcherHelper; friend class ::WatcherHelper;

View File

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

View File

@ -12,7 +12,7 @@ TEMPLATE = lib
CONFIG += lib_bundle CONFIG += lib_bundle
CONFIG += c++1z CONFIG += c++1z
VERSION = 5.3.0 VERSION = 5.3.1
SOURCES += \ SOURCES += \
PlatQt.cpp \ PlatQt.cpp \

View File

@ -32,7 +32,7 @@ def UpdateFile(filename, updated):
newOrChanged = "New" newOrChanged = "New"
with codecs.open(filename, "w", "utf-8") as outfile: with codecs.open(filename, "w", "utf-8") as outfile:
outfile.write(updated) outfile.write(updated)
print("%s %s" % (newOrChanged, filename)) print("%s:0: %s" % (filename, newOrChanged))
# Automatically generated sections contain start and end comments, # Automatically generated sections contain start and end comments,
# a definition line and the results. # a definition line and the results.

View File

@ -1397,7 +1397,7 @@ void CellBuffer::PerformRedoStep() {
void CellBuffer::ChangeHistorySet(bool set) { void CellBuffer::ChangeHistorySet(bool set) {
if (set) { if (set) {
if (!changeHistory) { if (!changeHistory && !uh.CanUndo()) {
changeHistory = std::make_unique<ChangeHistory>(Length()); changeHistory = std::make_unique<ChangeHistory>(Length());
} }
} else { } else {

View File

@ -45,7 +45,7 @@ void ChangeStack::PushDeletion(Sci::Position positionDeletion, int edition) {
void ChangeStack::PushInsertion(Sci::Position positionInsertion, Sci::Position length, int edition) { void ChangeStack::PushInsertion(Sci::Position positionInsertion, Sci::Position length, int edition) {
steps.back()++; steps.back()++;
insertions.push_back({ positionInsertion, length, edition, InsertionSpan::Direction::insertion }); insertions.push_back({ positionInsertion, length, edition, InsertionSpan::Direction::insertion });
}; }
size_t ChangeStack::PopStep() noexcept { size_t ChangeStack::PopStep() noexcept {
const size_t spans = steps.back(); const size_t spans = steps.back();

View File

@ -58,7 +58,6 @@ LexInterface::~LexInterface() noexcept = default;
void LexInterface::SetInstance(ILexer5 *instance_) { void LexInterface::SetInstance(ILexer5 *instance_) {
instance.reset(instance_); instance.reset(instance_);
pdoc->LexerChanged();
} }
void LexInterface::Colourise(Sci::Position start, Sci::Position end) { void LexInterface::Colourise(Sci::Position start, Sci::Position end) {
@ -2432,13 +2431,6 @@ void Document::StyleToAdjustingLineDuration(Sci::Position pos) {
durationStyleOneByte.AddSample(pos - stylingStart, epStyling.Duration()); durationStyleOneByte.AddSample(pos - stylingStart, epStyling.Duration());
} }
void Document::LexerChanged() {
// Tell the watchers the lexer has changed.
for (const WatcherWithUserData &watcher : watchers) {
watcher.watcher->NotifyLexerChanged(this, watcher.userData);
}
}
LexInterface *Document::GetLexInterface() const noexcept { LexInterface *Document::GetLexInterface() const noexcept {
return pli.get(); return pli.get();
} }

View File

@ -484,7 +484,6 @@ public:
Sci::Position GetEndStyled() const noexcept { return endStyled; } Sci::Position GetEndStyled() const noexcept { return endStyled; }
void EnsureStyledTo(Sci::Position pos); void EnsureStyledTo(Sci::Position pos);
void StyleToAdjustingLineDuration(Sci::Position pos); void StyleToAdjustingLineDuration(Sci::Position pos);
void LexerChanged();
int GetStyleClock() const noexcept { return styleClock; } int GetStyleClock() const noexcept { return styleClock; }
void IncrementStyleClock() noexcept; void IncrementStyleClock() noexcept;
void SCI_METHOD DecorationSetCurrentIndicator(int indicator) override; void SCI_METHOD DecorationSetCurrentIndicator(int indicator) override;
@ -621,7 +620,6 @@ public:
virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0; virtual void NotifyModified(Document *doc, DocModification mh, void *userData) = 0;
virtual void NotifyDeleted(Document *doc, void *userData) noexcept = 0; virtual void NotifyDeleted(Document *doc, void *userData) noexcept = 0;
virtual void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endPos) = 0; virtual void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endPos) = 0;
virtual void NotifyLexerChanged(Document *doc, void *userData) = 0;
virtual void NotifyErrorOccurred(Document *doc, void *userData, Scintilla::Status status) = 0; virtual void NotifyErrorOccurred(Document *doc, void *userData, Scintilla::Status status) = 0;
}; };

View File

@ -435,6 +435,21 @@ void LayoutSegments(IPositionCache *pCache,
std::string_view(&ll->chars[ts.start], ts.length), &ll->positions[ts.start + 1], multiThreaded); std::string_view(&ll->chars[ts.start], ts.length), &ll->positions[ts.start + 1], multiThreaded);
} }
} }
} else if (vstyle.styles[ll->styles[ts.start]].invisibleRepresentation[0]) {
const int styleInvisible = ll->styles[ts.start];
const std::string_view text = vstyle.styles[styleInvisible].invisibleRepresentation;
XYPOSITION positionsRepr[Representation::maxLength + 1];
// invisibleRepresentation is UTF-8 which only matches cache if document is UTF-8
// or it only contains ASCII which is a subset of all currently supported encodings.
if (textUnicode || ViewIsASCII(text)) {
pCache->MeasureWidths(surface, vstyle, styleInvisible, text, positionsRepr, multiThreaded);
} else {
surface->MeasureWidthsUTF8(vstyle.styles[styleInvisible].font.get(), text, positionsRepr);
}
const XYPOSITION representationWidth = positionsRepr[text.length() - 1];
for (int ii = 0; ii < ts.length; ii++) {
ll->positions[ts.start + 1 + ii] = representationWidth;
}
} }
} }
} }
@ -1244,7 +1259,8 @@ static void DrawIndicator(int indicNum, Sci::Position startPos, Sci::Position en
const XYPOSITION left = ll->XInLine(startPos) + horizontalOffset; const XYPOSITION left = ll->XInLine(startPos) + horizontalOffset;
const XYPOSITION right = ll->XInLine(endPos) + horizontalOffset; const XYPOSITION right = ll->XInLine(endPos) + horizontalOffset;
const PRectangle rcIndic(left, rcLine.top + vsDraw.maxAscent, right, rcLine.top + vsDraw.maxAscent + 3); const PRectangle rcIndic(left, rcLine.top + vsDraw.maxAscent, right,
std::max(rcLine.top + vsDraw.maxAscent + 3, rcLine.bottom));
if (bidiEnabled) { if (bidiEnabled) {
ScreenLine screenLine(ll, subLine, vsDraw, rcLine.right - xStart, tabWidthMinimumPixels); ScreenLine screenLine(ll, subLine, vsDraw, rcLine.right - xStart, tabWidthMinimumPixels);
@ -1638,6 +1654,11 @@ void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const Vi
surface->FillRectangle(Side(rcBorder, Edge::bottom, 1), colourBorder); surface->FillRectangle(Side(rcBorder, Edge::bottom, 1), colourBorder);
} }
} }
} else {
// No annotation to draw so show bug with bugColour
if (FlagSet(phase, DrawPhase::back)) {
surface->FillRectangle(rcSegment, bugColour.Opaque());
}
} }
} }
@ -2224,6 +2245,15 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
surface->DrawTextNoClip(rcSegment, textFont, surface->DrawTextNoClip(rcSegment, textFont,
rcSegment.top + vsDraw.maxAscent, text, textFore, textBack); rcSegment.top + vsDraw.maxAscent, text, textFore, textBack);
} }
} else if (vsDraw.styles[styleMain].invisibleRepresentation[0]) {
const std::string_view text = vsDraw.styles[styleMain].invisibleRepresentation;
if (phasesDraw != PhasesDraw::One) {
surface->DrawTextTransparentUTF8(rcSegment, textFont,
rcSegment.top + vsDraw.maxAscent, text, textFore);
} else {
surface->DrawTextNoClipUTF8(rcSegment, textFont,
rcSegment.top + vsDraw.maxAscent, text, textFore, textBack);
}
} }
if (vsDraw.viewWhitespace != WhiteSpace::Invisible || if (vsDraw.viewWhitespace != WhiteSpace::Invisible ||
(inIndentation && vsDraw.viewIndentationGuides != IndentView::None)) { (inIndentation && vsDraw.viewIndentationGuides != IndentView::None)) {
@ -2349,6 +2379,11 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl
return; // No further drawing return; // No further drawing
} }
const bool clipLine = !bufferedDraw && !LinesOverlap();
if (clipLine) {
surface->SetClip(rcLine);
}
// See if something overrides the line background colour. // See if something overrides the line background colour.
const std::optional<ColourRGBA> background = vsDraw.Background(model.GetMark(line), model.caret.active, ll->containsCaret); const std::optional<ColourRGBA> background = vsDraw.Background(model.GetMark(line), model.caret.active, ll->containsCaret);
@ -2424,6 +2459,10 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl
if (FlagSet(phase, DrawPhase::lineTranslucent)) { if (FlagSet(phase, DrawPhase::lineTranslucent)) {
DrawTranslucentLineState(surface, model, vsDraw, ll, line, rcLine, subLine, Layer::OverText); DrawTranslucentLineState(surface, model, vsDraw, ll, line, rcLine, subLine, Layer::OverText);
} }
if (clipLine) {
surface->PopClip();
}
} }
static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll, static void DrawFoldLines(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
@ -2771,10 +2810,10 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl
// Turn off change history marker backgrounds // Turn off change history marker backgrounds
constexpr unsigned int changeMarkers = constexpr unsigned int changeMarkers =
1u << static_cast<unsigned int>(MarkerOutline::HistoryRevertedToOrigin) | 1u << static_cast<unsigned int>(MarkerOutline::HistoryRevertedToOrigin) |
1u << static_cast<unsigned int>(MarkerOutline::HistorySaved) | 1u << static_cast<unsigned int>(MarkerOutline::HistorySaved) |
1u << static_cast<unsigned int>(MarkerOutline::HistoryModified) | 1u << static_cast<unsigned int>(MarkerOutline::HistoryModified) |
1u << static_cast<unsigned int>(MarkerOutline::HistoryRevertedToModified); 1u << static_cast<unsigned int>(MarkerOutline::HistoryRevertedToModified);
vsPrint.maskInLine &= ~changeMarkers; vsPrint.maskInLine &= ~changeMarkers;
const Sci::Line linePrintStart = model.pdoc->SciLineFromPosition(chrg.cpMin); const Sci::Line linePrintStart = model.pdoc->SciLineFromPosition(chrg.cpMin);

View File

@ -2379,9 +2379,6 @@ void Editor::NotifyStyleNeeded(Document *, void *, Sci::Position endStyleNeeded)
NotifyStyleToNeeded(endStyleNeeded); NotifyStyleToNeeded(endStyleNeeded);
} }
void Editor::NotifyLexerChanged(Document *, void *) {
}
void Editor::NotifyErrorOccurred(Document *, void *, Status status) { void Editor::NotifyErrorOccurred(Document *, void *, Status status) {
errorStatus = status; errorStatus = status;
} }
@ -5835,6 +5832,19 @@ void Editor::StyleSetMessage(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::StyleSetVisible: case Message::StyleSetVisible:
vs.styles[wParam].visible = lParam != 0; vs.styles[wParam].visible = lParam != 0;
break; break;
case Message::StyleSetInvisibleRepresentation: {
const char *utf8 = ConstCharPtrFromSPtr(lParam);
char *rep = vs.styles[wParam].invisibleRepresentation;
const int classified = UTF8Classify(utf8);
if (!(classified & UTF8MaskInvalid)) {
// valid UTF-8
int len = classified & UTF8MaskWidth;
while (len--)
*rep++ = *utf8++;
}
*rep = 0;
break;
}
case Message::StyleSetChangeable: case Message::StyleSetChangeable:
vs.styles[wParam].changeable = lParam != 0; vs.styles[wParam].changeable = lParam != 0;
break; break;
@ -5881,6 +5891,8 @@ sptr_t Editor::StyleGetMessage(Message iMessage, uptr_t wParam, sptr_t lParam) {
return vs.styles[wParam].visible ? 1 : 0; return vs.styles[wParam].visible ? 1 : 0;
case Message::StyleGetChangeable: case Message::StyleGetChangeable:
return vs.styles[wParam].changeable ? 1 : 0; return vs.styles[wParam].changeable ? 1 : 0;
case Message::StyleGetInvisibleRepresentation:
return StringResult(lParam, vs.styles[wParam].invisibleRepresentation);
case Message::StyleGetHotSpot: case Message::StyleGetHotSpot:
return vs.styles[wParam].hotspot ? 1 : 0; return vs.styles[wParam].hotspot ? 1 : 0;
case Message::StyleGetCheckMonospaced: case Message::StyleGetCheckMonospaced:
@ -6245,7 +6257,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::LineScroll: case Message::LineScroll:
ScrollTo(topLine + lParam); ScrollTo(topLine + lParam);
HorizontalScrollTo(xOffset + static_cast<int>(wParam) * static_cast<int>(vs.spaceWidth)); HorizontalScrollTo(xOffset + static_cast<int>(static_cast<int>(wParam) * vs.spaceWidth));
return 1; return 1;
case Message::SetXOffset: case Message::SetXOffset:
@ -7331,6 +7343,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::StyleSetChangeable: case Message::StyleSetChangeable:
case Message::StyleSetHotSpot: case Message::StyleSetHotSpot:
case Message::StyleSetCheckMonospaced: case Message::StyleSetCheckMonospaced:
case Message::StyleSetInvisibleRepresentation:
StyleSetMessage(iMessage, wParam, lParam); StyleSetMessage(iMessage, wParam, lParam);
break; break;
@ -7350,6 +7363,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::StyleGetChangeable: case Message::StyleGetChangeable:
case Message::StyleGetHotSpot: case Message::StyleGetHotSpot:
case Message::StyleGetCheckMonospaced: case Message::StyleGetCheckMonospaced:
case Message::StyleGetInvisibleRepresentation:
return StyleGetMessage(iMessage, wParam, lParam); return StyleGetMessage(iMessage, wParam, lParam);
case Message::StyleResetDefault: case Message::StyleResetDefault:

View File

@ -471,7 +471,6 @@ protected: // ScintillaBase subclass needs access to much of Editor
void NotifyModified(Document *document, DocModification mh, void *userData) override; void NotifyModified(Document *document, DocModification mh, void *userData) override;
void NotifyDeleted(Document *document, void *userData) noexcept override; void NotifyDeleted(Document *document, void *userData) noexcept override;
void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endStyleNeeded) override; void NotifyStyleNeeded(Document *doc, void *userData, Sci::Position endStyleNeeded) override;
void NotifyLexerChanged(Document *doc, void *userData) override;
void NotifyErrorOccurred(Document *doc, void *userData, Scintilla::Status status) override; void NotifyErrorOccurred(Document *doc, void *userData, Scintilla::Status status) override;
void NotifyMacroRecord(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam); void NotifyMacroRecord(Scintilla::Message iMessage, Scintilla::uptr_t wParam, Scintilla::sptr_t lParam);

View File

@ -75,10 +75,14 @@ XYPOSITION PixelAlignFloor(XYPOSITION xy, int pixelDivisions) noexcept {
return std::floor(xy * pixelDivisions) / pixelDivisions; return std::floor(xy * pixelDivisions) / pixelDivisions;
} }
XYPOSITION PixelAlignCeil(XYPOSITION xy, int pixelDivisions) noexcept {
return std::ceil(xy * pixelDivisions) / pixelDivisions;
}
Point PixelAlign(const Point &pt, int pixelDivisions) noexcept { Point PixelAlign(const Point &pt, int pixelDivisions) noexcept {
return Point( return Point(
std::round(pt.x * pixelDivisions) / pixelDivisions, PixelAlign(pt.x, pixelDivisions),
std::round(pt.y * pixelDivisions) / pixelDivisions); PixelAlign(pt.y, pixelDivisions));
} }
PRectangle PixelAlign(const PRectangle &rc, int pixelDivisions) noexcept { PRectangle PixelAlign(const PRectangle &rc, int pixelDivisions) noexcept {
@ -88,19 +92,19 @@ PRectangle PixelAlign(const PRectangle &rc, int pixelDivisions) noexcept {
// On retina displays, the positions should be moved to the nearest device // On retina displays, the positions should be moved to the nearest device
// pixel which is the nearest half logical pixel. // pixel which is the nearest half logical pixel.
return PRectangle( return PRectangle(
std::round(rc.left * pixelDivisions) / pixelDivisions, PixelAlign(rc.left, pixelDivisions),
PixelAlignFloor(rc.top, pixelDivisions), PixelAlignFloor(rc.top, pixelDivisions),
std::round(rc.right * pixelDivisions) / pixelDivisions, PixelAlign(rc.right, pixelDivisions),
PixelAlignFloor(rc.bottom, pixelDivisions)); PixelAlignFloor(rc.bottom, pixelDivisions));
} }
PRectangle PixelAlignOutside(const PRectangle &rc, int pixelDivisions) noexcept { PRectangle PixelAlignOutside(const PRectangle &rc, int pixelDivisions) noexcept {
// Move left and right side to extremes (floor(left) ceil(right)) to avoid blurry visuals. // Move left and right side to extremes (floor(left) ceil(right)) to avoid blurry visuals.
return PRectangle( return PRectangle(
std::floor(rc.left * pixelDivisions) / pixelDivisions, PixelAlignFloor(rc.left, pixelDivisions),
std::floor(rc.top * pixelDivisions) / pixelDivisions, PixelAlignFloor(rc.top, pixelDivisions),
std::ceil(rc.right * pixelDivisions) / pixelDivisions, PixelAlignCeil(rc.right, pixelDivisions),
std::floor(rc.bottom * pixelDivisions) / pixelDivisions); PixelAlignFloor(rc.bottom, pixelDivisions));
} }
ColourRGBA ColourRGBA::MixedWith(ColourRGBA other) const noexcept { ColourRGBA ColourRGBA::MixedWith(ColourRGBA other) const noexcept {

View File

@ -149,6 +149,7 @@ Interval HorizontalBounds(PRectangle rc) noexcept;
XYPOSITION PixelAlign(XYPOSITION xy, int pixelDivisions) noexcept; XYPOSITION PixelAlign(XYPOSITION xy, int pixelDivisions) noexcept;
XYPOSITION PixelAlignFloor(XYPOSITION xy, int pixelDivisions) noexcept; XYPOSITION PixelAlignFloor(XYPOSITION xy, int pixelDivisions) noexcept;
XYPOSITION PixelAlignCeil(XYPOSITION xy, int pixelDivisions) noexcept;
Point PixelAlign(const Point &pt, int pixelDivisions) noexcept; Point PixelAlign(const Point &pt, int pixelDivisions) noexcept;

View File

@ -265,15 +265,15 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r
case IndicatorStyle::Point: case IndicatorStyle::Point:
case IndicatorStyle::PointCharacter: case IndicatorStyle::PointCharacter:
if (rcCharacter.Width() >= 0.1) { if (rcCharacter.Width() >= 0.1) {
const XYPOSITION pixelHeight = std::floor(rc.Height() - 1.0f); // 1 pixel onto next line if multiphase const XYPOSITION pixelHeight = std::floor(rc.Height()); // 1 pixel onto next line if multiphase
const XYPOSITION x = (sacDraw.style == IndicatorStyle::Point) ? (rcCharacter.left) : ((rcCharacter.right + rcCharacter.left) / 2); const XYPOSITION x = (sacDraw.style == IndicatorStyle::Point) ? (rcCharacter.left) : ((rcCharacter.right + rcCharacter.left) / 2);
// 0.5f is to hit midpoint of pixels: // 0.5f is to hit midpoint of pixels:
const XYPOSITION ix = std::round(x) + 0.5f; const XYPOSITION ix = std::round(x) + 0.5f;
const XYPOSITION iy = std::floor(rc.top) + 0.5f; const XYPOSITION iy = std::ceil(rc.bottom) + 0.5f;
const Point pts[] = { const Point pts[] = {
Point(ix - pixelHeight, iy + pixelHeight), // Left Point(ix - pixelHeight, iy), // Left
Point(ix + pixelHeight, iy + pixelHeight), // Right Point(ix + pixelHeight, iy), // Right
Point(ix, iy) // Top Point(ix, iy - pixelHeight) // Top
}; };
surface->Polygon(pts, std::size(pts), FillStroke(sacDraw.fore)); surface->Polygon(pts, std::size(pts), FillStroke(sacDraw.fore));
} }
@ -281,11 +281,11 @@ void Indicator::Draw(Surface *surface, const PRectangle &rc, const PRectangle &r
case IndicatorStyle::PointTop: case IndicatorStyle::PointTop:
if (rcCharacter.Width() >= 0.1) { if (rcCharacter.Width() >= 0.1) {
const XYPOSITION pixelHeight = std::floor(rc.Height() - 1.0f); // 1 pixel onto previous line if multiphase const XYPOSITION pixelHeight = std::floor(rc.Height()); // 1 pixel onto previous line if multiphase
const XYPOSITION x = rcCharacter.left; const XYPOSITION x = rcCharacter.left;
// 0.5f is to hit midpoint of pixels: // 0.5f is to hit midpoint of pixels:
const XYPOSITION ix = std::round(x) + 0.5f; const XYPOSITION ix = std::round(x) + 0.5f;
const XYPOSITION iy = std::floor(rcLine.top) + 0.5f; const XYPOSITION iy = std::floor(rcLine.top) - 0.5f;
const Point pts[] = { const Point pts[] = {
Point(ix - pixelHeight, iy), // Left Point(ix - pixelHeight, iy), // Left
Point(ix + pixelHeight, iy), // Right Point(ix + pixelHeight, iy), // Right

View File

@ -239,10 +239,42 @@ int FoldingMark(FoldLevel level, FoldLevel levelNext, bool firstSubLine, bool la
return 0; return 0;
} }
LineMarker::FoldPart PartForFoldHighlight(const HighlightDelimiter &highlightDelimiter, Sci::Line lineDoc, bool firstSubLine, bool headWithTail, bool isExpanded) noexcept {
if (highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) {
if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) {
return LineMarker::FoldPart::body;
}
if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) {
if (firstSubLine) {
return headWithTail ? LineMarker::FoldPart::headWithTail : LineMarker::FoldPart::head;
}
if (isExpanded || headWithTail) {
return LineMarker::FoldPart::body;
}
} else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) {
return LineMarker::FoldPart::tail;
}
}
return LineMarker::FoldPart::undefined;
}
constexpr LineMarker::FoldPart PartForBar(bool markBefore, bool markAfter) {
if (markBefore) {
if (markAfter) {
return LineMarker::FoldPart::body;
}
return LineMarker::FoldPart::tail;
}
if (markAfter) {
return LineMarker::FoldPart::head;
}
return LineMarker::FoldPart::headWithTail;
}
} }
void MarginView::PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcOneMargin, const MarginStyle &marginStyle, void MarginView::PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcOneMargin, const MarginStyle &marginStyle,
const EditModel &model, const ViewStyle &vs) { const EditModel &model, const ViewStyle &vs) const {
const Point ptOrigin = model.GetVisibleOriginInMain(); const Point ptOrigin = model.GetVisibleOriginInMain();
const Sci::Line lineStartPaint = static_cast<Sci::Line>(rcOneMargin.top + ptOrigin.y) / vs.lineHeight; const Sci::Line lineStartPaint = static_cast<Sci::Line>(rcOneMargin.top + ptOrigin.y) / vs.lineHeight;
Sci::Line visibleLine = model.TopLineOfMain() + lineStartPaint; Sci::Line visibleLine = model.TopLineOfMain() + lineStartPaint;
@ -290,25 +322,27 @@ void MarginView::PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcOn
} }
bool headWithTail = false; bool headWithTail = false;
bool isExpanded = false;
if (marginStyle.ShowsFolding()) { if (marginStyle.ShowsFolding()) {
// Decide which fold indicator should be displayed // Decide which fold indicator should be displayed
const FoldLevel level = model.pdoc->GetFoldLevel(lineDoc); const FoldLevel level = model.pdoc->GetFoldLevel(lineDoc);
const FoldLevel levelNext = model.pdoc->GetFoldLevel(lineDoc + 1); const FoldLevel levelNext = model.pdoc->GetFoldLevel(lineDoc + 1);
const FoldLevel levelNum = LevelNumberPart(level); isExpanded = model.pcs->GetExpanded(lineDoc);
const FoldLevel levelNextNum = LevelNumberPart(levelNext);
const bool isExpanded = model.pcs->GetExpanded(lineDoc);
marks |= FoldingMark(level, levelNext, firstSubLine, lastSubLine, marks |= FoldingMark(level, levelNext, firstSubLine, lastSubLine,
isExpanded, needWhiteClosure, folderOpenMid, folderEnd); isExpanded, needWhiteClosure, folderOpenMid, folderEnd);
const FoldLevel levelNum = LevelNumberPart(level);
const FoldLevel levelNextNum = LevelNumberPart(levelNext);
// Change needWhiteClosure and headWithTail if needed // Change needWhiteClosure and headWithTail if needed
if (LevelIsHeader(level)) { if (LevelIsHeader(level)) {
needWhiteClosure = false; needWhiteClosure = false;
const Sci::Line firstFollowupLine = model.pcs->DocFromDisplay(model.pcs->DisplayFromDoc(lineDoc + 1));
const FoldLevel firstFollowupLineLevel = model.pdoc->GetFoldLevel(firstFollowupLine);
const FoldLevel secondFollowupLineLevelNum = LevelNumberPart(model.pdoc->GetFoldLevel(firstFollowupLine + 1));
if (!isExpanded) { if (!isExpanded) {
const Sci::Line firstFollowupLine = model.pcs->DocFromDisplay(model.pcs->DisplayFromDoc(lineDoc + 1));
const FoldLevel firstFollowupLineLevel = model.pdoc->GetFoldLevel(firstFollowupLine);
const FoldLevel secondFollowupLineLevelNum = LevelNumberPart(model.pdoc->GetFoldLevel(firstFollowupLine + 1));
if (LevelIsWhitespace(firstFollowupLineLevel) && if (LevelIsWhitespace(firstFollowupLineLevel) &&
(levelNum > secondFollowupLineLevelNum)) (levelNum > secondFollowupLineLevelNum))
needWhiteClosure = true; needWhiteClosure = true;
@ -397,44 +431,25 @@ void MarginView::PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcOn
marks &= marginStyle.mask; marks &= marginStyle.mask;
if (marks) { if (marks) {
for (int markBit = 0; (markBit < 32) && marks; markBit++) { // Draw all the bar markers first so they are underneath as they often cover
if (marks & 1) { // multiple lines for change history and other markers mark individual lines.
LineMarker::FoldPart part = LineMarker::FoldPart::undefined; int marksBar = marks;
if (marginStyle.ShowsFolding() && highlightDelimiter.IsFoldBlockHighlighted(lineDoc)) { for (int markBit = 0; (markBit <= MarkerMax) && marksBar; markBit++) {
if (highlightDelimiter.IsBodyOfFoldBlock(lineDoc)) { if ((marksBar & 1) && (vs.markers[markBit].markType == MarkerSymbol::Bar)) {
part = LineMarker::FoldPart::body; const int mask = 1 << markBit;
} else if (highlightDelimiter.IsHeadOfFoldBlock(lineDoc)) { const bool markBefore = firstSubLine ? (model.GetMark(lineDoc - 1) & mask) : true;
if (firstSubLine) { const bool markAfter = lastSubLine ? (model.GetMark(lineDoc + 1) & mask) : true;
part = headWithTail ? LineMarker::FoldPart::headWithTail : LineMarker::FoldPart::head; vs.markers[markBit].Draw(surface, rcMarker, vs.styles[StyleLineNumber].font.get(),
} else { PartForBar(markBefore, markAfter), marginStyle.style);
if (model.pcs->GetExpanded(lineDoc) || headWithTail) { }
part = LineMarker::FoldPart::body; marksBar >>= 1;
} else { }
part = LineMarker::FoldPart::undefined; // Draw all the other markers over the bar markers
} for (int markBit = 0; (markBit <= MarkerMax) && marks; markBit++) {
} if ((marks & 1) && (vs.markers[markBit].markType != MarkerSymbol::Bar)) {
} else if (highlightDelimiter.IsTailOfFoldBlock(lineDoc)) { const LineMarker::FoldPart part = marginStyle.ShowsFolding() ?
part = LineMarker::FoldPart::tail; PartForFoldHighlight(highlightDelimiter, lineDoc, firstSubLine, headWithTail, isExpanded) :
} LineMarker::FoldPart::undefined;
}
if (vs.markers[markBit].markType == MarkerSymbol::Bar) {
const int mask = 1 << markBit;
const bool markBefore = firstSubLine ? (model.GetMark(lineDoc-1) & mask) : true;
const bool markAfter = lastSubLine ? (model.GetMark(lineDoc+1) & mask) : true;
if (markBefore) {
if (markAfter) {
part = LineMarker::FoldPart::body;
} else {
part = LineMarker::FoldPart::tail;
}
} else {
if (markAfter) {
part = LineMarker::FoldPart::head;
} else {
part = LineMarker::FoldPart::headWithTail;
}
}
}
vs.markers[markBit].Draw(surface, rcMarker, vs.styles[StyleLineNumber].font.get(), part, marginStyle.style); vs.markers[markBit].Draw(surface, rcMarker, vs.styles[StyleLineNumber].font.get(), part, marginStyle.style);
} }
marks >>= 1; marks >>= 1;

View File

@ -37,7 +37,7 @@ public:
void DropGraphics() noexcept; void DropGraphics() noexcept;
void RefreshPixMaps(Surface *surfaceWindow, const ViewStyle &vsDraw); void RefreshPixMaps(Surface *surfaceWindow, const ViewStyle &vsDraw);
void PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcOneMargin, const MarginStyle &marginStyle, void PaintOneMargin(Surface *surface, PRectangle rc, PRectangle rcOneMargin, const MarginStyle &marginStyle,
const EditModel &model, const ViewStyle &vs); const EditModel &model, const ViewStyle &vs) const;
void PaintMargin(Surface *surface, Sci::Line topLine, PRectangle rc, PRectangle rcMargin, void PaintMargin(Surface *surface, Sci::Line topLine, PRectangle rc, PRectangle rcMargin,
const EditModel &model, const ViewStyle &vs); const EditModel &model, const ViewStyle &vs);
}; };

View File

@ -809,10 +809,6 @@ void ScintillaBase::NotifyStyleToNeeded(Sci::Position endStyleNeeded) {
Editor::NotifyStyleToNeeded(endStyleNeeded); Editor::NotifyStyleToNeeded(endStyleNeeded);
} }
void ScintillaBase::NotifyLexerChanged(Document *, void *) {
vs.EnsureStyle(0xff);
}
sptr_t ScintillaBase::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) { sptr_t ScintillaBase::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
switch (iMessage) { switch (iMessage) {
case Message::AutoCShow: case Message::AutoCShow:

View File

@ -82,7 +82,6 @@ protected:
void RightButtonDownWithModifiers(Point pt, unsigned int curTime, Scintilla::KeyMod modifiers) override; void RightButtonDownWithModifiers(Point pt, unsigned int curTime, Scintilla::KeyMod modifiers) override;
void NotifyStyleToNeeded(Sci::Position endStyleNeeded) override; void NotifyStyleToNeeded(Sci::Position endStyleNeeded) override;
void NotifyLexerChanged(Document *doc, void *userData) override;
public: public:
~ScintillaBase() override; ~ScintillaBase() override;

View File

@ -72,7 +72,8 @@ Style::Style(const char *fontName_) noexcept :
caseForce(CaseForce::mixed), caseForce(CaseForce::mixed),
visible(true), visible(true),
changeable(true), changeable(true),
hotspot(false) { hotspot(false),
invisibleRepresentation{} {
} }
void Style::Copy(std::shared_ptr<Font> font_, const FontMeasurements &fm_) noexcept { void Style::Copy(std::shared_ptr<Font> font_, const FontMeasurements &fm_) noexcept {

View File

@ -51,6 +51,7 @@ public:
bool visible; bool visible;
bool changeable; bool changeable;
bool hotspot; bool hotspot;
char invisibleRepresentation[5];
std::shared_ptr<Font> font; std::shared_ptr<Font> font;

View File

@ -168,6 +168,17 @@ class XiteWin():
self.face.features.update(faceLex.features) self.face.features.update(faceLex.features)
except FileNotFoundError: except FileNotFoundError:
print("Can't find " + "LexicalStyles.iface") print("Can't find " + "LexicalStyles.iface")
if scintillaIncludesLexers:
sciName = "SciLexer.DLL"
else:
sciName = "Scintilla.DLL"
try:
scintillaDLLPath = os.path.join(scintillaBinDirectory, sciName)
ctypes.cdll.LoadLibrary(scintillaDLLPath)
except OSError:
print("Can't find " + sciName)
print("Python is built for " + " ".join(platform.architecture()))
sys.exit()
self.titleDirty = True self.titleDirty = True
self.fullPath = "" self.fullPath = ""
@ -208,17 +219,6 @@ class XiteWin():
def OnCreate(self, hwnd): def OnCreate(self, hwnd):
self.win = hwnd self.win = hwnd
if scintillaIncludesLexers:
sciName = "SciLexer.DLL"
else:
sciName = "Scintilla.DLL"
try:
scintillaDLLPath = os.path.join(scintillaBinDirectory, sciName)
ctypes.cdll.LoadLibrary(scintillaDLLPath)
except OSError:
print("Can't find " + sciName)
print("Python is built for " + " ".join(platform.architecture()))
sys.exit()
self.sciHwnd = user32.CreateWindowExW(0, self.sciHwnd = user32.CreateWindowExW(0,
"Scintilla", "Source", "Scintilla", "Source",
WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_CLIPCHILDREN, WS_CHILD | WS_VSCROLL | WS_HSCROLL | WS_CLIPCHILDREN,

View File

@ -708,6 +708,32 @@ class TestSimple(unittest.TestCase):
self.assertEquals(self.ed.IsRangeWord(6, 7), 0) self.assertEquals(self.ed.IsRangeWord(6, 7), 0)
self.assertEquals(self.ed.IsRangeWord(6, 8), 1) self.assertEquals(self.ed.IsRangeWord(6, 8), 1)
class TestChangeHistory(unittest.TestCase):
def setUp(self):
self.xite = Xite.xiteFrame
self.ed = self.xite.ed
self.ed.ClearAll()
self.ed.EmptyUndoBuffer()
self.data = b"xy"
def testChangeHistory(self):
self.assertEquals(self.ed.ChangeHistory, 0)
self.assertEquals(self.ed.UndoCollection, 1)
self.ed.UndoCollection = 0
self.assertEquals(self.ed.UndoCollection, 0)
self.ed.InsertText(0, self.data)
self.ed.UndoCollection = 1
self.ed.ChangeHistory = 1
self.assertEquals(self.ed.ChangeHistory, 1)
self.ed.InsertText(0, self.data)
self.ed.DeleteRange(0, 2)
self.ed.ChangeHistory = 0
self.assertEquals(self.ed.ChangeHistory, 0)
self.ed.ChangeHistory = 1
self.assertEquals(self.ed.ChangeHistory, 1)
self.ed.Undo()
MODI = 1 MODI = 1
UNDO = 2 UNDO = 2
REDO = 4 REDO = 4
@ -1930,6 +1956,7 @@ class TestStyleAttributes(unittest.TestCase):
self.ed.EmptyUndoBuffer() self.ed.EmptyUndoBuffer()
self.testColour = 0x171615 self.testColour = 0x171615
self.testFont = b"Georgia" self.testFont = b"Georgia"
self.testRepresentation = "\N{BULLET}".encode("utf-8")
def tearDown(self): def tearDown(self):
self.ed.StyleResetDefault() self.ed.StyleResetDefault()
@ -1945,6 +1972,13 @@ class TestStyleAttributes(unittest.TestCase):
self.ed.StyleSetSizeFractional(self.ed.STYLE_DEFAULT, 1234) self.ed.StyleSetSizeFractional(self.ed.STYLE_DEFAULT, 1234)
self.assertEquals(self.ed.StyleGetSizeFractional(self.ed.STYLE_DEFAULT), 1234) self.assertEquals(self.ed.StyleGetSizeFractional(self.ed.STYLE_DEFAULT), 1234)
def testInvisibleRepresentation(self):
self.assertEquals(self.ed.StyleGetInvisibleRepresentation(self.ed.STYLE_DEFAULT), b"")
self.ed.StyleSetInvisibleRepresentation(self.ed.STYLE_DEFAULT, self.testRepresentation)
self.assertEquals(self.ed.StyleGetInvisibleRepresentation(self.ed.STYLE_DEFAULT), self.testRepresentation)
self.ed.StyleSetInvisibleRepresentation(self.ed.STYLE_DEFAULT, b"\000")
self.assertEquals(self.ed.StyleGetInvisibleRepresentation(self.ed.STYLE_DEFAULT), b"")
def testBold(self): def testBold(self):
self.ed.StyleSetBold(self.ed.STYLE_DEFAULT, 1) self.ed.StyleSetBold(self.ed.STYLE_DEFAULT, 1)
self.assertEquals(self.ed.StyleGetBold(self.ed.STYLE_DEFAULT), 1) self.assertEquals(self.ed.StyleGetBold(self.ed.STYLE_DEFAULT), 1)

View File

@ -148,36 +148,49 @@ TEST_CASE("PRectangle") {
// Whole pixels // Whole pixels
REQUIRE(PixelAlign(1.0, 1) == 1.0); REQUIRE(PixelAlign(1.0, 1) == 1.0);
REQUIRE(PixelAlignFloor(1.0, 1) == 1.0); REQUIRE(PixelAlignFloor(1.0, 1) == 1.0);
REQUIRE(PixelAlignCeil(1.0, 1) == 1.0);
REQUIRE(PixelAlign(1.25, 1) == 1.0); REQUIRE(PixelAlign(1.25, 1) == 1.0);
REQUIRE(PixelAlignFloor(1.25, 1) == 1.0); REQUIRE(PixelAlignFloor(1.25, 1) == 1.0);
REQUIRE(PixelAlignCeil(1.25, 1) == 2.0);
REQUIRE(PixelAlign(1.5, 1) == 2.0); REQUIRE(PixelAlign(1.5, 1) == 2.0);
REQUIRE(PixelAlignFloor(1.5, 1) == 1.0); REQUIRE(PixelAlignFloor(1.5, 1) == 1.0);
REQUIRE(PixelAlignCeil(1.5, 1) == 2.0);
REQUIRE(PixelAlign(1.75, 1) == 2.0); REQUIRE(PixelAlign(1.75, 1) == 2.0);
REQUIRE(PixelAlignFloor(1.75, 1) == 1.0); REQUIRE(PixelAlignFloor(1.75, 1) == 1.0);
REQUIRE(PixelAlignCeil(1.75, 1) == 2.0);
REQUIRE(PixelAlign(Point(1.75, 1.25), 1) == Point(2.0, 1.0));
REQUIRE(PixelAlign(Point(1.5, 1.0), 1) == Point(2.0, 1.0));
// Half pixels // Half pixels
REQUIRE(PixelAlign(1.0, 2) == 1.0); REQUIRE(PixelAlign(1.0, 2) == 1.0);
REQUIRE(PixelAlignFloor(1.0, 2) == 1.0); REQUIRE(PixelAlignFloor(1.0, 2) == 1.0);
REQUIRE(PixelAlignCeil(1.0, 2) == 1.0);
REQUIRE(PixelAlign(1.25, 2) == 1.5); REQUIRE(PixelAlign(1.25, 2) == 1.5);
REQUIRE(PixelAlignFloor(1.25, 2) == 1.0); REQUIRE(PixelAlignFloor(1.25, 2) == 1.0);
REQUIRE(PixelAlignCeil(1.25, 2) == 1.5);
REQUIRE(PixelAlign(1.5, 2) == 1.5); REQUIRE(PixelAlign(1.5, 2) == 1.5);
REQUIRE(PixelAlignFloor(1.5, 2) == 1.5); REQUIRE(PixelAlignFloor(1.5, 2) == 1.5);
REQUIRE(PixelAlignCeil(1.5, 2) == 1.5);
REQUIRE(PixelAlign(1.75, 2) == 2.0); REQUIRE(PixelAlign(1.75, 2) == 2.0);
REQUIRE(PixelAlignFloor(1.75, 2) == 1.5); REQUIRE(PixelAlignFloor(1.75, 2) == 1.5);
REQUIRE(PixelAlignCeil(1.75, 2) == 2.0);
REQUIRE(PixelAlign(Point(1.75, 1.25), 2) == Point(2.0, 1.5)); REQUIRE(PixelAlign(Point(1.75, 1.25), 2) == Point(2.0, 1.5));
REQUIRE(PixelAlign(Point(1.5, 1.0), 2) == Point(1.5, 1.0)); REQUIRE(PixelAlign(Point(1.5, 1.0), 2) == Point(1.5, 1.0));
// x->round, y->floored // x->round, y->floored
REQUIRE(PixelAlign(PRectangle(1.0, 1.25, 1.5, 1.75), 1) == PRectangle(1.0, 1.0, 2.0, 1.0));
REQUIRE(PixelAlign(PRectangle(1.0, 1.25, 1.5, 1.75), 2) == PRectangle(1.0, 1.0, 1.5, 1.5)); REQUIRE(PixelAlign(PRectangle(1.0, 1.25, 1.5, 1.75), 2) == PRectangle(1.0, 1.0, 1.5, 1.5));
// x->outside(floor left, ceil right), y->floored // x->outside(floor left, ceil right), y->floored
REQUIRE(PixelAlignOutside(PRectangle(1.1, 1.25, 1.6, 1.75), 1) == PRectangle(1.0, 1.0, 2.0, 1.0));
REQUIRE(PixelAlignOutside(PRectangle(1.1, 1.25, 1.6, 1.75), 2) == PRectangle(1.0, 1.0, 2.0, 1.5)); REQUIRE(PixelAlignOutside(PRectangle(1.1, 1.25, 1.6, 1.75), 2) == PRectangle(1.0, 1.0, 2.0, 1.5));
} }

View File

@ -1 +1 @@
530 531

View File

@ -3203,15 +3203,17 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) {
ID2D1DCRenderTarget *pDCRT = nullptr; ID2D1DCRenderTarget *pDCRT = nullptr;
HRESULT hr = pD2DFactory->CreateDCRenderTarget(&props, &pDCRT); HRESULT hr = pD2DFactory->CreateDCRenderTarget(&props, &pDCRT);
if (SUCCEEDED(hr) && pDCRT) { if (SUCCEEDED(hr) && pDCRT) {
RECT rcWindow; const long left = pDrawItem->rcItem.left + static_cast<long>(ItemInset.x + ImageInset.x);
GetClientRect(pDrawItem->hwndItem, &rcWindow);
hr = pDCRT->BindDC(pDrawItem->hDC, &rcWindow); RECT rcItem = pDrawItem->rcItem;
rcItem.left = left;
rcItem.right = rcItem.left + images.GetWidth();
hr = pDCRT->BindDC(pDrawItem->hDC, &rcItem);
if (SUCCEEDED(hr)) { if (SUCCEEDED(hr)) {
surfaceItem->Init(pDCRT, pDrawItem->hwndItem); surfaceItem->Init(pDCRT, pDrawItem->hwndItem);
pDCRT->BeginDraw(); pDCRT->BeginDraw();
const long left = pDrawItem->rcItem.left + static_cast<long>(ItemInset.x + ImageInset.x); const PRectangle rcImage = PRectangle::FromInts(0, 0, images.GetWidth(), rcItem.bottom - rcItem.top);
const PRectangle rcImage = PRectangle::FromInts(left, pDrawItem->rcItem.top,
left + images.GetWidth(), pDrawItem->rcItem.bottom);
surfaceItem->DrawRGBAImage(rcImage, surfaceItem->DrawRGBAImage(rcImage,
pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels()); pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
pDCRT->EndDraw(); pDCRT->EndDraw();

View File

@ -4,8 +4,8 @@
#include <windows.h> #include <windows.h>
#define VERSION_SCINTILLA "5.3.0" #define VERSION_SCINTILLA "5.3.1"
#define VERSION_WORDS 5, 3, 0, 0 #define VERSION_WORDS 5, 3, 1, 0
VS_VERSION_INFO VERSIONINFO VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_WORDS FILEVERSION VERSION_WORDS

View File

@ -309,6 +309,25 @@ public:
} }
}; };
class MouseWheelDelta {
int wheelDelta = 0;
public:
bool Accumulate(WPARAM wParam) noexcept {
wheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam);
return std::abs(wheelDelta) >= WHEEL_DELTA;
}
int Actions() noexcept {
const int actions = wheelDelta / WHEEL_DELTA;
wheelDelta = wheelDelta % WHEEL_DELTA;
return actions;
}
};
struct HorizontalScrollRange {
int pageWidth;
int documentWidth;
};
} }
namespace Scintilla::Internal { namespace Scintilla::Internal {
@ -326,7 +345,9 @@ class ScintillaWin :
SetCoalescableTimerSig SetCoalescableTimerFn; SetCoalescableTimerSig SetCoalescableTimerFn;
unsigned int linesPerScroll; ///< Intellimouse support unsigned int linesPerScroll; ///< Intellimouse support
int wheelDelta; ///< Wheel delta from roll unsigned int charsPerScroll; ///< Intellimouse support
MouseWheelDelta verticalWheelDelta;
MouseWheelDelta horizontalWheelDelta;
UINT dpi = USER_DEFAULT_SCREEN_DPI; UINT dpi = USER_DEFAULT_SCREEN_DPI;
ReverseArrowCursor reverseArrowCursor; ReverseArrowCursor reverseArrowCursor;
@ -437,6 +458,8 @@ class ScintillaWin :
void UpdateSystemCaret() override; void UpdateSystemCaret() override;
void SetVerticalScrollPos() override; void SetVerticalScrollPos() override;
void SetHorizontalScrollPos() override; void SetHorizontalScrollPos() override;
void HorizontalScrollToClamped(int xPos);
HorizontalScrollRange GetHorizontalScrollRange() const;
bool ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) override; bool ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) override;
void NotifyChange() override; void NotifyChange() override;
void NotifyFocus(bool focus) override; void NotifyFocus(bool focus) override;
@ -537,7 +560,7 @@ ScintillaWin::ScintillaWin(HWND hwnd) {
SetCoalescableTimerFn = nullptr; SetCoalescableTimerFn = nullptr;
linesPerScroll = 0; linesPerScroll = 0;
wheelDelta = 0; // Wheel delta from roll charsPerScroll = 0;
dpi = DpiForWindow(hwnd); dpi = DpiForWindow(hwnd);
@ -1575,6 +1598,7 @@ sptr_t ScintillaWin::MouseMessage(unsigned int iMessage, uptr_t wParam, sptr_t l
return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
if (!mouseWheelCaptures) { if (!mouseWheelCaptures) {
// if the mouse wheel is not captured, test if the mouse // if the mouse wheel is not captured, test if the mouse
// pointer is over the editor window and if not, don't // pointer is over the editor window and if not, don't
@ -1592,27 +1616,30 @@ sptr_t ScintillaWin::MouseMessage(unsigned int iMessage, uptr_t wParam, sptr_t l
break; break;
} }
// Don't handle datazoom. // Treat Shift+WM_MOUSEWHEEL as horizontal scrolling, not data-zoom.
// (A good idea for datazoom would be to "fold" or "unfold" details. if (iMessage == WM_MOUSEHWHEEL || (wParam & MK_SHIFT)) {
// i.e. if datazoomed out only class structures are visible, when datazooming in the control if (vs.wrap.state != Wrap::None || charsPerScroll == 0) {
// structures appear, then eventually the individual statements...) return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
if (wParam & MK_SHIFT) { }
return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
MouseWheelDelta &wheelDelta = (iMessage == WM_MOUSEHWHEEL) ? horizontalWheelDelta : verticalWheelDelta;
if (wheelDelta.Accumulate(wParam)) {
const int charsToScroll = charsPerScroll * wheelDelta.Actions();
const int widthToScroll = static_cast<int>(std::lround(charsToScroll * vs.aveCharWidth));
HorizontalScrollToClamped(xOffset + widthToScroll);
}
return 0;
} }
// Either SCROLL or ZOOM. We handle the wheel steppings calculation
wheelDelta -= GET_WHEEL_DELTA_WPARAM(wParam); // Either SCROLL vertically or ZOOM. We handle the wheel steppings calculation
if (std::abs(wheelDelta) >= WHEEL_DELTA && linesPerScroll > 0) { if (linesPerScroll != 0 && verticalWheelDelta.Accumulate(wParam)) {
Sci::Line linesToScroll = linesPerScroll; Sci::Line linesToScroll = linesPerScroll;
if (linesPerScroll == WHEEL_PAGESCROLL) if (linesPerScroll == WHEEL_PAGESCROLL)
linesToScroll = LinesOnScreen() - 1; linesToScroll = LinesOnScreen() - 1;
if (linesToScroll == 0) { if (linesToScroll == 0) {
linesToScroll = 1; linesToScroll = 1;
} }
linesToScroll *= (wheelDelta / WHEEL_DELTA); linesToScroll *= verticalWheelDelta.Actions();
if (wheelDelta >= 0)
wheelDelta = wheelDelta % WHEEL_DELTA;
else
wheelDelta = -(-wheelDelta % WHEEL_DELTA);
if (wParam & MK_CONTROL) { if (wParam & MK_CONTROL) {
// Zoom! We play with the font sizes in the styles. // Zoom! We play with the font sizes in the styles.
@ -2045,6 +2072,7 @@ sptr_t ScintillaWin::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
case WM_MOUSEMOVE: case WM_MOUSEMOVE:
case WM_MOUSELEAVE: case WM_MOUSELEAVE:
case WM_MOUSEWHEEL: case WM_MOUSEWHEEL:
case WM_MOUSEHWHEEL:
return MouseMessage(msg, wParam, lParam); return MouseMessage(msg, wParam, lParam);
case WM_SETCURSOR: case WM_SETCURSOR:
@ -2318,7 +2346,7 @@ void ScintillaWin::SetTrackMouseLeaveEvent(bool on) noexcept {
void ScintillaWin::UpdateBaseElements() { void ScintillaWin::UpdateBaseElements() {
struct ElementToIndex { Element element; int nIndex; }; struct ElementToIndex { Element element; int nIndex; };
ElementToIndex eti[] = { const ElementToIndex eti[] = {
{ Element::List, COLOR_WINDOWTEXT }, { Element::List, COLOR_WINDOWTEXT },
{ Element::ListBack, COLOR_WINDOW }, { Element::ListBack, COLOR_WINDOW },
{ Element::ListSelected, COLOR_HIGHLIGHTTEXT }, { Element::ListSelected, COLOR_HIGHLIGHTTEXT },
@ -2420,6 +2448,20 @@ bool ScintillaWin::ChangeScrollRange(int nBar, int nMin, int nMax, UINT nPage) n
return false; return false;
} }
void ScintillaWin::HorizontalScrollToClamped(int xPos) {
const HorizontalScrollRange range = GetHorizontalScrollRange();
HorizontalScrollTo(std::clamp(xPos, 0, range.documentWidth - range.pageWidth + 1));
}
HorizontalScrollRange ScintillaWin::GetHorizontalScrollRange() const {
const PRectangle rcText = GetTextRectangle();
int pageWidth = static_cast<int>(rcText.Width());
const int horizEndPreferred = std::max({ scrollWidth, pageWidth - 1, 0 });
if (!horizontalScrollBarVisible || Wrapping())
pageWidth = horizEndPreferred + 1;
return { pageWidth, horizEndPreferred };
}
bool ScintillaWin::ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) { bool ScintillaWin::ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) {
if (!IsVisible()) { if (!IsVisible()) {
return false; return false;
@ -2432,15 +2474,10 @@ bool ScintillaWin::ModifyScrollBars(Sci::Line nMax, Sci::Line nPage) {
if (ChangeScrollRange(SB_VERT, 0, static_cast<int>(vertEndPreferred), static_cast<unsigned int>(nPage))) { if (ChangeScrollRange(SB_VERT, 0, static_cast<int>(vertEndPreferred), static_cast<unsigned int>(nPage))) {
modified = true; modified = true;
} }
const HorizontalScrollRange range = GetHorizontalScrollRange();
const PRectangle rcText = GetTextRectangle(); if (ChangeScrollRange(SB_HORZ, 0, range.documentWidth, range.pageWidth)) {
int pageWidth = static_cast<int>(rcText.Width());
const int horizEndPreferred = std::max({scrollWidth, pageWidth - 1, 0});
if (!horizontalScrollBarVisible || Wrapping())
pageWidth = horizEndPreferred + 1;
if (ChangeScrollRange(SB_HORZ, 0, horizEndPreferred, pageWidth)) {
modified = true; modified = true;
if (scrollWidth < pageWidth) { if (scrollWidth < range.pageWidth) {
HorizontalScrollTo(0); HorizontalScrollTo(0);
} }
} }
@ -3180,6 +3217,10 @@ LRESULT ScintillaWin::ImeOnReconvert(LPARAM lParam) {
void ScintillaWin::GetIntelliMouseParameters() noexcept { void ScintillaWin::GetIntelliMouseParameters() noexcept {
// This retrieves the number of lines per scroll as configured in the Mouse Properties sheet in Control Panel // This retrieves the number of lines per scroll as configured in the Mouse Properties sheet in Control Panel
::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0); ::SystemParametersInfo(SPI_GETWHEELSCROLLLINES, 0, &linesPerScroll, 0);
if (!::SystemParametersInfo(SPI_GETWHEELSCROLLCHARS, 0, &charsPerScroll, 0)) {
// no horizontal scrolling configuration on Windows XP
charsPerScroll = (linesPerScroll == WHEEL_PAGESCROLL) ? 3 : linesPerScroll;
}
} }
void ScintillaWin::CopyToGlobal(GlobalMemory &gmUnicode, const SelectionText &selectedText) { void ScintillaWin::CopyToGlobal(GlobalMemory &gmUnicode, const SelectionText &selectedText) {
@ -3283,9 +3324,6 @@ void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) {
break; break;
case SB_PAGEDOWN: case SB_PAGEDOWN:
xPos += pageWidth; xPos += pageWidth;
if (xPos > scrollWidth - rcText.Width()) { // Hit the end exactly
xPos = scrollWidth - static_cast<int>(rcText.Width());
}
break; break;
case SB_TOP: case SB_TOP:
xPos = 0; xPos = 0;
@ -3305,7 +3343,7 @@ void ScintillaWin::HorizontalScrollMessage(WPARAM wParam) {
} }
break; break;
} }
HorizontalScrollTo(xPos); HorizontalScrollToClamped(xPos);
} }
/** /**

View File

@ -15,7 +15,7 @@ DIR_BIN=../bin
COMPONENT = $(DIR_BIN)/Scintilla.dll COMPONENT = $(DIR_BIN)/Scintilla.dll
LIBSCI = $(DIR_BIN)/libscintilla.a LIBSCI = $(DIR_BIN)/libscintilla.a
WARNINGS = -Wpedantic -Wall WARNINGS = -Wpedantic -Wall -Wextra
ifdef CLANG ifdef CLANG
CXX = clang++ CXX = clang++