Update: Scintilla 5.3.5 Lexilla 5.2.5

update to Scinitlla Release 5.3.5 (https://www.scintilla.org/scintilla535.zip)

    Released 31 May 2023.
    On Win32, implement IME context sensitivity with IMR_DOCUMENTFEED. Feature #1310.
    On Win32 remove dependence on MSIMG32.DLL by replacing AlphaBlend by GdiAlphaBlend. Bug #1923.
    On Qt, stop movement of IME candidate box.
    On Qt, report correct caret position within paragraph for IME retrieve surrounding text.
    On Qt for Cocoa, fix crash in entry of multi-character strings with IME.

and Lexilla Release 5.2.5 (https://www.scintilla.org/lexilla525.zip)

    Released 31 May 2023.
    Add CharacterSetArray constructor without setBase initial argument for common case where this is setNone and the initialSet argument completely defines the characters. This shortens and clarifies use of CharacterSetArray.
    Bash: implement highlighting inside quoted elements and here-docs. Controlled with properties lexer.bash.styling.inside.string, lexer.bash.styling.inside.backticks, lexer.bash.styling.inside.parameter, and lexer.bash.styling.inside.heredoc. Issue #154, Issue #153, Feature #1033.
    Bash: add property lexer.bash.command.substitution to choose how to style command substitutions. 0 → SCE_SH_BACKTICKS; 1 → surrounding "$(" and ")" as operators and contents styled as bash code; 2 → use distinct styles (base style + 64) for contents. Choice (2) is a provisional feature and details may change before it is finalized. Issue #153.
    Bash: fix nesting of parameters (SCE_SH_PARAM) like ${var/$sub/"${rep}}"}. Issue #154.
    Bash: fix single character special parameters like $? by limiting style. Issue #154.
    Bash: treat "$$" as special parameter and end scalars before "$". Issue #154.
    Bash: treat "<<" in arithmetic contexts as left bitwise shift operator instead of here-doc. Issue #137.
    Batch: style SCE_BAT_AFTER_LABEL used for rest of line after label which is not executed. Issue #148.
    F#: Lex interpolated verbatim strings as verbatim. Issue #156.
    VB: allow multiline strings when lexer.vb.strings.multiline set. Issue #151.

Close #13729
This commit is contained in:
Christian Grasser 2023-06-01 01:11:12 +02:00 committed by Don Ho
parent 043bd4f385
commit b39ca37c3a
95 changed files with 2047 additions and 856 deletions

View File

@ -29,7 +29,6 @@ shadowVariable:lexilla/lexers/LexAU3.cxx
constParameter:lexilla/lexers/LexBaan.cxx constParameter:lexilla/lexers/LexBaan.cxx
unreadVariable:lexilla/lexers/LexBaan.cxx unreadVariable:lexilla/lexers/LexBaan.cxx
constParameter:lexilla/lexers/LexBash.cxx constParameter:lexilla/lexers/LexBash.cxx
uninitMemberVar:lexilla/lexers/LexBash.cxx
variableScope:lexilla/lexers/LexBash.cxx variableScope:lexilla/lexers/LexBash.cxx
variableScope:lexilla/lexers/LexCmake.cxx variableScope:lexilla/lexers/LexCmake.cxx
knownConditionTrueFalse:lexilla/lexers/LexCmake.cxx knownConditionTrueFalse:lexilla/lexers/LexCmake.cxx
@ -46,7 +45,6 @@ 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 redundantContinue:lexilla/lexers/LexFortran.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
variableScope:lexilla/lexers/LexGui4Cli.cxx variableScope:lexilla/lexers/LexGui4Cli.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="20230313" /> <meta name="Date.Modified" content="20230531" />
<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.2.4<br /> <font color="#FFCC99" size="3">Release version 5.2.5<br />
Site last modified March 13 2023</font> Site last modified May 31 2023</font>
</td> </td>
<td width="20%"> <td width="20%">
&nbsp; &nbsp;
@ -77,13 +77,12 @@
</tr> </tr>
</table> </table>
<ul id="versionlist"> <ul id="versionlist">
<li>Version 5.2.5 improves Bash, Batch, F#, and VB.</li>
<li>Version 5.2.4 improves C++ and GDScript.</li> <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.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.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.1 improves Batch, F#, Markdown, and PowerShell.</li>
<li>Version 5.2.0 improves PowerShell and R.</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>
</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/lexilla524.zip"> <font size="4"> <a href="https://www.scintilla.org/lexilla525.zip">
Windows</a>&nbsp;&nbsp; Windows</a>&nbsp;&nbsp;
<a href="https://www.scintilla.org/lexilla524.tgz"> <a href="https://www.scintilla.org/lexilla525.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.2.4 Release 5.2.5
</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/lexilla524.zip">zip format</a> (1.2M) commonly used on Windows</li> <li><a href="https://www.scintilla.org/lexilla525.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> <li><a href="https://www.scintilla.org/lexilla525.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,63 @@
</tr> </tr>
</table> </table>
<h2>Releases</h2> <h2>Releases</h2>
<h3>
<a href="https://www.scintilla.org/lexilla525.zip">Release 5.2.5</a>
</h3>
<ul>
<li>
Released 31 May 2023.
</li>
<li>
Add CharacterSetArray constructor without setBase initial argument for common case
where this is setNone and the initialSet argument completely defines the characters.
This shortens and clarifies use of CharacterSetArray.
</li>
<li>
Bash: implement highlighting inside quoted elements and here-docs.
Controlled with properties lexer.bash.styling.inside.string, lexer.bash.styling.inside.backticks,
lexer.bash.styling.inside.parameter, and lexer.bash.styling.inside.heredoc.
<a href="https://github.com/ScintillaOrg/lexilla/issues/154">Issue #154</a>,
<a href="https://github.com/ScintillaOrg/lexilla/issues/153">Issue #153</a>,
<a href="https://sourceforge.net/p/scintilla/feature-requests/1033/">Feature #1033</a>.
</li>
<li>
Bash: add property lexer.bash.command.substitution to choose how to style command substitutions.
0 &rarr; SCE_SH_BACKTICKS;
1 &rarr; surrounding "$(" and ")" as operators and contents styled as bash code;
2 &rarr; use distinct styles (base style + 64) for contents.
Choice (2) is a provisional feature and details may change before it is finalized.
<a href="https://github.com/ScintillaOrg/lexilla/issues/153">Issue #153</a>.
</li>
<li>
Bash: fix nesting of parameters (SCE_SH_PARAM) like ${var/$sub/"${rep}}"}.
<a href="https://github.com/ScintillaOrg/lexilla/issues/154">Issue #154</a>.
</li>
<li>
Bash: fix single character special parameters like $? by limiting style.
<a href="https://github.com/ScintillaOrg/lexilla/issues/154">Issue #154</a>.
</li>
<li>
Bash: treat "$$" as special parameter and end scalars before "$".
<a href="https://github.com/ScintillaOrg/lexilla/issues/154">Issue #154</a>.
</li>
<li>
Bash: treat "&lt;&lt;" in arithmetic contexts as left bitwise shift operator instead of here-doc.
<a href="https://github.com/ScintillaOrg/lexilla/issues/137">Issue #137</a>.
</li>
<li>
Batch: style SCE_BAT_AFTER_LABEL used for rest of line after label which is not executed.
<a href="https://github.com/ScintillaOrg/lexilla/issues/148">Issue #148</a>.
</li>
<li>
F#: Lex interpolated verbatim strings as verbatim.
<a href="https://github.com/ScintillaOrg/lexilla/issues/156">Issue #156</a>.
</li>
<li>
VB: allow multiline strings when lexer.vb.strings.multiline set.
<a href="https://github.com/ScintillaOrg/lexilla/issues/151">Issue #151</a>.
</li>
</ul>
<h3> <h3>
<a href="https://www.scintilla.org/lexilla524.zip">Release 5.2.4</a> <a href="https://www.scintilla.org/lexilla524.zip">Release 5.2.4</a>
</h3> </h3>

View File

@ -602,6 +602,7 @@ val SCE_BAT_HIDE=4
val SCE_BAT_COMMAND=5 val SCE_BAT_COMMAND=5
val SCE_BAT_IDENTIFIER=6 val SCE_BAT_IDENTIFIER=6
val SCE_BAT_OPERATOR=7 val SCE_BAT_OPERATOR=7
val SCE_BAT_AFTER_LABEL=8
# Lexical states for SCLEX_TCMD # Lexical states for SCLEX_TCMD
lex TCMD=SCLEX_TCMD SCE_TCMD_ lex TCMD=SCLEX_TCMD SCE_TCMD_
val SCE_TCMD_DEFAULT=0 val SCE_TCMD_DEFAULT=0

View File

@ -676,6 +676,7 @@
#define SCE_BAT_COMMAND 5 #define SCE_BAT_COMMAND 5
#define SCE_BAT_IDENTIFIER 6 #define SCE_BAT_IDENTIFIER 6
#define SCE_BAT_OPERATOR 7 #define SCE_BAT_OPERATOR 7
#define SCE_BAT_AFTER_LABEL 8
#define SCE_TCMD_DEFAULT 0 #define SCE_TCMD_DEFAULT 0
#define SCE_TCMD_COMMENT 1 #define SCE_TCMD_COMMENT 1
#define SCE_TCMD_WORD 2 #define SCE_TCMD_WORD 2

File diff suppressed because it is too large Load Diff

View File

@ -5,12 +5,12 @@
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> // Copyright 1998-2001 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 <cstdlib>
#include <string.h> #include <cassert>
#include <stdio.h> #include <cstring>
#include <stdarg.h> #include <cctype>
#include <assert.h> #include <cstdio>
#include <ctype.h> #include <cstdarg>
#include <string> #include <string>
#include <string_view> #include <string_view>
@ -79,7 +79,7 @@ bool textQuoted(const char *lineBuffer, Sci_PositionU endPos) {
const size_t strLength = strlen(strQuotes); const size_t strLength = strlen(strQuotes);
for (size_t i = 0; i < strLength; i++) { for (size_t i = 0; i < strLength; i++) {
const char *pQuote = strchr(strBuffer, strQuotes[i]); const char *pQuote = strchr(strBuffer, strQuotes[i]);
while (pQuote != NULL) while (pQuote)
{ {
if (!IsEscaped(strBuffer, pQuote - strBuffer)) { if (!IsEscaped(strBuffer, pQuote - strBuffer)) {
CurrentStatus = !CurrentStatus; CurrentStatus = !CurrentStatus;
@ -159,7 +159,17 @@ void ColouriseBatchDoc(
styler.ColourTo(endPos, SCE_BAT_COMMENT); styler.ColourTo(endPos, SCE_BAT_COMMENT);
} else { } else {
// Colorize Real Label // Colorize Real Label
styler.ColourTo(endPos, SCE_BAT_LABEL); // :[\t ]*[^\t &+:<>|]+
const char *startLabelName = lineBuffer + offset + 1;
const size_t whitespaceLength = strspn(startLabelName, "\t ");
// Set of label-terminating characters determined experimentally
const char *endLabel = strpbrk(startLabelName + whitespaceLength, "\t &+:<>|");
if (endLabel) {
styler.ColourTo(startLine + offset + endLabel - startLabelName, SCE_BAT_LABEL);
styler.ColourTo(endPos, SCE_BAT_AFTER_LABEL); // New style
} else {
styler.ColourTo(endPos, SCE_BAT_LABEL);
}
} }
stopLineProcessing=true; stopLineProcessing=true;
// Check for Drive Change (Drive Change is internal command) - return if found // Check for Drive Change (Drive Change is internal command) - return if found
@ -630,9 +640,9 @@ void ColouriseBatchDoc(
const char *const batchWordListDesc[] = { const char *const batchWordListDesc[] = {
"Internal Commands", "Internal Commands",
"External Commands", "External Commands",
0 nullptr
}; };
} }
LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", 0, batchWordListDesc); LexerModule lmBatch(SCLEX_BATCH, ColouriseBatchDoc, "batch", nullptr, batchWordListDesc);

View File

@ -162,7 +162,7 @@ void highlightTaskMarker(StyleContext &sc, LexAccessor &styler,
class EscapeSequence { class EscapeSequence {
const CharacterSet setHexDigits = CharacterSet(CharacterSet::setDigits, "ABCDEFabcdef"); const CharacterSet setHexDigits = CharacterSet(CharacterSet::setDigits, "ABCDEFabcdef");
const CharacterSet setOctDigits = CharacterSet(CharacterSet::setNone, "01234567"); const CharacterSet setOctDigits = CharacterSet("01234567");
const CharacterSet setNoneNumeric; const CharacterSet setNoneNumeric;
const CharacterSet *escapeSetValid = nullptr; const CharacterSet *escapeSetValid = nullptr;
int digitsLeft = 0; int digitsLeft = 0;
@ -537,11 +537,11 @@ public:
explicit LexerCPP(bool caseSensitive_) : explicit LexerCPP(bool caseSensitive_) :
caseSensitive(caseSensitive_), caseSensitive(caseSensitive_),
setWord(CharacterSet::setAlphaNum, "._", true), setWord(CharacterSet::setAlphaNum, "._", true),
setNegationOp(CharacterSet::setNone, "!"), setNegationOp("!"),
setAddOp(CharacterSet::setNone, "+-"), setAddOp("+-"),
setMultOp(CharacterSet::setNone, "*/%"), setMultOp("*/%"),
setRelOp(CharacterSet::setNone, "=!<>"), setRelOp("=!<>"),
setLogicalOp(CharacterSet::setNone, "|&"), setLogicalOp("|&"),
subStyles(styleSubable, 0x80, 0x40, inactiveFlag) { subStyles(styleSubable, 0x80, 0x40, inactiveFlag) {
} }
// Deleted so LexerCPP objects can not be copied. // Deleted so LexerCPP objects can not be copied.
@ -770,14 +770,14 @@ void SCI_METHOD LexerCPP::Lex(Sci_PositionU startPos, Sci_Position length, int i
const StyleContext::Transform transform = caseSensitive ? const StyleContext::Transform transform = caseSensitive ?
StyleContext::Transform::none : StyleContext::Transform::lower; StyleContext::Transform::none : StyleContext::Transform::lower;
const CharacterSet setOKBeforeRE(CharacterSet::setNone, "([{=,:;!%^&*|?~+-"); const CharacterSet setOKBeforeRE("([{=,:;!%^&*|?~+-");
const CharacterSet setCouldBePostOp(CharacterSet::setNone, "+-"); const CharacterSet setCouldBePostOp("+-");
const CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]"); const CharacterSet setDoxygen(CharacterSet::setAlpha, "$@\\&<>#{}[]");
setWordStart = CharacterSet(CharacterSet::setAlpha, "_", true); setWordStart = CharacterSet(CharacterSet::setAlpha, "_", true);
const CharacterSet setInvalidRawFirst(CharacterSet::setNone, " )\\\t\v\f\n"); const CharacterSet setInvalidRawFirst(" )\\\t\v\f\n");
if (options.identifiersAllowDollars) { if (options.identifiersAllowDollars) {
setWordStart.Add('$'); setWordStart.Add('$');

View File

@ -84,12 +84,15 @@ struct OptionSetFSharp : public OptionSet<OptionsFSharp> {
struct FSharpString { struct FSharpString {
Sci_Position startPos = INVALID_POSITION; Sci_Position startPos = INVALID_POSITION;
int startChar = '"'; int startChar = '"', nextChar = '\0';
constexpr bool HasLength() const { constexpr bool HasLength() const {
return startPos > INVALID_POSITION; return startPos > INVALID_POSITION;
} }
constexpr bool CanInterpolate() const { constexpr bool CanInterpolate() const {
return startChar == '$'; return startChar == '$' || (startChar == '@' && nextChar == '$');
}
constexpr bool IsVerbatim() const {
return startChar == '@' || (startChar == '$' && nextChar == '@');
} }
}; };
@ -207,8 +210,9 @@ inline bool MatchQuotedExpressionEnd(const StyleContext &cxt) {
return (cxt.ch == '>' && cxt.chPrev == '@'); return (cxt.ch == '>' && cxt.chPrev == '@');
} }
inline bool MatchStringStart(const StyleContext &cxt) { inline bool MatchStringStart(StyleContext &cxt) {
return (cxt.ch == '"' || cxt.Match('@', '"') || cxt.Match('$', '"') || cxt.Match('`', '`')); return (cxt.ch == '"' || cxt.Match("@\"") || cxt.Match("$\"") || cxt.Match("@$\"") || cxt.Match("$@\"") ||
cxt.Match("``"));
} }
inline bool FollowsEscapedBackslash(StyleContext &cxt) { inline bool FollowsEscapedBackslash(StyleContext &cxt) {
@ -223,21 +227,21 @@ inline bool MatchStringEnd(StyleContext &cxt, const FSharpString &fsStr) {
// end of quoted identifier? // end of quoted identifier?
((cxt.ch == '`' && cxt.chPrev == '`') || ((cxt.ch == '`' && cxt.chPrev == '`') ||
// end of literal or interpolated triple-quoted string? // end of literal or interpolated triple-quoted string?
((fsStr.startChar == '"' || (fsStr.CanInterpolate() && cxt.chPrev != '$')) && ((fsStr.startChar == '"' || (fsStr.CanInterpolate() && !(fsStr.IsVerbatim() || cxt.chPrev == '$'))) &&
cxt.MatchIgnoreCase("\"\"\"")) || cxt.MatchIgnoreCase("\"\"\"")) ||
// end of verbatim string? // end of verbatim string?
(fsStr.startChar == '@' && (fsStr.IsVerbatim() &&
// embedded quotes must be in pairs // embedded quotes must be in pairs
cxt.ch == '"' && cxt.chNext != '"' && cxt.ch == '"' && cxt.chNext != '"' &&
(cxt.chPrev != '"' || (cxt.chPrev == '"' && (cxt.chPrev != '"' ||
// empty verbatim string? // empty verbatim string?
(cxt.GetRelative(-2) == '@' || ((cxt.GetRelative(-2) == '@' || cxt.GetRelative(-2) == '$') ||
// pair of quotes at end of string? // pair of quotes at end of string?
(cxt.GetRelative(-2) == '"' && cxt.GetRelative(-3) != '@'))))))) || (cxt.GetRelative(-2) == '"' && !(cxt.GetRelative(-3) == '@' || cxt.GetRelative(-3) == '$'))))))) ||
(!fsStr.HasLength() && cxt.ch == '"' && (!fsStr.HasLength() && cxt.ch == '"' &&
((cxt.chPrev != '\\' || (cxt.GetRelative(-2) == '\\' && !FollowsEscapedBackslash(cxt))) || ((cxt.chPrev != '\\' || (cxt.GetRelative(-2) == '\\' && !FollowsEscapedBackslash(cxt))) ||
// treat backslashes as char literals in verbatim strings // treat backslashes as char literals in verbatim strings
(fsStr.startChar == '@' && cxt.chPrev == '\\'))); (fsStr.IsVerbatim() && cxt.chPrev == '\\')));
} }
inline bool MatchCharacterStart(StyleContext &cxt) { inline bool MatchCharacterStart(StyleContext &cxt) {
@ -251,8 +255,8 @@ inline bool CanEmbedQuotes(StyleContext &cxt) {
// - https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/strings // - https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/strings
// - https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/interpolated-strings#syntax // - https://docs.microsoft.com/en-us/dotnet/fsharp/language-reference/interpolated-strings#syntax
// - https://fsharp.org/specs/language-spec/4.1/FSharpSpec-4.1-latest.pdf#page=25&zoom=auto,-98,600 // - https://fsharp.org/specs/language-spec/4.1/FSharpSpec-4.1-latest.pdf#page=25&zoom=auto,-98,600
return cxt.MatchIgnoreCase("$\"\"\"") || cxt.MatchIgnoreCase("\"\"\"") || cxt.Match('@', '"') || return cxt.Match("$\"\"\"") || cxt.Match("\"\"\"") || cxt.Match("@$\"\"\"") || cxt.Match("$@\"\"\"") ||
cxt.Match('`', '`'); cxt.Match('@', '"') || cxt.Match('`', '`');
} }
inline bool IsLineEnd(StyleContext &cxt, const Sci_Position offset) { inline bool IsLineEnd(StyleContext &cxt, const Sci_Position offset) {
@ -407,6 +411,7 @@ void SCI_METHOD LexerFSharp::Lex(Sci_PositionU start, Sci_Position length, int i
state = SCE_FSHARP_CHARACTER; state = SCE_FSHARP_CHARACTER;
} else if (MatchStringStart(sc)) { } else if (MatchStringStart(sc)) {
fsStr.startChar = sc.ch; fsStr.startChar = sc.ch;
fsStr.nextChar = sc.chNext;
fsStr.startPos = INVALID_POSITION; fsStr.startPos = INVALID_POSITION;
if (CanEmbedQuotes(sc)) { if (CanEmbedQuotes(sc)) {
// double quotes after this position should be non-terminating // double quotes after this position should be non-terminating
@ -414,7 +419,7 @@ void SCI_METHOD LexerFSharp::Lex(Sci_PositionU start, Sci_Position length, int i
} }
if (sc.ch == '`') { if (sc.ch == '`') {
state = SCE_FSHARP_QUOT_IDENTIFIER; state = SCE_FSHARP_QUOT_IDENTIFIER;
} else if (sc.ch == '@') { } else if (fsStr.IsVerbatim()) {
state = SCE_FSHARP_VERBATIM; state = SCE_FSHARP_VERBATIM;
} else { } else {
state = SCE_FSHARP_STRING; state = SCE_FSHARP_STRING;
@ -542,7 +547,7 @@ void SCI_METHOD LexerFSharp::Lex(Sci_PositionU start, Sci_Position length, int i
} else if (sc.chNext == '}') { } else if (sc.chNext == '}') {
isInterpolated = false; isInterpolated = false;
sc.Forward(); sc.Forward();
state = SCE_FSHARP_STRING; state = fsStr.IsVerbatim() ? SCE_FSHARP_VERBATIM : SCE_FSHARP_STRING;
} }
} else if (fsStr.CanInterpolate() && sc.ch == '{') { } else if (fsStr.CanInterpolate() && sc.ch == '{') {
isInterpolated = true; isInterpolated = true;
@ -607,7 +612,7 @@ void SCI_METHOD LexerFSharp::Lex(Sci_PositionU start, Sci_Position length, int i
!(setFormatFlags.Contains(sc.ch) || IsADigit(sc.ch)) || !(setFormatFlags.Contains(sc.ch) || IsADigit(sc.ch)) ||
(setFormatFlags.Contains(sc.ch) && sc.ch == sc.chNext))) { (setFormatFlags.Contains(sc.ch) && sc.ch == sc.chNext))) {
colorSpan++; colorSpan++;
state = (fsStr.startChar == '@') ? SCE_FSHARP_VERBATIM : SCE_FSHARP_STRING; state = fsStr.IsVerbatim() ? SCE_FSHARP_VERBATIM : SCE_FSHARP_STRING;
} }
break; break;
} }

View File

@ -65,9 +65,9 @@ static void ColouriseLuaDoc(
// Not exactly following number definition (several dots are seen as OK, etc.) // Not exactly following number definition (several dots are seen as OK, etc.)
// but probably enough in most cases. [pP] is for hex floats. // but probably enough in most cases. [pP] is for hex floats.
CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefpABCDEFP"); CharacterSet setNumber(CharacterSet::setDigits, ".-+abcdefpABCDEFP");
CharacterSet setExponent(CharacterSet::setNone, "eEpP"); CharacterSet setExponent("eEpP");
CharacterSet setLuaOperator(CharacterSet::setNone, "*/-+()={}~[];<>,.^%:#&|"); CharacterSet setLuaOperator("*/-+()={}~[];<>,.^%:#&|");
CharacterSet setEscapeSkip(CharacterSet::setNone, "\"'\\"); CharacterSet setEscapeSkip("\"'\\");
Sci_Position currentLine = styler.GetLine(startPos); Sci_Position currentLine = styler.GetLine(startPos);
// Initialize long string [[ ... ]] or block comment --[[ ... ]], // Initialize long string [[ ... ]] or block comment --[[ ... ]],

View File

@ -72,6 +72,10 @@ static void ColouriseVBDoc(Sci_PositionU startPos, Sci_Position length, int init
int visibleChars = 0; int visibleChars = 0;
int fileNbDigits = 0; int fileNbDigits = 0;
// property lexer.vb.strings.multiline
// Set to 1 to allow strings to continue over line ends.
bool allowMultilineStr = styler.GetPropertyInt("lexer.vb.strings.multiline", 0) != 0;
// Do not leak onto next line // Do not leak onto next line
if (initStyle == SCE_B_STRINGEOL || initStyle == SCE_B_COMMENT || initStyle == SCE_B_PREPROCESSOR) { if (initStyle == SCE_B_STRINGEOL || initStyle == SCE_B_COMMENT || initStyle == SCE_B_PREPROCESSOR) {
initStyle = SCE_B_DEFAULT; initStyle = SCE_B_DEFAULT;
@ -134,7 +138,7 @@ static void ColouriseVBDoc(Sci_PositionU startPos, Sci_Position length, int init
} }
sc.ForwardSetState(SCE_B_DEFAULT); sc.ForwardSetState(SCE_B_DEFAULT);
} }
} else if (sc.atLineEnd) { } else if (sc.atLineEnd && !allowMultilineStr) {
visibleChars = 0; visibleChars = 0;
sc.ChangeState(SCE_B_STRINGEOL); sc.ChangeState(SCE_B_STRINGEOL);
sc.ForwardSetState(SCE_B_DEFAULT); sc.ForwardSetState(SCE_B_DEFAULT);

View File

@ -33,6 +33,9 @@ public:
if (base & setDigits) if (base & setDigits)
AddString("0123456789"); AddString("0123456789");
} }
CharacterSetArray(const char *initialSet, bool valueAfter_=false) noexcept :
CharacterSetArray(setNone, initialSet, valueAfter_) {
}
// For compatibility with previous version but should not be used in new code. // For compatibility with previous version but should not be used in new code.
CharacterSetArray(setBase base, const char *initialSet, [[maybe_unused]]int size_, bool valueAfter_=false) noexcept : CharacterSetArray(setBase base, const char *initialSet, [[maybe_unused]]int size_, bool valueAfter_=false) noexcept :
CharacterSetArray(base, initialSet, valueAfter_) { CharacterSetArray(base, initialSet, valueAfter_) {

View File

@ -35,8 +35,7 @@ DefaultLexer::DefaultLexer(const char *languageName_, int language_,
nClasses(nClasses_) { nClasses(nClasses_) {
} }
DefaultLexer::~DefaultLexer() { DefaultLexer::~DefaultLexer() = default;
}
void SCI_METHOD DefaultLexer::Release() { void SCI_METHOD DefaultLexer::Release() {
delete this; delete this;

View File

@ -116,7 +116,7 @@ void LexerModule::Fold(Sci_PositionU startPos, Sci_Position lengthDoc, int initS
startPos = newStartPos; startPos = newStartPos;
initStyle = 0; initStyle = 0;
if (startPos > 0) { if (startPos > 0) {
initStyle = styler.StyleAt(startPos - 1); initStyle = styler.StyleIndexAt(startPos - 1);
} }
} }
fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler); fnFolder(startPos, lengthDoc, initStyle, keywordlists, styler);

View File

@ -22,7 +22,7 @@ using namespace Lexilla;
namespace { namespace {
typedef std::map<std::string, std::string, std::less<>> mapss; using mapss = std::map<std::string, std::string, std::less<>>;
mapss *PropsFromPointer(void *impl) noexcept { mapss *PropsFromPointer(void *impl) noexcept {
return static_cast<mapss *>(impl); return static_cast<mapss *>(impl);
@ -45,7 +45,7 @@ bool PropSetSimple::Set(std::string_view key, std::string_view val) {
mapss *props = PropsFromPointer(impl); mapss *props = PropsFromPointer(impl);
if (!props) if (!props)
return false; return false;
mapss::iterator it = props->find(key); mapss::iterator const it = props->find(key);
if (it != props->end()) { if (it != props->end()) {
if (val == it->second) if (val == it->second)
return false; return false;
@ -59,7 +59,7 @@ bool PropSetSimple::Set(std::string_view key, std::string_view val) {
const char *PropSetSimple::Get(std::string_view key) const { const char *PropSetSimple::Get(std::string_view key) const {
mapss *props = PropsFromPointer(impl); mapss *props = PropsFromPointer(impl);
if (props) { if (props) {
mapss::const_iterator keyPos = props->find(key); mapss::const_iterator const keyPos = props->find(key);
if (keyPos != props->end()) { if (keyPos != props->end()) {
return keyPos->second.c_str(); return keyPos->second.c_str();
} }

View File

@ -134,7 +134,7 @@ bool WordList::Set(const char *s) {
len = lenTemp; len = lenTemp;
std::fill(starts, std::end(starts), -1); std::fill(starts, std::end(starts), -1);
for (int l = static_cast<int>(len - 1); l >= 0; l--) { for (int l = static_cast<int>(len - 1); l >= 0; l--) {
unsigned char indexChar = words[l][0]; unsigned char const indexChar = words[l][0];
starts[indexChar] = l; starts[indexChar] = l;
} }
return true; return true;

View File

@ -41,24 +41,24 @@ sys.path.append(str(thisPath.parent.parent.parent / "scintilla" / "scripts"))
import FileGenerator import FileGenerator
neutralEncoding = "cp437" # Each byte value is valid in cp437 neutralEncoding = "iso-8859-1" # Each byte value is valid in iso-8859-1
def FindModules(lexFile): def FindModules(lexFile):
modules = [] modules = []
partLine = "" partLine = ""
with lexFile.open(encoding=neutralEncoding) as f: with lexFile.open(encoding=neutralEncoding) as f:
lineNum = 0 lineNum = 0
for l in f.readlines(): for line in f.readlines():
lineNum += 1 lineNum += 1
l = l.rstrip() line = line.rstrip()
if partLine or l.startswith("LexerModule"): if partLine or line.startswith("LexerModule"):
if ")" in l: if ")" in line:
l = partLine + l line = partLine + line
original = l original = line
l = l.replace("(", " ") line = line.replace("(", " ")
l = l.replace(")", " ") line = line.replace(")", " ")
l = l.replace(",", " ") line = line.replace(",", " ")
parts = l.split() parts = line.split()
lexerName = parts[4] lexerName = parts[4]
if not (lexerName.startswith('"') and lexerName.endswith('"')): if not (lexerName.startswith('"') and lexerName.endswith('"')):
print(f"{lexFile}:{lineNum}: Bad LexerModule statement:\n{original}") print(f"{lexFile}:{lineNum}: Bad LexerModule statement:\n{original}")
@ -67,7 +67,7 @@ def FindModules(lexFile):
modules.append([parts[1], parts[2], lexerName]) modules.append([parts[1], parts[2], lexerName])
partLine = "" partLine = ""
else: else:
partLine = partLine + l partLine = partLine + line
return modules return modules
def FindLexersInXcode(xCodeProject): def FindLexersInXcode(xCodeProject):
@ -113,11 +113,11 @@ knownIrregularProperties = [
def FindProperties(lexFile): def FindProperties(lexFile):
properties = {} properties = {}
with open(lexFile, encoding=neutralEncoding) as f: with open(lexFile, encoding=neutralEncoding) as f:
for l in f.readlines(): for s in f.readlines():
if ("GetProperty" in l or "DefineProperty" in l) and "\"" in l: if ("GetProperty" in s or "DefineProperty" in s) and "\"" in s:
l = l.strip() s = s.strip()
if not l.startswith("//"): # Drop comments if not s.startswith("//"): # Drop comments
propertyName = l.split("\"")[1] propertyName = s.split("\"")[1]
if propertyName.lower() == propertyName: if propertyName.lower() == propertyName:
# Only allow lower case property names # Only allow lower case property names
if propertyName in knownIrregularProperties or \ if propertyName in knownIrregularProperties or \
@ -130,36 +130,36 @@ def FindPropertyDocumentation(lexFile):
documents = {} documents = {}
with lexFile.open(encoding=neutralEncoding) as f: with lexFile.open(encoding=neutralEncoding) as f:
name = "" name = ""
for l in f.readlines(): for line in f.readlines():
l = l.strip() line = line.strip()
if "// property " in l: if "// property " in line:
propertyName = l.split()[2] propertyName = line.split()[2]
if propertyName.lower() == propertyName: if propertyName.lower() == propertyName:
# Only allow lower case property names # Only allow lower case property names
name = propertyName name = propertyName
documents[name] = "" documents[name] = ""
elif "DefineProperty" in l and "\"" in l: elif "DefineProperty" in line and "\"" in line:
propertyName = l.split("\"")[1] propertyName = line.split("\"")[1]
if propertyName.lower() == propertyName: if propertyName.lower() == propertyName:
# Only allow lower case property names # Only allow lower case property names
name = propertyName name = propertyName
documents[name] = "" documents[name] = ""
elif name: elif name:
if l.startswith("//"): if line.startswith("//"):
if documents[name]: if documents[name]:
documents[name] += " " documents[name] += " "
documents[name] += l[2:].strip() documents[name] += line[2:].strip()
elif l.startswith("\""): elif line.startswith("\""):
l = l[1:].strip() line = line[1:].strip()
if l.endswith(";"): if line.endswith(";"):
l = l[:-1].strip() line = line[:-1].strip()
if l.endswith(")"): if line.endswith(")"):
l = l[:-1].strip() line = line[:-1].strip()
if l.endswith("\""): if line.endswith("\""):
l = l[:-1] line = line[:-1]
# Fix escaped double quotes # Fix escaped double quotes
l = l.replace("\\\"", "\"") line = line.replace("\\\"", "\"")
documents[name] += l documents[name] += line
else: else:
name = "" name = ""
for name in list(documents.keys()): for name in list(documents.keys()):
@ -171,15 +171,15 @@ def FindCredits(historyFile):
credits = [] credits = []
stage = 0 stage = 0
with historyFile.open(encoding="utf-8") as f: with historyFile.open(encoding="utf-8") as f:
for l in f.readlines(): for line in f.readlines():
l = l.strip() line = line.strip()
if stage == 0 and l == "<table>": if stage == 0 and line == "<table>":
stage = 1 stage = 1
elif stage == 1 and l == "</table>": elif stage == 1 and line == "</table>":
stage = 2 stage = 2
if stage == 1 and l.startswith("<td>"): if stage == 1 and line.startswith("<td>"):
credit = l[4:-5] credit = line[4:-5]
if "<a" in l: if "<a" in line:
title, a, rest = credit.partition("<a href=") title, a, rest = credit.partition("<a href=")
urlplus, _bracket, end = rest.partition(">") urlplus, _bracket, end = rest.partition(">")
name = end.split("<")[0] name = end.split("<")[0]
@ -194,19 +194,19 @@ def FindCredits(historyFile):
def ciKey(a): def ciKey(a):
return str(a).lower() return str(a).lower()
def SortListInsensitive(l): def SortListInsensitive(list):
l.sort(key=ciKey) list.sort(key=ciKey)
class LexillaData: class LexillaData:
def __init__(self, scintillaRoot): def __init__(self, scintillaRoot):
# Discover version information # Discover version information
self.version = (scintillaRoot / "version.txt").read_text().strip() self.version = (scintillaRoot / "version.txt").read_text().strip()
self.versionDotted = self.version[0] + '.' + self.version[1] + '.' + \ self.versionDotted = self.version[0:-2] + '.' + self.version[-2] + '.' + \
self.version[2] self.version[-1]
self.versionCommad = self.versionDotted.replace(".", ", ") + ', 0' self.versionCommad = self.versionDotted.replace(".", ", ") + ', 0'
with (scintillaRoot / "doc" / "Lexilla.html").open() as f: with (scintillaRoot / "doc" / "Lexilla.html").open() as f:
self.dateModified = [l for l in f.readlines() if "Date.Modified" in l]\ self.dateModified = [d for d in f.readlines() if "Date.Modified" in d]\
[0].split('\"')[3] [0].split('\"')[3]
# 20130602 # 20130602
# Lexilla.html # Lexilla.html

View File

@ -105,7 +105,7 @@ def RegenerateAll(rootDirectory):
# Discover version information # Discover version information
version = (lexillaDir / "version.txt").read_text().strip() version = (lexillaDir / "version.txt").read_text().strip()
versionDotted = version[0] + '.' + version[1] + '.' + version[2] versionDotted = version[0:-2] + '.' + version[-2] + '.' + version[-1]
versionCommad = versionDotted.replace(".", ", ") + ', 0' versionCommad = versionDotted.replace(".", ", ") + ', 0'
rcPath = srcDir / "LexillaVersion.rc" rcPath = srcDir / "LexillaVersion.rc"
@ -116,7 +116,7 @@ def RegenerateAll(rootDirectory):
UpdateLineInFile(docDir / "LexillaDownload.html", " Release", UpdateLineInFile(docDir / "LexillaDownload.html", " Release",
" Release " + versionDotted) " Release " + versionDotted)
ReplaceREInFile(docDir / "LexillaDownload.html", ReplaceREInFile(docDir / "LexillaDownload.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>" + version, r"/www.scintilla.org/\g<1>" + version,
0) 0)

View File

@ -101,7 +101,7 @@
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>gdi32.lib;imm32.lib;ole32.lib;oleaut32.lib;msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>gdi32.lib;imm32.lib;ole32.lib;oleaut32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<CETCompat>true</CETCompat> <CETCompat>true</CETCompat>
<ModuleDefinitionFile>Lexilla.def</ModuleDefinitionFile> <ModuleDefinitionFile>Lexilla.def</ModuleDefinitionFile>
</Link> </Link>

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.2.4</string> <string>5.2.5</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

@ -853,7 +853,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.2.4; CURRENT_PROJECT_VERSION = 5.2.5;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 4F446KW87E; DEVELOPMENT_TEAM = 4F446KW87E;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
@ -880,7 +880,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.2.4; CURRENT_PROJECT_VERSION = 5.2.5;
DEAD_CODE_STRIPPING = YES; DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 4F446KW87E; DEVELOPMENT_TEAM = 4F446KW87E;
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;

View File

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

View File

@ -131,8 +131,12 @@ $(LEXILLA): $(LEXILLA_OBJS) $(VERSION_RESOURCE)
$(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@ $(CXX) $(CXXFLAGS) $(LDFLAGS) $^ -o $@
$(LIBLEXILLA): $(LEXILLA_OBJS) $(LIBLEXILLA): $(LEXILLA_OBJS)
ifeq ($(SHAREDEXTENSION),dylib)
libtool -static -o $@ $^
else
$(AR) rc $@ $^ $(AR) rc $@ $^
$(RANLIB) $@ $(RANLIB) $@
endif
# Automatically generate dependencies for most files with "make deps" # Automatically generate dependencies for most files with "make deps"
include deps.mak include deps.mak

View File

@ -885,9 +885,10 @@ bool TestFile(const std::filesystem::path &path, const PropertyMap &propertyMap)
} }
if (propertyMap.GetPropertyValue("testlexers.list.styles").value_or(0)) { if (propertyMap.GetPropertyValue("testlexers.list.styles").value_or(0)) {
std::vector<bool> used(0x80); std::vector<bool> used(0x100);
for (Sci_Position pos = 0; pos < pdoc->Length(); pos++) { for (Sci_Position pos = 0; pos < pdoc->Length(); pos++) {
const unsigned style = pdoc->StyleAt(pos); const unsigned char uchStyle = pdoc->StyleAt(pos);
const unsigned style = uchStyle;
used.at(style) = true; used.at(style) = true;
} }
PrintRanges(used); PrintRanges(used);

View File

@ -0,0 +1,60 @@
# Enumerate all styles: 0 to 13
# comment=2
# whitespace=0
# w
# error=1
0#0000
# number=3
123
# keyword=4
set
# double-quoted-string=5
"string"
# single-quoted-string=6
'str'
# operator=7
+
# identifier=8
identifier
# scalar=9
$scalar
$?Status
# parameter-expansion=10
${parameter}
# back-ticks=11
`ls`
# here-doc-delimiter=12, here-doc=13
<<EOF
Here-doc.
EOF
# other quoted types are mapped to current classes
# double-quoted-string=5
$"string"
$'str'
# back-ticks=11
$`ls`
$(ls)
# Use substyles
# Substyled identifier=128
map
# Substyled scalar=129
$CWD

View File

@ -0,0 +1,61 @@
0 400 0 # Enumerate all styles: 0 to 13
1 400 0
0 400 0 # comment=2
1 400 0
2 400 0 + # whitespace=0
0 401 0 | # w
1 400 0
0 400 0 # error=1
0 400 0 0#0000
1 400 0
0 400 0 # number=3
0 400 0 123
1 400 0
0 400 0 # keyword=4
0 400 0 set
1 400 0
0 400 0 # double-quoted-string=5
0 400 0 "string"
1 400 0
0 400 0 # single-quoted-string=6
0 400 0 'str'
1 400 0
0 400 0 # operator=7
0 400 0 +
1 400 0
0 400 0 # identifier=8
0 400 0 identifier
1 400 0
0 400 0 # scalar=9
0 400 0 $scalar
0 400 0 $?Status
1 400 0
0 400 0 # parameter-expansion=10
0 400 0 ${parameter}
1 400 0
0 400 0 # back-ticks=11
0 400 0 `ls`
1 400 0
0 400 0 # here-doc-delimiter=12, here-doc=13
2 400 0 + <<EOF
0 401 0 | Here-doc.
0 401 0 | EOF
1 400 0
0 400 0 # other quoted types are mapped to current classes
1 400 0
0 400 0 # double-quoted-string=5
0 400 0 $"string"
0 400 0 $'str'
1 400 0
0 400 0 # back-ticks=11
0 400 0 $`ls`
0 400 0 $(ls)
1 400 0
0 400 0 # Use substyles
1 400 0
0 400 0 # Substyled identifier=128
0 400 0 map
1 400 0
0 400 0 # Substyled scalar=129
0 400 0 $CWD
0 400 0

View File

@ -0,0 +1,60 @@
{2}# Enumerate all styles: 0 to 13{0}
{2}# comment=2{0}
{2}# whitespace=0{0}
{2}# w{0}
{2}# error=1{0}
{1}0#0000{0}
{2}# number=3{0}
{3}123{0}
{2}# keyword=4{0}
{4}set{0}
{2}# double-quoted-string=5{0}
{5}"string"{0}
{2}# single-quoted-string=6{0}
{6}'str'{0}
{2}# operator=7{0}
{7}+{0}
{2}# identifier=8{0}
{8}identifier{0}
{2}# scalar=9{0}
{9}$scalar{0}
{9}$?{8}Status{0}
{2}# parameter-expansion=10{0}
{10}${parameter}{0}
{2}# back-ticks=11{0}
{11}`ls`{0}
{2}# here-doc-delimiter=12, here-doc=13{0}
{12}<<EOF{13}
Here-doc.
EOF{0}
{2}# other quoted types are mapped to current classes{0}
{2}# double-quoted-string=5{0}
{5}$"string"{0}
{5}$'str'{0}
{2}# back-ticks=11{0}
{11}$`ls`{0}
{11}$(ls){0}
{2}# Use substyles{0}
{2}# Substyled identifier=128{0}
{128}map{0}
{2}# Substyled scalar=129{0}
{129}$CWD{0}

View File

@ -0,0 +1,77 @@
# Nested elements and other complex cases
# String with backtick inclusion
"x`ls`"
# Nested string
"x`ls "*.c"`"
# Not terminated at first "
"x`ls" # "`" #
# String with command inclusion
"x$(ls)"
# Nested command
$(ls -la$(ls *.c))
# Check strings and backticks in command
echo $('ls' "." `ls` $'.' $".")
# $( not terminated by ) if contains unterminated string
$('x) # ') #
$("x) # ") #
$(`x) # `) # Bash doesn't like this
$($'x) # ') #
$($"x) # ") #
# Parameter expansion
var=abcdef
sub=abc
rep='& '
echo ${var/$sub/"${rep}}"} #
# '$' in variable
echo $$PID
echo $var${var}
# Here-doc with internal elements
cat <<EOF
$scalar
${var}
$((1+2))
$(pwd)
`pwd`
EOF
# Quoted delimiter treats here-doc as simple string
cat <<"EOF"
$scalar
${var}
$((1+2))
$(pwd)
`pwd`
EOF
# Escaped same as quoted
cat <<\EOF
$scalar
EOF
# Nesting
echo "$((1 + 2))" #
echo "$[1 + 2]" #
# Multiple nesting levels
$(ls -la$(ls $(c) $'*.c' ` $(${s})`))
# Multi-line
$(ls |
more)
$(
`x`
"x"
`ls`
$'x'
$"x"
)
#end -- checks termination of previous

View File

@ -0,0 +1,78 @@
0 400 0 # Nested elements and other complex cases
1 400 0
0 400 0 # String with backtick inclusion
0 400 0 "x`ls`"
0 400 0 # Nested string
0 400 0 "x`ls "*.c"`"
0 400 0 # Not terminated at first "
0 400 0 "x`ls" # "`" #
1 400 0
0 400 0 # String with command inclusion
0 400 0 "x$(ls)"
1 400 0
0 400 0 # Nested command
0 400 0 $(ls -la$(ls *.c))
1 400 0
0 400 0 # Check strings and backticks in command
0 400 0 echo $('ls' "." `ls` $'.' $".")
1 400 0
0 400 0 # $( not terminated by ) if contains unterminated string
0 400 0 $('x) # ') #
0 400 0 $("x) # ") #
0 400 0 $(`x) # `) # Bash doesn't like this
0 400 0 $($'x) # ') #
0 400 0 $($"x) # ") #
1 400 0
0 400 0 # Parameter expansion
0 400 0 var=abcdef
0 400 0 sub=abc
0 400 0 rep='& '
0 400 0 echo ${var/$sub/"${rep}}"} #
1 400 0
0 400 0 # '$' in variable
0 400 0 echo $$PID
0 400 0 echo $var${var}
1 400 0
0 400 0 # Here-doc with internal elements
2 400 0 + cat <<EOF
0 401 0 | $scalar
0 401 0 | ${var}
0 401 0 | $((1+2))
0 401 0 | $(pwd)
0 401 0 | `pwd`
0 401 0 | EOF
1 400 0
0 400 0 # Quoted delimiter treats here-doc as simple string
2 400 0 + cat <<"EOF"
0 401 0 | $scalar
0 401 0 | ${var}
0 401 0 | $((1+2))
0 401 0 | $(pwd)
0 401 0 | `pwd`
0 401 0 | EOF
1 400 0
0 400 0 # Escaped same as quoted
2 400 0 + cat <<\EOF
0 401 0 | $scalar
0 401 0 | EOF
1 400 0
0 400 0 # Nesting
0 400 0 echo "$((1 + 2))" #
0 400 0 echo "$[1 + 2]" #
1 400 0
0 400 0 # Multiple nesting levels
0 400 0 $(ls -la$(ls $(c) $'*.c' ` $(${s})`))
1 400 0
0 400 0 # Multi-line
0 400 0 $(ls |
0 400 0 more)
1 400 0
0 400 0 $(
0 400 0 `x`
0 400 0 "x"
0 400 0 `ls`
0 400 0 $'x'
0 400 0 $"x"
0 400 0 )
0 400 0 #end -- checks termination of previous
0 400 0

View File

@ -0,0 +1,77 @@
{2}# Nested elements and other complex cases{0}
{2}# String with backtick inclusion{0}
{5}"x`ls`"{0}
{2}# Nested string{0}
{5}"x`ls "*.c"`"{0}
{2}# Not terminated at first "{0}
{5}"x`ls" # "`"{0} {2}#{0}
{2}# String with command inclusion{0}
{5}"x$(ls)"{0}
{2}# Nested command{0}
{11}$(ls -la$(ls *.c)){0}
{2}# Check strings and backticks in command{0}
{4}echo{0} {11}$('ls' "." `ls` $'.' $"."){0}
{2}# $( not terminated by ) if contains unterminated string{0}
{11}$('x) # '){0} {2}#{0}
{11}$("x) # "){0} {2}#{0}
{11}$(`x) # `){0} {2}# Bash doesn't like this{0}
{11}$($'x) # '){0} {2}#{0}
{11}$($"x) # "){0} {2}#{0}
{2}# Parameter expansion{0}
{8}var{7}={8}abcdef{0}
{8}sub{7}={8}abc{0}
{8}rep{7}={6}'& '{0}
{4}echo{0} {10}${var/$sub/"${rep}}"}{0} {2}#{0}
{2}# '$' in variable{0}
{4}echo{0} {9}$${8}PID{0}
{4}echo{0} {9}$var{10}${var}{0}
{2}# Here-doc with internal elements{0}
{4}cat{0} {12}<<EOF{13}
$scalar
${var}
$((1+2))
$(pwd)
`pwd`
EOF{0}
{2}# Quoted delimiter treats here-doc as simple string{0}
{4}cat{0} {12}<<"EOF"{13}
$scalar
${var}
$((1+2))
$(pwd)
`pwd`
EOF{0}
{2}# Escaped same as quoted{0}
{4}cat{0} {12}<<\EOF{13}
$scalar
EOF{0}
{2}# Nesting{0}
{4}echo{0} {5}"$((1 + 2))"{0} {2}#{0}
{4}echo{0} {5}"$[1 + 2]"{0} {2}#{0}
{2}# Multiple nesting levels{0}
{11}$(ls -la$(ls $(c) $'*.c' ` $(${s})`)){0}
{2}# Multi-line{0}
{11}$(ls |
more){0}
{11}$(
`x`
"x"
`ls`
$'x'
$"x"
){0}
{2}#end -- checks termination of previous{0}

View File

@ -0,0 +1,26 @@
# Use lexer.bash.command.substitution=2 to style command substitution
# so that both the scope of the command and the internal structure are visible.
# Nested command
$(ls -la$(ls *.c))
# Check strings and backticks in command
echo $('ls' "." `ls` $'.' $".")
PROJECT_DIR=$(rlwrap -S "Enter source path: " -e '' -i -o cat)
# Multiple nesting levels
$(ls -la$(ls $(c) $'*.c' ` $(${s})`))
# Multi-line
$(ls |
more)
$(
`x`
"x"
`ls`
$'x'
$"x"
)
#end -- checks termination of previous

View File

@ -0,0 +1,27 @@
2 400 0 + # Use lexer.bash.command.substitution=2 to style command substitution
0 401 0 | # so that both the scope of the command and the internal structure are visible.
1 400 0
0 400 0 # Nested command
0 400 0 $(ls -la$(ls *.c))
1 400 0
0 400 0 # Check strings and backticks in command
0 400 0 echo $('ls' "." `ls` $'.' $".")
1 400 0
0 400 0 PROJECT_DIR=$(rlwrap -S "Enter source path: " -e '' -i -o cat)
1 400 0
0 400 0 # Multiple nesting levels
0 400 0 $(ls -la$(ls $(c) $'*.c' ` $(${s})`))
1 400 0
0 400 0 # Multi-line
0 400 0 $(ls |
0 400 0 more)
1 400 0
0 400 0 $(
0 400 0 `x`
0 400 0 "x"
0 400 0 `ls`
0 400 0 $'x'
0 400 0 $"x"
0 400 0 )
0 400 0 #end -- checks termination of previous
0 400 0

View File

@ -0,0 +1,26 @@
{2}# Use lexer.bash.command.substitution=2 to style command substitution{0}
{2}# so that both the scope of the command and the internal structure are visible.{0}
{2}# Nested command{0}
{71}$({72}ls{64} {71}-{72}la{71}$({72}ls{64} {71}*.{72}c{71})){0}
{2}# Check strings and backticks in command{0}
{4}echo{0} {71}$({70}'ls'{64} {69}"."{64} {75}`ls`{64} {69}$'.'{64} {69}$"."{71}){0}
{8}PROJECT_DIR{7}={71}$({72}rlwrap{64} {72}-S{64} {69}"Enter source path: "{64} {72}-e{64} {70}''{64} {71}-{72}i{64} {72}-o{64} {72}cat{71}){0}
{2}# Multiple nesting levels{0}
{71}$({72}ls{64} {71}-{72}la{71}$({72}ls{64} {71}$({72}c{71}){64} {69}$'*.c'{64} {75}` $(${s})`{71})){0}
{2}# Multi-line{0}
{71}$({72}ls{64} {71}|{64}
{72}more{71}){0}
{71}$({64}
{75}`x`{64}
{69}"x"{64}
{75}`ls`{64}
{69}$'x'{64}
{69}$"x"{64}
{71}){0}
{2}#end -- checks termination of previous{0}

View File

@ -0,0 +1,77 @@
# Nested elements and other complex cases
# String with backtick inclusion
"x`ls`"
# Nested string
"x`ls "*.c"`"
# Not terminated at first "
"x`ls" # "`" #
# String with command inclusion
"x$(ls)"
# Nested command
$(ls -la$(ls *.c))
# Check strings and backticks in command
echo $('ls' "." `ls` $'.' $".")
# $( not terminated by ) if contains unterminated string
$('x) # ') #
$("x) # ") #
$(`x) # `) # Bash doesn't like this
$($'x) # ') #
$($"x) # ") #
# Parameter expansion
var=abcdef
sub=abc
rep='& '
echo ${var/$sub/"${rep}}"} #
# '$' in variable
echo $$PID
echo $var${var}
# Here-doc with internal elements
cat <<EOF
$scalar
${var}
$((1+2))
$(pwd)
`pwd`
EOF
# Quoted delimiter treats here-doc as simple string
cat <<"EOF"
$scalar
${var}
$((1+2))
$(pwd)
`pwd`
EOF
# Escaped same as quoted
cat <<\EOF
$scalar
EOF
# Nesting
echo "$((1 + 2))" #
echo "$[1 + 2]" #
# Multiple nesting levels
$(ls -la$(ls $(c) $'*.c' ` $(${s})`))
# Multi-line
$(ls |
more)
$(
`x`
"x"
`ls`
$'x'
$"x"
)
#end -- checks termination of previous

View File

@ -0,0 +1,78 @@
0 400 0 # Nested elements and other complex cases
1 400 0
0 400 0 # String with backtick inclusion
0 400 0 "x`ls`"
0 400 0 # Nested string
0 400 0 "x`ls "*.c"`"
0 400 0 # Not terminated at first "
0 400 0 "x`ls" # "`" #
1 400 0
0 400 0 # String with command inclusion
0 400 0 "x$(ls)"
1 400 0
0 400 0 # Nested command
0 400 0 $(ls -la$(ls *.c))
1 400 0
0 400 0 # Check strings and backticks in command
0 400 0 echo $('ls' "." `ls` $'.' $".")
1 400 0
0 400 0 # $( not terminated by ) if contains unterminated string
0 400 0 $('x) # ') #
0 400 0 $("x) # ") #
0 400 0 $(`x) # `) # Bash doesn't like this
0 400 0 $($'x) # ') #
0 400 0 $($"x) # ") #
1 400 0
0 400 0 # Parameter expansion
0 400 0 var=abcdef
0 400 0 sub=abc
0 400 0 rep='& '
0 400 0 echo ${var/$sub/"${rep}}"} #
1 400 0
0 400 0 # '$' in variable
0 400 0 echo $$PID
0 400 0 echo $var${var}
1 400 0
0 400 0 # Here-doc with internal elements
2 400 0 + cat <<EOF
0 401 0 | $scalar
0 401 0 | ${var}
0 401 0 | $((1+2))
0 401 0 | $(pwd)
0 401 0 | `pwd`
0 401 0 | EOF
1 400 0
0 400 0 # Quoted delimiter treats here-doc as simple string
2 400 0 + cat <<"EOF"
0 401 0 | $scalar
0 401 0 | ${var}
0 401 0 | $((1+2))
0 401 0 | $(pwd)
0 401 0 | `pwd`
0 401 0 | EOF
1 400 0
0 400 0 # Escaped same as quoted
2 400 0 + cat <<\EOF
0 401 0 | $scalar
0 401 0 | EOF
1 400 0
0 400 0 # Nesting
0 400 0 echo "$((1 + 2))" #
0 400 0 echo "$[1 + 2]" #
1 400 0
0 400 0 # Multiple nesting levels
0 400 0 $(ls -la$(ls $(c) $'*.c' ` $(${s})`))
1 400 0
0 400 0 # Multi-line
0 400 0 $(ls |
0 400 0 more)
1 400 0
0 400 0 $(
0 400 0 `x`
0 400 0 "x"
0 400 0 `ls`
0 400 0 $'x'
0 400 0 $"x"
0 400 0 )
0 400 0 #end -- checks termination of previous
0 400 0

View File

@ -0,0 +1,77 @@
{2}# Nested elements and other complex cases{0}
{2}# String with backtick inclusion{0}
{5}"x{11}`ls`{5}"{0}
{2}# Nested string{0}
{5}"x{11}`ls {5}"*.c"{11}`{5}"{0}
{2}# Not terminated at first "{0}
{5}"x{11}`ls{5}" # "{11}`{5}"{0} {2}#{0}
{2}# String with command inclusion{0}
{5}"x{7}$({8}ls{7}){5}"{0}
{2}# Nested command{0}
{7}$({8}ls{0} {7}-{8}la{7}$({8}ls{0} {7}*.{8}c{7})){0}
{2}# Check strings and backticks in command{0}
{4}echo{0} {7}$({6}'ls'{0} {5}"."{0} {11}`ls`{0} {5}$'.'{0} {5}$"."{7}){0}
{2}# $( not terminated by ) if contains unterminated string{0}
{7}$({6}'x) # '{7}){0} {2}#{0}
{7}$({5}"x) # "{7}){0} {2}#{0}
{7}$({11}`x) # `{7}){0} {2}# Bash doesn't like this{0}
{7}$({5}$'x) # '{7}){0} {2}#{0}
{7}$({5}$"x) # "{7}){0} {2}#{0}
{2}# Parameter expansion{0}
{8}var{7}={8}abcdef{0}
{8}sub{7}={8}abc{0}
{8}rep{7}={6}'& '{0}
{4}echo{0} {10}${var/{9}$sub{10}/{5}"{10}${rep}{5}}"{10}}{0} {2}#{0}
{2}# '$' in variable{0}
{4}echo{0} {9}$${8}PID{0}
{4}echo{0} {9}$var{10}${var}{0}
{2}# Here-doc with internal elements{0}
{4}cat{0} {12}<<EOF{13}
{9}$scalar{13}
{10}${var}{13}
{7}$(({3}1{7}+{3}2{7})){13}
{7}$({8}pwd{7}){13}
{11}`pwd`{13}
EOF{0}
{2}# Quoted delimiter treats here-doc as simple string{0}
{4}cat{0} {12}<<"EOF"{13}
$scalar
${var}
$((1+2))
$(pwd)
`pwd`
EOF{0}
{2}# Escaped same as quoted{0}
{4}cat{0} {12}<<\EOF{13}
$scalar
EOF{0}
{2}# Nesting{0}
{4}echo{0} {5}"{7}$(({3}1{0} {7}+{0} {3}2{7})){5}"{0} {2}#{0}
{4}echo{0} {5}"{7}$[{3}1{0} {7}+{0} {3}2{7}]{5}"{0} {2}#{0}
{2}# Multiple nesting levels{0}
{7}$({8}ls{0} {7}-{8}la{7}$({8}ls{0} {7}$({8}c{7}){0} {5}$'*.c'{0} {11}` {7}$({10}${s}{7}){11}`{7})){0}
{2}# Multi-line{0}
{7}$({8}ls{0} {7}|{0}
{8}more{7}){0}
{7}$({0}
{11}`x`{0}
{5}"x"{0}
{11}`ls`{0}
{5}$'x'{0}
{5}$"x"{0}
{7}){0}
{2}#end -- checks termination of previous{0}

View File

@ -2,3 +2,25 @@ lexer.*.bsh=bash
fold=1 fold=1
fold.comment=1 fold.comment=1
keywords.*.bsh=case cat do done echo else esac exit export fi find for if in set then while keywords.*.bsh=case cat do done echo else esac exit export fi find for if in set then while
# Can use substyles for identifiers and scalars
substyles.bash.8=1
substylewords.8.1.*.bsh=map
substyles.bash.9=1
substylewords.9.1.*.bsh=CWD
lexer.bash.styling.inside.string=0
lexer.bash.styling.inside.backticks=0
lexer.bash.styling.inside.parameter=0
lexer.bash.styling.inside.heredoc=0
lexer.bash.command.substitution=0
match NestedStyledInside.bsh
lexer.bash.styling.inside.string=1
lexer.bash.styling.inside.backticks=1
lexer.bash.styling.inside.parameter=1
lexer.bash.styling.inside.heredoc=1
lexer.bash.command.substitution=1
match NestedRich.bsh
lexer.bash.command.substitution=2

View File

@ -31,4 +31,9 @@ while read -r f; do
} >> $OUT_FILE } >> $OUT_FILE
done done
# Issue 137, should be shift but here-doc was detected
echo $(( x << END ))
pwd
END
INVALID_NUMBER=0#0000 INVALID_NUMBER=0#0000

View File

@ -31,5 +31,10 @@
0 402 0 | } >> $OUT_FILE 0 402 0 | } >> $OUT_FILE
0 401 0 | done 0 401 0 | done
1 400 0 1 400 0
0 400 0 # Issue 137, should be shift but here-doc was detected
0 400 0 echo $(( x << END ))
0 400 0 pwd
0 400 0 END
1 400 0
0 400 0 INVALID_NUMBER=0#0000 0 400 0 INVALID_NUMBER=0#0000
0 400 0 0 400 0

View File

@ -31,4 +31,9 @@ EOF{0}
{7}}{0} {7}>>{0} {9}$OUT_FILE{0} {7}}{0} {7}>>{0} {9}$OUT_FILE{0}
{4}done{0} {4}done{0}
{2}# Issue 137, should be shift but here-doc was detected{0}
{4}echo{0} {7}$(({0} {8}x{0} {7}<<{0} {8}END{0} {7})){0}
{8}pwd{0}
{8}END{0}
{8}INVALID_NUMBER{7}={1}0#0000{0} {8}INVALID_NUMBER{7}={1}0#0000{0}

View File

@ -54,6 +54,7 @@ echo %%0
echo %%%0 echo %%%0
echo %%%%~-abcd echo %%%%~-abcd
:TEST that after label style works
:: Bug 2304: "::" comments not recognised when second command on line :: Bug 2304: "::" comments not recognised when second command on line
Set /A xxx=%xxx%+1 & :: Increment Set /A xxx=%xxx%+1 & :: Increment
Set /A xxx=%xxx%+1 & ::Increment Set /A xxx=%xxx%+1 & ::Increment

View File

@ -54,6 +54,7 @@
0 400 0 echo %%%0 0 400 0 echo %%%0
0 400 0 echo %%%%~-abcd 0 400 0 echo %%%%~-abcd
0 400 0 0 400 0
0 400 0 :TEST that after label style works
0 400 0 :: Bug 2304: "::" comments not recognised when second command on line 0 400 0 :: Bug 2304: "::" comments not recognised when second command on line
0 400 0 Set /A xxx=%xxx%+1 & :: Increment 0 400 0 Set /A xxx=%xxx%+1 & :: Increment
0 400 0 Set /A xxx=%xxx%+1 & ::Increment 0 400 0 Set /A xxx=%xxx%+1 & ::Increment

View File

@ -54,6 +54,7 @@ rem 'echo' is word=2, 'a' is default=0
{2}echo{0} %%{6}%0{0} {2}echo{0} %%{6}%0{0}
{2}echo{0} %%{6}%%~-abcd{0} {2}echo{0} %%{6}%%~-abcd{0}
{3}:TEST{8} that after label style works
{1}:: Bug 2304: "::" comments not recognised when second command on line {1}:: Bug 2304: "::" comments not recognised when second command on line
{2}Set{0} /A xxx{7}={6}%xxx%{7}+{0}1 {7}&{0} {1}:: Increment {2}Set{0} /A xxx{7}={6}%xxx%{7}+{0}1 {7}&{0} {1}:: Increment
{2}Set{0} /A xxx{7}={6}%xxx%{7}+{0}1 {7}&{0} {1}::Increment {2}Set{0} /A xxx{7}={6}%xxx%{7}+{0}1 {7}&{0} {1}::Increment

View File

@ -6,30 +6,46 @@ let x = List.fold (*) 24.5 [ 1.; 2.; 3. ]
printfn "Speed: %.2f m/s" x printfn "Speed: %.2f m/s" x
printfn $"Speed: %.2f{x} m/s" printfn $"Speed: %.2f{x} m/s"
printfn $"Speed: {x:f2} m/s" printfn $"Speed: {x:f2} m/s"
printfn $@"Speed: %.2f{x} m/s"
printfn @$"Speed: {x:f2} m/s"
// expect " 147%" // expect " 147%"
printfn """%% increase:% .0F%% over last year""" x printfn """%% increase:% .0F%% over last year""" x
printfn $"""%% increase:% .0F{x}%% over last year""" printfn $"""%% increase:% .0F{x}%% over last year"""
printfn $"""%% increase:{x / 100.,5:P0} over last year""" printfn $"""%% increase:{x / 100.,5:P0} over last year"""
printfn $@"""%% increase:% .0F{x}%% over last year"""
printfn @$"""%% increase:{x / 100.,5:P0} over last year"""
// expect "1.5E+002" // expect "1.5E+002"
// NB: units should look like text even without a space // NB: units should look like text even without a space
printfn @"Time: %-0.1Esecs" x printfn @"Time: %-0.1Esecs" x
printfn $"Time: %-0.1E{x}secs" printfn $"Time: %-0.1E{x}secs"
printfn $"Time: {x:E1}secs" printfn $"Time: {x:E1}secs"
printfn $@"Time: %-0.1E{x}secs"
printfn @$"Time: {x:E1}secs"
// expect "\" +147\"" // expect "\" +147\""
printfn @"""Temp: %+12.3g K""" x printfn @"""Temp: %+12.3g K""" x
printfn $"""{'"'}Temp: %+12.3g{x} K{'"'}""" printfn $"""{'"'}Temp: %+12.3g{x} K{'"'}"""
printfn $"""{'"'}Temp: {'+',9}{x:g3} K{'"'}""" printfn $"""{'"'}Temp: {'+',9}{x:g3} K{'"'}"""
printfn $@"""Temp: %+12.3g{x} K"""
printfn @$"""Temp: {'+',9}{x:g3} K"""
// Since F# 6.0 // Since F# 6.0
printfn @"%B" 0b1_000_000 printfn @"%B" 0b1_000_000
printfn "%B" "\x40"B.[0] printfn "%B" "\x40"B.[0]
printfn $"""%B{'\064'B}""" printfn $"""%B{'\064'B}"""
printfn $@"""%B{0b1_000_000}"""
printfn @$"""%B{'\064'B}"""
// These don't work // These don't work
printfn ``%.2f`` x printfn ``%.2f`` x
printfn $"%.2f" x printfn $"%.2f" x
printfn $@"%.2f" x
printfn @$"%.2f" x
printfn $"%.2f {x}" printfn $"%.2f {x}"
printfn $@"%.2f {x}"
printfn @$"%.2f {x}"
printfn $"""%.2f {x}""" printfn $"""%.2f {x}"""
printfn $@"""%.2f {x}"""
printfn @$"""%.2f {x}"""

View File

@ -6,31 +6,47 @@
0 400 400 printfn "Speed: %.2f m/s" x 0 400 400 printfn "Speed: %.2f m/s" x
0 400 400 printfn $"Speed: %.2f{x} m/s" 0 400 400 printfn $"Speed: %.2f{x} m/s"
0 400 400 printfn $"Speed: {x:f2} m/s" 0 400 400 printfn $"Speed: {x:f2} m/s"
0 400 400 printfn $@"Speed: %.2f{x} m/s"
0 400 400 printfn @$"Speed: {x:f2} m/s"
1 400 400 1 400 400
0 400 400 // expect " 147%" 0 400 400 // expect " 147%"
0 400 400 printfn """%% increase:% .0F%% over last year""" x 0 400 400 printfn """%% increase:% .0F%% over last year""" x
0 400 400 printfn $"""%% increase:% .0F{x}%% over last year""" 0 400 400 printfn $"""%% increase:% .0F{x}%% over last year"""
0 400 400 printfn $"""%% increase:{x / 100.,5:P0} over last year""" 0 400 400 printfn $"""%% increase:{x / 100.,5:P0} over last year"""
0 400 400 printfn $@"""%% increase:% .0F{x}%% over last year"""
0 400 400 printfn @$"""%% increase:{x / 100.,5:P0} over last year"""
1 400 400 1 400 400
2 400 401 + // expect "1.5E+002" 2 400 401 + // expect "1.5E+002"
0 401 400 | // NB: units should look like text even without a space 0 401 400 | // NB: units should look like text even without a space
0 400 400 printfn @"Time: %-0.1Esecs" x 0 400 400 printfn @"Time: %-0.1Esecs" x
0 400 400 printfn $"Time: %-0.1E{x}secs" 0 400 400 printfn $"Time: %-0.1E{x}secs"
0 400 400 printfn $"Time: {x:E1}secs" 0 400 400 printfn $"Time: {x:E1}secs"
0 400 400 printfn $@"Time: %-0.1E{x}secs"
0 400 400 printfn @$"Time: {x:E1}secs"
1 400 400 1 400 400
0 400 400 // expect "\" +147\"" 0 400 400 // expect "\" +147\""
0 400 400 printfn @"""Temp: %+12.3g K""" x 0 400 400 printfn @"""Temp: %+12.3g K""" x
0 400 400 printfn $"""{'"'}Temp: %+12.3g{x} K{'"'}""" 0 400 400 printfn $"""{'"'}Temp: %+12.3g{x} K{'"'}"""
0 400 400 printfn $"""{'"'}Temp: {'+',9}{x:g3} K{'"'}""" 0 400 400 printfn $"""{'"'}Temp: {'+',9}{x:g3} K{'"'}"""
0 400 400 printfn $@"""Temp: %+12.3g{x} K"""
0 400 400 printfn @$"""Temp: {'+',9}{x:g3} K"""
1 400 400 1 400 400
0 400 400 // Since F# 6.0 0 400 400 // Since F# 6.0
0 400 400 printfn @"%B" 0b1_000_000 0 400 400 printfn @"%B" 0b1_000_000
0 400 400 printfn "%B" "\x40"B.[0] 0 400 400 printfn "%B" "\x40"B.[0]
0 400 400 printfn $"""%B{'\064'B}""" 0 400 400 printfn $"""%B{'\064'B}"""
0 400 400 printfn $@"""%B{0b1_000_000}"""
0 400 400 printfn @$"""%B{'\064'B}"""
1 400 400 1 400 400
0 400 400 // These don't work 0 400 400 // These don't work
0 400 400 printfn ``%.2f`` x 0 400 400 printfn ``%.2f`` x
0 400 400 printfn $"%.2f" x 0 400 400 printfn $"%.2f" x
0 400 400 printfn $@"%.2f" x
0 400 400 printfn @$"%.2f" x
0 400 400 printfn $"%.2f {x}" 0 400 400 printfn $"%.2f {x}"
0 400 400 printfn $@"%.2f {x}"
0 400 400 printfn @$"%.2f {x}"
0 400 400 printfn $"""%.2f {x}""" 0 400 400 printfn $"""%.2f {x}"""
0 400 400 printfn $@"""%.2f {x}"""
0 400 400 printfn @$"""%.2f {x}"""
1 400 400 1 400 400

View File

@ -6,30 +6,46 @@
{2}printfn{0} {15}"Speed: {19}%.2f{15} m/s"{0} {6}x{0} {2}printfn{0} {15}"Speed: {19}%.2f{15} m/s"{0} {6}x{0}
{2}printfn{0} {15}$"Speed: {19}%.2f{15}{x} m/s"{0} {2}printfn{0} {15}$"Speed: {19}%.2f{15}{x} m/s"{0}
{2}printfn{0} {15}$"Speed: {x{19}:f2{15}} m/s"{0} {2}printfn{0} {15}$"Speed: {x{19}:f2{15}} m/s"{0}
{2}printfn{0} {16}$@"Speed: {19}%.2f{16}{x} m/s"{0}
{2}printfn{0} {16}@$"Speed: {x{19}:f2{16}} m/s"{0}
{9}// expect " 147%"{0} {9}// expect " 147%"{0}
{2}printfn{0} {15}"""{19}%%{15} increase:{19}% .0F%%{15} over last year"""{0} {6}x{0} {2}printfn{0} {15}"""{19}%%{15} increase:{19}% .0F%%{15} over last year"""{0} {6}x{0}
{2}printfn{0} {15}$"""{19}%%{15} increase:{19}% .0F{15}{x}{19}%%{15} over last year"""{0} {2}printfn{0} {15}$"""{19}%%{15} increase:{19}% .0F{15}{x}{19}%%{15} over last year"""{0}
{2}printfn{0} {15}$"""{19}%%{15} increase:{x / 100.{19},5:P0{15}} over last year"""{0} {2}printfn{0} {15}$"""{19}%%{15} increase:{x / 100.{19},5:P0{15}} over last year"""{0}
{2}printfn{0} {16}$@"""{19}%%{16} increase:{19}% .0F{16}{x}{19}%%{16} over last year"""{0}
{2}printfn{0} {16}@$"""{19}%%{16} increase:{x / 100.{19},5:P0{16}} over last year"""{0}
{9}// expect "1.5E+002"{0} {9}// expect "1.5E+002"{0}
{9}// NB: units should look like text even without a space{0} {9}// NB: units should look like text even without a space{0}
{2}printfn{0} {16}@"Time: {19}%-0.1E{16}secs"{0} {6}x{0} {2}printfn{0} {16}@"Time: {19}%-0.1E{16}secs"{0} {6}x{0}
{2}printfn{0} {15}$"Time: {19}%-0.1E{15}{x}secs"{0} {2}printfn{0} {15}$"Time: {19}%-0.1E{15}{x}secs"{0}
{2}printfn{0} {15}$"Time: {x{19}:E1{15}}secs"{0} {2}printfn{0} {15}$"Time: {x{19}:E1{15}}secs"{0}
{2}printfn{0} {16}$@"Time: {19}%-0.1E{16}{x}secs"{0}
{2}printfn{0} {16}@$"Time: {x{19}:E1{16}}secs"{0}
{9}// expect "\" +147\""{0} {9}// expect "\" +147\""{0}
{2}printfn{0} {16}@"""Temp: {19}%+12.3g{16} K"""{0} {6}x{0} {2}printfn{0} {16}@"""Temp: {19}%+12.3g{16} K"""{0} {6}x{0}
{2}printfn{0} {15}$"""{'"'}Temp: {19}%+12.3g{15}{x} K{'"'}"""{0} {2}printfn{0} {15}$"""{'"'}Temp: {19}%+12.3g{15}{x} K{'"'}"""{0}
{2}printfn{0} {15}$"""{'"'}Temp: {'+'{19},9{15}}{x{19}:g3{15}} K{'"'}"""{0} {2}printfn{0} {15}$"""{'"'}Temp: {'+'{19},9{15}}{x{19}:g3{15}} K{'"'}"""{0}
{2}printfn{0} {16}$@"""Temp: {19}%+12.3g{16}{x} K"""{0}
{2}printfn{0} {16}@$"""Temp: {'+'{19},9{16}}{x{19}:g3{16}} K"""{0}
{9}// Since F# 6.0{0} {9}// Since F# 6.0{0}
{2}printfn{0} {16}@"{19}%B{16}"{0} {13}0b1_000_000{0} {2}printfn{0} {16}@"{19}%B{16}"{0} {13}0b1_000_000{0}
{2}printfn{0} {15}"{19}%B{15}"{0} {15}"\x40"B{0}.{12}[{13}0{12}]{0} {2}printfn{0} {15}"{19}%B{15}"{0} {15}"\x40"B{0}.{12}[{13}0{12}]{0}
{2}printfn{0} {15}$"""{19}%B{15}{'\064'B}"""{0} {2}printfn{0} {15}$"""{19}%B{15}{'\064'B}"""{0}
{2}printfn{0} {16}$@"""{19}%B{16}{0b1_000_000}"""{0}
{2}printfn{0} {16}@$"""{19}%B{16}{'\064'B}"""{0}
{9}// These don't work{0} {9}// These don't work{0}
{2}printfn{0} {7}``%.2f``{0} {6}x{0} {2}printfn{0} {7}``%.2f``{0} {6}x{0}
{2}printfn{0} {15}$"%.2f"{0} {6}x{0} {2}printfn{0} {15}$"%.2f"{0} {6}x{0}
{2}printfn{0} {16}$@"%.2f"{0} {6}x{0}
{2}printfn{0} {16}@$"%.2f"{0} {6}x{0}
{2}printfn{0} {15}$"%.2f {x}"{0} {2}printfn{0} {15}$"%.2f {x}"{0}
{2}printfn{0} {16}$@"%.2f {x}"{0}
{2}printfn{0} {16}@$"%.2f {x}"{0}
{2}printfn{0} {15}$"""%.2f {x}"""{0} {2}printfn{0} {15}$"""%.2f {x}"""{0}
{2}printfn{0} {16}$@"""%.2f {x}"""{0}
{2}printfn{0} {16}@$"""%.2f {x}"""{0}

View File

@ -1,2 +1,3 @@
lexer.*.vb=vb lexer.*.vb=vb
lexer.vb.strings.multiline=1
keywords.*.vb=as dim or string keywords.*.vb=as dim or string

View File

@ -3,6 +3,9 @@ Dim a As String = "hello, world"
Dim b As String = "hello world" Dim b As String = "hello world"
Dim c As String = "Joe said ""Hello"" to me" Dim c As String = "Joe said ""Hello"" to me"
Dim d As String = "\\\\server\\share\\file.txt" Dim d As String = "\\\\server\\share\\file.txt"
Dim e As String = "The brown fox
jumps over
the lazy dog"
' Character ' Character
""C "c"C "cc"C ""C "c"C "cc"C
' Date ' Date

View File

@ -3,6 +3,9 @@
0 400 0 Dim b As String = "hello world" 0 400 0 Dim b As String = "hello world"
0 400 0 Dim c As String = "Joe said ""Hello"" to me" 0 400 0 Dim c As String = "Joe said ""Hello"" to me"
0 400 0 Dim d As String = "\\\\server\\share\\file.txt" 0 400 0 Dim d As String = "\\\\server\\share\\file.txt"
0 400 0 Dim e As String = "The brown fox
0 400 0 jumps over
0 400 0 the lazy dog"
0 400 0 ' Character 0 400 0 ' Character
0 400 0 ""C "c"C "cc"C 0 400 0 ""C "c"C "cc"C
0 400 0 ' Date 0 400 0 ' Date

View File

@ -3,6 +3,9 @@
{3}Dim{0} {7}b{0} {3}As{0} {3}String{0} {6}={0} {4}"hello world"{0} {3}Dim{0} {7}b{0} {3}As{0} {3}String{0} {6}={0} {4}"hello world"{0}
{3}Dim{0} {7}c{0} {3}As{0} {3}String{0} {6}={0} {4}"Joe said ""Hello"" to me"{0} {3}Dim{0} {7}c{0} {3}As{0} {3}String{0} {6}={0} {4}"Joe said ""Hello"" to me"{0}
{3}Dim{0} {7}d{0} {3}As{0} {3}String{0} {6}={0} {4}"\\\\server\\share\\file.txt"{0} {3}Dim{0} {7}d{0} {3}As{0} {3}String{0} {6}={0} {4}"\\\\server\\share\\file.txt"{0}
{3}Dim{0} {7}e{0} {3}As{0} {3}String{0} {6}={0} {4}"The brown fox
jumps over
the lazy dog"{0}
{1}' Character {1}' Character
{4}""C{0} {4}"c"C{0} {4}"cc"C{0} {4}""C{0} {4}"c"C{0} {4}"cc"C{0}
{1}' Date {1}' Date

View File

@ -1 +1 @@
524 525

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.4</string> <string>5.3.5</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,8 @@
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.4; CURRENT_PROJECT_VERSION = 5.3.5;
DEAD_CODE_STRIPPING = YES;
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 +636,8 @@
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.4; CURRENT_PROJECT_VERSION = 5.3.5;
DEAD_CODE_STRIPPING = YES;
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 +667,8 @@
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.4; CURRENT_PROJECT_VERSION = 5.3.5;
DEAD_CODE_STRIPPING = YES;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;
@ -699,7 +702,8 @@
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.4; CURRENT_PROJECT_VERSION = 5.3.5;
DEAD_CODE_STRIPPING = YES;
DEFINES_MODULE = YES; DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_COMPATIBILITY_VERSION = 1;

View File

@ -0,0 +1,71 @@
// File to suppress cppcheck warnings for files that will not be fixed.
// Does not suppress warnings where an additional occurrence of the warning may be of interest.
// Coding style is to use assignments in constructor when there are many
// members to initialize or the initialization is complex or has comments.
useInitializationList
// These may be interesting but its not clear without examining each instance closely
// Would have to ensure that any_of/all_of has same early/late exits as current code and
// produces same result on empty collections
useStlAlgorithm
// Written with variable for consistency
knownArgument:scintilla/src/SparseVector.h
// The cast converts from 'unsigned char ' to 'char' so isn't unused.
// Redundant code: Found unused cast of expression 'leadByte'
constStatement:scintilla/src/Document.cxx
// Some non-explicit constructors are used for conversions or are private to lexers
noExplicitConstructor
// MarginView access to all bits is safe and is better defined in later versions of C++
shiftTooManyBitsSigned:scintilla/src/MarginView.cxx
// DLL entry points are unused inside Scintilla
unusedFunction:scintilla/win32/ScintillaDLL.cxx
// ScintillaDocument is providing an API and there are no consumers of the API inside Scintilla
unusedFunction:scintilla/qt/ScintillaEdit/ScintillaDocument.cpp
// Doesn't understand changing dropWentOutside in Editor
knownConditionTrueFalse:scintilla/qt/ScintillaEditBase/ScintillaQt.cpp
knownConditionTrueFalse:scintilla/win32/ScintillaWin.cxx
// G_DEFINE_TYPE is too complex to pass to cppcheck
unknownMacro:scintilla/gtk/PlatGTK.cxx
// maskSmooth set depending on preprocessor allowing Wayland definition
badBitmaskCheck:scintilla/gtk/ScintillaGTK.cxx
// Difficult to test accessibility so don't change
constVariable:scintilla/gtk/ScintillaGTKAccessible.cxx
// Have no way of testing ScintillaEdit so don't fix even simple warnings
cstyleCast:scintilla/qt/ScintillaEdit/ScintillaEdit.cpp
shadowFunction:scintilla/qt/ScintillaEdit/ScintillaEdit.cpp
// cppcheck fails emit from Qt
shadowFunction:scintilla/qt/ScintillaEditBase/ScintillaQt.cpp
shadowFunction:scintilla/qt/ScintillaEditBase/ScintillaEditBase.cpp
// moc_ files show #error as they are not built with standard context
preprocessorErrorDirective:scintilla/qt/*.cpp
// moc_ files are not understood by cppcheck
noValidConfiguration
// The performance cost of by-value passing is often small and using a reference decreases
// code legibility.
passedByValue
// Suppress everything in catch.hpp as won't be changing
*:scintilla/test/unit/catch.hpp
// Checks for moves move to variables that are not read but the moved from is checked
unreadVariable:scintilla/test/unit/*.cxx
accessMoved:scintilla/test/unit/*.cxx
// cppcheck fails REQUIRE from Catch
comparisonOfFuncReturningBoolError:scintilla/test/unit/*.cxx

View File

@ -148,10 +148,6 @@
GTK sample which can be used to find bugs or prototype new features.</a><br /> GTK sample which can be used to find bugs or prototype new features.</a><br />
<a class="jump" href="Lexer.txt">A detailed description of how to write a lexer, including a <a class="jump" href="Lexer.txt">A detailed description of how to write a lexer, including a
discussion of folding</a>.<br /> discussion of folding</a>.<br />
<a class="jump" href="http://sphere.sourceforge.net/flik/docs/scintilla-container_lexer.html">
How to implement a lexer in the container</a>.<br />
<a class="jump" href="http://sphere.sourceforge.net/flik/docs/scintilla-folding.html">
How to implement folding</a>.<br />
<a class="jump" href="https://github.com/geany/geany/files/5204338/Scintilla-var.aq-Tutorial.pdf"> <a class="jump" href="https://github.com/geany/geany/files/5204338/Scintilla-var.aq-Tutorial.pdf">
Beginner's Guide to lexing and folding</a>.<br /> Beginner's Guide to lexing and folding</a>.<br />
The <a class="jump" href="SciCoding.html">coding style</a> used in Scintilla and SciTE is The <a class="jump" href="SciCoding.html">coding style</a> used in Scintilla and SciTE is
@ -4883,7 +4879,74 @@ struct Sci_TextToFindFull {
A windowed IME <code>SC_IME_WINDOWED</code> (0) may be more similar in appearance and A windowed IME <code>SC_IME_WINDOWED</code> (0) may be more similar in appearance and
behaviour to the IME in other applications. behaviour to the IME in other applications.
An inline IME <code>SC_IME_INLINE</code> (1) may work better with some Scintilla features such as An inline IME <code>SC_IME_INLINE</code> (1) may work better with some Scintilla features such as
rectangular and multiple selection.</p> rectangular and multiple selection, with IME interactions such as retrieve-surrounding or reconversion feature.</p>
<table class="standard" summary="IME input method">
<caption>IME input method support (O=present, X=absent)</caption>
<thead align="left">
<tr>
<th>IME input method</th>
<th>Windows</th>
<th>Gtk</th>
<th>Qt</th>
<th>macOS</th>
</tr>
</thead>
<tbody valign="top">
<tr>
<th align="left"><code>SC_IME_WINDOWED</code></th>
<td>O</td>
<td>O</td>
<td>X</td>
<td>X</td>
</tr>
<tr>
<th align="left"><code>SC_IME_INLINE</code></th>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
</tbody>
</table>
<p></p>
<table class="standard" summary="IME interaction">
<caption>IME interaction support</caption>
<thead align="left">
<tr>
<th>IME interaction</th>
<th>Windows</th>
<th>Gtk</th>
<th>Qt</th>
<th>macOS</th>
</tr>
</thead>
<tbody valign="top">
<tr>
<th align="left">Retrieve Surrounding</th>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
<tr>
<th align="left">Reconversion</th>
<td>O</td>
<td>O</td>
<td>O</td>
<td>O</td>
</tr>
<tr>
<th align="left">Delete Surrounding</th>
<td>O</td>
<td>O</td>
<td>X</td>
<td>O</td>
</tr>
</tbody>
</table>
<p>The windowed behaviour can be chosen with <code>SCI_SETIMEINTERACTION(SC_IME_WINDOWED)</code> <p>The windowed behaviour can be chosen with <code>SCI_SETIMEINTERACTION(SC_IME_WINDOWED)</code>
and the inline behaviour with <code>SCI_SETIMEINTERACTION(SC_IME_INLINE)</code>. and the inline behaviour with <code>SCI_SETIMEINTERACTION(SC_IME_INLINE)</code>.
Scintilla may ignore this call in some cases. For example, the inline behaviour might only be supported for some languages.</p> Scintilla may ignore this call in some cases. For example, the inline behaviour might only be supported for some languages.</p>

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/scintilla534.zip"> <font size="4"> <a href="https://www.scintilla.org/scintilla535.zip">
Windows</a>&nbsp;&nbsp; Windows</a>&nbsp;&nbsp;
<a href="https://www.scintilla.org/scintilla534.tgz"> <a href="https://www.scintilla.org/scintilla535.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.4 Release 5.3.5
</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/scintilla534.zip">zip format</a> (1.4M) commonly used on Windows</li> <li><a href="https://www.scintilla.org/scintilla535.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> <li><a href="https://www.scintilla.org/scintilla535.tgz">tgz format</a> (1.3M) 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

@ -576,9 +576,37 @@
<td>Ferdinand Oeinck</td> <td>Ferdinand Oeinck</td>
<td>Michael Heath</td> <td>Michael Heath</td>
<td>Enrico Tröger</td> <td>Enrico Tröger</td>
</tr><tr>
<td>Chengzhi Li</td>
</tr> </tr>
</table> </table>
<h2>Releases</h2> <h2>Releases</h2>
<h3>
<a href="https://www.scintilla.org/scintilla535.zip">Release 5.3.5</a>
</h3>
<ul>
<li>
Released 31 May 2023.
</li>
<li>
On Win32, implement IME context sensitivity with IMR_DOCUMENTFEED.
<a href="https://sourceforge.net/p/scintilla/feature-requests/1310/">Feature #1310</a>.
</li>
<li>
On Win32 remove dependence on MSIMG32.DLL by replacing AlphaBlend
by GdiAlphaBlend.
<a href="https://sourceforge.net/p/scintilla/bugs/1923/">Bug #1923</a>.
</li>
<li>
On Qt, stop movement of IME candidate box.
</li>
<li>
On Qt, report correct caret position within paragraph for IME retrieve surrounding text.
</li>
<li>
On Qt for Cocoa, fix crash in entry of multi-character strings with IME.
</li>
</ul>
<h3> <h3>
<a href="https://www.scintilla.org/scintilla534.zip">Release 5.3.4</a> <a href="https://www.scintilla.org/scintilla534.zip">Release 5.3.4</a>
</h3> </h3>

View File

@ -29,6 +29,10 @@
<h3> <h3>
Ports and Bindings of Scintilla Ports and Bindings of Scintilla
</h3> </h3>
<p>
<a href="https://github.com/mneuroth/SciTEQt">SciTEQt</a>
is a port of the SciTE editor to the Qt QML/Quick platform.
</p>
<p> <p>
<a href="https://orbitalquark.github.io/scinterm">Scinterm</a> <a href="https://orbitalquark.github.io/scinterm">Scinterm</a>
is an implementation of Scintilla for the ncurses platform. is an implementation of Scintilla for the ncurses platform.
@ -127,6 +131,14 @@
<h3> <h3>
Projects using Scintilla Projects using Scintilla
</h3> </h3>
<p>
<a href="https://github.com/dail8859/NotepadNext">Notepad Next</a>
is a cross-platform reimplementation of Notepad++.
</p>
<p>
<a href="https://github.com/dolphinsmalltalk/Dolphin">Dolphin Smalltalk</a>
is an implementation of the Smalltalk language for Windows.
</p>
<p> <p>
<a href="https://github.com/simdsoft/x-studio/blob/master/README_EN.md">x-studio</a> <a href="https://github.com/simdsoft/x-studio/blob/master/README_EN.md">x-studio</a>
is a powerful and very lightweight developer IDE that supports Lua debugging. is a powerful and very lightweight developer IDE that supports Lua debugging.

View File

@ -9,9 +9,16 @@
<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="20230308" /> <meta name="Date.Modified" content="20230531" />
<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 {
background: url(https://www.scintilla.org/ScintillaLogo.png) no-repeat;
background-image: image-set(
url(https://www.scintilla.org/ScintillaLogo.png) 1x,
url(https://www.scintilla.org/ScintillaLogo2x.png) 2x );
height:150px;
}
#versionlist { #versionlist {
margin: 0; margin: 0;
padding: .5em; padding: .5em;
@ -48,16 +55,13 @@
<body bgcolor="#FFFFFF" text="#000000"> <body bgcolor="#FFFFFF" text="#000000">
<table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0"> <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr> <tr>
<td width="256">
<img src="SciWord.jpg" height="78" width="256" alt="Scintilla" />
</td>
<td width="40%" align="left"> <td width="40%" align="left">
<font color="#FFCC99" size="4"> A free source code editing component for Win32, <font color="#FFCC99" size="4"> A free source code editing component for Win32,
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.4<br /> <font color="#FFCC99" size="3"> Release version 5.3.5<br />
Site last modified March 8 2023</font> Site last modified May 31 2023</font>
</td> </td>
<td width="20%"> <td width="20%">
&nbsp; &nbsp;
@ -66,18 +70,18 @@
</table> </table>
<table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0"> <table bgcolor="#000000" width="100%" cellspacing="0" cellpadding="0" border="0">
<tr> <tr>
<td width="100%" style="background: url(SciBreak.jpg) no-repeat;height:150px;"> <td width="100%" class="logo">
&nbsp; &nbsp;
</td> </td>
</tr> </tr>
</table> </table>
<ul id="versionlist"> <ul id="versionlist">
<li>Version 5.3.5 improves IME support on Win32 and Qt.</li>
<li>Version 5.3.4 adds multithreaded wrapping.</li> <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.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.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.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>
</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

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

View File

@ -268,8 +268,15 @@ void ScintillaEditBase::keyPressEvent(QKeyEvent *event)
QString text = event->text(); QString text = event->text();
if (input && !text.isEmpty() && text[0].isPrint()) { if (input && !text.isEmpty() && text[0].isPrint()) {
QByteArray utext = sqt->BytesForDocument(text); const int strLen = text.length();
sqt->InsertCharacter(std::string_view(utext.data(), utext.size()), CharacterSource::DirectInput); for (int i = 0; i < strLen;) {
const int ucWidth = text.at(i).isHighSurrogate() ? 2 : 1;
const QString oneCharUTF16 = text.mid(i, ucWidth);
const QByteArray oneChar = sqt->BytesForDocument(oneCharUTF16);
sqt->InsertCharacter(std::string_view(oneChar.data(), oneChar.length()), CharacterSource::DirectInput);
i += ucWidth;
}
} else { } else {
event->ignore(); event->ignore();
} }
@ -478,8 +485,6 @@ static std::vector<int> MapImeIndicators(QInputMethodEvent *event)
int indicator = IndicatorUnknown; int indicator = IndicatorUnknown;
switch (charFormat.underlineStyle()) { switch (charFormat.underlineStyle()) {
case QTextCharFormat::NoUnderline: // win32, linux case QTextCharFormat::NoUnderline: // win32, linux
indicator = IndicatorTarget;
break;
case QTextCharFormat::SingleUnderline: // osx case QTextCharFormat::SingleUnderline: // osx
case QTextCharFormat::DashUnderline: // win32, linux case QTextCharFormat::DashUnderline: // win32, linux
indicator = IndicatorInput; indicator = IndicatorInput;
@ -535,6 +540,7 @@ void ScintillaEditBase::inputMethodEvent(QInputMethodEvent *event)
} }
sqt->view.imeCaretBlockOverride = false; sqt->view.imeCaretBlockOverride = false;
preeditPos = -1; // reset not to interrupt Qt::ImCursorRectangle.
if (!event->commitString().isEmpty()) { if (!event->commitString().isEmpty()) {
const QString &commitStr = event->commitString(); const QString &commitStr = event->commitString();
@ -561,6 +567,9 @@ void ScintillaEditBase::inputMethodEvent(QInputMethodEvent *event)
sqt->ClearBeforeTentativeStart(); sqt->ClearBeforeTentativeStart();
sqt->pdoc->TentativeStart(); // TentativeActive() from now on. sqt->pdoc->TentativeStart(); // TentativeActive() from now on.
// Fix candidate window position at the start of preeditString.
preeditPos = sqt->CurrentPosition();
std::vector<int> imeIndicator = MapImeIndicators(event); std::vector<int> imeIndicator = MapImeIndicators(event);
for (int i = 0; i < preeditStrLen;) { for (int i = 0; i < preeditStrLen;) {
@ -592,10 +601,14 @@ void ScintillaEditBase::inputMethodEvent(QInputMethodEvent *event)
sqt->view.imeCaretBlockOverride = true; sqt->view.imeCaretBlockOverride = true;
} }
// Set candidate box position for Qt::ImMicroFocus. // Set Candidate window position again at imeCaret when target input.
preeditPos = sqt->CurrentPosition(); const bool targetAny = std::any_of(imeIndicator.begin(), imeIndicator.end(), [](int i) noexcept {
return i == IndicatorTarget;
});
if (targetAny)
preeditPos = sqt->CurrentPosition();
sqt->EnsureCaretVisible(); sqt->EnsureCaretVisible();
updateMicroFocus();
} }
sqt->ShowCaretAtCurrentPosition(); sqt->ShowCaretAtCurrentPosition();
} }
@ -642,7 +655,7 @@ QVariant ScintillaEditBase::inputMethodQuery(Qt::InputMethodQuery query) const
case Qt::ImCursorPosition: case Qt::ImCursorPosition:
{ {
const Scintilla::Position paraStart = sqt->pdoc->ParaUp(pos); const Scintilla::Position paraStart = sqt->pdoc->ParaUp(pos);
return QVariant(static_cast<int>(pos - paraStart)); return static_cast<int>(sqt->pdoc->CountUTF16(paraStart, pos));
} }
case Qt::ImSurroundingText: case Qt::ImSurroundingText:

View File

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

View File

@ -5,7 +5,8 @@
# Requires Python 2.7 or later # Requires Python 2.7 or later
def sanitiseLine(line): def sanitiseLine(line):
if line[-1:] == '\n': line = line[:-1] if line[-1:] == '\n':
line = line[:-1]
if line.find("##") != -1: if line.find("##") != -1:
line = line[:line.find("##")] line = line[:line.find("##")]
line = line.strip() line = line.strip()

View File

@ -143,16 +143,16 @@ def UpdateLineInPlistFile(path, key, value):
lines = [] lines = []
keyCurrent = "" keyCurrent = ""
with codecs.open(path, "rb", "utf-8") as f: with codecs.open(path, "rb", "utf-8") as f:
for l in f.readlines(): for line in f.readlines():
ls = l.strip() ls = line.strip()
if ls.startswith("<key>"): if ls.startswith("<key>"):
keyCurrent = ls.replace("<key>", "").replace("</key>", "") keyCurrent = ls.replace("<key>", "").replace("</key>", "")
elif ls.startswith("<string>"): elif ls.startswith("<string>"):
if keyCurrent == key: if keyCurrent == key:
start, tag, rest = l.partition("<string>") start, tag, rest = line.partition("<string>")
_val, etag, end = rest.partition("</string>") _val, etag, end = rest.partition("</string>")
l = start + tag + value + etag + end line = start + tag + value + etag + end
lines.append(l) lines.append(line)
contents = "".join(lines) contents = "".join(lines)
UpdateFile(path, contents) UpdateFile(path, contents)
@ -160,13 +160,13 @@ def UpdateLineInFile(path, linePrefix, lineReplace):
lines = [] lines = []
updated = False updated = False
with codecs.open(path, "r", "utf-8") as f: with codecs.open(path, "r", "utf-8") as f:
for l in f.readlines(): for line in f.readlines():
l = l.rstrip() line = line.rstrip()
if not updated and l.startswith(linePrefix): if not updated and line.startswith(linePrefix):
lines.append(lineReplace) lines.append(lineReplace)
updated = True updated = True
else: else:
lines.append(l) lines.append(line)
if not updated: if not updated:
print(f"{path}:0: Can't find '{linePrefix}'") print(f"{path}:0: Can't find '{linePrefix}'")
contents = lineEnd.join(lines) + lineEnd contents = lineEnd.join(lines) + lineEnd
@ -176,7 +176,7 @@ def ReadFileAsList(path):
"""Read all the lnes in the file and return as a list of strings without line ends. """Read all the lnes in the file and return as a list of strings without line ends.
""" """
with codecs.open(path, "r", "utf-8") as f: with codecs.open(path, "r", "utf-8") as f:
return [l.rstrip('\n') for l in f] return [line.rstrip('\n') for line in f]
def UpdateFileFromLines(path, lines, lineEndToUse): def UpdateFileFromLines(path, lines, lineEndToUse):
"""Join the lines with the lineEndToUse then update file if the result is different. """Join the lines with the lineEndToUse then update file if the result is different.
@ -194,19 +194,19 @@ def FindSectionInList(lines, markers):
start = -1 start = -1
end = -1 end = -1
state = 0 state = 0
for i, l in enumerate(lines): for i, line in enumerate(lines):
if markers[0] in l: if markers[0] in line:
if markers[1]: if markers[1]:
state = 1 state = 1
else: else:
start = i+1 start = i+1
state = 2 state = 2
elif state == 1: elif state == 1:
if markers[1] in l: if markers[1] in line:
start = i+1 start = i+1
state = 2 state = 2
elif state == 2: elif state == 2:
if markers[2] in l: if markers[2] in line:
end = i end = i
state = 3 state = 3
# Check that section was found # Check that section was found

View File

@ -21,11 +21,11 @@ import itertools, string, sys
from FileGenerator import Regenerate from FileGenerator import Regenerate
def contiguousRanges(l, diff): def contiguousRanges(ll, diff):
# l is s list of lists # ll is a list of lists
# group into lists where first element of each element differs by diff # group into lists where first element of each element differs by diff
out = [[l[0]]] out = [[ll[0]]]
for s in l[1:]: for s in ll[1:]:
if s[0] != out[-1][-1][0] + diff: if s[0] != out[-1][-1][0] + diff:
out.append([]) out.append([])
out[-1].append(s) out[-1].append(s)
@ -99,7 +99,7 @@ def groupRanges(symmetrics):
rangeCoverage = list(flatten([range(r[0], r[0]+r[2]*r[3], r[3]) for r in rangeGroups])) rangeCoverage = list(flatten([range(r[0], r[0]+r[2]*r[3], r[3]) for r in rangeGroups]))
nonRanges = [(l, u) for l, u, _d in symmetrics if l not in rangeCoverage] nonRanges = [(x, u) for x, u, _d in symmetrics if x not in rangeCoverage]
return rangeGroups, nonRanges return rangeGroups, nonRanges

View File

@ -15,12 +15,12 @@ def HeaderFromIncludeLine(s):
return s.strip()[1:].strip()[7:].strip() return s.strip()[1:].strip()[7:].strip()
def ExtractHeaders(file): def ExtractHeaders(file):
with file.open(encoding="cp437") as infile: with file.open(encoding="iso-8859-1") as infile:
return [HeaderFromIncludeLine(l) for l in infile if IsHeader(l)] return [HeaderFromIncludeLine(h) for h in infile if IsHeader(h)]
def ExtractWithPrefix(file, prefix): def ExtractWithPrefix(file, prefix):
with file.open(encoding="cp437") as infile: with file.open(encoding="iso-8859-1") as infile:
return [l.strip()[len(prefix):] for l in infile if l.startswith(prefix)] return [s.strip()[len(prefix):] for s in infile if s.startswith(prefix)]
def ExcludeName(name, excludes): def ExcludeName(name, excludes):
return any(exclude in name for exclude in excludes) return any(exclude in name for exclude in excludes)

View File

@ -34,7 +34,7 @@ def UpdateVersionNumbers(sci, root):
UpdateLineInFile(root / "doc/ScintillaDownload.html", " Release", UpdateLineInFile(root / "doc/ScintillaDownload.html", " Release",
" Release " + sci.versionDotted) " Release " + sci.versionDotted)
ReplaceREInFile(root / "doc/ScintillaDownload.html", 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, r"/www.scintilla.org/\g<1>" + sci.version,
0) 0)
UpdateLineInFile(root / "doc/index.html", UpdateLineInFile(root / "doc/index.html",

View File

@ -25,15 +25,15 @@ def FindCredits(historyFile, removeLinks=True):
credits = [] credits = []
stage = 0 stage = 0
with historyFile.open(encoding="utf-8") as f: with historyFile.open(encoding="utf-8") as f:
for l in f.readlines(): for line in f.readlines():
l = l.strip() line = line.strip()
if stage == 0 and l == "<table>": if stage == 0 and line == "<table>":
stage = 1 stage = 1
elif stage == 1 and l == "</table>": elif stage == 1 and line == "</table>":
stage = 2 stage = 2
if stage == 1 and l.startswith("<td>"): if stage == 1 and line.startswith("<td>"):
credit = l[4:-5] credit = line[4:-5]
if removeLinks and "<a" in l: if removeLinks and "<a" in line:
title, _a, rest = credit.partition("<a href=") title, _a, rest = credit.partition("<a href=")
urlplus, _bracket, end = rest.partition(">") urlplus, _bracket, end = rest.partition(">")
name = end.split("<")[0] name = end.split("<")[0]
@ -49,12 +49,12 @@ class ScintillaData:
def __init__(self, scintillaRoot): def __init__(self, scintillaRoot):
# Discover version information # Discover version information
self.version = (scintillaRoot / "version.txt").read_text().strip() self.version = (scintillaRoot / "version.txt").read_text().strip()
self.versionDotted = self.version[0] + '.' + self.version[1] + '.' + \ self.versionDotted = self.version[0:-2] + '.' + self.version[-2] + '.' + \
self.version[2] self.version[-1]
self.versionCommad = self.versionDotted.replace(".", ", ") + ', 0' self.versionCommad = self.versionDotted.replace(".", ", ") + ', 0'
with (scintillaRoot / "doc" / "index.html").open() as f: with (scintillaRoot / "doc" / "index.html").open() as f:
self.dateModified = [l for l in f.readlines() if "Date.Modified" in l]\ self.dateModified = [d for d in f.readlines() if "Date.Modified" in d]\
[0].split('\"')[3] [0].split('\"')[3]
# 20130602 # 20130602
# index.html, SciTE.html # index.html, SciTE.html

View File

@ -108,14 +108,14 @@ void DrawArrow(Surface *surface, const PRectangle &rc, bool upArrow, ColourRGBA
constexpr XYPOSITION pixelMove = 0.0f; constexpr XYPOSITION pixelMove = 0.0f;
if (upArrow) { // Up arrow if (upArrow) { // Up arrow
Point pts[] = { const Point pts[] = {
Point(centreX - halfWidth + pixelMove, centreY + quarterWidth + 0.5f), Point(centreX - halfWidth + pixelMove, centreY + quarterWidth + 0.5f),
Point(centreX + halfWidth + pixelMove, centreY + quarterWidth + 0.5f), Point(centreX + halfWidth + pixelMove, centreY + quarterWidth + 0.5f),
Point(centreX + pixelMove, centreY - halfWidth + quarterWidth + 0.5f), Point(centreX + pixelMove, centreY - halfWidth + quarterWidth + 0.5f),
}; };
surface->Polygon(pts, std::size(pts), FillStroke(colourBG)); surface->Polygon(pts, std::size(pts), FillStroke(colourBG));
} else { // Down arrow } else { // Down arrow
Point pts[] = { const Point pts[] = {
Point(centreX - halfWidth + pixelMove, centreY - quarterWidth + 0.5f), Point(centreX - halfWidth + pixelMove, centreY - quarterWidth + 0.5f),
Point(centreX + halfWidth + pixelMove, centreY - quarterWidth + 0.5f), Point(centreX + halfWidth + pixelMove, centreY - quarterWidth + 0.5f),
Point(centreX + pixelMove, centreY + halfWidth - quarterWidth + 0.5f), Point(centreX + pixelMove, centreY + halfWidth - quarterWidth + 0.5f),

View File

@ -580,7 +580,7 @@ constexpr std::string_view complexCaseConversions =
// Maximum length of a case conversion result is 6 bytes in UTF-8 // Maximum length of a case conversion result is 6 bytes in UTF-8
constexpr size_t maxConversionLength = 6; constexpr size_t maxConversionLength = 6;
class CaseConverter : public ICaseConverter { class CaseConverter final : public ICaseConverter {
struct ConversionString { struct ConversionString {
char conversion[maxConversionLength+1]{}; char conversion[maxConversionLength+1]{};
}; };
@ -605,7 +605,6 @@ class CaseConverter : public ICaseConverter {
return character < other.character; return character < other.character;
} }
}; };
CaseConversion conversion;
typedef std::vector<CharacterConversion> CharacterToConversion; typedef std::vector<CharacterConversion> CharacterToConversion;
CharacterToConversion characterToConversion; CharacterToConversion characterToConversion;
// The parallel arrays // The parallel arrays
@ -613,14 +612,7 @@ class CaseConverter : public ICaseConverter {
std::vector<ConversionString> conversions; std::vector<ConversionString> conversions;
public: 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;
CaseConverter &operator=(const CaseConverter &) = delete;
CaseConverter &operator=(CaseConverter &&) = delete;
virtual ~CaseConverter() noexcept = default;
bool Initialised() const noexcept { bool Initialised() const noexcept {
return !characters.empty(); return !characters.empty();
} }
@ -690,15 +682,13 @@ public:
// Empty the original calculated data completely // Empty the original calculated data completely
CharacterToConversion().swap(characterToConversion); CharacterToConversion().swap(characterToConversion);
} }
void AddSymmetric(int lower, int upper); void AddSymmetric(CaseConversion conversion, int lower, int upper);
void SetupConversions(); void SetupConversions(CaseConversion conversion);
}; };
CaseConverter caseConvFold(CaseConversion::fold); CaseConverter caseConvList[3];
CaseConverter caseConvUp(CaseConversion::upper);
CaseConverter caseConvLow(CaseConversion::lower);
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 character = (conversion == CaseConversion::upper) ? lower : upper;
const int source = (conversion == CaseConversion::upper) ? upper : lower; const int source = (conversion == CaseConversion::upper) ? upper : lower;
char converted[maxConversionLength+1]{}; char converted[maxConversionLength+1]{};
@ -720,7 +710,7 @@ std::string_view NextField(std::string_view &view) {
return field; return field;
} }
void CaseConverter::SetupConversions() { void CaseConverter::SetupConversions(CaseConversion conversion) {
// First initialize for the symmetric ranges // First initialize for the symmetric ranges
for (size_t i=0; i<std::size(symmetricCaseConversionRanges);) { for (size_t i=0; i<std::size(symmetricCaseConversionRanges);) {
const int lower = symmetricCaseConversionRanges[i++]; const int lower = symmetricCaseConversionRanges[i++];
@ -728,14 +718,14 @@ void CaseConverter::SetupConversions() {
const int length = symmetricCaseConversionRanges[i++]; const int length = symmetricCaseConversionRanges[i++];
const int pitch = symmetricCaseConversionRanges[i++]; const int pitch = symmetricCaseConversionRanges[i++];
for (int j=0; j<length*pitch; j+=pitch) { for (int j=0; j<length*pitch; j+=pitch) {
AddSymmetric(lower+j, upper+j); AddSymmetric(conversion, lower+j, upper+j);
} }
} }
// Add the symmetric singletons // Add the symmetric singletons
for (size_t i=0; i<std::size(symmetricCaseConversions);) { for (size_t i=0; i<std::size(symmetricCaseConversions);) {
const int lower = symmetricCaseConversions[i++]; const int lower = symmetricCaseConversions[i++];
const int upper = symmetricCaseConversions[i++]; const int upper = symmetricCaseConversions[i++];
AddSymmetric(lower, upper); AddSymmetric(conversion, lower, upper);
} }
// Add the complex cases // Add the complex cases
std::string_view sComplex = complexCaseConversions; std::string_view sComplex = complexCaseConversions;
@ -768,21 +758,11 @@ void CaseConverter::SetupConversions() {
} }
CaseConverter *ConverterForConversion(CaseConversion conversion) { CaseConverter *ConverterForConversion(CaseConversion conversion) {
CaseConverter *pCaseConv = &caseConvFold; const unsigned index = static_cast<unsigned>(conversion);
switch (conversion) { assert(index < std::size(caseConvList));
case CaseConversion::fold: CaseConverter *pCaseConv = &caseConvList[index];
pCaseConv = &caseConvFold;
break;
case CaseConversion::upper:
pCaseConv = &caseConvUp;
break;
case CaseConversion::lower:
default:
pCaseConv = &caseConvLow;
break;
}
if (!pCaseConv->Initialised()) { if (!pCaseConv->Initialised()) {
pCaseConv->SetupConversions(); pCaseConv->SetupConversions(conversion);
} }
return pCaseConv; return pCaseConv;
} }

View File

@ -2880,7 +2880,7 @@ public:
}; };
// Define a way for the Regular Expression code to access the document // Define a way for the Regular Expression code to access the document
class DocumentIndexer : public CharacterIndexer { class DocumentIndexer final : public CharacterIndexer {
Document *pdoc; Document *pdoc;
Sci::Position end; Sci::Position end;
public: public:
@ -2888,13 +2888,6 @@ public:
pdoc(pdoc_), end(end_) { pdoc(pdoc_), end(end_) {
} }
DocumentIndexer(const DocumentIndexer &) = delete;
DocumentIndexer(DocumentIndexer &&) = delete;
DocumentIndexer &operator=(const DocumentIndexer &) = delete;
DocumentIndexer &operator=(DocumentIndexer &&) = delete;
~DocumentIndexer() override = default;
char CharAt(Sci::Position index) const noexcept override { char CharAt(Sci::Position index) const noexcept override {
if (index < 0 || index >= end) if (index < 0 || index >= end)
return 0; return 0;

View File

@ -26,6 +26,7 @@
#include <memory> #include <memory>
#include <chrono> #include <chrono>
#include <atomic> #include <atomic>
#include <mutex>
#include <thread> #include <thread>
#include <future> #include <future>
@ -1510,7 +1511,7 @@ bool Editor::WrapBlock(Surface *surface, Sci::Line lineToWrap, Sci::Line lineToW
// Lines that are less likely to be re-examined should not be read from or written to the cache. // Lines that are less likely to be re-examined should not be read from or written to the cache.
const SignificantLines significantLines { const SignificantLines significantLines {
pdoc->SciLineFromPosition(sel.MainCaret()), pdoc->SciLineFromPosition(sel.MainCaret()),
topLine, pcs->DocFromDisplay(topLine),
LinesOnScreen() + 1, LinesOnScreen() + 1,
view.llc.GetLevel(), view.llc.GetLevel(),
}; };
@ -1914,7 +1915,7 @@ Sci::Position Editor::FormatRange(Scintilla::Message iMessage, Scintilla::uptr_t
void *ptr = PtrFromSPtr(lParam); void *ptr = PtrFromSPtr(lParam);
if (iMessage == Message::FormatRange) { if (iMessage == Message::FormatRange) {
RangeToFormat *pfr = static_cast<RangeToFormat *>(ptr); RangeToFormat *pfr = static_cast<RangeToFormat *>(ptr);
CharacterRangeFull chrg{ pfr->chrg.cpMin,pfr->chrg.cpMax }; const CharacterRangeFull chrg{ pfr->chrg.cpMin,pfr->chrg.cpMax };
AutoSurface surface(pfr->hdc, this, Technology::Default); AutoSurface surface(pfr->hdc, this, Technology::Default);
AutoSurface surfaceMeasure(pfr->hdcTarget, this, Technology::Default); AutoSurface surfaceMeasure(pfr->hdcTarget, this, Technology::Default);
if (!surface || !surfaceMeasure) { if (!surface || !surfaceMeasure) {

View File

@ -172,6 +172,7 @@ PRectangle PixelAlignOutside(const PRectangle &rc, int pixelDivisions) noexcept;
*/ */
constexpr const float componentMaximum = 255.0f; constexpr const float componentMaximum = 255.0f;
class ColourRGBA { class ColourRGBA {
static constexpr int rgbMask = 0xffffff;
int co; int co;
public: public:
constexpr explicit ColourRGBA(int co_ = 0) noexcept : co(co_) { constexpr explicit ColourRGBA(int co_ = 0) noexcept : co(co_) {
@ -190,11 +191,11 @@ public:
} }
static constexpr ColourRGBA FromIpRGB(intptr_t co_) noexcept { static constexpr ColourRGBA FromIpRGB(intptr_t co_) noexcept {
return ColourRGBA(static_cast<int>(co_) | (0xffu << 24)); return ColourRGBA((co_ & rgbMask) | (0xffu << 24));
} }
constexpr ColourRGBA WithoutAlpha() const noexcept { constexpr ColourRGBA WithoutAlpha() const noexcept {
return ColourRGBA(co & 0xffffff); return ColourRGBA(co & rgbMask);
} }
constexpr ColourRGBA Opaque() const noexcept { constexpr ColourRGBA Opaque() const noexcept {
@ -206,7 +207,7 @@ public:
} }
constexpr int OpaqueRGB() const noexcept { constexpr int OpaqueRGB() const noexcept {
return co & 0xffffff; return co & rgbMask;
} }
// Red, green and blue values as bytes 0..255 // Red, green and blue values as bytes 0..255

View File

@ -144,7 +144,7 @@ void DrawTail(Surface *surface, XYPOSITION leftLine, XYPOSITION rightTail, XYPOS
const XYPOSITION strokeTop = centreY + slopeLength; const XYPOSITION strokeTop = centreY + slopeLength;
const XYPOSITION halfWidth = widthSymbolStroke / 2.0f; const XYPOSITION halfWidth = widthSymbolStroke / 2.0f;
const XYPOSITION strokeMiddle = strokeTop + halfWidth; const XYPOSITION strokeMiddle = strokeTop + halfWidth;
Point lines[] = { const Point lines[] = {
// Stick // Stick
Point(rightTail, strokeMiddle), Point(rightTail, strokeMiddle),
Point(leftLine + halfWidth + slopeLength, strokeMiddle), Point(leftLine + halfWidth + slopeLength, strokeMiddle),
@ -396,7 +396,7 @@ void LineMarker::Draw(Surface *surface, const PRectangle &rcWhole, const Font *f
break; break;
case MarkerSymbol::Arrow: { case MarkerSymbol::Arrow: {
Point pts[] = { const Point pts[] = {
Point(centreX - dimOn4, centreY - dimOn2), Point(centreX - dimOn4, centreY - dimOn2),
Point(centreX - dimOn4, centreY + dimOn2), Point(centreX - dimOn4, centreY + dimOn2),
Point(centreX + dimOn2 - dimOn4, centreY), Point(centreX + dimOn2 - dimOn4, centreY),
@ -406,7 +406,7 @@ void LineMarker::Draw(Surface *surface, const PRectangle &rcWhole, const Font *f
break; break;
case MarkerSymbol::ArrowDown: { case MarkerSymbol::ArrowDown: {
Point pts[] = { const Point pts[] = {
Point(centreX - dimOn2, centreY - dimOn4), Point(centreX - dimOn2, centreY - dimOn4),
Point(centreX + dimOn2, centreY - dimOn4), Point(centreX + dimOn2, centreY - dimOn4),
Point(centreX, centreY + dimOn2 - dimOn4), Point(centreX, centreY + dimOn2 - dimOn4),
@ -416,7 +416,7 @@ void LineMarker::Draw(Surface *surface, const PRectangle &rcWhole, const Font *f
break; break;
case MarkerSymbol::Plus: { case MarkerSymbol::Plus: {
Point pts[] = { const Point pts[] = {
Point(centreX - armSize, centreY - 1), Point(centreX - armSize, centreY - 1),
Point(centreX - 1, centreY - 1), Point(centreX - 1, centreY - 1),
Point(centreX - 1, centreY - armSize), Point(centreX - 1, centreY - armSize),
@ -435,7 +435,7 @@ void LineMarker::Draw(Surface *surface, const PRectangle &rcWhole, const Font *f
break; break;
case MarkerSymbol::Minus: { case MarkerSymbol::Minus: {
Point pts[] = { const Point pts[] = {
Point(centreX - armSize, centreY - 1), Point(centreX - armSize, centreY - 1),
Point(centreX + armSize, centreY - 1), Point(centreX + armSize, centreY - 1),
Point(centreX + armSize, centreY + 1), Point(centreX + armSize, centreY + 1),
@ -489,7 +489,7 @@ void LineMarker::Draw(Surface *surface, const PRectangle &rcWhole, const Font *f
break; break;
case MarkerSymbol::ShortArrow: { case MarkerSymbol::ShortArrow: {
Point pts[] = { const Point pts[] = {
Point(centreX, centreY + dimOn2), Point(centreX, centreY + dimOn2),
Point(centreX + dimOn2, centreY), Point(centreX + dimOn2, centreY),
Point(centreX, centreY - dimOn2), Point(centreX, centreY - dimOn2),
@ -547,7 +547,7 @@ void LineMarker::Draw(Surface *surface, const PRectangle &rcWhole, const Font *f
case MarkerSymbol::Bookmark: { case MarkerSymbol::Bookmark: {
const XYPOSITION halfHeight = std::floor(minDim / 3); const XYPOSITION halfHeight = std::floor(minDim / 3);
Point pts[] = { const Point pts[] = {
Point(rcWhole.left, centreY - halfHeight), Point(rcWhole.left, centreY - halfHeight),
Point(rcWhole.right - strokeWidth - 2, centreY - halfHeight), Point(rcWhole.right - strokeWidth - 2, centreY - halfHeight),
Point(rcWhole.right - strokeWidth - 2 - halfHeight, centreY), Point(rcWhole.right - strokeWidth - 2 - halfHeight, centreY),
@ -560,7 +560,7 @@ void LineMarker::Draw(Surface *surface, const PRectangle &rcWhole, const Font *f
case MarkerSymbol::VerticalBookmark: { case MarkerSymbol::VerticalBookmark: {
const XYPOSITION halfWidth = std::floor(minDim / 3); const XYPOSITION halfWidth = std::floor(minDim / 3);
Point pts[] = { const Point pts[] = {
Point(centreX - halfWidth, centreY - dimOn2), Point(centreX - halfWidth, centreY - dimOn2),
Point(centreX + halfWidth, centreY - dimOn2), Point(centreX + halfWidth, centreY - dimOn2),
Point(centreX + halfWidth, centreY + dimOn2), Point(centreX + halfWidth, centreY + dimOn2),

View File

@ -92,7 +92,7 @@ void DrawWrapMarker(Surface *surface, PRectangle rcPlace,
} }
}; };
Relative rel = { x0, isEndMarker ? 1 : -1, y0, 1, widthStroke / 2.0f }; const Relative rel = { x0, isEndMarker ? 1 : -1, y0, 1, widthStroke / 2.0f };
// arrow head // arrow head
const Point head[] = { const Point head[] = {

View File

@ -461,7 +461,7 @@ bool SignificantLines::LineMayCache(Sci::Line line) const noexcept {
case LineCache::Caret: case LineCache::Caret:
return line == lineCaret; return line == lineCaret;
case LineCache::Page: case LineCache::Page:
return (abs(line - lineCaret) < linesOnScreen) || return (std::abs(line - lineCaret) < linesOnScreen) ||
((line >= lineTop) && (line <= (lineTop + linesOnScreen))); ((line >= lineTop) && (line <= (lineTop + linesOnScreen)));
case LineCache::Document: case LineCache::Document:
default: default:

View File

@ -14,8 +14,6 @@ namespace Scintilla::Internal {
class CharacterIndexer { class CharacterIndexer {
public: public:
virtual char CharAt(Sci::Position index) const=0; virtual char CharAt(Sci::Position index) const=0;
virtual ~CharacterIndexer() {
}
}; };
class RESearch { class RESearch {

View File

@ -265,7 +265,7 @@ void ScintillaBase::AutoCompleteStart(Sci::Position lenEntered, const char *list
} }
} }
ListOptions options{ const ListOptions options{
vs.ElementColour(Element::List), vs.ElementColour(Element::List),
vs.ElementColour(Element::ListBack), vs.ElementColour(Element::ListBack),
vs.ElementColour(Element::ListSelected), vs.ElementColour(Element::ListSelected),

View File

@ -266,7 +266,7 @@ void RGBAImage::SetPixel(int x, int y, ColourRGBA colour) noexcept {
namespace { namespace {
unsigned char AlphaMultiplied(unsigned char value, unsigned char alpha) { constexpr unsigned char AlphaMultiplied(unsigned char value, unsigned char alpha) noexcept {
return (value * alpha / UCHAR_MAX) & 0xffU; return (value * alpha / UCHAR_MAX) & 0xffU;
} }

View File

@ -2,9 +2,9 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import ctypes, os, sys import ctypes
from ctypes import c_int, c_ulong, c_char_p, c_wchar_p, c_ushort, c_uint, c_long, c_ssize_t from ctypes import c_int, c_char_p, c_long, c_ssize_t
def IsEnumeration(t): def IsEnumeration(t):
return t[:1].isupper() return t[:1].isupper()
@ -52,7 +52,7 @@ class SciCall:
self._ptr = ptr self._ptr = ptr
self._msg = msg self._msg = msg
self._stringResult = stringResult self._stringResult = stringResult
def __call__(self, w=0, l=0): def __call__(self, w=0, lp=0):
ww = ctypes.cast(w, c_char_p) ww = ctypes.cast(w, c_char_p)
if self._stringResult: if self._stringResult:
lengthBytes = self._fn(self._ptr, self._msg, ww, None) lengthBytes = self._fn(self._ptr, self._msg, ww, None)
@ -63,7 +63,7 @@ class SciCall:
assert lengthBytes == lengthBytes2 assert lengthBytes == lengthBytes2
return bytearray(result)[:lengthBytes] return bytearray(result)[:lengthBytes]
else: else:
ll = ctypes.cast(l, c_char_p) ll = ctypes.cast(lp, c_char_p)
return self._fn(self._ptr, self._msg, ww, ll) return self._fn(self._ptr, self._msg, ww, ll)
sciFX = ctypes.CFUNCTYPE(c_ssize_t, c_char_p, c_int, c_char_p, c_char_p) sciFX = ctypes.CFUNCTYPE(c_ssize_t, c_char_p, c_int, c_char_p, c_char_p)

View File

@ -8,8 +8,7 @@ from __future__ import unicode_literals
import os, platform, sys, unittest import os, platform, sys, unittest
import ctypes import ctypes
from ctypes import wintypes from ctypes import c_int, c_char_p, c_wchar_p, c_ushort, c_uint
from ctypes import c_int, c_ulong, c_char_p, c_wchar_p, c_ushort, c_uint, c_long
from ctypes.wintypes import HWND, WPARAM, LPARAM, HANDLE, HBRUSH, LPCWSTR from ctypes.wintypes import HWND, WPARAM, LPARAM, HANDLE, HBRUSH, LPCWSTR
user32=ctypes.windll.user32 user32=ctypes.windll.user32
gdi32=ctypes.windll.gdi32 gdi32=ctypes.windll.gdi32
@ -248,11 +247,11 @@ class XiteWin():
def Invalidate(self): def Invalidate(self):
user32.InvalidateRect(self.win, 0, 0) user32.InvalidateRect(self.win, 0, 0)
def WndProc(self, h, m, w, l): def WndProc(self, h, m, wp, lp):
user32.DefWindowProcW.argtypes = [HWND, c_uint, WPARAM, LPARAM] user32.DefWindowProcW.argtypes = [HWND, c_uint, WPARAM, LPARAM]
ms = sgsm.get(m, "XXX") ms = sgsm.get(m, "XXX")
if trace: if trace:
print("%s %s %s %s" % (hex(h)[2:],ms,w,l)) print("%s %s %s %s" % (hex(h)[2:],ms,wp,lp))
if ms == "WM_CLOSE": if ms == "WM_CLOSE":
user32.PostQuitMessage(0) user32.PostQuitMessage(0)
elif ms == "WM_CREATE": elif ms == "WM_CREATE":
@ -260,20 +259,20 @@ class XiteWin():
return 0 return 0
elif ms == "WM_SIZE": elif ms == "WM_SIZE":
# Work out size # Work out size
if w != 1: if wp != 1:
self.OnSize() self.OnSize()
return 0 return 0
elif ms == "WM_COMMAND": elif ms == "WM_COMMAND":
cmdCode = w & 0xffff cmdCode = wp & 0xffff
if cmdCode in self.cmds: if cmdCode in self.cmds:
self.Command(self.cmds[cmdCode]) self.Command(self.cmds[cmdCode])
return 0 return 0
elif ms == "WM_ACTIVATE": elif ms == "WM_ACTIVATE":
if w != WA_INACTIVE: if wp != WA_INACTIVE:
self.FocusOnEditor() self.FocusOnEditor()
return 0 return 0
else: else:
return user32.DefWindowProcW(h, m, w, l) return user32.DefWindowProcW(h, m, wp, lp)
return 0 return 0
def Command(self, name): def Command(self, name):
@ -506,7 +505,7 @@ class XiteWin():
self.Open() self.Open()
def CmdSave(self): def CmdSave(self):
if (self.fullPath == None) or (len(self.fullPath) == 0): if (self.fullPath is None) or (len(self.fullPath) == 0):
self.SaveAs() self.SaveAs()
else: else:
self.Save() self.Save()

View File

@ -5,7 +5,7 @@
from __future__ import with_statement from __future__ import with_statement
from __future__ import unicode_literals from __future__ import unicode_literals
import os, string, sys, time, unittest import string, time, unittest
try: try:
start = time.perf_counter() start = time.perf_counter()

View File

@ -414,7 +414,7 @@ class TestSimple(unittest.TestCase):
self.xite.ChooseLexer(b"cpp") self.xite.ChooseLexer(b"cpp")
self.ed.SetCodePage(65001) self.ed.SetCodePage(65001)
self.ed.SetLineEndTypesAllowed(1) self.ed.SetLineEndTypesAllowed(1)
text = b"x\xe2\x80\xa9y"; text = b"x\xe2\x80\xa9y"
self.ed.AddText(5, text) self.ed.AddText(5, text)
self.assertEquals(self.ed.LineCount, 2) self.assertEquals(self.ed.LineCount, 2)
@ -501,7 +501,7 @@ class TestSimple(unittest.TestCase):
self.xite.ChooseLexer(b"cpp") self.xite.ChooseLexer(b"cpp")
self.ed.SetCodePage(65001) self.ed.SetCodePage(65001)
self.ed.SetLineEndTypesAllowed(1) self.ed.SetLineEndTypesAllowed(1)
text = b"x\xc2\x85y"; text = b"x\xc2\x85y"
self.ed.AddText(4, text) self.ed.AddText(4, text)
self.assertEquals(self.ed.LineCount, 2) self.assertEquals(self.ed.LineCount, 2)
@ -1165,8 +1165,10 @@ class TestMarkers(unittest.TestCase):
def testTwiceAddedDelete(self): def testTwiceAddedDelete(self):
handle = self.ed.MarkerAdd(1,1) handle = self.ed.MarkerAdd(1,1)
self.assertNotEqual(handle, -1)
self.assertEquals(self.ed.MarkerGet(1), 2) self.assertEquals(self.ed.MarkerGet(1), 2)
handle2 = self.ed.MarkerAdd(1,1) handle2 = self.ed.MarkerAdd(1,1)
self.assertNotEqual(handle2, -1)
self.assertEquals(self.ed.MarkerGet(1), 2) self.assertEquals(self.ed.MarkerGet(1), 2)
self.ed.MarkerDelete(1,1) self.ed.MarkerDelete(1,1)
self.assertEquals(self.ed.MarkerGet(1), 2) self.assertEquals(self.ed.MarkerGet(1), 2)
@ -1207,7 +1209,9 @@ class TestMarkers(unittest.TestCase):
def testMarkerNext(self): def testMarkerNext(self):
self.assertEquals(self.ed.MarkerNext(0, 2), -1) self.assertEquals(self.ed.MarkerNext(0, 2), -1)
h1 = self.ed.MarkerAdd(0,1) h1 = self.ed.MarkerAdd(0,1)
self.assertNotEqual(h1, -1)
h2 = self.ed.MarkerAdd(2,1) h2 = self.ed.MarkerAdd(2,1)
self.assertNotEqual(h2, -1)
self.assertEquals(self.ed.MarkerNext(0, 2), 0) self.assertEquals(self.ed.MarkerNext(0, 2), 0)
self.assertEquals(self.ed.MarkerNext(1, 2), 2) self.assertEquals(self.ed.MarkerNext(1, 2), 2)
self.assertEquals(self.ed.MarkerNext(2, 2), 2) self.assertEquals(self.ed.MarkerNext(2, 2), 2)
@ -2448,8 +2452,6 @@ class TestIndices(unittest.TestCase):
def testUTF16(self): def testUTF16(self):
self.assertEquals(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE) self.assertEquals(self.ed.GetLineCharacterIndex(), self.ed.SC_LINECHARACTERINDEX_NONE)
t = "\U00010348flﬔ-"
tv = t.encode("UTF-8")
self.ed.SetContents(self.tv) self.ed.SetContents(self.tv)
self.ed.AllocateLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF16) self.ed.AllocateLineCharacterIndex(self.ed.SC_LINECHARACTERINDEX_UTF16)
self.assertEquals(self.ed.IndexPositionFromLine(0, self.ed.SC_LINECHARACTERINDEX_UTF16), 0) self.assertEquals(self.ed.IndexPositionFromLine(0, self.ed.SC_LINECHARACTERINDEX_UTF16), 0)
@ -2821,7 +2823,8 @@ class TestSubStyles(unittest.TestCase):
def testSecondary(self): def testSecondary(self):
inactiveDistance = self.ed.DistanceToSecondaryStyles() inactiveDistance = self.ed.DistanceToSecondaryStyles()
self.assertEquals(self.ed.GetPrimaryStyleFromStyle(self.ed.SCE_C_IDENTIFIER+inactiveDistance), self.ed.SCE_C_IDENTIFIER) inactiveIdentifier = self.ed.SCE_C_IDENTIFIER+inactiveDistance
self.assertEquals(self.ed.GetPrimaryStyleFromStyle(inactiveIdentifier), self.ed.SCE_C_IDENTIFIER)
class TestCallTip(unittest.TestCase): class TestCallTip(unittest.TestCase):

View File

@ -10,11 +10,10 @@
from __future__ import with_statement from __future__ import with_statement
from __future__ import unicode_literals from __future__ import unicode_literals
import codecs, ctypes, os, sys, unittest import ctypes, unittest
from MessageNumbers import msgs, sgsm from MessageNumbers import msgs
import ctypes
user32 = ctypes.windll.user32 user32 = ctypes.windll.user32
import XiteWin as Xite import XiteWin as Xite
@ -32,8 +31,8 @@ class TestWins(unittest.TestCase):
# Helper methods # Helper methods
def Send(self, msg, w, l): def Send(self, msg, wp, lp):
return user32.SendMessageW(self.sciHwnd, msgs[msg], w, l) return user32.SendMessageW(self.sciHwnd, msgs[msg], wp, lp)
def GetTextLength(self): def GetTextLength(self):
return self.Send("WM_GETTEXTLENGTH", 0, 0) return self.Send("WM_GETTEXTLENGTH", 0, 0)

View File

@ -1 +1 @@
534 535

View File

@ -963,7 +963,7 @@ void SurfaceGDI::AlphaRectangle(PRectangle rc, XYPOSITION cornerSize, FillStroke
section.SetSymmetric(x, corner - x, valOutline); section.SetSymmetric(x, corner - x, valOutline);
} }
AlphaBlend(hdc, rcw.left, rcw.top, size.cx, size.cy, section.DC(), 0, 0, size.cx, size.cy, mergeAlpha); GdiAlphaBlend(hdc, rcw.left, rcw.top, size.cx, size.cy, section.DC(), 0, 0, size.cx, size.cy, mergeAlpha);
} }
} else { } else {
BrushColour(fillStroke.stroke.colour); BrushColour(fillStroke.stroke.colour);
@ -1002,7 +1002,7 @@ void SurfaceGDI::GradientRectangle(PRectangle rc, const std::vector<ColourStop>
} }
} }
AlphaBlend(hdc, rcw.left, rcw.top, size.cx, size.cy, section.DC(), 0, 0, size.cx, size.cy, mergeAlpha); GdiAlphaBlend(hdc, rcw.left, rcw.top, size.cx, size.cy, section.DC(), 0, 0, size.cx, size.cy, mergeAlpha);
} }
} }
@ -1019,7 +1019,7 @@ void SurfaceGDI::DrawRGBAImage(PRectangle rc, int width, int height, const unsig
DIBSection section(hdc, size); DIBSection section(hdc, size);
if (section) { if (section) {
RGBAImage::BGRAFromRGBA(section.Bytes(), pixelsImage, static_cast<size_t>(width) * height); RGBAImage::BGRAFromRGBA(section.Bytes(), pixelsImage, static_cast<size_t>(width) * height);
AlphaBlend(hdc, static_cast<int>(rc.left), static_cast<int>(rc.top), GdiAlphaBlend(hdc, static_cast<int>(rc.left), static_cast<int>(rc.top),
static_cast<int>(rc.Width()), static_cast<int>(rc.Height()), section.DC(), static_cast<int>(rc.Width()), static_cast<int>(rc.Height()), section.DC(),
0, 0, width, height, mergeAlpha); 0, 0, width, height, mergeAlpha);
} }
@ -1713,19 +1713,19 @@ void SurfaceD2D::RoundedRectangle(PRectangle rc, FillStroke fillStroke) {
const FLOAT minDimension = static_cast<FLOAT>(std::min(rc.Width(), rc.Height())) / 2.0f; const FLOAT minDimension = static_cast<FLOAT>(std::min(rc.Width(), rc.Height())) / 2.0f;
const FLOAT radius = std::min(4.0f, minDimension); const FLOAT radius = std::min(4.0f, minDimension);
if (fillStroke.fill.colour == fillStroke.stroke.colour) { if (fillStroke.fill.colour == fillStroke.stroke.colour) {
D2D1_ROUNDED_RECT roundedRectFill = { const D2D1_ROUNDED_RECT roundedRectFill = {
RectangleFromPRectangle(rc), RectangleFromPRectangle(rc),
radius, radius }; radius, radius };
D2DPenColourAlpha(fillStroke.fill.colour); D2DPenColourAlpha(fillStroke.fill.colour);
pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush); pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
} else { } else {
D2D1_ROUNDED_RECT roundedRectFill = { const D2D1_ROUNDED_RECT roundedRectFill = {
RectangleFromPRectangle(rc.Inset(1.0)), RectangleFromPRectangle(rc.Inset(1.0)),
radius-1, radius-1 }; radius-1, radius-1 };
D2DPenColourAlpha(fillStroke.fill.colour); D2DPenColourAlpha(fillStroke.fill.colour);
pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush); pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
D2D1_ROUNDED_RECT roundedRect = { const D2D1_ROUNDED_RECT roundedRect = {
RectangleFromPRectangle(rc.Inset(0.5)), RectangleFromPRectangle(rc.Inset(0.5)),
radius, radius }; radius, radius };
D2DPenColourAlpha(fillStroke.stroke.colour); D2DPenColourAlpha(fillStroke.stroke.colour);
@ -1749,12 +1749,12 @@ void SurfaceD2D::AlphaRectangle(PRectangle rc, XYPOSITION cornerSize, FillStroke
pRenderTarget->DrawRectangle(rectOutline, pBrush, fillStroke.stroke.WidthF()); pRenderTarget->DrawRectangle(rectOutline, pBrush, fillStroke.stroke.WidthF());
} else { } else {
const float cornerSizeF = static_cast<float>(cornerSize); const float cornerSizeF = static_cast<float>(cornerSize);
D2D1_ROUNDED_RECT roundedRectFill = { const D2D1_ROUNDED_RECT roundedRectFill = {
rectFill, cornerSizeF - 1.0f, cornerSizeF - 1.0f }; rectFill, cornerSizeF - 1.0f, cornerSizeF - 1.0f };
D2DPenColourAlpha(fillStroke.fill.colour); D2DPenColourAlpha(fillStroke.fill.colour);
pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush); pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
D2D1_ROUNDED_RECT roundedRect = { const D2D1_ROUNDED_RECT roundedRect = {
rectOutline, cornerSizeF, cornerSizeF}; rectOutline, cornerSizeF, cornerSizeF};
D2DPenColourAlpha(fillStroke.stroke.colour); D2DPenColourAlpha(fillStroke.stroke.colour);
pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush, fillStroke.stroke.WidthF()); pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush, fillStroke.stroke.WidthF());
@ -1814,7 +1814,7 @@ void SurfaceD2D::DrawRGBAImage(PRectangle rc, int width, int height, const unsig
ID2D1Bitmap *bitmap = nullptr; ID2D1Bitmap *bitmap = nullptr;
const D2D1_SIZE_U size = D2D1::SizeU(width, height); const D2D1_SIZE_U size = D2D1::SizeU(width, height);
D2D1_BITMAP_PROPERTIES props = {{DXGI_FORMAT_B8G8R8A8_UNORM, const D2D1_BITMAP_PROPERTIES props = {{DXGI_FORMAT_B8G8R8A8_UNORM,
D2D1_ALPHA_MODE_PREMULTIPLIED}, 72.0, 72.0}; D2D1_ALPHA_MODE_PREMULTIPLIED}, 72.0, 72.0};
const HRESULT hr = pRenderTarget->CreateBitmap(size, image.data(), const HRESULT hr = pRenderTarget->CreateBitmap(size, image.data(),
width * 4, &props, &bitmap); width * 4, &props, &bitmap);
@ -1857,12 +1857,12 @@ void SurfaceD2D::Stadium(PRectangle rc, FillStroke fillStroke, Ends ends) {
const FLOAT halfStroke = fillStroke.stroke.WidthF() / 2.0f; const FLOAT halfStroke = fillStroke.stroke.WidthF() / 2.0f;
if (ends == Surface::Ends::semiCircles) { if (ends == Surface::Ends::semiCircles) {
const D2D1_RECT_F rect = RectangleFromPRectangle(rc); const D2D1_RECT_F rect = RectangleFromPRectangle(rc);
D2D1_ROUNDED_RECT roundedRectFill = { RectangleInset(rect, fillStroke.stroke.WidthF()), const D2D1_ROUNDED_RECT roundedRectFill = { RectangleInset(rect, fillStroke.stroke.WidthF()),
radiusFill, radiusFill }; radiusFill, radiusFill };
D2DPenColourAlpha(fillStroke.fill.colour); D2DPenColourAlpha(fillStroke.fill.colour);
pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush); pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush);
D2D1_ROUNDED_RECT roundedRect = { RectangleInset(rect, halfStroke), const D2D1_ROUNDED_RECT roundedRect = { RectangleInset(rect, halfStroke),
radius, radius }; radius, radius };
D2DPenColourAlpha(fillStroke.stroke.colour); D2DPenColourAlpha(fillStroke.stroke.colour);
pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush, fillStroke.stroke.WidthF()); pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush, fillStroke.stroke.WidthF());
@ -1954,7 +1954,7 @@ void SurfaceD2D::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
} }
} }
class BlobInline : public IDWriteInlineObject { class BlobInline final : public IDWriteInlineObject {
XYPOSITION width; XYPOSITION width;
// IUnknown // IUnknown
@ -1980,12 +1980,6 @@ class BlobInline : public IDWriteInlineObject {
public: public:
BlobInline(XYPOSITION width_=0.0f) noexcept : width(width_) { BlobInline(XYPOSITION width_=0.0f) noexcept : width(width_) {
} }
// Defaulted so BlobInline objects can be copied.
BlobInline(const BlobInline &) = default;
BlobInline(BlobInline &&) = default;
BlobInline &operator=(const BlobInline &) = default;
BlobInline &operator=(BlobInline &&) = default;
virtual ~BlobInline() noexcept = default;
}; };
/// Implement IUnknown /// Implement IUnknown
@ -1995,9 +1989,9 @@ STDMETHODIMP BlobInline::QueryInterface(REFIID riid, PVOID *ppv) {
// Never called so not checked. // Never called so not checked.
*ppv = nullptr; *ppv = nullptr;
if (riid == IID_IUnknown) if (riid == IID_IUnknown)
*ppv = static_cast<IUnknown *>(this); *ppv = this;
if (riid == __uuidof(IDWriteInlineObject)) if (riid == __uuidof(IDWriteInlineObject))
*ppv = static_cast<IDWriteInlineObject *>(this); *ppv = this;
if (!*ppv) if (!*ppv)
return E_NOINTERFACE; return E_NOINTERFACE;
return S_OK; return S_OK;
@ -2869,7 +2863,7 @@ void Window::SetCursor(Cursor curs) {
coordinates */ coordinates */
PRectangle Window::GetMonitorRect(Point pt) { PRectangle Window::GetMonitorRect(Point pt) {
const PRectangle rcPosition = GetPosition(); const PRectangle rcPosition = GetPosition();
POINT ptDesktop = {static_cast<LONG>(pt.x + rcPosition.left), const POINT ptDesktop = {static_cast<LONG>(pt.x + rcPosition.left),
static_cast<LONG>(pt.y + rcPosition.top)}; static_cast<LONG>(pt.y + rcPosition.top)};
HMONITOR hMonitor = MonitorFromPoint(ptDesktop, MONITOR_DEFAULTTONEAREST); HMONITOR hMonitor = MonitorFromPoint(ptDesktop, MONITOR_DEFAULTTONEAREST);
@ -2915,7 +2909,7 @@ public:
} }
void AllocItem(const char *text, int pixId) { void AllocItem(const char *text, int pixId) {
ListItemData lid = { text, pixId }; const ListItemData lid = { text, pixId };
data.push_back(lid); data.push_back(lid);
} }

View File

@ -19,7 +19,7 @@ extern void Platform_Initialise(void *hInstance) noexcept;
extern void Platform_Finalise(bool fromDllMain) noexcept; extern void Platform_Finalise(bool fromDllMain) noexcept;
constexpr RECT RectFromPRectangle(PRectangle prc) noexcept { constexpr RECT RectFromPRectangle(PRectangle prc) noexcept {
RECT rc = { static_cast<LONG>(prc.left), static_cast<LONG>(prc.top), const RECT rc = { static_cast<LONG>(prc.left), static_cast<LONG>(prc.top),
static_cast<LONG>(prc.right), static_cast<LONG>(prc.bottom) }; static_cast<LONG>(prc.right), static_cast<LONG>(prc.bottom) };
return rc; return rc;
} }

View File

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

View File

@ -101,7 +101,7 @@
<Link> <Link>
<SubSystem>Windows</SubSystem> <SubSystem>Windows</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation> <GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>gdi32.lib;imm32.lib;ole32.lib;oleaut32.lib;msimg32.lib;%(AdditionalDependencies)</AdditionalDependencies> <AdditionalDependencies>gdi32.lib;imm32.lib;ole32.lib;oleaut32.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link> </Link>
</ItemDefinitionGroup> </ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">

View File

@ -200,44 +200,82 @@ constexpr bool KeyboardIsNumericKeypadFunction(uptr_t wParam, sptr_t lParam) {
} }
} }
typedef void VFunction(void);
/** /**
*/ */
class FormatEnumerator { class FormatEnumerator final : public IEnumFORMATETC {
public: public:
VFunction **vtbl;
ULONG ref; ULONG ref;
ULONG pos; ULONG pos;
std::vector<CLIPFORMAT> formats; std::vector<CLIPFORMAT> formats;
FormatEnumerator(ULONG pos_, const CLIPFORMAT formats_[], size_t formatsLen_); FormatEnumerator(ULONG pos_, const CLIPFORMAT formats_[], size_t formatsLen_);
// IUnknown
STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv) override;
STDMETHODIMP_(ULONG)AddRef() override;
STDMETHODIMP_(ULONG)Release() override;
// IEnumFORMATETC
STDMETHODIMP Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) override;
STDMETHODIMP Skip(ULONG celt) override;
STDMETHODIMP Reset() override;
STDMETHODIMP Clone(IEnumFORMATETC **ppenum) override;
}; };
/** /**
*/ */
class DropSource { class DropSource final : public IDropSource {
public: public:
VFunction **vtbl; ScintillaWin *sci = nullptr;
ScintillaWin *sci;
DropSource() noexcept; // IUnknown
STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv) override;
STDMETHODIMP_(ULONG)AddRef() override;
STDMETHODIMP_(ULONG)Release() override;
// IDropSource
STDMETHODIMP QueryContinueDrag(BOOL fEsc, DWORD grfKeyState) override;
STDMETHODIMP GiveFeedback(DWORD) override;
}; };
/** /**
*/ */
class DataObject { class DataObject final : public IDataObject {
public: public:
VFunction **vtbl; ScintillaWin *sci = nullptr;
ScintillaWin *sci;
DataObject() noexcept; // IUnknown
STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv) override;
STDMETHODIMP_(ULONG)AddRef() override;
STDMETHODIMP_(ULONG)Release() override;
// IDataObject
STDMETHODIMP GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) override;
STDMETHODIMP GetDataHere(FORMATETC *, STGMEDIUM *) override;
STDMETHODIMP QueryGetData(FORMATETC *pFE) override;
STDMETHODIMP GetCanonicalFormatEtc(FORMATETC *, FORMATETC *pFEOut) override;
STDMETHODIMP SetData(FORMATETC *, STGMEDIUM *, BOOL) override;
STDMETHODIMP EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnum) override;
STDMETHODIMP DAdvise(FORMATETC *, DWORD, IAdviseSink *, PDWORD) override;
STDMETHODIMP DUnadvise(DWORD) override;
STDMETHODIMP EnumDAdvise(IEnumSTATDATA **) override;
}; };
/** /**
*/ */
class DropTarget { class DropTarget final : public IDropTarget {
public: public:
VFunction **vtbl; ScintillaWin *sci = nullptr;
ScintillaWin *sci;
DropTarget() noexcept; // IUnknown
STDMETHODIMP QueryInterface(REFIID riid, PVOID *ppv) override;
STDMETHODIMP_(ULONG)AddRef() override;
STDMETHODIMP_(ULONG)Release() override;
// IDropTarget
STDMETHODIMP DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) override;
STDMETHODIMP DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) override;
STDMETHODIMP DragLeave() override;
STDMETHODIMP Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) override;
}; };
class IMContext { class IMContext {
@ -411,6 +449,7 @@ class ScintillaWin :
void ImeStartComposition(); void ImeStartComposition();
void ImeEndComposition(); void ImeEndComposition();
LRESULT ImeOnReconvert(LPARAM lParam); LRESULT ImeOnReconvert(LPARAM lParam);
LRESULT ImeOnDocumentFeed(LPARAM lParam) const;
sptr_t HandleCompositionWindowed(uptr_t wParam, sptr_t lParam); sptr_t HandleCompositionWindowed(uptr_t wParam, sptr_t lParam);
sptr_t HandleCompositionInline(uptr_t wParam, sptr_t lParam); sptr_t HandleCompositionInline(uptr_t wParam, sptr_t lParam);
static bool KoreanIME() noexcept; static bool KoreanIME() noexcept;
@ -782,8 +821,8 @@ void ScintillaWin::StartDrag() {
inDragDrop = DragDrop::dragging; inDragDrop = DragDrop::dragging;
DWORD dwEffect = 0; DWORD dwEffect = 0;
dropWentOutside = true; dropWentOutside = true;
IDataObject *pDataObject = reinterpret_cast<IDataObject *>(&dob); IDataObject *pDataObject = &dob;
IDropSource *pDropSource = reinterpret_cast<IDropSource *>(&ds); IDropSource *pDropSource = &ds;
//Platform::DebugPrintf("About to DoDragDrop %x %x\n", pDataObject, pDropSource); //Platform::DebugPrintf("About to DoDragDrop %x %x\n", pDataObject, pDropSource);
const HRESULT hr = ::DoDragDrop( const HRESULT hr = ::DoDragDrop(
pDataObject, pDataObject,
@ -1777,6 +1816,9 @@ sptr_t ScintillaWin::IMEMessage(unsigned int iMessage, uptr_t wParam, sptr_t lPa
if (wParam == IMR_RECONVERTSTRING) { if (wParam == IMR_RECONVERTSTRING) {
return ImeOnReconvert(lParam); return ImeOnReconvert(lParam);
} }
if (wParam == IMR_DOCUMENTFEED) {
return ImeOnDocumentFeed(lParam);
}
return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam); return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
} }
@ -2022,7 +2064,7 @@ sptr_t ScintillaWin::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
UpdateBaseElements(); UpdateBaseElements();
// Get Intellimouse scroll line parameters // Get Intellimouse scroll line parameters
GetIntelliMouseParameters(); GetIntelliMouseParameters();
::RegisterDragDrop(MainHWND(), reinterpret_cast<IDropTarget *>(&dt)); ::RegisterDragDrop(MainHWND(), &dt);
break; break;
case WM_COMMAND: case WM_COMMAND:
@ -2802,97 +2844,82 @@ void ScintillaWin::ClaimSelection() {
} }
/// Implement IUnknown /// Implement IUnknown
STDMETHODIMP FormatEnumerator::QueryInterface(REFIID riid, PVOID *ppv) {
STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe);
STDMETHODIMP FormatEnumerator_QueryInterface(FormatEnumerator *fe, REFIID riid, PVOID *ppv) {
//Platform::DebugPrintf("EFE QI"); //Platform::DebugPrintf("EFE QI");
*ppv = nullptr; *ppv = nullptr;
if (riid == IID_IUnknown) if (riid == IID_IUnknown || riid == IID_IEnumFORMATETC) {
*ppv = reinterpret_cast<IEnumFORMATETC *>(fe); *ppv = this;
if (riid == IID_IEnumFORMATETC) } else {
*ppv = reinterpret_cast<IEnumFORMATETC *>(fe);
if (!*ppv)
return E_NOINTERFACE; return E_NOINTERFACE;
FormatEnumerator_AddRef(fe); }
AddRef();
return S_OK; return S_OK;
} }
STDMETHODIMP_(ULONG)FormatEnumerator_AddRef(FormatEnumerator *fe) { STDMETHODIMP_(ULONG)FormatEnumerator::AddRef() {
return ++fe->ref; return ++ref;
} }
STDMETHODIMP_(ULONG)FormatEnumerator_Release(FormatEnumerator *fe) { STDMETHODIMP_(ULONG)FormatEnumerator::Release() {
fe->ref--; const ULONG refs = --ref;
if (fe->ref > 0) if (refs == 0) {
return fe->ref; delete this;
delete fe; }
return 0; return refs;
} }
/// Implement IEnumFORMATETC /// Implement IEnumFORMATETC
STDMETHODIMP FormatEnumerator_Next(FormatEnumerator *fe, ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) { STDMETHODIMP FormatEnumerator::Next(ULONG celt, FORMATETC *rgelt, ULONG *pceltFetched) {
if (!rgelt) return E_POINTER; if (!rgelt) return E_POINTER;
ULONG putPos = 0; ULONG putPos = 0;
while ((fe->pos < fe->formats.size()) && (putPos < celt)) { while ((pos < formats.size()) && (putPos < celt)) {
rgelt->cfFormat = fe->formats[fe->pos]; rgelt->cfFormat = formats[pos];
rgelt->ptd = nullptr; rgelt->ptd = nullptr;
rgelt->dwAspect = DVASPECT_CONTENT; rgelt->dwAspect = DVASPECT_CONTENT;
rgelt->lindex = -1; rgelt->lindex = -1;
rgelt->tymed = TYMED_HGLOBAL; rgelt->tymed = TYMED_HGLOBAL;
rgelt++; rgelt++;
fe->pos++; pos++;
putPos++; putPos++;
} }
if (pceltFetched) if (pceltFetched)
*pceltFetched = putPos; *pceltFetched = putPos;
return putPos ? S_OK : S_FALSE; return putPos ? S_OK : S_FALSE;
} }
STDMETHODIMP FormatEnumerator_Skip(FormatEnumerator *fe, ULONG celt) { STDMETHODIMP FormatEnumerator::Skip(ULONG celt) {
fe->pos += celt; pos += celt;
return S_OK; return S_OK;
} }
STDMETHODIMP FormatEnumerator_Reset(FormatEnumerator *fe) { STDMETHODIMP FormatEnumerator::Reset() {
fe->pos = 0; pos = 0;
return S_OK; return S_OK;
} }
STDMETHODIMP FormatEnumerator_Clone(FormatEnumerator *fe, IEnumFORMATETC **ppenum) { STDMETHODIMP FormatEnumerator::Clone(IEnumFORMATETC **ppenum) {
FormatEnumerator *pfe; FormatEnumerator *pfe;
try { try {
pfe = new FormatEnumerator(fe->pos, &fe->formats[0], fe->formats.size()); pfe = new FormatEnumerator(pos, &formats[0], formats.size());
} catch (...) { } catch (...) {
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} }
return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC, return pfe->QueryInterface(IID_IEnumFORMATETC, reinterpret_cast<void **>(ppenum));
reinterpret_cast<void **>(ppenum));
} }
static VFunction *vtFormatEnumerator[] = {
(VFunction *)(FormatEnumerator_QueryInterface),
(VFunction *)(FormatEnumerator_AddRef),
(VFunction *)(FormatEnumerator_Release),
(VFunction *)(FormatEnumerator_Next),
(VFunction *)(FormatEnumerator_Skip),
(VFunction *)(FormatEnumerator_Reset),
(VFunction *)(FormatEnumerator_Clone)
};
FormatEnumerator::FormatEnumerator(ULONG pos_, const CLIPFORMAT formats_[], size_t formatsLen_) { FormatEnumerator::FormatEnumerator(ULONG pos_, const CLIPFORMAT formats_[], size_t formatsLen_) {
vtbl = vtFormatEnumerator;
ref = 0; // First QI adds first reference... ref = 0; // First QI adds first reference...
pos = pos_; pos = pos_;
formats.insert(formats.begin(), formats_, formats_+formatsLen_); formats.insert(formats.begin(), formats_, formats_+formatsLen_);
} }
/// Implement IUnknown /// Implement IUnknown
STDMETHODIMP DropSource_QueryInterface(DropSource *ds, REFIID riid, PVOID *ppv) { STDMETHODIMP DropSource::QueryInterface(REFIID riid, PVOID *ppv) {
return ds->sci->QueryInterface(riid, ppv); return sci->QueryInterface(riid, ppv);
} }
STDMETHODIMP_(ULONG)DropSource_AddRef(DropSource *ds) { STDMETHODIMP_(ULONG)DropSource::AddRef() {
return ds->sci->AddRef(); return sci->AddRef();
} }
STDMETHODIMP_(ULONG)DropSource_Release(DropSource *ds) { STDMETHODIMP_(ULONG)DropSource::Release() {
return ds->sci->Release(); return sci->Release();
} }
/// Implement IDropSource /// Implement IDropSource
STDMETHODIMP DropSource_QueryContinueDrag(DropSource *, BOOL fEsc, DWORD grfKeyState) { STDMETHODIMP DropSource::QueryContinueDrag(BOOL fEsc, DWORD grfKeyState) {
if (fEsc) if (fEsc)
return DRAGDROP_S_CANCEL; return DRAGDROP_S_CANCEL;
if (!(grfKeyState & MK_LBUTTON)) if (!(grfKeyState & MK_LBUTTON))
@ -2900,46 +2927,33 @@ STDMETHODIMP DropSource_QueryContinueDrag(DropSource *, BOOL fEsc, DWORD grfKeyS
return S_OK; return S_OK;
} }
STDMETHODIMP DropSource_GiveFeedback(DropSource *, DWORD) { STDMETHODIMP DropSource::GiveFeedback(DWORD) {
return DRAGDROP_S_USEDEFAULTCURSORS; return DRAGDROP_S_USEDEFAULTCURSORS;
} }
static VFunction *vtDropSource[] = {
(VFunction *)(DropSource_QueryInterface),
(VFunction *)(DropSource_AddRef),
(VFunction *)(DropSource_Release),
(VFunction *)(DropSource_QueryContinueDrag),
(VFunction *)(DropSource_GiveFeedback)
};
DropSource::DropSource() noexcept {
vtbl = vtDropSource;
sci = nullptr;
}
/// Implement IUnkown /// Implement IUnkown
STDMETHODIMP DataObject_QueryInterface(DataObject *pd, REFIID riid, PVOID *ppv) { STDMETHODIMP DataObject::QueryInterface(REFIID riid, PVOID *ppv) {
//Platform::DebugPrintf("DO QI %x\n", pd); //Platform::DebugPrintf("DO QI %p\n", this);
return pd->sci->QueryInterface(riid, ppv); return sci->QueryInterface(riid, ppv);
} }
STDMETHODIMP_(ULONG)DataObject_AddRef(DataObject *pd) { STDMETHODIMP_(ULONG)DataObject::AddRef() {
return pd->sci->AddRef(); return sci->AddRef();
} }
STDMETHODIMP_(ULONG)DataObject_Release(DataObject *pd) { STDMETHODIMP_(ULONG)DataObject::Release() {
return pd->sci->Release(); return sci->Release();
} }
/// Implement IDataObject /// Implement IDataObject
STDMETHODIMP DataObject_GetData(DataObject *pd, FORMATETC *pFEIn, STGMEDIUM *pSTM) { STDMETHODIMP DataObject::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) {
return pd->sci->GetData(pFEIn, pSTM); return sci->GetData(pFEIn, pSTM);
} }
STDMETHODIMP DataObject_GetDataHere(DataObject *, FORMATETC *, STGMEDIUM *) { STDMETHODIMP DataObject::GetDataHere(FORMATETC *, STGMEDIUM *) {
//Platform::DebugPrintf("DOB GetDataHere\n"); //Platform::DebugPrintf("DOB GetDataHere\n");
return E_NOTIMPL; return E_NOTIMPL;
} }
STDMETHODIMP DataObject_QueryGetData(DataObject *pd, FORMATETC *pFE) { STDMETHODIMP DataObject::QueryGetData(FORMATETC *pFE) {
if (pd->sci->DragIsRectangularOK(pFE->cfFormat) && IsValidFormatEtc(pFE)) { if (sci->DragIsRectangularOK(pFE->cfFormat) && IsValidFormatEtc(pFE)) {
return S_OK; return S_OK;
} }
@ -2950,7 +2964,7 @@ STDMETHODIMP DataObject_QueryGetData(DataObject *pd, FORMATETC *pFE) {
} }
} }
STDMETHODIMP DataObject_GetCanonicalFormatEtc(DataObject *, FORMATETC *, FORMATETC *pFEOut) { STDMETHODIMP DataObject::GetCanonicalFormatEtc(FORMATETC *, FORMATETC *pFEOut) {
//Platform::DebugPrintf("DOB GetCanon\n"); //Platform::DebugPrintf("DOB GetCanon\n");
pFEOut->cfFormat = CF_UNICODETEXT; pFEOut->cfFormat = CF_UNICODETEXT;
pFEOut->ptd = nullptr; pFEOut->ptd = nullptr;
@ -2960,12 +2974,12 @@ STDMETHODIMP DataObject_GetCanonicalFormatEtc(DataObject *, FORMATETC *, FORMATE
return S_OK; return S_OK;
} }
STDMETHODIMP DataObject_SetData(DataObject *, FORMATETC *, STGMEDIUM *, BOOL) { STDMETHODIMP DataObject::SetData(FORMATETC *, STGMEDIUM *, BOOL) {
//Platform::DebugPrintf("DOB SetData\n"); //Platform::DebugPrintf("DOB SetData\n");
return E_FAIL; return E_FAIL;
} }
STDMETHODIMP DataObject_EnumFormatEtc(DataObject *pd, DWORD dwDirection, IEnumFORMATETC **ppEnum) { STDMETHODIMP DataObject::EnumFormatEtc(DWORD dwDirection, IEnumFORMATETC **ppEnum) {
try { try {
//Platform::DebugPrintf("DOB EnumFormatEtc %d\n", dwDirection); //Platform::DebugPrintf("DOB EnumFormatEtc %d\n", dwDirection);
if (dwDirection != DATADIR_GET) { if (dwDirection != DATADIR_GET) {
@ -2975,115 +2989,77 @@ STDMETHODIMP DataObject_EnumFormatEtc(DataObject *pd, DWORD dwDirection, IEnumFO
const CLIPFORMAT formats[] = {CF_UNICODETEXT}; const CLIPFORMAT formats[] = {CF_UNICODETEXT};
FormatEnumerator *pfe = new FormatEnumerator(0, formats, std::size(formats)); FormatEnumerator *pfe = new FormatEnumerator(0, formats, std::size(formats));
return FormatEnumerator_QueryInterface(pfe, IID_IEnumFORMATETC, return pfe->QueryInterface(IID_IEnumFORMATETC, reinterpret_cast<void **>(ppEnum));
reinterpret_cast<void **>(ppEnum));
} catch (std::bad_alloc &) { } catch (std::bad_alloc &) {
pd->sci->errorStatus = Status::BadAlloc; sci->errorStatus = Status::BadAlloc;
return E_OUTOFMEMORY; return E_OUTOFMEMORY;
} catch (...) { } catch (...) {
pd->sci->errorStatus = Status::Failure; sci->errorStatus = Status::Failure;
return E_FAIL; return E_FAIL;
} }
} }
STDMETHODIMP DataObject_DAdvise(DataObject *, FORMATETC *, DWORD, IAdviseSink *, PDWORD) { STDMETHODIMP DataObject::DAdvise(FORMATETC *, DWORD, IAdviseSink *, PDWORD) {
//Platform::DebugPrintf("DOB DAdvise\n"); //Platform::DebugPrintf("DOB DAdvise\n");
return E_FAIL; return E_FAIL;
} }
STDMETHODIMP DataObject_DUnadvise(DataObject *, DWORD) { STDMETHODIMP DataObject::DUnadvise(DWORD) {
//Platform::DebugPrintf("DOB DUnadvise\n"); //Platform::DebugPrintf("DOB DUnadvise\n");
return E_FAIL; return E_FAIL;
} }
STDMETHODIMP DataObject_EnumDAdvise(DataObject *, IEnumSTATDATA **) { STDMETHODIMP DataObject::EnumDAdvise(IEnumSTATDATA **) {
//Platform::DebugPrintf("DOB EnumDAdvise\n"); //Platform::DebugPrintf("DOB EnumDAdvise\n");
return E_FAIL; return E_FAIL;
} }
static VFunction *vtDataObject[] = {
(VFunction *)(DataObject_QueryInterface),
(VFunction *)(DataObject_AddRef),
(VFunction *)(DataObject_Release),
(VFunction *)(DataObject_GetData),
(VFunction *)(DataObject_GetDataHere),
(VFunction *)(DataObject_QueryGetData),
(VFunction *)(DataObject_GetCanonicalFormatEtc),
(VFunction *)(DataObject_SetData),
(VFunction *)(DataObject_EnumFormatEtc),
(VFunction *)(DataObject_DAdvise),
(VFunction *)(DataObject_DUnadvise),
(VFunction *)(DataObject_EnumDAdvise)
};
DataObject::DataObject() noexcept {
vtbl = vtDataObject;
sci = nullptr;
}
/// Implement IUnknown /// Implement IUnknown
STDMETHODIMP DropTarget_QueryInterface(DropTarget *dt, REFIID riid, PVOID *ppv) { STDMETHODIMP DropTarget::QueryInterface(REFIID riid, PVOID *ppv) {
//Platform::DebugPrintf("DT QI %x\n", dt); //Platform::DebugPrintf("DT QI %p\n", this);
return dt->sci->QueryInterface(riid, ppv); return sci->QueryInterface(riid, ppv);
} }
STDMETHODIMP_(ULONG)DropTarget_AddRef(DropTarget *dt) { STDMETHODIMP_(ULONG)DropTarget::AddRef() {
return dt->sci->AddRef(); return sci->AddRef();
} }
STDMETHODIMP_(ULONG)DropTarget_Release(DropTarget *dt) { STDMETHODIMP_(ULONG)DropTarget::Release() {
return dt->sci->Release(); return sci->Release();
} }
/// Implement IDropTarget by forwarding to Scintilla /// Implement IDropTarget by forwarding to Scintilla
STDMETHODIMP DropTarget_DragEnter(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState, STDMETHODIMP DropTarget::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
POINTL pt, PDWORD pdwEffect) {
try { try {
return dt->sci->DragEnter(pIDataSource, grfKeyState, pt, pdwEffect); return sci->DragEnter(pIDataSource, grfKeyState, pt, pdwEffect);
} catch (...) { } catch (...) {
dt->sci->errorStatus = Status::Failure; sci->errorStatus = Status::Failure;
} }
return E_FAIL; return E_FAIL;
} }
STDMETHODIMP DropTarget_DragOver(DropTarget *dt, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) { STDMETHODIMP DropTarget::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
try { try {
return dt->sci->DragOver(grfKeyState, pt, pdwEffect); return sci->DragOver(grfKeyState, pt, pdwEffect);
} catch (...) { } catch (...) {
dt->sci->errorStatus = Status::Failure; sci->errorStatus = Status::Failure;
} }
return E_FAIL; return E_FAIL;
} }
STDMETHODIMP DropTarget_DragLeave(DropTarget *dt) { STDMETHODIMP DropTarget::DragLeave() {
try { try {
return dt->sci->DragLeave(); return sci->DragLeave();
} catch (...) { } catch (...) {
dt->sci->errorStatus = Status::Failure; sci->errorStatus = Status::Failure;
} }
return E_FAIL; return E_FAIL;
} }
STDMETHODIMP DropTarget_Drop(DropTarget *dt, LPDATAOBJECT pIDataSource, DWORD grfKeyState, STDMETHODIMP DropTarget::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
POINTL pt, PDWORD pdwEffect) {
try { try {
return dt->sci->Drop(pIDataSource, grfKeyState, pt, pdwEffect); return sci->Drop(pIDataSource, grfKeyState, pt, pdwEffect);
} catch (...) { } catch (...) {
dt->sci->errorStatus = Status::Failure; sci->errorStatus = Status::Failure;
} }
return E_FAIL; return E_FAIL;
} }
static VFunction *vtDropTarget[] = {
(VFunction *)(DropTarget_QueryInterface),
(VFunction *)(DropTarget_AddRef),
(VFunction *)(DropTarget_Release),
(VFunction *)(DropTarget_DragEnter),
(VFunction *)(DropTarget_DragOver),
(VFunction *)(DropTarget_DragLeave),
(VFunction *)(DropTarget_Drop)
};
DropTarget::DropTarget() noexcept {
vtbl = vtDropTarget;
sci = nullptr;
}
/** /**
* DBCS: support Input Method Editor (IME). * DBCS: support Input Method Editor (IME).
* Called when IME Window opened. * Called when IME Window opened.
@ -3216,6 +3192,50 @@ LRESULT ScintillaWin::ImeOnReconvert(LPARAM lParam) {
return rcSize; return rcSize;
} }
LRESULT ScintillaWin::ImeOnDocumentFeed(LPARAM lParam) const {
// This is called while typing preedit string in.
// So there is no selection.
// Limit feed within one line without EOL.
// Look around: lineStart |<-- |compStart| - caret - compEnd| -->| lineEnd.
const Sci::Position curPos = CurrentPosition();
const Sci::Line curLine = pdoc->SciLineFromPosition(curPos);
const Sci::Position lineStart = pdoc->LineStart(curLine);
const Sci::Position lineEnd = pdoc->LineEnd(curLine);
const std::wstring rcFeed = StringDecode(RangeText(lineStart, lineEnd), CodePageOfDocument());
const int rcFeedLen = static_cast<int>(rcFeed.length()) * sizeof(wchar_t);
const int rcSize = sizeof(RECONVERTSTRING) + rcFeedLen + sizeof(wchar_t);
RECONVERTSTRING *rc = static_cast<RECONVERTSTRING *>(PtrFromSPtr(lParam));
if (!rc)
return rcSize;
wchar_t *rcFeedStart = reinterpret_cast<wchar_t*>(rc + 1);
memcpy(rcFeedStart, &rcFeed[0], rcFeedLen);
IMContext imc(MainHWND());
if (!imc.hIMC)
return 0;
const size_t compStrLen = imc.GetCompositionString(GCS_COMPSTR).size();
const int imeCaretPos = imc.GetImeCaretPos();
const Sci::Position compStart = pdoc->GetRelativePositionUTF16(curPos, -imeCaretPos);
const Sci::Position compStrOffset = pdoc->CountUTF16(lineStart, compStart);
// Fill in reconvert structure.
// Let IME to decide what the target is.
rc->dwVersion = 0; //constant
rc->dwStrLen = static_cast<DWORD>(rcFeed.length());
rc->dwStrOffset = sizeof(RECONVERTSTRING); //constant
rc->dwCompStrLen = static_cast<DWORD>(compStrLen);
rc->dwCompStrOffset = static_cast<DWORD>(compStrOffset) * sizeof(wchar_t);
rc->dwTargetStrLen = rc->dwCompStrLen;
rc->dwTargetStrOffset = rc->dwCompStrOffset;
return rcSize; // MS API says reconv structure to be returned.
}
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);
@ -3411,14 +3431,15 @@ DWORD ScintillaWin::EffectFromState(DWORD grfKeyState) const noexcept {
/// Implement IUnknown /// Implement IUnknown
STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) { STDMETHODIMP ScintillaWin::QueryInterface(REFIID riid, PVOID *ppv) {
*ppv = nullptr; *ppv = nullptr;
if (riid == IID_IUnknown) if (riid == IID_IUnknown) {
*ppv = reinterpret_cast<IDropTarget *>(&dt); *ppv = &dt;
if (riid == IID_IDropSource) } else if (riid == IID_IDropSource) {
*ppv = reinterpret_cast<IDropSource *>(&ds); *ppv = &ds;
if (riid == IID_IDropTarget) } else if (riid == IID_IDropTarget) {
*ppv = reinterpret_cast<IDropTarget *>(&dt); *ppv = &dt;
if (riid == IID_IDataObject) } else if (riid == IID_IDataObject) {
*ppv = reinterpret_cast<IDataObject *>(&dob); *ppv = &dob;
}
if (!*ppv) if (!*ppv)
return E_NOINTERFACE; return E_NOINTERFACE;
return S_OK; return S_OK;

View File

@ -45,7 +45,7 @@ vpath %.h ../src ../include
vpath %.cxx ../src vpath %.cxx ../src
LDFLAGS=-shared -static -mwindows LDFLAGS=-shared -static -mwindows
LIBS=-lgdi32 -luser32 -limm32 -lole32 -luuid -loleaut32 -lmsimg32 $(LIBSMINGW) LIBS=-lgdi32 -luser32 -limm32 -lole32 -luuid -loleaut32 $(LIBSMINGW)
INCLUDES=-I ../include -I ../src INCLUDES=-I ../include -I ../src

View File

@ -42,7 +42,7 @@ CXXNDEBUG=-O2 -MT -DNDEBUG -GL
NAME=-Fo NAME=-Fo
LDFLAGS=-OPT:REF -LTCG -IGNORE:4197 -DEBUG $(SUBSYSTEM) $(CETCOMPAT) LDFLAGS=-OPT:REF -LTCG -IGNORE:4197 -DEBUG $(SUBSYSTEM) $(CETCOMPAT)
LDDEBUG= LDDEBUG=
LIBS=KERNEL32.lib USER32.lib GDI32.lib IMM32.lib OLE32.lib OLEAUT32.lib MSIMG32.lib LIBS=KERNEL32.lib USER32.lib GDI32.lib IMM32.lib OLE32.lib OLEAUT32.lib
NOLOGO=-nologo NOLOGO=-nologo
!IFDEF QUIET !IFDEF QUIET