Merge pull request #4650 from RaiKoHoff/Dev_Master

Update:  Scintilla v5.3.4.  Lexilla v5.2.4
This commit is contained in:
Pairi Daiza 2023-03-15 08:54:07 +01:00 committed by GitHub
commit a11b041c3e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 346 additions and 148 deletions

View File

@ -61,7 +61,6 @@ unreadVariable:lexilla/lexers/LexJulia.cxx
variableScope:lexilla/lexers/LexJulia.cxx
variableScope:lexilla/lexers/LexLaTeX.cxx
constParameter:lexilla/lexers/LexLaTeX.cxx
constParameter:lexilla/lexers/LexLisp.cxx
constParameter:lexilla/lexers/LexMagik.cxx
constParameter:lexilla/lexers/LexMatlab.cxx
unreadVariable:lexilla/lexers/LexMatlab.cxx
@ -91,7 +90,6 @@ redundantInitialization:lexilla/lexers/LexRegistry.cxx
constParameter:lexilla/lexers/LexRuby.cxx
knownConditionTrueFalse:lexilla/lexers/LexRuby.cxx
constParameter:lexilla/lexers/LexRust.cxx
constParameter:lexilla/lexers/LexScriptol.cxx
knownConditionTrueFalse:lexilla/lexers/LexScriptol.cxx
variableScope:lexilla/lexers/LexSpecman.cxx
unreadVariable:lexilla/lexers/LexSpice.cxx
@ -128,29 +126,12 @@ constParameterCallback:lexilla/lexers/LexPython.cxx
constParameterCallback:lexilla/lexers/LexScriptol.cxx
constParameterCallback:lexilla/lexers/LexVB.cxx
constVariable:lexilla/lexers/LexA68k.cxx
constVariable:lexilla/lexers/LexAsn1.cxx
constVariable:lexilla/lexers/LexCLW.cxx
constVariable:lexilla/lexers/LexCOBOL.cxx
constVariable:lexilla/lexers/LexCSS.cxx
constVariable:lexilla/lexers/LexCrontab.cxx
constVariable:lexilla/lexers/LexEScript.cxx
constVariable:lexilla/lexers/LexEiffel.cxx
constVariable:lexilla/lexers/LexForth.cxx
constVariable:lexilla/lexers/LexGui4Cli.cxx
constVariable:lexilla/lexers/LexKix.cxx
constVariable:lexilla/lexers/LexLout.cxx
constVariable:lexilla/lexers/LexMetapost.cxx
constVariable:lexilla/lexers/LexModula.cxx
constVariable:lexilla/lexers/LexOpal.cxx
constVariable:lexilla/lexers/LexPS.cxx
constVariable:lexilla/lexers/LexPascal.cxx
constVariable:lexilla/lexers/LexRebol.cxx
constVariable:lexilla/lexers/LexSorcus.cxx
constVariable:lexilla/lexers/LexStata.cxx
constVariable:lexilla/lexers/LexTACL.cxx
constVariable:lexilla/lexers/LexTADS3.cxx
constVariable:lexilla/lexers/LexTAL.cxx
// cppcheck appears wrong as atKeyPath must be remembered between loops
variableScope:lexilla/lexers/LexRegistry.cxx

View File

@ -9,7 +9,7 @@
<meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
<meta name="Description"
content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
<meta name="Date.Modified" content="20230208" />
<meta name="Date.Modified" content="20230313" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
.logo {
@ -61,8 +61,8 @@
<font color="#FFCC99" size="4"> A library of language lexers for use with Scintilla</font>
</td>
<td width="40%" align="right">
<font color="#FFCC99" size="3">Release version 5.2.2<br />
Site last modified February 8 2023</font>
<font color="#FFCC99" size="3">Release version 5.2.4<br />
Site last modified March 13 2023</font>
</td>
<td width="20%">
&nbsp;
@ -77,13 +77,13 @@
</tr>
</table>
<ul id="versionlist">
<li>Version 5.2.4 improves C++ and GDScript.</li>
<li>Version 5.2.3 improves Makefile, Ruby, and YAML.</li>
<li>Version 5.2.2 improves C++, Matlab, Modula-3, Python, and X12.</li>
<li>Version 5.2.1 improves Batch, F#, Markdown, and PowerShell.</li>
<li>Version 5.2.0 improves PowerShell and R.</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.7 improves CMake, HTML, Matlab, Raku, Ruby, and VHDL.</li>
<li>Version 5.1.6 improves Markdown and Ruby.</li>
</ul>
<ul id="menu">
<li id="remote1"><a href="https://www.scintilla.org/SciTEImage.html">Screenshot</a></li>

View File

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

View File

@ -585,12 +585,29 @@
</tr>
</table>
<h2>Releases</h2>
<h3>
<a href="https://www.scintilla.org/lexilla524.zip">Release 5.2.4</a>
</h3>
<ul>
<li>
Released 13 March 2023.
</li>
<li>
C++: Fix failure to recognize keywords containing upper case.
<a href="https://github.com/ScintillaOrg/lexilla/issues/149">Issue #149</a>.
</li>
<li>
GDScript: Support % and $ node paths.
<a href="https://github.com/ScintillaOrg/lexilla/issues/145">Issue #145</a>,
<a href="https://github.com/ScintillaOrg/lexilla/pull/146">Pull request #146</a>.
</li>
</ul>
<h3>
<a href="https://www.scintilla.org/lexilla523.zip">Release 5.2.3</a>
</h3>
<ul>
<li>
Released 8 February 2023.
Released 8 March 2023.
</li>
<li>
Add scripts/PromoteNew.bat script to promote .new files after checking.

View File

@ -2306,3 +2306,4 @@ val SCE_GD_COMMENTBLOCK=12
val SCE_GD_STRINGEOL=13
val SCE_GD_WORD2=14
val SCE_GD_ANNOTATION=15
val SCE_GD_NODEPATH=16

View File

@ -2054,6 +2054,7 @@
#define SCE_GD_STRINGEOL 13
#define SCE_GD_WORD2 14
#define SCE_GD_ANNOTATION 15
#define SCE_GD_NODEPATH 16
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */
#endif

View File

@ -91,6 +91,10 @@ constexpr bool IsSpaceOrTab(int ch) noexcept {
return ch == ' ' || ch == '\t';
}
constexpr bool IsOperatorOrSpace(int ch) noexcept {
return isoperator(ch) || IsASpace(ch);
}
bool OnlySpaceOrTab(const std::string &s) noexcept {
for (const char ch : s) {
if (!IsSpaceOrTab(ch))
@ -138,23 +142,18 @@ BracketPair FindBracketPair(Tokens &tokens) {
void highlightTaskMarker(StyleContext &sc, LexAccessor &styler,
int activity, const WordList &markerList, bool caseSensitive){
if ((isoperator(sc.chPrev) || IsASpace(sc.chPrev)) && markerList.Length()) {
constexpr Sci_PositionU lengthMarker = 50;
char marker[lengthMarker+1] = "";
const Sci_PositionU currPos = sc.currentPos;
Sci_PositionU i = 0;
while (i < lengthMarker) {
const char ch = styler.SafeGetCharAt(currPos + i);
if (IsASpace(ch) || isoperator(ch)) {
if (IsOperatorOrSpace(sc.chPrev) && !IsOperatorOrSpace(sc.ch) && markerList.Length()) {
std::string marker;
for (Sci_PositionU currPos = sc.currentPos; true; currPos++) {
const char ch = styler.SafeGetCharAt(currPos);
if (IsOperatorOrSpace(ch)) {
break;
}
if (caseSensitive)
marker[i] = ch;
marker.push_back(ch);
else
marker[i] = MakeLowerCase(ch);
i++;
marker.push_back(MakeLowerCase(ch));
}
marker[i] = '\0';
if (markerList.InList(marker)) {
sc.SetState(SCE_C_TASKMARKER|activity);
}
@ -767,6 +766,9 @@ Sci_Position SCI_METHOD LexerCPP::WordListSet(int n, const char *wl) {
void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int initStyle, IDocument *pAccess) {
LexAccessor styler(pAccess);
const StyleContext::Transform transform = caseSensitive ?
StyleContext::Transform::none : StyleContext::Transform::lower;
const CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-");
const CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-");
@ -843,6 +845,8 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1);
SparseState<std::string> rawSTNew(lineCurrent);
std::string currentText;
int activitySet = preproc.ActiveState();
const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_C_IDENTIFIER);
@ -928,31 +932,29 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
break;
case SCE_C_IDENTIFIER:
if (sc.atLineStart || sc.atLineEnd || !setWord.Contains(sc.ch) || (sc.ch == '.')) {
char s[1000];
if (caseSensitive) {
sc.GetCurrent(s, sizeof(s));
} else {
sc.GetCurrentLowered(s, sizeof(s));
}
if (keywords.InList(s)) {
lastWordWasUUID = strcmp(s, "uuid") == 0;
sc.GetCurrentString(currentText, transform);
if (keywords.InList(currentText)) {
lastWordWasUUID = currentText == "uuid";
sc.ChangeState(SCE_C_WORD|activitySet);
} else if (keywords2.InList(s)) {
} else if (keywords2.InList(currentText)) {
sc.ChangeState(SCE_C_WORD2|activitySet);
} else if (keywords4.InList(s)) {
} else if (keywords4.InList(currentText)) {
sc.ChangeState(SCE_C_GLOBALCLASS|activitySet);
} else {
const int subStyle = classifierIdentifiers.ValueFor(s);
const int subStyle = classifierIdentifiers.ValueFor(currentText);
if (subStyle >= 0) {
sc.ChangeState(subStyle|activitySet);
}
}
const bool literalString = sc.ch == '\"';
if (literalString || sc.ch == '\'') {
size_t lenS = strlen(s);
std::string_view s = currentText;
size_t lenS = s.length();
const bool raw = literalString && sc.chPrev == 'R' && !setInvalidRawFirst.Contains(sc.chNext);
if (raw)
s[lenS--] = '\0';
if (raw) {
s.remove_suffix(1);
lenS--;
}
const bool valid =
(lenS == 0) ||
((lenS == 1) && ((s[0] == 'L') || (s[0] == 'u') || (s[0] == 'U'))) ||
@ -1066,33 +1068,27 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
seenDocKeyBrace = true;
} else if (!setDoxygen.Contains(sc.ch)
&& !(seenDocKeyBrace && (sc.ch == ',' || sc.ch == '.'))) {
char s[100];
if (caseSensitive) {
sc.GetCurrent(s, sizeof(s));
} else {
sc.GetCurrentLowered(s, sizeof(s));
}
if (!(IsASpace(sc.ch) || (sc.ch == 0))) {
sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet);
} else if (!keywords3.InList(s + 1) && !keywords3.InList(s)) {
const int subStyleCDKW = classifierDocKeyWords.ValueFor(s+1);
if (subStyleCDKW >= 0) {
sc.ChangeState(subStyleCDKW|activitySet);
} else {
sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet);
} else {
sc.GetCurrentString(currentText, transform);
assert(!currentText.empty());
std::string currentSuffix = currentText.substr(1);
if (!keywords3.InList(currentSuffix) && !keywords3.InList(currentText)) {
const int subStyleCDKW = classifierDocKeyWords.ValueFor(currentSuffix.c_str());
if (subStyleCDKW >= 0) {
sc.ChangeState(subStyleCDKW | activitySet);
} else {
sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR | activitySet);
}
}
}
sc.SetState(styleBeforeDCKeyword|activitySet);
seenDocKeyBrace = false;
} else if (sc.ch == '>') {
char s[100];
if (caseSensitive) {
sc.GetCurrent(s, sizeof(s));
} else {
sc.GetCurrentLowered(s, sizeof(s));
}
if (!keywords3.InList(s)) {
const int subStyleCDKW = classifierDocKeyWords.ValueFor(s + 1);
sc.GetCurrentString(currentText, transform);
if (!keywords3.InList(currentText)) {
const int subStyleCDKW = classifierDocKeyWords.ValueFor(currentText.substr(1));
if (subStyleCDKW >= 0) {
sc.ChangeState(subStyleCDKW | activitySet);
} else {
@ -1222,7 +1218,7 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
}
break;
case SCE_C_TASKMARKER:
if (isoperator(sc.ch) || IsASpace(sc.ch)) {
if (IsOperatorOrSpace(sc.ch)) {
sc.SetState(styleBeforeTaskMarker|activitySet);
styleBeforeTaskMarker = SCE_C_DEFAULT;
}

View File

@ -71,3 +71,14 @@ void StyleContext::GetCurrent(char *s, Sci_PositionU len) {
void StyleContext::GetCurrentLowered(char *s, Sci_PositionU len) {
styler.GetRangeLowered(styler.GetStartSegment(), currentPos, s, len);
}
void StyleContext::GetCurrentString(std::string &string, Transform transform) {
const Sci_PositionU startPos = styler.GetStartSegment();
const Sci_PositionU len = currentPos - styler.GetStartSegment();
string.resize(len);
if (transform == Transform::lower) {
styler.GetRangeLowered(startPos, currentPos, string.data(), len + 1);
} else {
styler.GetRange(startPos, currentPos, string.data(), len + 1);
}
}

View File

@ -160,7 +160,6 @@ public:
const unsigned char uch1 = ch1;
return (ch == uch0) && (chNext == uch1);
}
bool Match(const char *s) {
const unsigned char su = *s;
if (ch != su)
@ -183,7 +182,8 @@ public:
bool MatchIgnoreCase(const char *s);
void GetCurrent(char *s, Sci_PositionU len);
void GetCurrentLowered(char *s, Sci_PositionU len);
enum class Transform { none, lower };
void GetCurrentString(std::string &string, Transform transform);
// >>>>>>>>>>>>>>> BEG NON STD SCI PATCH >>>>>>>>>>>>>>>

View File

@ -9,6 +9,7 @@
#include <cassert>
#include <cstring>
#include <string>
#include <algorithm>
#include <iterator>
#include <memory>
@ -182,6 +183,12 @@ bool WordList::InList(const char *s) const noexcept {
return false;
}
/** convenience overload so can easily call with std::string.
*/
bool WordList::InList(const std::string &s) const noexcept {
return InList(s.c_str());
}
/** similar to InList, but word s can be a substring of keyword.
* eg. the keyword define is defined as def~ine. This means the word must start
* with def to be a keyword, but also defi, defin and define are valid.

View File

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

View File

@ -0,0 +1,23 @@
@echo off
rem Promote new result files.
rem Find all the *.new files under test\examples and copy them to their expected name without ".new".
rem Run after RunTest.bat if ".new" result files are correct.
pushd ..\test\examples
for /R %%f in (*.new) do (call :moveFile %%f)
popd
goto :eof
:moveFile
set pathWithNew=%1
set directory=%~dp1
set fileWithNew=%~nx1
set fileNoNew=%~n1
set pathNoNew=%pathWithNew:~0,-4%
if exist %pathNoNew% (
echo Move %fileWithNew% to %fileNoNew% in %directory%
) else (
echo New %fileWithNew% to %fileNoNew% in %directory%
)
move %pathWithNew% %pathNoNew%
goto :eof

View File

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

View File

@ -792,6 +792,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@ -851,6 +852,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@ -875,7 +877,8 @@
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 5.2.2;
CURRENT_PROJECT_VERSION = 5.2.4;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 4F446KW87E;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
@ -901,7 +904,8 @@
buildSettings = {
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 5.2.2;
CURRENT_PROJECT_VERSION = 5.2.4;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 4F446KW87E;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;

View File

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

View File

@ -1 +1 @@
522
524

View File

@ -2,4 +2,4 @@ This is only a repository to track Scintilla (https://sourceforge.net/p/scintill
resp. (http://hg.code.sf.net/p/scintilla/code)
resp. GitHub Mirror: (https://github.com/missdeer/scintilla)
changes for Notepad3 (https://github.com/rizonesoft/Notepad3) development.

View File

@ -7982,7 +7982,7 @@ sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){
<p><b id="SCI_SETLAYOUTTHREADS">SCI_SETLAYOUTTHREADS(int threads)</b><br />
<b id="SCI_GETLAYOUTTHREADS">SCI_GETLAYOUTTHREADS &rarr; int</b><br />
The time taken to measure text runs on wide lines can be improved by performing the task
The time taken to measure text runs on wide lines or when wrapping can be improved by performing the task
concurrently on multiple threads when
<a class="seealso" href="#SCI_SUPPORTSFEATURE">SCI_SUPPORTSFEATURE(SC_SUPPORTS_THREAD_SAFE_MEASURE_WIDTHS)</a>
is available.

View File

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

View File

@ -584,7 +584,10 @@
</h3>
<ul>
<li>
Released 8 February 2023.
Released 8 March 2023.
</li>
<li>
Add multithreaded wrap to significantly improve performance of wrapping large files.
</li>
<li>
More typesafe bindings of *Full APIs in ScintillaCall.

View File

@ -9,7 +9,7 @@
<meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
<meta name="Description"
content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
<meta name="Date.Modified" content="20230208" />
<meta name="Date.Modified" content="20230308" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
#versionlist {
@ -56,8 +56,8 @@
GTK, and macOS</font>
</td>
<td width="40%" align="right">
<font color="#FFCC99" size="3"> Release version 5.3.3<br />
Site last modified February 8 2023</font>
<font color="#FFCC99" size="3"> Release version 5.3.4<br />
Site last modified March 8 2023</font>
</td>
<td width="20%">
&nbsp;
@ -72,12 +72,12 @@
</tr>
</table>
<ul id="versionlist">
<li>Version 5.3.4 adds multithreaded wrapping.</li>
<li>Version 5.3.3 fixes minor bugs in APIs and platform layers.</li>
<li>Version 5.3.2 adds SCI_REPLACETARGETMINIMAL to modify text without marking unchanged start and end text in change history.</li>
<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.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>
</ul>
<ul id="menu">
<li id="remote1"><a href="https://www.scintilla.org/SciTEImage.html">Screenshot</a></li>

View File

@ -161,7 +161,7 @@ def checkDocumentation():
#~ if api not in headers:
#~ print("No header for ", api)
# Examine definitions
# Examine definitions
#<b id="SCI_SETLAYOUTCACHE">SCI_SETLAYOUTCACHE(int cacheMode)</b>
defPattern = re.compile(r'<b id="([A-Z_0-9]+)">([A-Z][A-Za-z0-9_() *#\"=<>/&;,\n-]+?)</b>')
for api, sig in re.findall(defPattern, docs):
@ -201,7 +201,7 @@ def checkDocumentation():
with open(outName, "wt") as docFile:
docFile.write(docs)
# Examine constant definitions
# Examine constant definitions
#<code>SC_CARETSTICKY_WHITESPACE</code> (2)
constPattern = re.compile(r'<code>(\w+)</code> *\((\w+)\)')
for name, val in re.findall(constPattern, docs):

View File

@ -34,7 +34,7 @@ def UpdateVersionNumbers(sci, root):
UpdateLineInFile(root / "doc/ScintillaDownload.html", " Release",
" Release " + sci.versionDotted)
ReplaceREInFile(root / "doc/ScintillaDownload.html",
r"/www.scintilla.org/([a-zA-Z]+)\d\d\d",
r"/www.scintilla.org/([a-zA-Z]+)\d{3,5}",
r"/www.scintilla.org/\g<1>" + sci.version,
0)
UpdateLineInFile(root / "doc/index.html",

View File

@ -49,8 +49,8 @@ class ScintillaData:
def __init__(self, scintillaRoot):
# Discover version information
self.version = (scintillaRoot / "version.txt").read_text().strip()
self.versionDotted = self.version[0] + '.' + self.version[1] + '.' + \
self.version[2]
self.versionDotted = self.version[0:-2] + '.' + self.version[-2] + '.' + \
self.version[-1]
self.versionCommad = self.versionDotted.replace(".", ", ") + ', 0'
with (scintillaRoot / "doc" / "index.html").open() as f:

View File

@ -605,7 +605,6 @@ class CaseConverter : public ICaseConverter {
return character < other.character;
}
};
CaseConversion conversion;
typedef std::vector<CharacterConversion> CharacterToConversion;
CharacterToConversion characterToConversion;
// The parallel arrays
@ -613,8 +612,7 @@ class CaseConverter : public ICaseConverter {
std::vector<ConversionString> conversions;
public:
explicit CaseConverter(CaseConversion conversion_) : conversion(conversion_) {
};
CaseConverter() noexcept = default;
// Deleted so CaseConverter objects can not be copied.
CaseConverter(const CaseConverter &) = delete;
CaseConverter(CaseConverter &&) = delete;
@ -690,15 +688,13 @@ public:
// Empty the original calculated data completely
CharacterToConversion().swap(characterToConversion);
}
void AddSymmetric(int lower, int upper);
void SetupConversions();
void AddSymmetric(CaseConversion conversion, int lower, int upper);
void SetupConversions(CaseConversion conversion);
};
CaseConverter caseConvFold(CaseConversion::fold);
CaseConverter caseConvUp(CaseConversion::upper);
CaseConverter caseConvLow(CaseConversion::lower);
CaseConverter caseConvList[3];
void CaseConverter::AddSymmetric(int lower, int upper) {
void CaseConverter::AddSymmetric(CaseConversion conversion, int lower, int upper) {
const int character = (conversion == CaseConversion::upper) ? lower : upper;
const int source = (conversion == CaseConversion::upper) ? upper : lower;
char converted[maxConversionLength+1]{};
@ -720,7 +716,7 @@ std::string_view NextField(std::string_view &view) {
return field;
}
void CaseConverter::SetupConversions() {
void CaseConverter::SetupConversions(CaseConversion conversion) {
// First initialize for the symmetric ranges
for (size_t i=0; i<std::size(symmetricCaseConversionRanges);) {
const int lower = symmetricCaseConversionRanges[i++];
@ -728,14 +724,14 @@ void CaseConverter::SetupConversions() {
const int length = symmetricCaseConversionRanges[i++];
const int pitch = symmetricCaseConversionRanges[i++];
for (int j=0; j<length*pitch; j+=pitch) {
AddSymmetric(lower+j, upper+j);
AddSymmetric(conversion, lower+j, upper+j);
}
}
// Add the symmetric singletons
for (size_t i=0; i<std::size(symmetricCaseConversions);) {
const int lower = symmetricCaseConversions[i++];
const int upper = symmetricCaseConversions[i++];
AddSymmetric(lower, upper);
AddSymmetric(conversion, lower, upper);
}
// Add the complex cases
std::string_view sComplex = complexCaseConversions;
@ -768,21 +764,11 @@ void CaseConverter::SetupConversions() {
}
CaseConverter *ConverterForConversion(CaseConversion conversion) {
CaseConverter *pCaseConv = &caseConvFold;
switch (conversion) {
case CaseConversion::fold:
pCaseConv = &caseConvFold;
break;
case CaseConversion::upper:
pCaseConv = &caseConvUp;
break;
case CaseConversion::lower:
default:
pCaseConv = &caseConvLow;
break;
}
const unsigned index = static_cast<unsigned>(conversion);
assert(index < std::size(caseConvList));
CaseConverter *pCaseConv = &caseConvList[index];
if (!pCaseConv->Initialised()) {
pCaseConv->SetupConversions();
pCaseConv->SetupConversions(conversion);
}
return pCaseConv;
}

View File

@ -448,6 +448,10 @@ Sci_Position SCI_METHOD Document::LineStart(Sci_Position line) const noexcept {
return cb.LineStart(line);
}
Range Document::LineRange(Sci::Line line) const noexcept {
return {cb.LineStart(line), cb.LineStart(line + 1)};
}
bool Document::IsLineStartPosition(Sci::Position position) const {
return LineStart(LineFromPosition(position)) == position;
}

View File

@ -54,6 +54,10 @@ public:
return start == end;
}
[[nodiscard]] Sci::Position Length() const noexcept {
return (start <= end) ? (end - start) : (start - end);
}
Sci::Position First() const noexcept {
return (start <= end) ? start : end;
}
@ -454,6 +458,7 @@ public:
int MarkerNumberFromLine(Sci::Line line, int which) const noexcept;
int MarkerHandleFromLine(Sci::Line line, int which) const noexcept;
Sci_Position SCI_METHOD LineStart(Sci_Position line) const noexcept override;
[[nodiscard]] Range LineRange(Sci::Line line) const noexcept;
bool IsLineStartPosition(Sci::Position position) const;
Sci_Position SCI_METHOD LineEnd(Sci_Position line) const noexcept override;
Sci::Position LineEndPosition(Sci::Position position) const;

View File

@ -397,7 +397,7 @@ void LayoutSegments(IPositionCache *pCache,
* Copy the given @a line and its styles from the document into local arrays.
* Also determine the x position at which each character starts.
*/
void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, int width) {
void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewStyle &vstyle, LineLayout *ll, int width, bool callerMultiThreaded) {
if (!ll)
return;
@ -494,7 +494,7 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
const size_t threadsForLength = std::max(1, numCharsInLine / bytesPerLayoutThread);
size_t threads = std::min<size_t>({ segments.size(), threadsForLength, maxLayoutThreads });
if (!surface->SupportsFeature(Supports::ThreadSafeMeasureWidths)) {
if (!surface->SupportsFeature(Supports::ThreadSafeMeasureWidths) || callerMultiThreaded) {
threads = 1;
}
@ -502,6 +502,7 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
const bool textUnicode = CpUtf8 == model.pdoc->dbcsCodePage;
const bool multiThreaded = threads > 1;
const bool multiThreadedContext = multiThreaded || callerMultiThreaded;
IPositionCache *pCache = posCache.get();
// If only 1 thread needed then use the main thread, else spin up multiple
@ -511,8 +512,8 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
for (size_t th = 0; th < threads; th++) {
// Find relative positions of everything except for tabs
std::future<void> fut = std::async(policy,
[pCache, surface, &vstyle, &ll, &segments, &nextIndex, textUnicode, multiThreaded]() {
LayoutSegments(pCache, surface, vstyle, ll, segments, nextIndex, textUnicode, multiThreaded);
[pCache, surface, &vstyle, &ll, &segments, &nextIndex, textUnicode, multiThreadedContext]() {
LayoutSegments(pCache, surface, vstyle, ll, segments, nextIndex, textUnicode, multiThreadedContext);
});
futures.push_back(std::move(fut));
}

View File

@ -119,7 +119,7 @@ public:
std::shared_ptr<LineLayout> RetrieveLineLayout(Sci::Line lineNumber, const EditModel &model);
void LayoutLine(const EditModel &model, Surface *surface, const ViewStyle &vstyle,
LineLayout *ll, int width);
LineLayout *ll, int width, bool callerMultiThreaded=false);
static void UpdateBidiData(const EditModel &model, const ViewStyle &vstyle, LineLayout *ll);

View File

@ -25,6 +25,9 @@
#include <iterator>
#include <memory>
#include <chrono>
#include <atomic>
#include <thread>
#include <future>
#include "ScintillaTypes.h"
#include "ScintillaMessages.h"
@ -274,6 +277,11 @@ Sci::Line Editor::TopLineOfMain() const noexcept {
return topLine;
}
Point Editor::ClientSize() const {
const PRectangle rcClient = GetClientRectangle();
return Point(rcClient.Width(), rcClient.Height());
}
PRectangle Editor::GetClientRectangle() const {
return wMain.GetClientPosition();
}
@ -290,8 +298,8 @@ PRectangle Editor::GetTextRectangle() const {
}
Sci::Line Editor::LinesOnScreen() const {
const PRectangle rcClient = GetClientRectangle();
const int htClient = static_cast<int>(rcClient.bottom - rcClient.top);
const Point sizeClient = ClientSize();
const int htClient = static_cast<int>(sizeClient.y);
//Platform::DebugPrintf("lines on screen = %d\n", htClient / lineHeight + 1);
return htClient / vs.lineHeight;
}
@ -1468,6 +1476,130 @@ bool Editor::WrapOneLine(Surface *surface, Sci::Line lineToWrap) {
return pcs->SetHeight(lineToWrap, linesWrapped);
}
namespace {
// Lines less than lengthToMultiThread are laid out in blocks in parallel.
// Longer lines are multi-threaded inside LayoutLine.
// This allows faster processing when lines differ greatly in length and thus time to lay out.
constexpr Sci::Position lengthToMultiThread = 4000;
}
bool Editor::WrapBlock(Surface *surface, Sci::Line lineToWrap, Sci::Line lineToWrapEnd) {
const size_t linesBeingWrapped = static_cast<size_t>(lineToWrapEnd - lineToWrap);
std::vector<int> linesAfterWrap(linesBeingWrapped);
size_t threads = std::min<size_t>({ linesBeingWrapped, view.maxLayoutThreads });
if (!surface->SupportsFeature(Supports::ThreadSafeMeasureWidths)) {
threads = 1;
}
const bool multiThreaded = threads > 1;
ElapsedPeriod epWrapping;
// Wrap all the short lines in multiple threads
// If only 1 thread needed then use the main thread, else spin up multiple
const std::launch policy = multiThreaded ? std::launch::async : std::launch::deferred;
std::atomic<size_t> nextIndex = 0;
// Lines that are less likely to be re-examined should not be read from or written to the cache.
const SignificantLines significantLines {
pdoc->SciLineFromPosition(sel.MainCaret()),
pcs->DocFromDisplay(topLine),
LinesOnScreen() + 1,
view.llc.GetLevel(),
};
// Protect the line layout cache from being accessed from multiple threads simultaneously
std::mutex mutexRetrieve;
std::vector<std::future<void>> futures;
for (size_t th = 0; th < threads; th++) {
std::future<void> fut = std::async(policy,
[=, &surface, &nextIndex, &linesAfterWrap, &mutexRetrieve]() {
// llTemporary is reused for non-significant lines, avoiding allocation costs.
std::shared_ptr<LineLayout> llTemporary = std::make_shared<LineLayout>(-1, 200);
while (true) {
const size_t i = nextIndex.fetch_add(1, std::memory_order_acq_rel);
if (i >= linesBeingWrapped) {
break;
}
const Sci::Line lineNumber = lineToWrap + i;
const Range rangeLine = pdoc->LineRange(lineNumber);
const Sci::Position lengthLine = rangeLine.Length();
if (lengthLine < lengthToMultiThread) {
std::shared_ptr<LineLayout> ll;
if (significantLines.LineMayCache(lineNumber)) {
std::lock_guard<std::mutex> guard(mutexRetrieve);
ll = view.RetrieveLineLayout(lineNumber, *this);
} else {
ll = llTemporary;
ll->ReSet(lineNumber, lengthLine);
}
view.LayoutLine(*this, surface, vs, ll.get(), wrapWidth, multiThreaded);
linesAfterWrap[i] = ll->lines;
}
}
});
futures.push_back(std::move(fut));
}
for (const std::future<void> &f : futures) {
f.wait();
}
// End of multiple threads
// Multiply duration by number of threads to produce (near) equivalence to duration if single threaded
const double durationShortLines = epWrapping.Duration(true);
const double durationShortLinesThreads = durationShortLines * threads;
// Wrap all the long lines in the main thread.
// LayoutLine may then multi-thread over segments in each line.
std::shared_ptr<LineLayout> llLarge = std::make_shared<LineLayout>(-1, 200);
for (size_t indexLarge = 0; indexLarge < linesBeingWrapped; indexLarge++) {
const Sci::Line lineNumber = lineToWrap + indexLarge;
const Range rangeLine = pdoc->LineRange(lineNumber);
const Sci::Position lengthLine = rangeLine.Length();
if (lengthLine >= lengthToMultiThread) {
std::shared_ptr<LineLayout> ll;
if (significantLines.LineMayCache(lineNumber)) {
ll = view.RetrieveLineLayout(lineNumber, *this);
} else {
ll = llLarge;
ll->ReSet(lineNumber, lengthLine);
}
view.LayoutLine(*this, surface, vs, ll.get(), wrapWidth);
linesAfterWrap[indexLarge] = ll->lines;
}
}
const double durationLongLines = epWrapping.Duration();
const size_t bytesBeingWrapped = pdoc->LineStart(lineToWrap + linesBeingWrapped) - pdoc->LineStart(lineToWrap);
size_t wrapsDone = 0;
for (size_t i = 0; i < linesBeingWrapped; i++) {
const Sci::Line lineNumber = lineToWrap + i;
int linesWrapped = linesAfterWrap[i];
if (vs.annotationVisible != AnnotationVisible::Hidden) {
linesWrapped += pdoc->AnnotationLines(lineNumber);
}
if (pcs->SetHeight(lineNumber, linesWrapped)) {
wrapsDone++;
}
wrapPending.Wrapped(lineNumber);
}
durationWrapOneByte.AddSample(bytesBeingWrapped, durationShortLinesThreads + durationLongLines);
return wrapsDone > 0;
}
// Perform wrapping for a subset of the lines needing wrapping.
// wsAll: wrap all lines which need wrapping in this single call
// wsVisible: wrap currently visible lines
@ -1549,16 +1681,7 @@ bool Editor::WrapLines(WrapScope ws) {
if (surface) {
//Platform::DebugPrintf("Wraplines: scope=%0d need=%0d..%0d perform=%0d..%0d\n", ws, wrapPending.start, wrapPending.end, lineToWrap, lineToWrapEnd);
const size_t bytesBeingWrapped = pdoc->LineStart(lineToWrapEnd) - pdoc->LineStart(lineToWrap);
ElapsedPeriod epWrapping;
while (lineToWrap < lineToWrapEnd) {
if (WrapOneLine(surface, lineToWrap)) {
wrapOccurred = true;
}
wrapPending.Wrapped(lineToWrap);
lineToWrap++;
}
durationWrapOneByte.AddSample(bytesBeingWrapped, epWrapping.Duration());
wrapOccurred = WrapBlock(surface, lineToWrap, lineToWrapEnd);
goodTopLine = pcs->DisplayFromDoc(lineDocTop) + std::min(
subLineTop, static_cast<Sci::Line>(pcs->GetHeight(lineDocTop)-1));

View File

@ -312,6 +312,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
Point GetVisibleOriginInMain() const override;
PointDocument DocumentPointFromView(Point ptView) const; // Convert a point from view space to document
Sci::Line TopLineOfMain() const noexcept final; // Return the line at Main's y coordinate 0
virtual Point ClientSize() const;
virtual PRectangle GetClientRectangle() const;
virtual PRectangle GetClientDrawingRectangle();
PRectangle GetTextRectangle() const;
@ -403,6 +404,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
bool Wrapping() const noexcept;
void NeedWrapping(Sci::Line docLineStart=0, Sci::Line docLineEnd=WrapPending::lineLarge);
bool WrapOneLine(Surface *surface, Sci::Line lineToWrap);
bool WrapBlock(Surface *surface, Sci::Line lineToWrap, Sci::Line lineToWrapEnd);
enum class WrapScope {wsAll, wsVisible, wsIdle};
bool WrapLines(WrapScope ws);
void LinesJoin();

View File

@ -102,6 +102,13 @@ void LineLayout::Resize(int maxLineLength_) {
}
}
void LineLayout::ReSet(Sci::Line lineNumber_, Sci::Position maxLineLength_) {
lineNumber = lineNumber_;
Resize(static_cast<int>(maxLineLength_));
lines = 0;
Invalidate(ValidLevel::invalid);
}
void LineLayout::EnsureBidiData() {
if (!bidiData) {
bidiData = std::make_unique<BidiData>();
@ -114,6 +121,7 @@ void LineLayout::Free() noexcept {
styles.reset();
positions.reset();
lineStarts.reset();
lenLineStarts = 0;
bidiData.reset();
}
@ -446,6 +454,21 @@ XYPOSITION ScreenLine::TabPositionAfter(XYPOSITION xPosition) const noexcept {
return (std::floor((xPosition + TabWidthMinimumPixels()) / TabWidth()) + 1) * TabWidth();
}
bool SignificantLines::LineMayCache(Sci::Line line) const noexcept {
switch (level) {
case LineCache::None:
return false;
case LineCache::Caret:
return line == lineCaret;
case LineCache::Page:
return (abs(line - lineCaret) < linesOnScreen) ||
((line >= lineTop) && (line <= (lineTop + linesOnScreen)));
case LineCache::Document:
default:
return true;
}
}
LineLayoutCache::LineLayoutCache() :
level(LineCache::None),
allInvalidated(false), styleClock(-1) {

View File

@ -83,6 +83,7 @@ public:
void operator=(LineLayout &&) = delete;
virtual ~LineLayout();
void Resize(int maxLineLength_);
void ReSet(Sci::Line lineNumber_, Sci::Position maxLineLength_);
void EnsureBidiData();
void Free() noexcept;
void ClearPositions();
@ -140,6 +141,14 @@ struct ScreenLine : public IScreenLine {
XYPOSITION TabPositionAfter(XYPOSITION xPosition) const noexcept override;
};
struct SignificantLines {
Sci::Line lineCaret;
Sci::Line lineTop;
Sci::Line linesOnScreen;
Scintilla::LineCache level;
bool LineMayCache(Sci::Line line) const noexcept;
};
/**
*/
class LineLayoutCache {

View File

@ -1 +1 @@
533
534

View File

@ -6,8 +6,8 @@
#include <windows.h>
#define VERSION_SCINTILLA "5.3.3"
#define VERSION_WORDS 5, 3, 3, 0
#define VERSION_SCINTILLA "5.3.4"
#define VERSION_WORDS 5, 3, 4, 0
VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_WORDS