mirror of
https://github.com/notepad-plus-plus/notepad-plus-plus.git
synced 2025-07-06 13:34:44 +02:00
Update Scintilla from 5.2.1 to 5.2.2 and Lexilla from 5.1.5 to 5.1.6
Close #11537
This commit is contained in:
parent
3b0d5242ac
commit
100d45f7cf
Binary file not shown.
Binary file not shown.
1
lexilla/.gitattributes
vendored
1
lexilla/.gitattributes
vendored
@ -19,6 +19,7 @@
|
|||||||
**.def text
|
**.def text
|
||||||
**.manifest text
|
**.manifest text
|
||||||
**.properties text
|
**.properties text
|
||||||
|
**.session text
|
||||||
**.styled text
|
**.styled text
|
||||||
**.folded text
|
**.folded text
|
||||||
**.adoc text
|
**.adoc text
|
||||||
|
@ -55,7 +55,7 @@ std::wstring WideStringFromUTF8(std::string_view sv) {
|
|||||||
const int sLength = static_cast<int>(sv.length());
|
const int sLength = static_cast<int>(sv.length());
|
||||||
const int cchWide = ::MultiByteToWideChar(CP_UTF8, 0, sv.data(), sLength, nullptr, 0);
|
const int cchWide = ::MultiByteToWideChar(CP_UTF8, 0, sv.data(), sLength, nullptr, 0);
|
||||||
std::wstring sWide(cchWide, 0);
|
std::wstring sWide(cchWide, 0);
|
||||||
::MultiByteToWideChar(CP_UTF8, 0, sv.data(), sLength, &sWide[0], cchWide);
|
::MultiByteToWideChar(CP_UTF8, 0, sv.data(), sLength, sWide.data(), cchWide);
|
||||||
return sWide;
|
return sWide;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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="20220209" />
|
<meta name="Date.Modified" content="20220331" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
.logo {
|
.logo {
|
||||||
@ -61,8 +61,8 @@
|
|||||||
<font color="#FFCC99" size="4"> A library of language lexers for use with Scintilla</font>
|
<font color="#FFCC99" size="4"> A library of language lexers for use with Scintilla</font>
|
||||||
</td>
|
</td>
|
||||||
<td width="40%" align="right">
|
<td width="40%" align="right">
|
||||||
<font color="#FFCC99" size="3">Release version 5.1.5<br />
|
<font color="#FFCC99" size="3">Release version 5.1.6<br />
|
||||||
Site last modified February 9 2022</font>
|
Site last modified March 31 2022</font>
|
||||||
</td>
|
</td>
|
||||||
<td width="20%">
|
<td width="20%">
|
||||||
|
|
||||||
@ -77,6 +77,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<ul id="versionlist">
|
<ul id="versionlist">
|
||||||
|
<li>Version 5.1.6 improves Markdown and Ruby.</li>
|
||||||
<li>Version 5.1.5 improves Bash, Batch, F#, HTML, Inno Setup, and Python.</li>
|
<li>Version 5.1.5 improves Bash, Batch, F#, HTML, Inno Setup, and Python.</li>
|
||||||
<li>Version 5.1.4 adds lexers for AsciiDoc and GDScript.</li>
|
<li>Version 5.1.4 adds lexers for AsciiDoc and GDScript.</li>
|
||||||
<li>Version 5.1.3 improves Rust.</li>
|
<li>Version 5.1.3 improves Rust.</li>
|
||||||
|
@ -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/lexilla515.zip">
|
<font size="4"> <a href="https://www.scintilla.org/lexilla516.zip">
|
||||||
Windows</a>
|
Windows</a>
|
||||||
<a href="https://www.scintilla.org/lexilla515.tgz">
|
<a href="https://www.scintilla.org/lexilla516.tgz">
|
||||||
GTK/Linux</a>
|
GTK/Linux</a>
|
||||||
</font>
|
</font>
|
||||||
</td>
|
</td>
|
||||||
@ -42,7 +42,7 @@
|
|||||||
containing very few restrictions.
|
containing very few restrictions.
|
||||||
</p>
|
</p>
|
||||||
<h3>
|
<h3>
|
||||||
Release 5.1.5
|
Release 5.1.6
|
||||||
</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/lexilla515.zip">zip format</a> (1.1M) commonly used on Windows</li>
|
<li><a href="https://www.scintilla.org/lexilla516.zip">zip format</a> (1.1M) commonly used on Windows</li>
|
||||||
<li><a href="https://www.scintilla.org/lexilla515.tgz">tgz format</a> (0.9M) commonly used on Linux and compatible operating systems</li>
|
<li><a href="https://www.scintilla.org/lexilla516.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>
|
||||||
|
@ -577,6 +577,7 @@
|
|||||||
<td>Arkadiusz Michalski</td>
|
<td>Arkadiusz Michalski</td>
|
||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td>Red_M</td>
|
<td>Red_M</td>
|
||||||
|
<td>cdbdev</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<h2>Releases</h2>
|
<h2>Releases</h2>
|
||||||
@ -585,13 +586,49 @@
|
|||||||
</h3>
|
</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li>
|
<li>
|
||||||
Released 9 February 2022.
|
Released 31 March 2022.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Implement conditional statements "if" and "match", comparison function "$(=", and "FileNameExt"
|
||||||
|
property in TestLexers to allow varying lexer properties over different files.
|
||||||
|
<a href="https://github.com/ScintillaOrg/lexilla/issues/62">Issue #62</a>.
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
Add LexAccessor::BufferStyleAt to retrieve style values to simplify logic and
|
Add LexAccessor::BufferStyleAt to retrieve style values to simplify logic and
|
||||||
improve performance.
|
improve performance.
|
||||||
<a href="https://github.com/ScintillaOrg/lexilla/issues/54">Issue #54</a>.
|
<a href="https://github.com/ScintillaOrg/lexilla/issues/54">Issue #54</a>.
|
||||||
</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
Markdown: Optionally style all of Markdown header lines.
|
||||||
|
Enabled with lexer.markdown.header.eolfill=1.
|
||||||
|
<a href="https://github.com/ScintillaOrg/lexilla/issues/60">Issue #60</a>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Ruby: Fix operator method styling so next word not treated as method name.
|
||||||
|
<a href="https://github.com/ScintillaOrg/lexilla/issues/65">Issue #65</a>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Ruby: Fix folding for Ruby 3 endless method definition.
|
||||||
|
<a href="https://github.com/ScintillaOrg/lexilla/issues/65">Issue #65</a>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Ruby: Fold string array SCE_RB_STRING_QW.
|
||||||
|
<a href="https://github.com/ScintillaOrg/lexilla/issues/65">Issue #65</a>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Ruby: Fix final \n in indented heredoc to be SCE_RB_HERE_Q.
|
||||||
|
<a href="https://github.com/ScintillaOrg/lexilla/issues/66">Issue #66</a>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Ruby: Fix heredoc recognition when '.' and ',' used in method calls and after SCE_RB_GLOBAL.
|
||||||
|
Classify word after heredoc delimiter instead of styling as keyword.
|
||||||
|
<a href="https://github.com/ScintillaOrg/lexilla/issues/67">Issue #67</a>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Ruby: Improve method highlighting so method name is styled as SCE_RB_DEFNAME and class/object
|
||||||
|
is styled appropriately.
|
||||||
|
<a href="https://github.com/ScintillaOrg/lexilla/issues/68">Issue #68</a>.
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>
|
<h3>
|
||||||
<a href="https://www.scintilla.org/lexilla515.zip">Release 5.1.5</a>
|
<a href="https://www.scintilla.org/lexilla515.zip">Release 5.1.5</a>
|
||||||
|
@ -66,6 +66,7 @@ constexpr bool IsNewline(const int ch) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// True if can follow ch down to the end with possibly trailing whitespace
|
// True if can follow ch down to the end with possibly trailing whitespace
|
||||||
|
// Does not set the state SCE_MARKDOWN_LINE_BEGIN as to allow further processing
|
||||||
static bool FollowToLineEnd(const int ch, const int state, const Sci_PositionU endPos, StyleContext &sc) {
|
static bool FollowToLineEnd(const int ch, const int state, const Sci_PositionU endPos, StyleContext &sc) {
|
||||||
Sci_Position i = 0;
|
Sci_Position i = 0;
|
||||||
while (sc.GetRelative(++i) == ch)
|
while (sc.GetRelative(++i) == ch)
|
||||||
@ -74,9 +75,8 @@ static bool FollowToLineEnd(const int ch, const int state, const Sci_PositionU e
|
|||||||
while (IsASpaceOrTab(sc.GetRelative(i)) && sc.currentPos + i < endPos)
|
while (IsASpaceOrTab(sc.GetRelative(i)) && sc.currentPos + i < endPos)
|
||||||
++i;
|
++i;
|
||||||
if (IsNewline(sc.GetRelative(i)) || sc.currentPos + i == endPos) {
|
if (IsNewline(sc.GetRelative(i)) || sc.currentPos + i == endPos) {
|
||||||
|
sc.SetState(state);
|
||||||
sc.Forward(i);
|
sc.Forward(i);
|
||||||
sc.ChangeState(state);
|
|
||||||
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else return false;
|
else return false;
|
||||||
@ -176,6 +176,10 @@ static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int
|
|||||||
// in the default state.
|
// in the default state.
|
||||||
bool freezeCursor = false;
|
bool freezeCursor = false;
|
||||||
|
|
||||||
|
// property lexer.markdown.header.eolfill
|
||||||
|
// Set to 1 to highlight all ATX header text.
|
||||||
|
bool headerEOLFill = styler.GetPropertyInt("lexer.markdown.header.eolfill", 0) == 1;
|
||||||
|
|
||||||
StyleContext sc(startPos, static_cast<Sci_PositionU>(length), initStyle, styler);
|
StyleContext sc(startPos, static_cast<Sci_PositionU>(length), initStyle, styler);
|
||||||
|
|
||||||
while (sc.More()) {
|
while (sc.More()) {
|
||||||
@ -265,22 +269,45 @@ static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int
|
|||||||
}
|
}
|
||||||
else if (sc.state == SCE_MARKDOWN_LINE_BEGIN) {
|
else if (sc.state == SCE_MARKDOWN_LINE_BEGIN) {
|
||||||
// Header
|
// Header
|
||||||
if (sc.Match("######"))
|
if (sc.Match("######")) {
|
||||||
|
if (headerEOLFill)
|
||||||
|
sc.SetState(SCE_MARKDOWN_HEADER6);
|
||||||
|
else
|
||||||
SetStateAndZoom(SCE_MARKDOWN_HEADER6, 6, '#', sc);
|
SetStateAndZoom(SCE_MARKDOWN_HEADER6, 6, '#', sc);
|
||||||
else if (sc.Match("#####"))
|
}
|
||||||
|
else if (sc.Match("#####")) {
|
||||||
|
if (headerEOLFill)
|
||||||
|
sc.SetState(SCE_MARKDOWN_HEADER5);
|
||||||
|
else
|
||||||
SetStateAndZoom(SCE_MARKDOWN_HEADER5, 5, '#', sc);
|
SetStateAndZoom(SCE_MARKDOWN_HEADER5, 5, '#', sc);
|
||||||
else if (sc.Match("####"))
|
}
|
||||||
|
else if (sc.Match("####")) {
|
||||||
|
if (headerEOLFill)
|
||||||
|
sc.SetState(SCE_MARKDOWN_HEADER4);
|
||||||
|
else
|
||||||
SetStateAndZoom(SCE_MARKDOWN_HEADER4, 4, '#', sc);
|
SetStateAndZoom(SCE_MARKDOWN_HEADER4, 4, '#', sc);
|
||||||
else if (sc.Match("###"))
|
}
|
||||||
|
else if (sc.Match("###")) {
|
||||||
|
if (headerEOLFill)
|
||||||
|
sc.SetState(SCE_MARKDOWN_HEADER3);
|
||||||
|
else
|
||||||
SetStateAndZoom(SCE_MARKDOWN_HEADER3, 3, '#', sc);
|
SetStateAndZoom(SCE_MARKDOWN_HEADER3, 3, '#', sc);
|
||||||
else if (sc.Match("##"))
|
}
|
||||||
|
else if (sc.Match("##")) {
|
||||||
|
if (headerEOLFill)
|
||||||
|
sc.SetState(SCE_MARKDOWN_HEADER2);
|
||||||
|
else
|
||||||
SetStateAndZoom(SCE_MARKDOWN_HEADER2, 2, '#', sc);
|
SetStateAndZoom(SCE_MARKDOWN_HEADER2, 2, '#', sc);
|
||||||
|
}
|
||||||
else if (sc.Match("#")) {
|
else if (sc.Match("#")) {
|
||||||
// Catch the special case of an unordered list
|
// Catch the special case of an unordered list
|
||||||
if (sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) {
|
if (sc.chNext == '.' && IsASpaceOrTab(sc.GetRelative(2))) {
|
||||||
precharCount = 0;
|
precharCount = 0;
|
||||||
sc.SetState(SCE_MARKDOWN_PRECHAR);
|
sc.SetState(SCE_MARKDOWN_PRECHAR);
|
||||||
}
|
}
|
||||||
|
else if (headerEOLFill) {
|
||||||
|
sc.SetState(SCE_MARKDOWN_HEADER1);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
SetStateAndZoom(SCE_MARKDOWN_HEADER1, 1, '#', sc);
|
SetStateAndZoom(SCE_MARKDOWN_HEADER1, 1, '#', sc);
|
||||||
}
|
}
|
||||||
@ -292,14 +319,18 @@ static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int
|
|||||||
sc.SetState(SCE_MARKDOWN_DEFAULT);
|
sc.SetState(SCE_MARKDOWN_DEFAULT);
|
||||||
}
|
}
|
||||||
else if (sc.ch == '=') {
|
else if (sc.ch == '=') {
|
||||||
if (HasPrevLineContent(sc) && FollowToLineEnd('=', SCE_MARKDOWN_HEADER1, endPos, sc))
|
if (HasPrevLineContent(sc) && FollowToLineEnd('=', SCE_MARKDOWN_HEADER1, endPos, sc)) {
|
||||||
;
|
if (!headerEOLFill)
|
||||||
|
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
sc.SetState(SCE_MARKDOWN_DEFAULT);
|
sc.SetState(SCE_MARKDOWN_DEFAULT);
|
||||||
}
|
}
|
||||||
else if (sc.ch == '-') {
|
else if (sc.ch == '-') {
|
||||||
if (HasPrevLineContent(sc) && FollowToLineEnd('-', SCE_MARKDOWN_HEADER2, endPos, sc))
|
if (HasPrevLineContent(sc) && FollowToLineEnd('-', SCE_MARKDOWN_HEADER2, endPos, sc)) {
|
||||||
;
|
if (!headerEOLFill)
|
||||||
|
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
precharCount = 0;
|
precharCount = 0;
|
||||||
sc.SetState(SCE_MARKDOWN_PRECHAR);
|
sc.SetState(SCE_MARKDOWN_PRECHAR);
|
||||||
@ -317,7 +348,13 @@ static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int
|
|||||||
else if (sc.state == SCE_MARKDOWN_HEADER1 || sc.state == SCE_MARKDOWN_HEADER2 ||
|
else if (sc.state == SCE_MARKDOWN_HEADER1 || sc.state == SCE_MARKDOWN_HEADER2 ||
|
||||||
sc.state == SCE_MARKDOWN_HEADER3 || sc.state == SCE_MARKDOWN_HEADER4 ||
|
sc.state == SCE_MARKDOWN_HEADER3 || sc.state == SCE_MARKDOWN_HEADER4 ||
|
||||||
sc.state == SCE_MARKDOWN_HEADER5 || sc.state == SCE_MARKDOWN_HEADER6) {
|
sc.state == SCE_MARKDOWN_HEADER5 || sc.state == SCE_MARKDOWN_HEADER6) {
|
||||||
if (IsNewline(sc.ch))
|
if (headerEOLFill) {
|
||||||
|
if (sc.atLineStart) {
|
||||||
|
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
|
||||||
|
freezeCursor = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (IsNewline(sc.ch))
|
||||||
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
|
sc.SetState(SCE_MARKDOWN_LINE_BEGIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -420,7 +457,8 @@ static void ColorizeMarkdownDoc(Sci_PositionU startPos, Sci_Position length, int
|
|||||||
// Emphasis
|
// Emphasis
|
||||||
else if (sc.ch == '*' && sc.chNext != ' ' && IsCompleteStyleRegion(sc, "*")) {
|
else if (sc.ch == '*' && sc.chNext != ' ' && IsCompleteStyleRegion(sc, "*")) {
|
||||||
sc.SetState(SCE_MARKDOWN_EM1);
|
sc.SetState(SCE_MARKDOWN_EM1);
|
||||||
} else if (sc.ch == '_' && sc.chNext != ' ' && IsCompleteStyleRegion(sc, "_")) {
|
}
|
||||||
|
else if (sc.ch == '_' && sc.chNext != ' ' && IsCompleteStyleRegion(sc, "_")) {
|
||||||
sc.SetState(SCE_MARKDOWN_EM2);
|
sc.SetState(SCE_MARKDOWN_EM2);
|
||||||
}
|
}
|
||||||
// Strikeout
|
// Strikeout
|
||||||
|
@ -102,7 +102,7 @@ static bool keywordIsModifier(const char *word,
|
|||||||
Sci_Position pos,
|
Sci_Position pos,
|
||||||
Accessor &styler);
|
Accessor &styler);
|
||||||
|
|
||||||
static int ClassifyWordRb(Sci_PositionU start, Sci_PositionU end, WordList &keywords, Accessor &styler, char *prevWord) {
|
static int ClassifyWordRb(Sci_PositionU start, Sci_PositionU end, char ch, WordList &keywords, Accessor &styler, char *prevWord) {
|
||||||
char s[MAX_KEYWORD_LENGTH];
|
char s[MAX_KEYWORD_LENGTH];
|
||||||
Sci_PositionU i, j;
|
Sci_PositionU i, j;
|
||||||
Sci_PositionU lim = end - start + 1; // num chars to copy
|
Sci_PositionU lim = end - start + 1; // num chars to copy
|
||||||
@ -113,13 +113,22 @@ static int ClassifyWordRb(Sci_PositionU start, Sci_PositionU end, WordList &keyw
|
|||||||
s[j] = styler[i];
|
s[j] = styler[i];
|
||||||
}
|
}
|
||||||
s[j] = '\0';
|
s[j] = '\0';
|
||||||
int chAttr;
|
int chAttr = SCE_RB_IDENTIFIER;
|
||||||
|
int style = SCE_RB_DEFAULT;
|
||||||
if (0 == strcmp(prevWord, "class"))
|
if (0 == strcmp(prevWord, "class"))
|
||||||
chAttr = SCE_RB_CLASSNAME;
|
chAttr = SCE_RB_CLASSNAME;
|
||||||
else if (0 == strcmp(prevWord, "module"))
|
else if (0 == strcmp(prevWord, "module"))
|
||||||
chAttr = SCE_RB_MODULE_NAME;
|
chAttr = SCE_RB_MODULE_NAME;
|
||||||
else if (0 == strcmp(prevWord, "def"))
|
else if (0 == strcmp(prevWord, "def")) {
|
||||||
chAttr = SCE_RB_DEFNAME;
|
chAttr = SCE_RB_DEFNAME;
|
||||||
|
if (ch == '.') {
|
||||||
|
if (strcmp(s, "self") == 0) {
|
||||||
|
style = SCE_RB_WORD_DEMOTED;
|
||||||
|
} else {
|
||||||
|
style = SCE_RB_IDENTIFIER;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else if (keywords.InList(s) && ((start == 0) || !followsDot(start - 1, styler))) {
|
else if (keywords.InList(s) && ((start == 0) || !followsDot(start - 1, styler))) {
|
||||||
if (keywordIsAmbiguous(s)
|
if (keywordIsAmbiguous(s)
|
||||||
&& keywordIsModifier(s, start, styler)) {
|
&& keywordIsModifier(s, start, styler)) {
|
||||||
@ -136,15 +145,15 @@ static int ClassifyWordRb(Sci_PositionU start, Sci_PositionU end, WordList &keyw
|
|||||||
chAttr = SCE_RB_WORD_DEMOTED;
|
chAttr = SCE_RB_WORD_DEMOTED;
|
||||||
} else {
|
} else {
|
||||||
chAttr = SCE_RB_WORD;
|
chAttr = SCE_RB_WORD;
|
||||||
}
|
style = SCE_RB_WORD;
|
||||||
} else
|
|
||||||
chAttr = SCE_RB_IDENTIFIER;
|
|
||||||
styler.ColourTo(end, chAttr);
|
|
||||||
if (chAttr == SCE_RB_WORD) {
|
|
||||||
strcpy(prevWord, s);
|
strcpy(prevWord, s);
|
||||||
} else {
|
}
|
||||||
|
}
|
||||||
|
if (style == SCE_RB_DEFAULT) {
|
||||||
|
style = chAttr;
|
||||||
prevWord[0] = 0;
|
prevWord[0] = 0;
|
||||||
}
|
}
|
||||||
|
styler.ColourTo(end, style);
|
||||||
return chAttr;
|
return chAttr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +470,6 @@ static Sci_Position findExpressionStart(Sci_Position pos,
|
|||||||
|
|
||||||
static bool sureThisIsNotHeredoc(Sci_Position lt2StartPos,
|
static bool sureThisIsNotHeredoc(Sci_Position lt2StartPos,
|
||||||
Accessor &styler) {
|
Accessor &styler) {
|
||||||
int prevStyle;
|
|
||||||
// Use full document, not just part we're styling
|
// Use full document, not just part we're styling
|
||||||
Sci_Position lengthDoc = styler.Length();
|
Sci_Position lengthDoc = styler.Length();
|
||||||
Sci_Position lineStart = styler.GetLine(lt2StartPos);
|
Sci_Position lineStart = styler.GetLine(lt2StartPos);
|
||||||
@ -478,9 +486,10 @@ static bool sureThisIsNotHeredoc(Sci_Position lt2StartPos,
|
|||||||
if (firstWordPosn >= lt2StartPos) {
|
if (firstWordPosn >= lt2StartPos) {
|
||||||
return definitely_not_a_here_doc;
|
return definitely_not_a_here_doc;
|
||||||
}
|
}
|
||||||
prevStyle = styler.StyleAt(firstWordPosn);
|
int prevStyle = styler.StyleAt(firstWordPosn);
|
||||||
// If we have '<<' following a keyword, it's not a heredoc
|
// If we have '<<' following a keyword, it's not a heredoc
|
||||||
if (prevStyle != SCE_RB_IDENTIFIER
|
if (prevStyle != SCE_RB_IDENTIFIER
|
||||||
|
&& prevStyle != SCE_RB_GLOBAL // $stdout and $stderr
|
||||||
&& prevStyle != SCE_RB_SYMBOL
|
&& prevStyle != SCE_RB_SYMBOL
|
||||||
&& prevStyle != SCE_RB_INSTANCE_VAR
|
&& prevStyle != SCE_RB_INSTANCE_VAR
|
||||||
&& prevStyle != SCE_RB_CLASS_VAR) {
|
&& prevStyle != SCE_RB_CLASS_VAR) {
|
||||||
@ -595,7 +604,7 @@ static bool sureThisIsNotHeredoc(Sci_Position lt2StartPos,
|
|||||||
return definitely_not_a_here_doc;
|
return definitely_not_a_here_doc;
|
||||||
} else {
|
} else {
|
||||||
char ch = styler[j];
|
char ch = styler[j];
|
||||||
if (ch == '#' || isEOLChar(ch)) {
|
if (ch == '#' || isEOLChar(ch) || ch == '.' || ch == ',') {
|
||||||
// This is OK, so break and continue;
|
// This is OK, so break and continue;
|
||||||
break;
|
break;
|
||||||
} else {
|
} else {
|
||||||
@ -714,6 +723,7 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
false);
|
false);
|
||||||
|
|
||||||
bool preferRE = true;
|
bool preferRE = true;
|
||||||
|
bool afterDef = false;
|
||||||
int state = initStyle;
|
int state = initStyle;
|
||||||
Sci_Position lengthDoc = startPos + length;
|
Sci_Position lengthDoc = startPos + length;
|
||||||
|
|
||||||
@ -791,7 +801,12 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
if (HereDoc.State == 1 && isEOLChar(ch)) {
|
if (HereDoc.State == 1 && isEOLChar(ch)) {
|
||||||
// Begin of here-doc (the line after the here-doc delimiter):
|
// Begin of here-doc (the line after the here-doc delimiter):
|
||||||
HereDoc.State = 2;
|
HereDoc.State = 2;
|
||||||
styler.ColourTo(i-1, state);
|
if (state == SCE_RB_WORD) {
|
||||||
|
const Sci_Position wordStartPos = styler.GetStartSegment();
|
||||||
|
ClassifyWordRb(wordStartPos, i - 1, ch, keywords, styler, prevWord);
|
||||||
|
} else {
|
||||||
|
styler.ColourTo(i - 1, state);
|
||||||
|
}
|
||||||
// Don't check for a missing quote, just jump into
|
// Don't check for a missing quote, just jump into
|
||||||
// the here-doc state
|
// the here-doc state
|
||||||
state = SCE_RB_HERE_Q;
|
state = SCE_RB_HERE_Q;
|
||||||
@ -862,7 +877,10 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
Quote.New();
|
Quote.New();
|
||||||
Quote.Open(ch);
|
Quote.Open(ch);
|
||||||
} else if (ch == '<' && chNext == '<' && chNext2 != '=') {
|
} else if (ch == '<' && chNext == '<' && chNext2 != '=') {
|
||||||
|
if (afterDef) {
|
||||||
|
afterDef = false;
|
||||||
|
prevWord[0] = 0;
|
||||||
|
}
|
||||||
// Recognise the '<<' symbol - either a here document or a binary op
|
// Recognise the '<<' symbol - either a here document or a binary op
|
||||||
styler.ColourTo(i - 1, state);
|
styler.ColourTo(i - 1, state);
|
||||||
i++;
|
i++;
|
||||||
@ -893,6 +911,7 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
}
|
}
|
||||||
preferRE = (state != SCE_RB_HERE_DELIM);
|
preferRE = (state != SCE_RB_HERE_DELIM);
|
||||||
} else if (ch == ':') {
|
} else if (ch == ':') {
|
||||||
|
afterDef = false;
|
||||||
styler.ColourTo(i - 1, state);
|
styler.ColourTo(i - 1, state);
|
||||||
if (chNext == ':') {
|
if (chNext == ':') {
|
||||||
// Mark "::" as an operator, not symbol start
|
// Mark "::" as an operator, not symbol start
|
||||||
@ -1009,7 +1028,7 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
state = SCE_RB_DEFAULT;
|
state = SCE_RB_DEFAULT;
|
||||||
preferRE = true;
|
preferRE = true;
|
||||||
}
|
}
|
||||||
} else if (ch == '%') {
|
} else if (ch == '%' && !afterDef) {
|
||||||
styler.ColourTo(i - 1, state);
|
styler.ColourTo(i - 1, state);
|
||||||
bool have_string = false;
|
bool have_string = false;
|
||||||
if (strchr(q_chars, chNext) && !isSafeWordcharOrHigh(chNext2)) {
|
if (strchr(q_chars, chNext) && !isSafeWordcharOrHigh(chNext2)) {
|
||||||
@ -1046,6 +1065,7 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
preferRE = true;
|
preferRE = true;
|
||||||
}
|
}
|
||||||
} else if (ch == '?') {
|
} else if (ch == '?') {
|
||||||
|
afterDef = false;
|
||||||
styler.ColourTo(i - 1, state);
|
styler.ColourTo(i - 1, state);
|
||||||
if (iswhitespace(chNext) || chNext == '\n' || chNext == '\r') {
|
if (iswhitespace(chNext) || chNext == '\n' || chNext == '\r') {
|
||||||
styler.ColourTo(i, SCE_RB_OPERATOR);
|
styler.ColourTo(i, SCE_RB_OPERATOR);
|
||||||
@ -1057,6 +1077,16 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
}
|
}
|
||||||
} else if (isoperator(ch) || ch == '.') {
|
} else if (isoperator(ch) || ch == '.') {
|
||||||
styler.ColourTo(i - 1, state);
|
styler.ColourTo(i - 1, state);
|
||||||
|
if (afterDef && ch != '.') {
|
||||||
|
afterDef = false;
|
||||||
|
prevWord[0] = 0;
|
||||||
|
if (chNext == '@' && (ch == '+' || ch == '-' || ch == '!')) {
|
||||||
|
// unary operator method
|
||||||
|
ch = chNext;
|
||||||
|
chNext = chNext2;
|
||||||
|
i += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
styler.ColourTo(i, SCE_RB_OPERATOR);
|
styler.ColourTo(i, SCE_RB_OPERATOR);
|
||||||
// If we're ending an expression or block,
|
// If we're ending an expression or block,
|
||||||
// assume it ends an object, and the ambivalent
|
// assume it ends an object, and the ambivalent
|
||||||
@ -1082,6 +1112,7 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
}
|
}
|
||||||
// Stay in default state
|
// Stay in default state
|
||||||
} else if (isEOLChar(ch)) {
|
} else if (isEOLChar(ch)) {
|
||||||
|
afterDef = false;
|
||||||
// Make sure it's a true line-end, with no backslash
|
// Make sure it's a true line-end, with no backslash
|
||||||
if ((ch == '\r' || (ch == '\n' && chPrev != '\r'))
|
if ((ch == '\r' || (ch == '\n' && chPrev != '\r'))
|
||||||
&& chPrev != '\\') {
|
&& chPrev != '\\') {
|
||||||
@ -1089,6 +1120,9 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
preferRE = true;
|
preferRE = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (afterDef && state != SCE_RB_DEFAULT) {
|
||||||
|
afterDef = false;
|
||||||
|
}
|
||||||
} else if (state == SCE_RB_WORD) {
|
} else if (state == SCE_RB_WORD) {
|
||||||
if (ch == '.' || !isSafeWordcharOrHigh(ch)) {
|
if (ch == '.' || !isSafeWordcharOrHigh(ch)) {
|
||||||
// Words include x? in all contexts,
|
// Words include x? in all contexts,
|
||||||
@ -1127,9 +1161,10 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
preferRE = false;
|
preferRE = false;
|
||||||
} else {
|
} else {
|
||||||
Sci_Position wordStartPos = styler.GetStartSegment();
|
Sci_Position wordStartPos = styler.GetStartSegment();
|
||||||
int word_style = ClassifyWordRb(wordStartPos, i - 1, keywords, styler, prevWord);
|
int word_style = ClassifyWordRb(wordStartPos, i - 1, ch, keywords, styler, prevWord);
|
||||||
switch (word_style) {
|
switch (word_style) {
|
||||||
case SCE_RB_WORD:
|
case SCE_RB_WORD:
|
||||||
|
afterDef = strcmp(prevWord, "def") == 0;
|
||||||
preferRE = RE_CanFollowKeyword(prevWord);
|
preferRE = RE_CanFollowKeyword(prevWord);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1152,6 +1187,7 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
if (ch == '.') {
|
if (ch == '.') {
|
||||||
// We might be redefining an operator-method
|
// We might be redefining an operator-method
|
||||||
preferRE = false;
|
preferRE = false;
|
||||||
|
afterDef = word_style == SCE_RB_DEFNAME;
|
||||||
}
|
}
|
||||||
// And if it's the first
|
// And if it's the first
|
||||||
redo_char(i, ch, chNext, chNext2, state); // pass by ref
|
redo_char(i, ch, chNext, chNext2, state); // pass by ref
|
||||||
@ -1300,7 +1336,7 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
i - HereDoc.DelimiterLength + 1,
|
i - HereDoc.DelimiterLength + 1,
|
||||||
lengthDoc,
|
lengthDoc,
|
||||||
HereDoc.Delimiter)) {
|
HereDoc.Delimiter)) {
|
||||||
styler.ColourTo(i - 1 - HereDoc.DelimiterLength, state);
|
styler.ColourTo(i - HereDoc.DelimiterLength, state);
|
||||||
styler.ColourTo(i, SCE_RB_HERE_DELIM);
|
styler.ColourTo(i, SCE_RB_HERE_DELIM);
|
||||||
state = SCE_RB_DEFAULT;
|
state = SCE_RB_DEFAULT;
|
||||||
preferRE = false;
|
preferRE = false;
|
||||||
@ -1459,7 +1495,7 @@ static void ColouriseRbDoc(Sci_PositionU startPos, Sci_Position length, int init
|
|||||||
if (state == SCE_RB_WORD) {
|
if (state == SCE_RB_WORD) {
|
||||||
// We've ended on a word, possibly at EOF, and need to
|
// We've ended on a word, possibly at EOF, and need to
|
||||||
// classify it.
|
// classify it.
|
||||||
(void) ClassifyWordRb(styler.GetStartSegment(), lengthDoc - 1, keywords, styler, prevWord);
|
(void) ClassifyWordRb(styler.GetStartSegment(), lengthDoc - 1, '\0', keywords, styler, prevWord);
|
||||||
} else {
|
} else {
|
||||||
styler.ColourTo(lengthDoc - 1, state);
|
styler.ColourTo(lengthDoc - 1, state);
|
||||||
}
|
}
|
||||||
@ -1754,10 +1790,21 @@ static void FoldRbDoc(Sci_PositionU startPos, Sci_Position length, int initStyle
|
|||||||
& SC_FOLDLEVELNUMBERMASK
|
& SC_FOLDLEVELNUMBERMASK
|
||||||
& ~SC_FOLDLEVELBASE);
|
& ~SC_FOLDLEVELBASE);
|
||||||
int levelCurrent = levelPrev;
|
int levelCurrent = levelPrev;
|
||||||
|
char chPrev = '\0';
|
||||||
char chNext = styler[startPos];
|
char chNext = styler[startPos];
|
||||||
int styleNext = styler.StyleAt(startPos);
|
int styleNext = styler.StyleAt(startPos);
|
||||||
int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1);
|
int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1);
|
||||||
bool buffer_ends_with_eol = false;
|
// detect endless method definition to fix up code folding
|
||||||
|
enum class MethodDefinition {
|
||||||
|
None,
|
||||||
|
Define,
|
||||||
|
Operator,
|
||||||
|
Name,
|
||||||
|
Argument,
|
||||||
|
};
|
||||||
|
MethodDefinition method_definition = MethodDefinition::None;
|
||||||
|
int argument_paren_count = 0;
|
||||||
|
|
||||||
for (Sci_PositionU i = startPos; i < endPos; i++) {
|
for (Sci_PositionU i = startPos; i < endPos; i++) {
|
||||||
char ch = chNext;
|
char ch = chNext;
|
||||||
chNext = styler.SafeGetCharAt(i + 1);
|
chNext = styler.SafeGetCharAt(i + 1);
|
||||||
@ -1800,8 +1847,10 @@ static void FoldRbDoc(Sci_PositionU startPos, Sci_Position length, int initStyle
|
|||||||
// Don't decrement below 0
|
// Don't decrement below 0
|
||||||
if (levelCurrent > 0)
|
if (levelCurrent > 0)
|
||||||
levelCurrent--;
|
levelCurrent--;
|
||||||
|
} else if (!strcmp(prevWord, "def")) {
|
||||||
|
levelCurrent++;
|
||||||
|
method_definition = MethodDefinition::Define;
|
||||||
} else if (!strcmp(prevWord, "if")
|
} else if (!strcmp(prevWord, "if")
|
||||||
|| !strcmp(prevWord, "def")
|
|
||||||
|| !strcmp(prevWord, "class")
|
|| !strcmp(prevWord, "class")
|
||||||
|| !strcmp(prevWord, "module")
|
|| !strcmp(prevWord, "module")
|
||||||
|| !strcmp(prevWord, "begin")
|
|| !strcmp(prevWord, "begin")
|
||||||
@ -1820,8 +1869,64 @@ static void FoldRbDoc(Sci_PositionU startPos, Sci_Position length, int initStyle
|
|||||||
} else if (styleNext == SCE_RB_DEFAULT) {
|
} else if (styleNext == SCE_RB_DEFAULT) {
|
||||||
levelCurrent--;
|
levelCurrent--;
|
||||||
}
|
}
|
||||||
|
} else if (style == SCE_RB_STRING_QW) {
|
||||||
|
if (stylePrev != style) {
|
||||||
|
levelCurrent++;
|
||||||
|
} else if (styleNext != style) {
|
||||||
|
levelCurrent--;
|
||||||
}
|
}
|
||||||
if (atEOL) {
|
}
|
||||||
|
if (method_definition != MethodDefinition::None) {
|
||||||
|
switch (method_definition) {
|
||||||
|
case MethodDefinition::Define:
|
||||||
|
if (style == SCE_RB_OPERATOR) {
|
||||||
|
method_definition = MethodDefinition::Operator;
|
||||||
|
} else if (style == SCE_RB_DEFNAME || style == SCE_RB_WORD_DEMOTED || style == SCE_RB_CLASSNAME || style == SCE_RB_IDENTIFIER) {
|
||||||
|
method_definition = MethodDefinition::Name;
|
||||||
|
} else if (!(style == SCE_RB_WORD || IsASpaceOrTab(ch))) {
|
||||||
|
method_definition = MethodDefinition::None;
|
||||||
|
}
|
||||||
|
if (method_definition <= MethodDefinition::Define) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// fall through for unary operator or single letter name
|
||||||
|
[[fallthrough]];
|
||||||
|
case MethodDefinition::Operator:
|
||||||
|
case MethodDefinition::Name:
|
||||||
|
if (isEOLChar(chNext) || chNext == '#') {
|
||||||
|
method_definition = MethodDefinition::None;
|
||||||
|
} else if (chNext == '(' || chNext <= ' ') {
|
||||||
|
// setter method cannot be defined in an endless method definition.
|
||||||
|
if (ch == '=' && (method_definition == MethodDefinition::Name || chPrev == ']')) {
|
||||||
|
method_definition = MethodDefinition::None;
|
||||||
|
} else {
|
||||||
|
method_definition = MethodDefinition::Argument;
|
||||||
|
argument_paren_count = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case MethodDefinition::Argument:
|
||||||
|
if (style == SCE_RB_OPERATOR) {
|
||||||
|
if (ch == '(') {
|
||||||
|
++argument_paren_count;
|
||||||
|
} else if (ch == ')') {
|
||||||
|
--argument_paren_count;
|
||||||
|
} else if (argument_paren_count == 0) {
|
||||||
|
method_definition = MethodDefinition::None;
|
||||||
|
if (ch == '=' && levelCurrent > 0) {
|
||||||
|
levelCurrent--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (argument_paren_count == 0 && !IsASpaceOrTab(ch)) {
|
||||||
|
// '=' must be first character after method name or right parenthesis
|
||||||
|
method_definition = MethodDefinition::None;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (atEOL || (i == endPos - 1)) {
|
||||||
int lev = levelPrev;
|
int lev = levelPrev;
|
||||||
if (visibleChars == 0 && foldCompact)
|
if (visibleChars == 0 && foldCompact)
|
||||||
lev |= SC_FOLDLEVELWHITEFLAG;
|
lev |= SC_FOLDLEVELWHITEFLAG;
|
||||||
@ -1831,23 +1936,14 @@ static void FoldRbDoc(Sci_PositionU startPos, Sci_Position length, int initStyle
|
|||||||
lineCurrent++;
|
lineCurrent++;
|
||||||
levelPrev = levelCurrent;
|
levelPrev = levelCurrent;
|
||||||
visibleChars = 0;
|
visibleChars = 0;
|
||||||
buffer_ends_with_eol = true;
|
method_definition = MethodDefinition::None;
|
||||||
|
argument_paren_count = 0;
|
||||||
} else if (!isspacechar(ch)) {
|
} else if (!isspacechar(ch)) {
|
||||||
visibleChars++;
|
visibleChars++;
|
||||||
buffer_ends_with_eol = false;
|
|
||||||
}
|
}
|
||||||
|
chPrev = ch;
|
||||||
stylePrev = style;
|
stylePrev = style;
|
||||||
}
|
}
|
||||||
// Fill in the real level of the next line, keeping the current flags as they will be filled in later
|
|
||||||
if (!buffer_ends_with_eol) {
|
|
||||||
int new_lev = levelCurrent;
|
|
||||||
if (visibleChars == 0 && foldCompact)
|
|
||||||
new_lev |= SC_FOLDLEVELWHITEFLAG;
|
|
||||||
if ((levelCurrent > levelPrev) && (visibleChars > 0))
|
|
||||||
new_lev |= SC_FOLDLEVELHEADERFLAG;
|
|
||||||
levelCurrent = new_lev;
|
|
||||||
}
|
|
||||||
styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *const rubyWordListDesc[] = {
|
static const char *const rubyWordListDesc[] = {
|
||||||
|
@ -122,12 +122,12 @@ public:
|
|||||||
}
|
}
|
||||||
// Return style value from buffer when in buffer, else retrieve from document.
|
// Return style value from buffer when in buffer, else retrieve from document.
|
||||||
// This is faster and can avoid calls to Flush() as that may be expensive.
|
// This is faster and can avoid calls to Flush() as that may be expensive.
|
||||||
char BufferStyleAt(Sci_Position position) const {
|
int BufferStyleAt(Sci_Position position) const {
|
||||||
const Sci_Position index = position - startPosStyling;
|
const Sci_Position index = position - startPosStyling;
|
||||||
if (index >= 0 && index < validLen) {
|
if (index >= 0 && index < validLen) {
|
||||||
return styleBuf[index];
|
return static_cast<unsigned char>(styleBuf[index]);
|
||||||
}
|
}
|
||||||
return pAccess->StyleAt(position);
|
return static_cast<unsigned char>(pAccess->StyleAt(position));
|
||||||
}
|
}
|
||||||
Sci_Position GetLine(Sci_Position position) const {
|
Sci_Position GetLine(Sci_Position position) const {
|
||||||
return pAccess->LineFromPosition(position);
|
return pAccess->LineFromPosition(position);
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
// This file is in the public domain.
|
// This file is in the public domain.
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <cstdint>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@ -20,6 +21,33 @@
|
|||||||
|
|
||||||
using namespace Lexilla;
|
using namespace Lexilla;
|
||||||
|
|
||||||
|
StyleContext::StyleContext(Sci_PositionU startPos, Sci_PositionU length,
|
||||||
|
int initStyle, LexAccessor &styler_, char chMask) :
|
||||||
|
styler(styler_),
|
||||||
|
multiByteAccess((styler.Encoding() == EncodingType::eightBit) ? nullptr : styler.MultiByteAccess()),
|
||||||
|
lengthDocument(static_cast<Sci_PositionU>(styler.Length())),
|
||||||
|
endPos(((startPos + length) < lengthDocument) ? (startPos + length) : (lengthDocument+1)),
|
||||||
|
lineDocEnd(styler.GetLine(lengthDocument)),
|
||||||
|
currentPosLastRelative(SIZE_MAX),
|
||||||
|
currentPos(startPos),
|
||||||
|
currentLine(styler.GetLine(startPos)),
|
||||||
|
lineEnd(styler.LineEnd(currentLine)),
|
||||||
|
lineStartNext(styler.LineStart(currentLine + 1)),
|
||||||
|
atLineStart(static_cast<Sci_PositionU>(styler.LineStart(currentLine)) == startPos),
|
||||||
|
// Mask off all bits which aren't in the chMask.
|
||||||
|
state(initStyle &chMask) {
|
||||||
|
|
||||||
|
styler.StartAt(startPos /*, chMask*/);
|
||||||
|
styler.StartSegment(startPos);
|
||||||
|
|
||||||
|
// Variable width is now 0 so GetNextChar gets the char at currentPos into chNext/widthNext
|
||||||
|
GetNextChar();
|
||||||
|
ch = chNext;
|
||||||
|
width = widthNext;
|
||||||
|
|
||||||
|
GetNextChar();
|
||||||
|
}
|
||||||
|
|
||||||
bool StyleContext::MatchIgnoreCase(const char *s) {
|
bool StyleContext::MatchIgnoreCase(const char *s) {
|
||||||
if (MakeLowerCase(ch) != static_cast<unsigned char>(*s))
|
if (MakeLowerCase(ch) != static_cast<unsigned char>(*s))
|
||||||
return false;
|
return false;
|
||||||
@ -54,19 +82,6 @@ bool StyleContext::MatchIgnoreCase2(const char *s) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void getRange(Sci_PositionU start,
|
|
||||||
Sci_PositionU end,
|
|
||||||
LexAccessor &styler,
|
|
||||||
char *s,
|
|
||||||
Sci_PositionU len) {
|
|
||||||
Sci_PositionU i = 0;
|
|
||||||
while ((i < end - start + 1) && (i < len-1)) {
|
|
||||||
s[i] = styler[start + i];
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
s[i] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
void StyleContext::GetCurrent(char *s, Sci_PositionU len) {
|
void StyleContext::GetCurrent(char *s, Sci_PositionU len) {
|
||||||
styler.GetRange(styler.GetStartSegment(), currentPos, s, len);
|
styler.GetRange(styler.GetStartSegment(), currentPos, s, len);
|
||||||
}
|
}
|
||||||
|
@ -16,21 +16,21 @@ namespace Lexilla {
|
|||||||
// syntactically significant. UTF-8 avoids this as all trail bytes are >= 0x80
|
// syntactically significant. UTF-8 avoids this as all trail bytes are >= 0x80
|
||||||
class StyleContext {
|
class StyleContext {
|
||||||
LexAccessor &styler;
|
LexAccessor &styler;
|
||||||
Scintilla::IDocument *multiByteAccess;
|
Scintilla::IDocument * const multiByteAccess;
|
||||||
Sci_PositionU endPos;
|
const Sci_PositionU lengthDocument;
|
||||||
Sci_PositionU lengthDocument;
|
const Sci_PositionU endPos;
|
||||||
|
const Sci_Position lineDocEnd;
|
||||||
|
|
||||||
// Used for optimizing GetRelativeCharacter
|
// Used for optimizing GetRelativeCharacter
|
||||||
Sci_PositionU posRelative;
|
Sci_PositionU posRelative = 0;
|
||||||
Sci_PositionU currentPosLastRelative;
|
Sci_PositionU currentPosLastRelative;
|
||||||
Sci_Position offsetRelative;
|
Sci_Position offsetRelative = 0;
|
||||||
|
|
||||||
void GetNextChar() {
|
void GetNextChar() {
|
||||||
if (multiByteAccess) {
|
if (multiByteAccess) {
|
||||||
chNext = multiByteAccess->GetCharacterAndWidth(currentPos+width, &widthNext);
|
chNext = multiByteAccess->GetCharacterAndWidth(currentPos+width, &widthNext);
|
||||||
} else {
|
} else {
|
||||||
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+width, 0));
|
chNext = static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+width, 0));
|
||||||
widthNext = 1;
|
|
||||||
}
|
}
|
||||||
// End of line determined from line end position, allowing CR, LF,
|
// End of line determined from line end position, allowing CR, LF,
|
||||||
// CRLF and Unicode line ends as set by document.
|
// CRLF and Unicode line ends as set by document.
|
||||||
@ -43,59 +43,19 @@ class StyleContext {
|
|||||||
public:
|
public:
|
||||||
Sci_PositionU currentPos;
|
Sci_PositionU currentPos;
|
||||||
Sci_Position currentLine;
|
Sci_Position currentLine;
|
||||||
Sci_Position lineDocEnd;
|
|
||||||
Sci_Position lineEnd;
|
Sci_Position lineEnd;
|
||||||
Sci_Position lineStartNext;
|
Sci_Position lineStartNext;
|
||||||
bool atLineStart;
|
bool atLineStart;
|
||||||
bool atLineEnd;
|
bool atLineEnd = false;
|
||||||
int state;
|
int state;
|
||||||
int chPrev;
|
int chPrev = 0;
|
||||||
int ch;
|
int ch = 0;
|
||||||
Sci_Position width;
|
Sci_Position width = 0;
|
||||||
int chNext;
|
int chNext = 0;
|
||||||
Sci_Position widthNext;
|
Sci_Position widthNext = 1;
|
||||||
|
|
||||||
StyleContext(Sci_PositionU startPos, Sci_PositionU length,
|
StyleContext(Sci_PositionU startPos, Sci_PositionU length,
|
||||||
int initStyle, LexAccessor &styler_, char chMask='\377') :
|
int initStyle, LexAccessor &styler_, char chMask = '\377');
|
||||||
styler(styler_),
|
|
||||||
multiByteAccess(nullptr),
|
|
||||||
endPos(startPos + length),
|
|
||||||
posRelative(0),
|
|
||||||
currentPosLastRelative(0x7FFFFFFF),
|
|
||||||
offsetRelative(0),
|
|
||||||
currentPos(startPos),
|
|
||||||
currentLine(-1),
|
|
||||||
lineEnd(-1),
|
|
||||||
lineStartNext(-1),
|
|
||||||
atLineEnd(false),
|
|
||||||
state(initStyle & chMask), // Mask off all bits which aren't in the chMask.
|
|
||||||
chPrev(0),
|
|
||||||
ch(0),
|
|
||||||
width(0),
|
|
||||||
chNext(0),
|
|
||||||
widthNext(1) {
|
|
||||||
if (styler.Encoding() != EncodingType::eightBit) {
|
|
||||||
multiByteAccess = styler.MultiByteAccess();
|
|
||||||
}
|
|
||||||
styler.StartAt(startPos /*, chMask*/);
|
|
||||||
styler.StartSegment(startPos);
|
|
||||||
currentLine = styler.GetLine(startPos);
|
|
||||||
lineEnd = styler.LineEnd(currentLine);
|
|
||||||
lineStartNext = styler.LineStart(currentLine+1);
|
|
||||||
lengthDocument = static_cast<Sci_PositionU>(styler.Length());
|
|
||||||
if (endPos == lengthDocument)
|
|
||||||
endPos++;
|
|
||||||
lineDocEnd = styler.GetLine(lengthDocument);
|
|
||||||
atLineStart = static_cast<Sci_PositionU>(styler.LineStart(currentLine)) == startPos;
|
|
||||||
|
|
||||||
// Variable width is now 0 so GetNextChar gets the char at currentPos into chNext/widthNext
|
|
||||||
width = 0;
|
|
||||||
GetNextChar();
|
|
||||||
ch = chNext;
|
|
||||||
width = widthNext;
|
|
||||||
|
|
||||||
GetNextChar();
|
|
||||||
}
|
|
||||||
// Deleted so StyleContext objects can not be copied.
|
// Deleted so StyleContext objects can not be copied.
|
||||||
StyleContext(const StyleContext &) = delete;
|
StyleContext(const StyleContext &) = delete;
|
||||||
StyleContext &operator=(const StyleContext &) = delete;
|
StyleContext &operator=(const StyleContext &) = delete;
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
|
|
||||||
// C++ wrappers of C standard library
|
// C++ wrappers of C standard library
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
|
#include <cstdint>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
rem Test lexers
|
rem Test lexers
|
||||||
rem build lexilla.dll and TestLexers.exe then run TestLexers.exe
|
rem build lexilla.dll and TestLexers.exe then run TestLexers.exe
|
||||||
cd ../src
|
cd ../src
|
||||||
make DEBUG=1
|
make --jobs=4 DEBUG=1
|
||||||
cd ../test
|
cd ../test
|
||||||
make DEBUG=1
|
make DEBUG=1
|
||||||
make test
|
make test
|
||||||
|
@ -1,7 +1,12 @@
|
|||||||
# Test lexers
|
# Test lexers
|
||||||
# build lexilla.so and TestLexers then run TestLexers
|
# build lexilla.so and TestLexers then run TestLexers
|
||||||
|
JOBS="--jobs=$(getconf _NPROCESSORS_ONLN)"
|
||||||
|
(
|
||||||
cd ../src
|
cd ../src
|
||||||
make DEBUG=1
|
make "$JOBS" DEBUG=1
|
||||||
|
)
|
||||||
|
(
|
||||||
cd ../test
|
cd ../test
|
||||||
make DEBUG=1
|
make DEBUG=1
|
||||||
make test
|
make test
|
||||||
|
)
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>5.1.5</string>
|
<string>5.1.6</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
@ -851,7 +851,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 5.1.5;
|
CURRENT_PROJECT_VERSION = 5.1.6;
|
||||||
DEVELOPMENT_TEAM = 4F446KW87E;
|
DEVELOPMENT_TEAM = 4F446KW87E;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 1;
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
@ -877,7 +877,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 5.1.5;
|
CURRENT_PROJECT_VERSION = 5.1.6;
|
||||||
DEVELOPMENT_TEAM = 4F446KW87E;
|
DEVELOPMENT_TEAM = 4F446KW87E;
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
DYLIB_CURRENT_VERSION = 1;
|
DYLIB_CURRENT_VERSION = 1;
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
||||||
<plist version="1.0">
|
|
||||||
<dict>
|
|
||||||
<key>IDEDidComputeMac32BitWarning</key>
|
|
||||||
<true/>
|
|
||||||
</dict>
|
|
||||||
</plist>
|
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#define VERSION_LEXILLA "5.1.5"
|
#define VERSION_LEXILLA "5.1.6"
|
||||||
#define VERSION_WORDS 5, 1, 5, 0
|
#define VERSION_WORDS 5, 1, 6, 0
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION VERSION_WORDS
|
FILEVERSION VERSION_WORDS
|
||||||
|
@ -100,8 +100,14 @@ Other settings are treated as lexer or folder properties and forwarded to the le
|
|||||||
|
|
||||||
It is often necessary to set 'fold' in SciTE.properties to cause folding.
|
It is often necessary to set 'fold' in SciTE.properties to cause folding.
|
||||||
|
|
||||||
If there is a need to test additional configurations of keywords or properties then
|
Properties can be set for a particular file with an "if $(=" or "match" expression like so:
|
||||||
create another subdirectory with the different settings in a new SciTE.properties.
|
if $(= $(FileNameExt);HeaderEOLFill_1.md)
|
||||||
|
lexer.markdown.header.eolfill=1
|
||||||
|
match Header*1.md
|
||||||
|
lexer.markdown.header.eolfill=1
|
||||||
|
|
||||||
|
More complex tests with additional configurations of keywords or properties can be performed
|
||||||
|
by creating another subdirectory with the different settings in a new SciTE.properties.
|
||||||
|
|
||||||
There is some support for running benchmarks on lexers and folders. The properties
|
There is some support for running benchmarks on lexers and folders. The properties
|
||||||
testlexers.repeat.lex and testlexers.repeat.fold specify the number of times example
|
testlexers.repeat.lex and testlexers.repeat.fold specify the number of times example
|
||||||
|
@ -40,6 +40,7 @@ namespace {
|
|||||||
};
|
};
|
||||||
|
|
||||||
int UnicodeFromUTF8(const unsigned char *us) noexcept {
|
int UnicodeFromUTF8(const unsigned char *us) noexcept {
|
||||||
|
assert(us);
|
||||||
switch (UTF8BytesOfLead[us[0]]) {
|
switch (UTF8BytesOfLead[us[0]]) {
|
||||||
case 1:
|
case 1:
|
||||||
return us[0];
|
return us[0];
|
||||||
@ -56,6 +57,56 @@ namespace {
|
|||||||
return (ch >= 0x80) && (ch < 0xc0);
|
return (ch >= 0x80) && (ch < 0xc0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
constexpr unsigned char TrailByteValue(unsigned char c) {
|
||||||
|
// The top 2 bits are 0b10 to indicate a trail byte.
|
||||||
|
// The lower 6 bits contain the value.
|
||||||
|
return c & 0b0011'1111;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::u32string UTF32FromUTF8(std::string_view svu8) {
|
||||||
|
std::u32string ret;
|
||||||
|
for (size_t i = 0; i < svu8.length();) {
|
||||||
|
unsigned char ch = svu8.at(i);
|
||||||
|
const unsigned int byteCount = UTF8BytesOfLead[ch];
|
||||||
|
unsigned int value = 0;
|
||||||
|
|
||||||
|
if (i + byteCount > svu8.length()) {
|
||||||
|
// Trying to read past end
|
||||||
|
ret.push_back(ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
|
switch (byteCount) {
|
||||||
|
case 1:
|
||||||
|
value = ch;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
value = (ch & 0x1F) << 6;
|
||||||
|
ch = svu8.at(i++);
|
||||||
|
value += TrailByteValue(ch);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
value = (ch & 0xF) << 12;
|
||||||
|
ch = svu8.at(i++);
|
||||||
|
value += TrailByteValue(ch) << 6;
|
||||||
|
ch = svu8.at(i++);
|
||||||
|
value += TrailByteValue(ch);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
value = (ch & 0x7) << 18;
|
||||||
|
ch = svu8.at(i++);
|
||||||
|
value += TrailByteValue(ch) << 12;
|
||||||
|
ch = svu8.at(i++);
|
||||||
|
value += TrailByteValue(ch) << 6;
|
||||||
|
ch = svu8.at(i++);
|
||||||
|
value += TrailByteValue(ch);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ret.push_back(value);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestDocument::Set(std::string_view sv) {
|
void TestDocument::Set(std::string_view sv) {
|
||||||
@ -65,7 +116,7 @@ void TestDocument::Set(std::string_view sv) {
|
|||||||
endStyled = 0;
|
endStyled = 0;
|
||||||
lineStarts.push_back(0);
|
lineStarts.push_back(0);
|
||||||
for (size_t pos = 0; pos < text.length(); pos++) {
|
for (size_t pos = 0; pos < text.length(); pos++) {
|
||||||
if (text[pos] == '\n') {
|
if (text.at(pos) == '\n') {
|
||||||
lineStarts.push_back(pos + 1);
|
lineStarts.push_back(pos + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,15 +196,16 @@ void SCI_METHOD TestDocument::StartStyling(Sci_Position position) {
|
|||||||
|
|
||||||
bool SCI_METHOD TestDocument::SetStyleFor(Sci_Position length, char style) {
|
bool SCI_METHOD TestDocument::SetStyleFor(Sci_Position length, char style) {
|
||||||
for (Sci_Position i = 0; i < length; i++) {
|
for (Sci_Position i = 0; i < length; i++) {
|
||||||
textStyles[endStyled] = style;
|
textStyles.at(endStyled) = style;
|
||||||
endStyled++;
|
endStyled++;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SCI_METHOD TestDocument::SetStyles(Sci_Position length, const char *styles) {
|
bool SCI_METHOD TestDocument::SetStyles(Sci_Position length, const char *styles) {
|
||||||
|
assert(styles);
|
||||||
for (Sci_Position i = 0; i < length; i++) {
|
for (Sci_Position i = 0; i < length; i++) {
|
||||||
textStyles[endStyled] = styles[i];
|
textStyles.at(endStyled) = styles[i];
|
||||||
endStyled++;
|
endStyled++;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -252,8 +304,9 @@ int SCI_METHOD TestDocument::GetCharacterAndWidth(Sci_Position position, Sci_Pos
|
|||||||
}
|
}
|
||||||
const int widthCharBytes = UTF8BytesOfLead[leadByte];
|
const int widthCharBytes = UTF8BytesOfLead[leadByte];
|
||||||
unsigned char charBytes[] = { leadByte,0,0,0 };
|
unsigned char charBytes[] = { leadByte,0,0,0 };
|
||||||
for (int b = 1; b < widthCharBytes; b++)
|
for (int b = 1; b < widthCharBytes; b++) {
|
||||||
charBytes[b] = text[position + b];
|
charBytes[b] = text.at(position + b);
|
||||||
|
}
|
||||||
|
|
||||||
if (pWidth) {
|
if (pWidth) {
|
||||||
*pWidth = widthCharBytes;
|
*pWidth = widthCharBytes;
|
||||||
|
@ -8,6 +8,8 @@
|
|||||||
#ifndef TESTDOCUMENT_H
|
#ifndef TESTDOCUMENT_H
|
||||||
#define TESTDOCUMENT_H
|
#define TESTDOCUMENT_H
|
||||||
|
|
||||||
|
std::u32string UTF32FromUTF8(std::string_view svu8);
|
||||||
|
|
||||||
class TestDocument : public Scintilla::IDocument {
|
class TestDocument : public Scintilla::IDocument {
|
||||||
std::string text;
|
std::string text;
|
||||||
std::string textStyles;
|
std::string textStyles;
|
||||||
|
@ -29,9 +29,233 @@
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
constexpr char MakeLowerCase(char c) noexcept {
|
||||||
|
if (c >= 'A' && c <= 'Z') {
|
||||||
|
return c - 'A' + 'a';
|
||||||
|
} else {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] void LowerCaseAZ(std::string &s) {
|
||||||
|
std::transform(s.begin(), s.end(), s.begin(), MakeLowerCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
int IntFromString(std::u32string_view s) noexcept {
|
||||||
|
if (s.empty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
const bool negate = s.front() == '-';
|
||||||
|
if (negate) {
|
||||||
|
s.remove_prefix(1);
|
||||||
|
}
|
||||||
|
int value = 0;
|
||||||
|
while (!s.empty()) {
|
||||||
|
value = value * 10 + s.front() - '0';
|
||||||
|
s.remove_prefix(1);
|
||||||
|
}
|
||||||
|
return negate ? -value : value;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PatternMatch(std::u32string_view pattern, std::u32string_view text) noexcept {
|
||||||
|
if (pattern == text) {
|
||||||
|
return true;
|
||||||
|
} else if (pattern.empty()) {
|
||||||
|
return false;
|
||||||
|
} else if (pattern.front() == '\\') {
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
if (pattern.empty()) {
|
||||||
|
// Escape with nothing being escaped
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (text.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pattern.front() == text.front()) {
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
text.remove_prefix(1);
|
||||||
|
return PatternMatch(pattern, text);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else if (pattern.front() == '*') {
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
if (!pattern.empty() && pattern.front() == '*') {
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
// "**" matches anything including "/"
|
||||||
|
while (!text.empty()) {
|
||||||
|
if (PatternMatch(pattern, text)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
text.remove_prefix(1);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (!text.empty()) {
|
||||||
|
if (PatternMatch(pattern, text)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (text.front() == '/') {
|
||||||
|
// "/" not matched by single "*"
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
text.remove_prefix(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(text.empty());
|
||||||
|
// Consumed whole text with wildcard so match if pattern consumed
|
||||||
|
return pattern.empty();
|
||||||
|
} else if (text.empty()) {
|
||||||
|
return false;
|
||||||
|
} else if (pattern.front() == '?') {
|
||||||
|
if (text.front() == '/') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
text.remove_prefix(1);
|
||||||
|
return PatternMatch(pattern, text);
|
||||||
|
} else if (pattern.front() == '[') {
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
if (pattern.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const bool positive = pattern.front() != '!';
|
||||||
|
if (!positive) {
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
if (pattern.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool inSet = false;
|
||||||
|
if (!pattern.empty() && pattern.front() == ']') {
|
||||||
|
// First is allowed to be ']'
|
||||||
|
if (pattern.front() == text.front()) {
|
||||||
|
inSet = true;
|
||||||
|
}
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
}
|
||||||
|
char32_t start = 0;
|
||||||
|
while (!pattern.empty() && pattern.front() != ']') {
|
||||||
|
if (pattern.front() == '-') {
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
if (!pattern.empty()) {
|
||||||
|
const char32_t end = pattern.front();
|
||||||
|
if ((text.front() >= start) && (text.front() <= end)) {
|
||||||
|
inSet = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (pattern.front() == text.front()) {
|
||||||
|
inSet = true;
|
||||||
|
}
|
||||||
|
if (!pattern.empty()) {
|
||||||
|
start = pattern.front();
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pattern.empty()) {
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
}
|
||||||
|
if (inSet != positive) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
text.remove_prefix(1);
|
||||||
|
return PatternMatch(pattern, text);
|
||||||
|
} else if (pattern.front() == '{') {
|
||||||
|
if (pattern.length() < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const size_t endParen = pattern.find('}');
|
||||||
|
if (endParen == std::u32string_view::npos) {
|
||||||
|
// Malformed {x} pattern
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::u32string_view parenExpression = pattern.substr(1, endParen - 1);
|
||||||
|
bool inSet = false;
|
||||||
|
const size_t dotdot = parenExpression.find(U"..");
|
||||||
|
if (dotdot != std::u32string_view::npos) {
|
||||||
|
// Numeric range: {10..20}
|
||||||
|
const std::u32string_view firstRange = parenExpression.substr(0, dotdot);
|
||||||
|
const std::u32string_view lastRange = parenExpression.substr(dotdot+2);
|
||||||
|
if (firstRange.empty() || lastRange.empty()) {
|
||||||
|
// Malformed {s..e} range pattern
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const size_t endInteger = text.find_last_of(U"-0123456789");
|
||||||
|
if (endInteger == std::u32string_view::npos) {
|
||||||
|
// No integer in text
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const std::u32string_view intPart = text.substr(0, endInteger+1);
|
||||||
|
const int first = IntFromString(firstRange);
|
||||||
|
const int last = IntFromString(lastRange);
|
||||||
|
const int value = IntFromString(intPart);
|
||||||
|
if ((value >= first) && (value <= last)) {
|
||||||
|
inSet = true;
|
||||||
|
text.remove_prefix(intPart.length());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Alternates: {a,b,cd}
|
||||||
|
size_t comma = parenExpression.find(',');
|
||||||
|
for (;;) {
|
||||||
|
const bool finalAlt = comma == std::u32string_view::npos;
|
||||||
|
const std::u32string_view oneAlt = finalAlt ? parenExpression :
|
||||||
|
parenExpression.substr(0, comma);
|
||||||
|
if (oneAlt == text.substr(0, oneAlt.length())) {
|
||||||
|
// match
|
||||||
|
inSet = true;
|
||||||
|
text.remove_prefix(oneAlt.length());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (finalAlt) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parenExpression.remove_prefix(oneAlt.length() + 1);
|
||||||
|
comma = parenExpression.find(',');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!inSet) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
pattern.remove_prefix(endParen + 1);
|
||||||
|
return PatternMatch(pattern, text);
|
||||||
|
} else if (pattern.front() == text.front()) {
|
||||||
|
pattern.remove_prefix(1);
|
||||||
|
text.remove_prefix(1);
|
||||||
|
return PatternMatch(pattern, text);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool PathMatch(std::string pattern, std::string relPath) {
|
||||||
|
#if defined(_WIN32)
|
||||||
|
// Convert Windows path separators to Unix
|
||||||
|
std::replace(relPath.begin(), relPath.end(), '\\', '/');
|
||||||
|
#endif
|
||||||
|
#if defined(_WIN32) || defined(__APPLE__)
|
||||||
|
// Case-insensitive, only does ASCII but fine for test example files
|
||||||
|
LowerCaseAZ(pattern);
|
||||||
|
LowerCaseAZ(relPath);
|
||||||
|
#endif
|
||||||
|
const std::u32string patternU32 = UTF32FromUTF8(pattern);
|
||||||
|
const std::u32string relPathU32 = UTF32FromUTF8(relPath);
|
||||||
|
if (PatternMatch(patternU32, relPathU32)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const size_t lastSlash = relPathU32.rfind('/');
|
||||||
|
if (lastSlash == std::string::npos) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Match against just filename
|
||||||
|
const std::u32string fileNameU32 = relPathU32.substr(lastSlash+1);
|
||||||
|
return PatternMatch(patternU32, fileNameU32);
|
||||||
|
}
|
||||||
|
|
||||||
constexpr std::string_view suffixStyled = ".styled";
|
constexpr std::string_view suffixStyled = ".styled";
|
||||||
constexpr std::string_view suffixFolded = ".folded";
|
constexpr std::string_view suffixFolded = ".folded";
|
||||||
|
|
||||||
|
constexpr std::string_view prefixIf = "if ";
|
||||||
|
constexpr std::string_view prefixMatch = "match ";
|
||||||
|
constexpr std::string_view prefixEqual = "= ";
|
||||||
|
constexpr std::string_view prefixComment = "#";
|
||||||
|
|
||||||
std::string ReadFile(std::filesystem::path path) {
|
std::string ReadFile(std::filesystem::path path) {
|
||||||
std::ifstream ifs(path, std::ios::binary);
|
std::ifstream ifs(path, std::ios::binary);
|
||||||
std::string content((std::istreambuf_iterator<char>(ifs)),
|
std::string content((std::istreambuf_iterator<char>(ifs)),
|
||||||
@ -40,6 +264,7 @@ std::string ReadFile(std::filesystem::path path) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string MarkedDocument(const Scintilla::IDocument *pdoc) {
|
std::string MarkedDocument(const Scintilla::IDocument *pdoc) {
|
||||||
|
assert(pdoc);
|
||||||
std::ostringstream os(std::ios::binary);
|
std::ostringstream os(std::ios::binary);
|
||||||
char prevStyle = -1;
|
char prevStyle = -1;
|
||||||
for (Sci_Position pos = 0; pos < pdoc->Length(); pos++) {
|
for (Sci_Position pos = 0; pos < pdoc->Length(); pos++) {
|
||||||
@ -71,6 +296,7 @@ void PrintLevel(std::ostringstream &os, int level) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string FoldedDocument(const Scintilla::IDocument *pdoc) {
|
std::string FoldedDocument(const Scintilla::IDocument *pdoc) {
|
||||||
|
assert(pdoc);
|
||||||
std::ostringstream os(std::ios::binary);
|
std::ostringstream os(std::ios::binary);
|
||||||
Sci_Position linePrev = -1;
|
Sci_Position linePrev = -1;
|
||||||
char ch = '\0';
|
char ch = '\0';
|
||||||
@ -94,12 +320,115 @@ std::pair<std::string, std::string> MarkedAndFoldedDocument(const Scintilla::IDo
|
|||||||
return { MarkedDocument(pdoc), FoldedDocument(pdoc) };
|
return { MarkedDocument(pdoc), FoldedDocument(pdoc) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> StringSplit(const std::string_view &text, int separator) {
|
||||||
|
std::vector<std::string> vs(text.empty() ? 0 : 1);
|
||||||
|
for (std::string_view::const_iterator it = text.begin(); it != text.end(); ++it) {
|
||||||
|
if (*it == separator) {
|
||||||
|
vs.push_back(std::string());
|
||||||
|
} else {
|
||||||
|
vs.back() += *it;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static constexpr bool IsSpaceOrTab(char ch) noexcept {
|
||||||
|
return (ch == ' ') || (ch == '\t');
|
||||||
|
}
|
||||||
|
|
||||||
class PropertyMap {
|
class PropertyMap {
|
||||||
|
|
||||||
|
std::string Evaluate(std::string_view text) {
|
||||||
|
if (text.find(' ') != std::string_view::npos) {
|
||||||
|
if (text.starts_with(prefixEqual)) {
|
||||||
|
const std::string_view sExpressions = text.substr(prefixEqual.length());
|
||||||
|
std::vector<std::string> parts = StringSplit(sExpressions, ';');
|
||||||
|
if (parts.size() > 1) {
|
||||||
|
for (size_t part = 1; part < parts.size(); part++) {
|
||||||
|
if (parts.at(part) != parts.at(0)) {
|
||||||
|
return "0";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
} else {
|
||||||
|
std::optional<std::string> value = GetProperty(text);
|
||||||
|
if (value) {
|
||||||
|
return *value;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Expand(std::string withVars) {
|
||||||
|
constexpr size_t maxVars = 100;
|
||||||
|
size_t varStart = withVars.rfind("$(");
|
||||||
|
for (size_t count = 0; (count < maxVars) && (varStart != std::string::npos); count++) {
|
||||||
|
const size_t varEnd = withVars.find(')', varStart + 2);
|
||||||
|
if (varEnd == std::string::npos) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string_view whole = withVars;
|
||||||
|
const std::string_view var = whole.substr(varStart + 2, varEnd - (varStart + 2));
|
||||||
|
const std::string val = Evaluate(var);
|
||||||
|
|
||||||
|
withVars.erase(varStart, varEnd - varStart + 1);
|
||||||
|
withVars.insert(varStart, val);
|
||||||
|
|
||||||
|
varStart = withVars.rfind("$(");
|
||||||
|
}
|
||||||
|
return withVars;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProcessLine(std::string_view text, bool ifIsTrue) {
|
||||||
|
// If clause ends with first non-indented line
|
||||||
|
if (!ifIsTrue && (text.empty() || IsSpaceOrTab(text.at(0)))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ifIsTrue = true;
|
||||||
|
if (text.starts_with(prefixIf)) {
|
||||||
|
const std::string value = Expand(std::string(text.substr(prefixIf.length())));
|
||||||
|
if (value == "0" || value == "") {
|
||||||
|
ifIsTrue = false;
|
||||||
|
}
|
||||||
|
} else if (text.starts_with(prefixMatch)) {
|
||||||
|
std::optional<std::string> fileNameExt = GetProperty("FileNameExt");
|
||||||
|
if (fileNameExt) {
|
||||||
|
std::string pattern(text.substr(prefixMatch.length()));
|
||||||
|
// Remove trailing white space
|
||||||
|
while (!pattern.empty() && IsSpaceOrTab(pattern.back())) {
|
||||||
|
pattern.pop_back();
|
||||||
|
}
|
||||||
|
ifIsTrue = PathMatch(pattern, *fileNameExt);
|
||||||
|
} else {
|
||||||
|
ifIsTrue = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while (!text.empty() && IsSpaceOrTab(text.at(0))) {
|
||||||
|
text.remove_prefix(1);
|
||||||
|
}
|
||||||
|
if (text.starts_with(prefixComment)) {
|
||||||
|
return ifIsTrue;
|
||||||
|
}
|
||||||
|
const size_t positionEquals = text.find("=");
|
||||||
|
if (positionEquals != std::string::npos) {
|
||||||
|
const std::string key(text.substr(0, positionEquals));
|
||||||
|
const std::string_view value = text.substr(positionEquals + 1);
|
||||||
|
properties[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ifIsTrue;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using PropMap = std::map<std::string, std::string>;
|
using PropMap = std::map<std::string, std::string>;
|
||||||
PropMap properties;
|
PropMap properties;
|
||||||
|
|
||||||
void ReadFromFile(std::filesystem::path path) {
|
void ReadFromFile(std::filesystem::path path) {
|
||||||
|
bool ifIsTrue = true;
|
||||||
std::ifstream ifs(path);
|
std::ifstream ifs(path);
|
||||||
std::string line;
|
std::string line;
|
||||||
std::string logicalLine;
|
std::string logicalLine;
|
||||||
@ -112,12 +441,7 @@ public:
|
|||||||
if (logicalLine.ends_with("\\")) {
|
if (logicalLine.ends_with("\\")) {
|
||||||
logicalLine.pop_back();
|
logicalLine.pop_back();
|
||||||
} else {
|
} else {
|
||||||
const size_t positionEquals = logicalLine.find("=");
|
ifIsTrue = ProcessLine(logicalLine, ifIsTrue);
|
||||||
if (positionEquals != std::string::npos) {
|
|
||||||
const std::string key = logicalLine.substr(0, positionEquals);
|
|
||||||
const std::string value = logicalLine.substr(positionEquals + 1);
|
|
||||||
properties[key] = value;
|
|
||||||
}
|
|
||||||
logicalLine.clear();
|
logicalLine.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -171,7 +495,8 @@ bool CheckSame(std::string_view augmentedText, std::string_view augmentedTextNew
|
|||||||
}
|
}
|
||||||
const size_t lineNumber = FirstLineDifferent(augmentedText, augmentedTextNew) + 1;
|
const size_t lineNumber = FirstLineDifferent(augmentedText, augmentedTextNew) + 1;
|
||||||
std::cout << "\n" << path.string() << ":" << lineNumber << ":";
|
std::cout << "\n" << path.string() << ":" << lineNumber << ":";
|
||||||
std::cout << " has different " << item << "\n\n";
|
const std::string differenceType = augmentedText.empty() ? "new" : "different";
|
||||||
|
std::cout << " has " << differenceType << " " << item << "\n\n";
|
||||||
std::filesystem::path pathNew = path;
|
std::filesystem::path pathNew = path;
|
||||||
pathNew += suffix;
|
pathNew += suffix;
|
||||||
pathNew += ".new";
|
pathNew += ".new";
|
||||||
@ -204,6 +529,7 @@ int UnixToWindows(std::string &s) {
|
|||||||
const std::string BOM = "\xEF\xBB\xBF";
|
const std::string BOM = "\xEF\xBB\xBF";
|
||||||
|
|
||||||
void StyleLineByLine(TestDocument &doc, Scintilla::ILexer5 *plex) {
|
void StyleLineByLine(TestDocument &doc, Scintilla::ILexer5 *plex) {
|
||||||
|
assert(plex);
|
||||||
Scintilla::IDocument *pdoc = &doc;
|
Scintilla::IDocument *pdoc = &doc;
|
||||||
const Sci_Position lines = doc.LineFromPosition(doc.Length());
|
const Sci_Position lines = doc.LineFromPosition(doc.Length());
|
||||||
Sci_Position startLine = 0;
|
Sci_Position startLine = 0;
|
||||||
@ -218,7 +544,8 @@ void StyleLineByLine(TestDocument &doc, Scintilla::ILexer5 *plex) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestCRLF(std::filesystem::path path, const std::string s, Scintilla::ILexer5 *plex, bool disablePerLineTests) {
|
bool TestCRLF(std::filesystem::path path, const std::string s, Scintilla::ILexer5 *plex, bool disablePerLineTests) {
|
||||||
|
bool success = true;
|
||||||
// Convert all line ends to \r\n to check if styles change between \r and \n which makes
|
// Convert all line ends to \r\n to check if styles change between \r and \n which makes
|
||||||
// it difficult to test on different platforms when files may have line ends changed.
|
// it difficult to test on different platforms when files may have line ends changed.
|
||||||
std::string text = s;
|
std::string text = s;
|
||||||
@ -244,6 +571,7 @@ void TestCRLF(std::filesystem::path path, const std::string s, Scintilla::ILexer
|
|||||||
std::cout << path.string() << ":" << line << ":" <<
|
std::cout << path.string() << ":" << line << ":" <<
|
||||||
" different styles between \\r and \\n at " <<
|
" different styles between \\r and \\n at " <<
|
||||||
pos << ": " << prevStyle << ", " << styleNow << "\n";
|
pos << ": " << prevStyle << ", " << styleNow << "\n";
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
line++;
|
line++;
|
||||||
}
|
}
|
||||||
@ -265,9 +593,11 @@ void TestCRLF(std::filesystem::path path, const std::string s, Scintilla::ILexer
|
|||||||
|
|
||||||
if (styledText != styledTextUnix) {
|
if (styledText != styledTextUnix) {
|
||||||
std::cout << "\n" << path.string() << ":1: has different styles with \\n versus \\r\\n line ends\n\n";
|
std::cout << "\n" << path.string() << ":1: has different styles with \\n versus \\r\\n line ends\n\n";
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
if (foldedText != foldedTextUnix) {
|
if (foldedText != foldedTextUnix) {
|
||||||
std::cout << "\n" << path.string() << ":1: has different folds with \\n versus \\r\\n line ends\n\n";
|
std::cout << "\n" << path.string() << ":1: has different folds with \\n versus \\r\\n line ends\n\n";
|
||||||
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test line by line lexing/folding with Unix \n line ends
|
// Test line by line lexing/folding with Unix \n line ends
|
||||||
@ -277,14 +607,21 @@ void TestCRLF(std::filesystem::path path, const std::string s, Scintilla::ILexer
|
|||||||
// Convert results from \n to \r\n run
|
// Convert results from \n to \r\n run
|
||||||
UnixToWindows(styledTextNewPerLine);
|
UnixToWindows(styledTextNewPerLine);
|
||||||
UnixToWindows(foldedTextNewPerLine);
|
UnixToWindows(foldedTextNewPerLine);
|
||||||
CheckSame(styledTextUnix, styledTextNewPerLine, "per-line styles \\n", suffixStyled, path);
|
if (!CheckSame(styledTextUnix, styledTextNewPerLine, "per-line styles \\n", suffixStyled, path)) {
|
||||||
CheckSame(foldedTextUnix, foldedTextNewPerLine, "per-line folds \\n", suffixFolded, path);
|
success = false;
|
||||||
|
}
|
||||||
|
if (!CheckSame(foldedTextUnix, foldedTextNewPerLine, "per-line folds \\n", suffixFolded, path)) {
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
plex->Release();
|
plex->Release();
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestILexer(Scintilla::ILexer5 *plex) {
|
void TestILexer(Scintilla::ILexer5 *plex) {
|
||||||
|
assert(plex);
|
||||||
|
|
||||||
// Test each method of the ILexer interface.
|
// Test each method of the ILexer interface.
|
||||||
// Mostly ensures there are no crashes when calling methods.
|
// Mostly ensures there are no crashes when calling methods.
|
||||||
// Some methods are tested later (Release, Lex, Fold).
|
// Some methods are tested later (Release, Lex, Fold).
|
||||||
@ -320,11 +657,11 @@ void TestILexer(Scintilla::ILexer5 *plex) {
|
|||||||
[[maybe_unused]] const int lineEndTypes = plex->LineEndTypesSupported();
|
[[maybe_unused]] const int lineEndTypes = plex->LineEndTypesSupported();
|
||||||
assert(lineEndTypes == 0 || lineEndTypes == 1);
|
assert(lineEndTypes == 0 || lineEndTypes == 1);
|
||||||
|
|
||||||
if (const char *bases = plex->GetSubStyleBases()) {
|
if (std::string_view bases = plex->GetSubStyleBases(); !bases.empty()) {
|
||||||
// Allocate a substyle for each possible style
|
// Allocate a substyle for each possible style
|
||||||
while (*bases) {
|
while (!bases.empty()) {
|
||||||
constexpr int newStyles = 3;
|
constexpr int newStyles = 3;
|
||||||
const int base = *bases;
|
const int base = bases.front();
|
||||||
const int baseStyle = plex->AllocateSubStyles(base, newStyles);
|
const int baseStyle = plex->AllocateSubStyles(base, newStyles);
|
||||||
[[maybe_unused]] const int styleBack = plex->StyleFromSubStyle(baseStyle);
|
[[maybe_unused]] const int styleBack = plex->StyleFromSubStyle(baseStyle);
|
||||||
assert(styleBack == base);
|
assert(styleBack == base);
|
||||||
@ -333,7 +670,7 @@ void TestILexer(Scintilla::ILexer5 *plex) {
|
|||||||
assert(start == baseStyle);
|
assert(start == baseStyle);
|
||||||
[[maybe_unused]] const int len = plex->SubStylesLength(base);
|
[[maybe_unused]] const int len = plex->SubStylesLength(base);
|
||||||
assert(len == newStyles);
|
assert(len == newStyles);
|
||||||
bases++;
|
bases.remove_prefix(1);
|
||||||
}
|
}
|
||||||
plex->FreeSubStyles();
|
plex->FreeSubStyles();
|
||||||
}
|
}
|
||||||
@ -359,6 +696,8 @@ void TestILexer(Scintilla::ILexer5 *plex) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SetProperties(Scintilla::ILexer5 *plex, const PropertyMap &propertyMap, std::string_view fileName) {
|
void SetProperties(Scintilla::ILexer5 *plex, const PropertyMap &propertyMap, std::string_view fileName) {
|
||||||
|
assert(plex);
|
||||||
|
|
||||||
// Set keywords, keywords2, ... keywords9, for this file
|
// Set keywords, keywords2, ... keywords9, for this file
|
||||||
for (int kw = 0; kw < 10; kw++) {
|
for (int kw = 0; kw < 10; kw++) {
|
||||||
std::string kwChoice("keywords");
|
std::string kwChoice("keywords");
|
||||||
@ -374,9 +713,7 @@ void SetProperties(Scintilla::ILexer5 *plex, const PropertyMap &propertyMap, std
|
|||||||
|
|
||||||
// Set parameters of lexer
|
// Set parameters of lexer
|
||||||
for (auto const &[key, val] : propertyMap.properties) {
|
for (auto const &[key, val] : propertyMap.properties) {
|
||||||
if (key.starts_with("#")) {
|
if (key.starts_with("lexer.*")) {
|
||||||
// Ignore comments
|
|
||||||
} else if (key.starts_with("lexer.*")) {
|
|
||||||
// Ignore as processed earlier
|
// Ignore as processed earlier
|
||||||
} else if (key.starts_with("keywords")) {
|
} else if (key.starts_with("keywords")) {
|
||||||
// Ignore as processed earlier
|
// Ignore as processed earlier
|
||||||
@ -455,16 +792,16 @@ bool TestFile(const std::filesystem::path &path, const PropertyMap &propertyMap)
|
|||||||
|
|
||||||
plex->Release();
|
plex->Release();
|
||||||
|
|
||||||
|
if (success) {
|
||||||
Scintilla::ILexer5 *plexCRLF = Lexilla::MakeLexer(*language);
|
Scintilla::ILexer5 *plexCRLF = Lexilla::MakeLexer(*language);
|
||||||
SetProperties(plexCRLF, propertyMap, path.filename().string());
|
SetProperties(plexCRLF, propertyMap, path.filename().string());
|
||||||
TestCRLF(path, text, plexCRLF, disablePerLineTests);
|
success = TestCRLF(path, text, plexCRLF, disablePerLineTests);
|
||||||
|
}
|
||||||
|
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TestDirectory(std::filesystem::path directory, std::filesystem::path basePath) {
|
bool TestDirectory(std::filesystem::path directory, std::filesystem::path basePath) {
|
||||||
PropertyMap properties;
|
|
||||||
properties.ReadFromFile(directory / "SciTE.properties");
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
for (auto &p : std::filesystem::directory_iterator(directory)) {
|
for (auto &p : std::filesystem::directory_iterator(directory)) {
|
||||||
if (!p.is_directory()) {
|
if (!p.is_directory()) {
|
||||||
@ -473,6 +810,9 @@ bool TestDirectory(std::filesystem::path directory, std::filesystem::path basePa
|
|||||||
extension != suffixFolded) {
|
extension != suffixFolded) {
|
||||||
const std::filesystem::path relativePath = p.path().lexically_relative(basePath);
|
const std::filesystem::path relativePath = p.path().lexically_relative(basePath);
|
||||||
std::cout << "Lexing " << relativePath.string() << '\n';
|
std::cout << "Lexing " << relativePath.string() << '\n';
|
||||||
|
PropertyMap properties;
|
||||||
|
properties.properties["FileNameExt"] = p.path().filename().string();
|
||||||
|
properties.ReadFromFile(directory / "SciTE.properties");
|
||||||
if (!TestFile(p, properties)) {
|
if (!TestFile(p, properties)) {
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,9 @@
|
|||||||
code.page=65001
|
code.page=65001
|
||||||
lexer.*.md=markdown
|
lexer.*.md=markdown
|
||||||
fold=1
|
fold=1
|
||||||
|
|
||||||
|
# Tests for the lexer.markdown.header.eolfill property, issue #62
|
||||||
|
if $(= $(FileNameExt);HeaderEOLFill_0.md)
|
||||||
|
lexer.markdown.header.eolfill=0
|
||||||
|
if $(= $(FileNameExt);HeaderEOLFill_1.md)
|
||||||
|
lexer.markdown.header.eolfill=1
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
lexer.*.rb=ruby
|
lexer.*.rb=ruby
|
||||||
keywords.*.rb=class def end
|
keywords.*.rb=begin class def do end if module return self super true while \
|
||||||
|
__FILE__ __LINE__
|
||||||
fold=1
|
fold=1
|
||||||
|
@ -3,4 +3,4 @@
|
|||||||
0 402 0 | i = 1
|
0 402 0 | i = 1
|
||||||
0 402 0 | puts "Example"
|
0 402 0 | puts "Example"
|
||||||
0 402 0 | end
|
0 402 0 | end
|
||||||
0 400 0 end
|
0 401 0 | end
|
@ -1 +1 @@
|
|||||||
515
|
516
|
@ -96,8 +96,7 @@ char ScintillaCall::CharacterAt(Position position) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int ScintillaCall::UnsignedStyleAt(Position position) {
|
int ScintillaCall::UnsignedStyleAt(Position position) {
|
||||||
// Returns signed value but easier to use as unsigned
|
return static_cast<int>(Call(Message::GetStyleIndexAt, position));
|
||||||
return static_cast<unsigned char>(Call(Message::GetStyleAt, position));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ScintillaCall::StringOfSpan(Span span) {
|
std::string ScintillaCall::StringOfSpan(Span span) {
|
||||||
@ -192,6 +191,10 @@ int ScintillaCall::StyleAt(Position pos) {
|
|||||||
return static_cast<int>(Call(Message::GetStyleAt, pos));
|
return static_cast<int>(Call(Message::GetStyleAt, pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int ScintillaCall::StyleIndexAt(Position pos) {
|
||||||
|
return static_cast<int>(Call(Message::GetStyleIndexAt, pos));
|
||||||
|
}
|
||||||
|
|
||||||
void ScintillaCall::Redo() {
|
void ScintillaCall::Redo() {
|
||||||
Call(Message::Redo);
|
Call(Message::Redo);
|
||||||
}
|
}
|
||||||
|
@ -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.1</string>
|
<string>5.2.2</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(CURRENT_PROJECT_VERSION)</string>
|
<string>$(CURRENT_PROJECT_VERSION)</string>
|
||||||
<key>NSHumanReadableCopyright</key>
|
<key>NSHumanReadableCopyright</key>
|
||||||
|
@ -565,7 +565,7 @@
|
|||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 5.2.1;
|
CURRENT_PROJECT_VERSION = 5.2.2;
|
||||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
@ -627,7 +627,7 @@
|
|||||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
CURRENT_PROJECT_VERSION = 5.2.1;
|
CURRENT_PROJECT_VERSION = 5.2.2;
|
||||||
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;
|
||||||
@ -657,7 +657,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "-";
|
CODE_SIGN_IDENTITY = "-";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 5.2.1;
|
CURRENT_PROJECT_VERSION = 5.2.2;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
@ -691,7 +691,7 @@
|
|||||||
CODE_SIGN_IDENTITY = "-";
|
CODE_SIGN_IDENTITY = "-";
|
||||||
CODE_SIGN_STYLE = Manual;
|
CODE_SIGN_STYLE = Manual;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 5.2.1;
|
CURRENT_PROJECT_VERSION = 5.2.2;
|
||||||
DEFINES_MODULE = YES;
|
DEFINES_MODULE = YES;
|
||||||
DEVELOPMENT_TEAM = "";
|
DEVELOPMENT_TEAM = "";
|
||||||
DYLIB_COMPATIBILITY_VERSION = 1;
|
DYLIB_COMPATIBILITY_VERSION = 1;
|
||||||
|
@ -1100,7 +1100,7 @@ void ScintillaCocoa::CTPaint(void *gc, NSRect rc) {
|
|||||||
#pragma unused(rc)
|
#pragma unused(rc)
|
||||||
std::unique_ptr<Surface> surfaceWindow(Surface::Allocate(Technology::Default));
|
std::unique_ptr<Surface> surfaceWindow(Surface::Allocate(Technology::Default));
|
||||||
surfaceWindow->Init(gc, wMain.GetID());
|
surfaceWindow->Init(gc, wMain.GetID());
|
||||||
surfaceWindow->SetMode(SurfaceMode(ct.codePage, BidirectionalR2L()));
|
surfaceWindow->SetMode(CurrentSurfaceMode());
|
||||||
ct.PaintCT(surfaceWindow.get());
|
ct.PaintCT(surfaceWindow.get());
|
||||||
surfaceWindow->Release();
|
surfaceWindow->Release();
|
||||||
}
|
}
|
||||||
@ -1456,7 +1456,7 @@ void ScintillaCocoa::StartDrag() {
|
|||||||
|
|
||||||
// To get a bitmap of the text we're dragging, we just use Paint on a pixmap surface.
|
// To get a bitmap of the text we're dragging, we just use Paint on a pixmap surface.
|
||||||
SurfaceImpl si;
|
SurfaceImpl si;
|
||||||
si.SetMode(SurfaceMode(CodePage(), BidirectionalR2L()));
|
si.SetMode(CurrentSurfaceMode());
|
||||||
std::unique_ptr<SurfaceImpl> sw = si.AllocatePixMapImplementation(static_cast<int>(client.Width()), static_cast<int>(client.Height()));
|
std::unique_ptr<SurfaceImpl> sw = si.AllocatePixMapImplementation(static_cast<int>(client.Width()), static_cast<int>(client.Height()));
|
||||||
|
|
||||||
const bool lastHideSelection = view.hideSelection;
|
const bool lastHideSelection = view.hideSelection;
|
||||||
|
@ -129,7 +129,7 @@
|
|||||||
|
|
||||||
<h1>Scintilla Documentation</h1>
|
<h1>Scintilla Documentation</h1>
|
||||||
|
|
||||||
<p>Last edited 2 February 2021 NH</p>
|
<p>Last edited 9 March 2022 NH</p>
|
||||||
|
|
||||||
<p style="background:#90F0C0">Scintilla 5 has moved the lexers from Scintilla into a new
|
<p style="background:#90F0C0">Scintilla 5 has moved the lexers from Scintilla into a new
|
||||||
<a href="Lexilla.html">Lexilla</a> project.<br />
|
<a href="Lexilla.html">Lexilla</a> project.<br />
|
||||||
@ -543,6 +543,7 @@
|
|||||||
<a class="message" href="#SCI_CLEARDOCUMENTSTYLE">SCI_CLEARDOCUMENTSTYLE</a><br />
|
<a class="message" href="#SCI_CLEARDOCUMENTSTYLE">SCI_CLEARDOCUMENTSTYLE</a><br />
|
||||||
<a class="message" href="#SCI_GETCHARAT">SCI_GETCHARAT(position pos) → int</a><br />
|
<a class="message" href="#SCI_GETCHARAT">SCI_GETCHARAT(position pos) → int</a><br />
|
||||||
<a class="message" href="#SCI_GETSTYLEAT">SCI_GETSTYLEAT(position pos) → int</a><br />
|
<a class="message" href="#SCI_GETSTYLEAT">SCI_GETSTYLEAT(position pos) → int</a><br />
|
||||||
|
<a class="message" href="#SCI_GETSTYLEINDEXAT">SCI_GETSTYLEINDEXAT(position pos) → int</a><br />
|
||||||
<a class="message" href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT(<unused>, Sci_TextRange *tr) → position</a><br />
|
<a class="message" href="#SCI_GETSTYLEDTEXT">SCI_GETSTYLEDTEXT(<unused>, Sci_TextRange *tr) → position</a><br />
|
||||||
<a class="message" href="#SCI_RELEASEALLEXTENDEDSTYLES">SCI_RELEASEALLEXTENDEDSTYLES</a><br />
|
<a class="message" href="#SCI_RELEASEALLEXTENDEDSTYLES">SCI_RELEASEALLEXTENDEDSTYLES</a><br />
|
||||||
<a class="message" href="#SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES(int numberStyles) → int</a><br />
|
<a class="message" href="#SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES(int numberStyles) → int</a><br />
|
||||||
@ -694,9 +695,15 @@
|
|||||||
This returns the character at <code class="parameter">pos</code> in the document or 0 if <code class="parameter">pos</code> is
|
This returns the character at <code class="parameter">pos</code> in the document or 0 if <code class="parameter">pos</code> is
|
||||||
negative or past the end of the document.</p>
|
negative or past the end of the document.</p>
|
||||||
|
|
||||||
<p><b id="SCI_GETSTYLEAT">SCI_GETSTYLEAT(position pos) → int</b><br />
|
<p>
|
||||||
|
<b id="SCI_GETSTYLEAT">SCI_GETSTYLEAT(position pos) → int</b><br />
|
||||||
|
<b id="SCI_GETSTYLEINDEXAT">SCI_GETSTYLEINDEXAT(position pos) → int</b><br />
|
||||||
This returns the style at <code class="parameter">pos</code> in the document, or 0 if <code class="parameter">pos</code> is
|
This returns the style at <code class="parameter">pos</code> in the document, or 0 if <code class="parameter">pos</code> is
|
||||||
negative or past the end of the document.</p>
|
negative or past the end of the document.
|
||||||
|
<code>SCI_GETSTYLEAT</code> may return a negative number for styles over 127 whereas <code>SCI_GETSTYLEINDEXAT</code>
|
||||||
|
will only return positive numbers.
|
||||||
|
<code>SCI_GETSTYLEINDEXAT</code> should be preferred as it handles styles more consistently and may avoid problems
|
||||||
|
with lexers that define more than 128 styles.</p>
|
||||||
|
|
||||||
<p><b id="SCI_RELEASEALLEXTENDEDSTYLES">SCI_RELEASEALLEXTENDEDSTYLES</b><br />
|
<p><b id="SCI_RELEASEALLEXTENDEDSTYLES">SCI_RELEASEALLEXTENDEDSTYLES</b><br />
|
||||||
<b id="SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES(int numberStyles) → int</b><br />
|
<b id="SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES(int numberStyles) → int</b><br />
|
||||||
|
@ -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/scintilla521.zip">
|
<font size="4"> <a href="https://www.scintilla.org/scintilla522.zip">
|
||||||
Windows</a>
|
Windows</a>
|
||||||
<a href="https://www.scintilla.org/scintilla521.tgz">
|
<a href="https://www.scintilla.org/scintilla522.tgz">
|
||||||
GTK/Linux</a>
|
GTK/Linux</a>
|
||||||
</font>
|
</font>
|
||||||
</td>
|
</td>
|
||||||
@ -42,7 +42,7 @@
|
|||||||
containing very few restrictions.
|
containing very few restrictions.
|
||||||
</p>
|
</p>
|
||||||
<h3>
|
<h3>
|
||||||
Release 5.2.1
|
Release 5.2.2
|
||||||
</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/scintilla521.zip">zip format</a> (1.3M) commonly used on Windows</li>
|
<li><a href="https://www.scintilla.org/scintilla522.zip">zip format</a> (1.3M) commonly used on Windows</li>
|
||||||
<li><a href="https://www.scintilla.org/scintilla521.tgz">tgz format</a> (1.2M) commonly used on Linux and compatible operating systems</li>
|
<li><a href="https://www.scintilla.org/scintilla522.tgz">tgz format</a> (1.2M) commonly used on Linux and compatible operating systems</li>
|
||||||
</ul>
|
</ul>
|
||||||
Instructions for building on both Windows and Linux are included in the readme file.
|
Instructions for building on both Windows and Linux are included in the readme file.
|
||||||
<h4>
|
<h4>
|
||||||
|
@ -569,9 +569,37 @@
|
|||||||
</tr><tr>
|
</tr><tr>
|
||||||
<td>Arkadiusz Michalski</td>
|
<td>Arkadiusz Michalski</td>
|
||||||
<td>Christian Schmitz</td>
|
<td>Christian Schmitz</td>
|
||||||
|
<td>Michael Berlenz</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<h2>Releases</h2>
|
<h2>Releases</h2>
|
||||||
|
<h3>
|
||||||
|
<a href="https://www.scintilla.org/scintilla522.zip">Release 5.2.2</a>
|
||||||
|
</h3>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
Released 31 March 2022.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Add SCI_GETSTYLEINDEXAT API to return styles over 127 as positive integers.
|
||||||
|
<a href="https://sourceforge.net/p/scintilla/feature-requests/1431/">Feature #1431</a>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
On GTK, scroll horizontally with shift + scroll wheel.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Fix crash with unexpected right-to-left text on GTK.
|
||||||
|
<a href="https://sourceforge.net/p/scintilla/bugs/2309/">Bug #2309</a>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
Fix position of end-of-line annotation when fold display text is visible.
|
||||||
|
<a href="https://sourceforge.net/p/scintilla/bugs/2320/">Bug #2320</a>.
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
On Direct2D, support per-monitor text rendering parameters.
|
||||||
|
<a href="https://sourceforge.net/p/scintilla/feature-requests/1432/">Feature #1432</a>.
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<h3>
|
<h3>
|
||||||
<a href="https://www.scintilla.org/scintilla521.zip">Release 5.2.1</a>
|
<a href="https://www.scintilla.org/scintilla521.zip">Release 5.2.1</a>
|
||||||
</h3>
|
</h3>
|
||||||
|
@ -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="20220224" />
|
<meta name="Date.Modified" content="20220331" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
#versionlist {
|
#versionlist {
|
||||||
@ -56,8 +56,8 @@
|
|||||||
GTK, and macOS</font>
|
GTK, and macOS</font>
|
||||||
</td>
|
</td>
|
||||||
<td width="40%" align="right">
|
<td width="40%" align="right">
|
||||||
<font color="#FFCC99" size="3"> Release version 5.2.1<br />
|
<font color="#FFCC99" size="3"> Release version 5.2.2<br />
|
||||||
Site last modified February 24 2022</font>
|
Site last modified March 31 2022</font>
|
||||||
</td>
|
</td>
|
||||||
<td width="20%">
|
<td width="20%">
|
||||||
|
|
||||||
@ -72,6 +72,7 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<ul id="versionlist">
|
<ul id="versionlist">
|
||||||
|
<li>Version 5.2.2 on GTK, scroll horizontally with Shift + Scroll Wheel.</li>
|
||||||
<li>Version 5.2.1 fixes leaks on GTK.</li>
|
<li>Version 5.2.1 fixes leaks on GTK.</li>
|
||||||
<li>Version 5.2.0 adds multithreaded layout to significantly improve performance for very wide lines.</li>
|
<li>Version 5.2.0 adds multithreaded layout to significantly improve performance for very wide lines.</li>
|
||||||
<li>Version 5.1.5 changes string-returning APIs to be more consistent and removes ScintillaEditPy.</li>
|
<li>Version 5.1.5 changes string-returning APIs to be more consistent and removes ScintillaEditPy.</li>
|
||||||
|
@ -822,6 +822,8 @@ void SurfaceImpl::DrawTextTransparent(PRectangle rc, const Font *font_, XYPOSITI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
class ClusterIterator {
|
class ClusterIterator {
|
||||||
UniquePangoLayoutIter iter;
|
UniquePangoLayoutIter iter;
|
||||||
PangoRectangle pos {};
|
PangoRectangle pos {};
|
||||||
@ -836,6 +838,7 @@ public:
|
|||||||
lenPositions(static_cast<int>(text.length())) {
|
lenPositions(static_cast<int>(text.length())) {
|
||||||
LayoutSetText(layout, text);
|
LayoutSetText(layout, text);
|
||||||
iter.reset(pango_layout_get_iter(layout));
|
iter.reset(pango_layout_get_iter(layout));
|
||||||
|
curIndex = pango_layout_iter_get_index(iter.get());
|
||||||
pango_layout_iter_get_cluster_extents(iter.get(), nullptr, &pos);
|
pango_layout_iter_get_cluster_extents(iter.get(), nullptr, &pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -848,12 +851,24 @@ public:
|
|||||||
} else {
|
} else {
|
||||||
finished = true;
|
finished = true;
|
||||||
position = pango_units_to_double(pos.x + pos.width);
|
position = pango_units_to_double(pos.x + pos.width);
|
||||||
curIndex = lenPositions;
|
curIndex = pango_layout_iter_get_index(iter.get());
|
||||||
}
|
}
|
||||||
distance = position - positionStart;
|
distance = position - positionStart;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Something has gone wrong so set all the characters as equally spaced.
|
||||||
|
void EquallySpaced(PangoLayout *layout, XYPOSITION *positions, size_t lenPositions) {
|
||||||
|
int widthLayout = 0;
|
||||||
|
pango_layout_get_size(layout, &widthLayout, nullptr);
|
||||||
|
const XYPOSITION widthTotal = pango_units_to_double(widthLayout);
|
||||||
|
for (size_t bytePos=0; bytePos<lenPositions; bytePos++) {
|
||||||
|
positions[bytePos] = widthTotal / lenPositions * (bytePos + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) {
|
void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSITION *positions) {
|
||||||
if (PFont(font_)->fd) {
|
if (PFont(font_)->fd) {
|
||||||
UniquePangoContext contextMeasure = MeasuringContext();
|
UniquePangoContext contextMeasure = MeasuringContext();
|
||||||
@ -863,8 +878,13 @@ void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSI
|
|||||||
pango_layout_set_font_description(layoutMeasure.get(), PFont(font_)->fd.get());
|
pango_layout_set_font_description(layoutMeasure.get(), PFont(font_)->fd.get());
|
||||||
if (et == EncodingType::utf8) {
|
if (et == EncodingType::utf8) {
|
||||||
// Simple and direct as UTF-8 is native Pango encoding
|
// Simple and direct as UTF-8 is native Pango encoding
|
||||||
int i = 0;
|
|
||||||
ClusterIterator iti(layoutMeasure.get(), text);
|
ClusterIterator iti(layoutMeasure.get(), text);
|
||||||
|
int i = iti.curIndex;
|
||||||
|
if (i != 0) {
|
||||||
|
// Unexpected start to iteration, could be bidirectional text
|
||||||
|
EquallySpaced(layoutMeasure.get(), positions, text.length());
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (!iti.finished) {
|
while (!iti.finished) {
|
||||||
iti.Next();
|
iti.Next();
|
||||||
const int places = iti.curIndex - i;
|
const int places = iti.curIndex - i;
|
||||||
@ -889,8 +909,13 @@ void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSI
|
|||||||
// character byte lengths.
|
// character byte lengths.
|
||||||
Converter convMeasure("UCS-2", CharacterSetID(characterSet), false);
|
Converter convMeasure("UCS-2", CharacterSetID(characterSet), false);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int clusterStart = 0;
|
|
||||||
ClusterIterator iti(layoutMeasure.get(), utfForm);
|
ClusterIterator iti(layoutMeasure.get(), utfForm);
|
||||||
|
int clusterStart = iti.curIndex;
|
||||||
|
if (clusterStart != 0) {
|
||||||
|
// Unexpected start to iteration, could be bidirectional text
|
||||||
|
EquallySpaced(layoutMeasure.get(), positions, text.length());
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (!iti.finished) {
|
while (!iti.finished) {
|
||||||
iti.Next();
|
iti.Next();
|
||||||
const int clusterEnd = iti.curIndex;
|
const int clusterEnd = iti.curIndex;
|
||||||
@ -920,22 +945,22 @@ void SurfaceImpl::MeasureWidths(const Font *font_, std::string_view text, XYPOSI
|
|||||||
utfForm = UTF8FromLatin1(text);
|
utfForm = UTF8FromLatin1(text);
|
||||||
}
|
}
|
||||||
size_t i = 0;
|
size_t i = 0;
|
||||||
int clusterStart = 0;
|
|
||||||
// Each 8-bit input character may take 1 or 2 bytes in UTF-8
|
// Each 8-bit input character may take 1 or 2 bytes in UTF-8
|
||||||
// and groups of up to 3 may be represented as ligatures.
|
// and groups of up to 3 may be represented as ligatures.
|
||||||
ClusterIterator iti(layoutMeasure.get(), utfForm);
|
ClusterIterator iti(layoutMeasure.get(), utfForm);
|
||||||
|
int clusterStart = iti.curIndex;
|
||||||
|
if (clusterStart != 0) {
|
||||||
|
// Unexpected start to iteration, could be bidirectional text
|
||||||
|
EquallySpaced(layoutMeasure.get(), positions, lenPositions);
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (!iti.finished) {
|
while (!iti.finished) {
|
||||||
iti.Next();
|
iti.Next();
|
||||||
const int clusterEnd = iti.curIndex;
|
const int clusterEnd = iti.curIndex;
|
||||||
const int ligatureLength = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart);
|
const int ligatureLength = g_utf8_strlen(utfForm.c_str() + clusterStart, clusterEnd - clusterStart);
|
||||||
if (rtlCheck && ((clusterEnd <= clusterStart) || (ligatureLength == 0) || (ligatureLength > 3))) {
|
if (rtlCheck && ((clusterEnd <= clusterStart) || (ligatureLength == 0) || (ligatureLength > 3))) {
|
||||||
// Something has gone wrong: exit quickly but pretend all the characters are equally spaced:
|
// Something has gone wrong: exit quickly but pretend all the characters are equally spaced:
|
||||||
int widthLayout = 0;
|
EquallySpaced(layoutMeasure.get(), positions, lenPositions);
|
||||||
pango_layout_get_size(layoutMeasure.get(), &widthLayout, nullptr);
|
|
||||||
const XYPOSITION widthTotal = pango_units_to_double(widthLayout);
|
|
||||||
for (size_t bytePos=0; bytePos<lenPositions; bytePos++) {
|
|
||||||
positions[bytePos] = widthTotal / lenPositions * (bytePos + 1);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3);
|
PLATFORM_ASSERT(ligatureLength > 0 && ligatureLength <= 3);
|
||||||
@ -1029,8 +1054,13 @@ void SurfaceImpl::MeasureWidthsUTF8(const Font *font_, std::string_view text, XY
|
|||||||
|
|
||||||
pango_layout_set_font_description(layoutMeasure.get(), PFont(font_)->fd.get());
|
pango_layout_set_font_description(layoutMeasure.get(), PFont(font_)->fd.get());
|
||||||
// Simple and direct as UTF-8 is native Pango encoding
|
// Simple and direct as UTF-8 is native Pango encoding
|
||||||
int i = 0;
|
|
||||||
ClusterIterator iti(layoutMeasure.get(), text);
|
ClusterIterator iti(layoutMeasure.get(), text);
|
||||||
|
int i = iti.curIndex;
|
||||||
|
if (i != 0) {
|
||||||
|
// Unexpected start to iteration, could be bidirectional text
|
||||||
|
EquallySpaced(layoutMeasure.get(), positions, text.length());
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (!iti.finished) {
|
while (!iti.finished) {
|
||||||
iti.Next();
|
iti.Next();
|
||||||
const int places = iti.curIndex - i;
|
const int places = iti.curIndex - i;
|
||||||
|
@ -1999,11 +1999,6 @@ gint ScintillaGTK::ScrollEvent(GtkWidget *widget, GdkEventScroll *event) {
|
|||||||
// issues spurious button 2 mouse events during wheeling, which can cause
|
// issues spurious button 2 mouse events during wheeling, which can cause
|
||||||
// problems (a patch for both was submitted by archaeopteryx.com on 13Jun2001)
|
// problems (a patch for both was submitted by archaeopteryx.com on 13Jun2001)
|
||||||
|
|
||||||
// Data zoom not supported
|
|
||||||
if (event->state & GDK_SHIFT_MASK) {
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if GTK_CHECK_VERSION(3,4,0)
|
#if GTK_CHECK_VERSION(3,4,0)
|
||||||
// Smooth scrolling not supported
|
// Smooth scrolling not supported
|
||||||
if (event->direction == GDK_SCROLL_SMOOTH) {
|
if (event->direction == GDK_SCROLL_SMOOTH) {
|
||||||
@ -2012,8 +2007,10 @@ gint ScintillaGTK::ScrollEvent(GtkWidget *widget, GdkEventScroll *event) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Horizontal scrolling
|
// Horizontal scrolling
|
||||||
if (event->direction == GDK_SCROLL_LEFT || event->direction == GDK_SCROLL_RIGHT) {
|
if (event->direction == GDK_SCROLL_LEFT || event->direction == GDK_SCROLL_RIGHT || event->state & GDK_SHIFT_MASK) {
|
||||||
sciThis->HorizontalScrollTo(sciThis->xOffset + cLineScroll);
|
int hScroll = gtk_adjustment_get_step_increment(sciThis->adjustmenth);
|
||||||
|
hScroll *= cLineScroll; // scroll by this many characters
|
||||||
|
sciThis->HorizontalScrollTo(sciThis->xOffset + hScroll);
|
||||||
|
|
||||||
// Text font size zoom
|
// Text font size zoom
|
||||||
} else if (event->state & GDK_CONTROL_MASK) {
|
} else if (event->state & GDK_CONTROL_MASK) {
|
||||||
|
@ -15,10 +15,8 @@
|
|||||||
typedef ptrdiff_t Sci_Position;
|
typedef ptrdiff_t Sci_Position;
|
||||||
|
|
||||||
// Unsigned variant used for ILexer::Lex and ILexer::Fold
|
// Unsigned variant used for ILexer::Lex and ILexer::Fold
|
||||||
// Definitions of common types
|
|
||||||
typedef size_t Sci_PositionU;
|
typedef size_t Sci_PositionU;
|
||||||
|
|
||||||
|
|
||||||
// For Sci_CharacterRange which is defined as long to be compatible with Win32 CHARRANGE
|
// For Sci_CharacterRange which is defined as long to be compatible with Win32 CHARRANGE
|
||||||
typedef intptr_t Sci_PositionCR;
|
typedef intptr_t Sci_PositionCR;
|
||||||
|
|
||||||
|
@ -57,6 +57,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
|
|||||||
#define SCI_GETCURRENTPOS 2008
|
#define SCI_GETCURRENTPOS 2008
|
||||||
#define SCI_GETANCHOR 2009
|
#define SCI_GETANCHOR 2009
|
||||||
#define SCI_GETSTYLEAT 2010
|
#define SCI_GETSTYLEAT 2010
|
||||||
|
#define SCI_GETSTYLEINDEXAT 2038
|
||||||
#define SCI_REDO 2011
|
#define SCI_REDO 2011
|
||||||
#define SCI_SETUNDOCOLLECTION 2012
|
#define SCI_SETUNDOCOLLECTION 2012
|
||||||
#define SCI_SELECTALL 2013
|
#define SCI_SELECTALL 2013
|
||||||
|
@ -130,6 +130,9 @@ get position GetAnchor=2009(,)
|
|||||||
# Returns the style byte at the position.
|
# Returns the style byte at the position.
|
||||||
get int GetStyleAt=2010(position pos,)
|
get int GetStyleAt=2010(position pos,)
|
||||||
|
|
||||||
|
# Returns the unsigned style byte at the position.
|
||||||
|
get int GetStyleIndexAt=2038(position pos,)
|
||||||
|
|
||||||
# Redoes the next action on the undo history.
|
# Redoes the next action on the undo history.
|
||||||
fun void Redo=2011(,)
|
fun void Redo=2011(,)
|
||||||
|
|
||||||
|
@ -88,6 +88,7 @@ public:
|
|||||||
Position CurrentPos();
|
Position CurrentPos();
|
||||||
Position Anchor();
|
Position Anchor();
|
||||||
int StyleAt(Position pos);
|
int StyleAt(Position pos);
|
||||||
|
int StyleIndexAt(Position pos);
|
||||||
void Redo();
|
void Redo();
|
||||||
void SetUndoCollection(bool collectUndo);
|
void SetUndoCollection(bool collectUndo);
|
||||||
void SelectAll();
|
void SelectAll();
|
||||||
|
@ -28,6 +28,7 @@ enum class Message {
|
|||||||
GetCurrentPos = 2008,
|
GetCurrentPos = 2008,
|
||||||
GetAnchor = 2009,
|
GetAnchor = 2009,
|
||||||
GetStyleAt = 2010,
|
GetStyleAt = 2010,
|
||||||
|
GetStyleIndexAt = 2038,
|
||||||
Redo = 2011,
|
Redo = 2011,
|
||||||
SetUndoCollection = 2012,
|
SetUndoCollection = 2012,
|
||||||
SelectAll = 2013,
|
SelectAll = 2013,
|
||||||
|
@ -13,7 +13,7 @@ TEMPLATE = lib
|
|||||||
CONFIG += lib_bundle
|
CONFIG += lib_bundle
|
||||||
CONFIG += c++1z
|
CONFIG += c++1z
|
||||||
|
|
||||||
VERSION = 5.2.1
|
VERSION = 5.2.2
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
ScintillaEdit.cpp \
|
ScintillaEdit.cpp \
|
||||||
|
@ -339,19 +339,8 @@ void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern)
|
|||||||
{
|
{
|
||||||
// Tile pattern over rectangle
|
// Tile pattern over rectangle
|
||||||
SurfaceImpl *surface = dynamic_cast<SurfaceImpl *>(&surfacePattern);
|
SurfaceImpl *surface = dynamic_cast<SurfaceImpl *>(&surfacePattern);
|
||||||
// Currently assumes 8x8 pattern
|
const QPixmap *pixmap = static_cast<QPixmap *>(surface->GetPaintDevice());
|
||||||
int widthPat = 8;
|
GetPainter()->drawTiledPixmap(QRectFromPRect(rc), *pixmap);
|
||||||
int heightPat = 8;
|
|
||||||
for (int xTile = rc.left; xTile < rc.right; xTile += widthPat) {
|
|
||||||
int widthx = (xTile + widthPat > rc.right) ? rc.right - xTile : widthPat;
|
|
||||||
for (int yTile = rc.top; yTile < rc.bottom; yTile += heightPat) {
|
|
||||||
int heighty = (yTile + heightPat > rc.bottom) ? rc.bottom - yTile : heightPat;
|
|
||||||
QRect source(0, 0, widthx, heighty);
|
|
||||||
QRect target(xTile, yTile, widthx, heighty);
|
|
||||||
QPixmap *pixmap = static_cast<QPixmap *>(surface->GetPaintDevice());
|
|
||||||
GetPainter()->drawPixmap(target, *pixmap, source);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceImpl::RoundedRectangle(PRectangle rc, FillStroke fillStroke)
|
void SurfaceImpl::RoundedRectangle(PRectangle rc, FillStroke fillStroke)
|
||||||
|
@ -12,7 +12,7 @@ TEMPLATE = lib
|
|||||||
CONFIG += lib_bundle
|
CONFIG += lib_bundle
|
||||||
CONFIG += c++1z
|
CONFIG += c++1z
|
||||||
|
|
||||||
VERSION = 5.2.1
|
VERSION = 5.2.2
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
PlatQt.cpp \
|
PlatQt.cpp \
|
||||||
|
@ -272,24 +272,14 @@ void CallTip::MouseClick(Point pt) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
PRectangle CallTip::CallTipStart(Sci::Position pos, Point pt, int textHeight, const char *defn,
|
PRectangle CallTip::CallTipStart(Sci::Position pos, Point pt, int textHeight, const char *defn,
|
||||||
const char *faceName, int size,
|
int codePage_, Surface *surfaceMeasure, std::shared_ptr<Font> font_) {
|
||||||
int codePage_, CharacterSet characterSet,
|
|
||||||
Technology technology,
|
|
||||||
const char *localeName,
|
|
||||||
const Window &wParent) {
|
|
||||||
clickPlace = 0;
|
clickPlace = 0;
|
||||||
val = defn;
|
val = defn;
|
||||||
codePage = codePage_;
|
codePage = codePage_;
|
||||||
std::unique_ptr<Surface> surfaceMeasure = Surface::Allocate(technology);
|
|
||||||
surfaceMeasure->Init(wParent.GetID());
|
|
||||||
surfaceMeasure->SetMode(SurfaceMode(codePage, false));
|
|
||||||
highlight = Chunk();
|
highlight = Chunk();
|
||||||
inCallTipMode = true;
|
inCallTipMode = true;
|
||||||
posStartCallTip = pos;
|
posStartCallTip = pos;
|
||||||
const XYPOSITION deviceHeight = static_cast<XYPOSITION>(surfaceMeasure->DeviceHeightFont(size));
|
font = font_;
|
||||||
const FontParameters fp(faceName, deviceHeight / FontSizeMultiplier, FontWeight::Normal,
|
|
||||||
false, FontQuality::QualityDefault, technology, characterSet, localeName);
|
|
||||||
font = Font::Allocate(fp);
|
|
||||||
// Look for multiple lines in the text
|
// Look for multiple lines in the text
|
||||||
// Only support \n here - simply means container must avoid \r!
|
// Only support \n here - simply means container must avoid \r!
|
||||||
const int numLines = 1 + static_cast<int>(std::count(val.begin(), val.end(), '\n'));
|
const int numLines = 1 + static_cast<int>(std::count(val.begin(), val.end(), '\n'));
|
||||||
@ -300,7 +290,7 @@ PRectangle CallTip::CallTipStart(Sci::Position pos, Point pt, int textHeight, co
|
|||||||
#if !PLAT_CURSES
|
#if !PLAT_CURSES
|
||||||
widthArrow = lineHeight * 9 / 10;
|
widthArrow = lineHeight * 9 / 10;
|
||||||
#endif
|
#endif
|
||||||
const int width = PaintContents(surfaceMeasure.get(), false) + insetX;
|
const int width = PaintContents(surfaceMeasure, false) + insetX;
|
||||||
|
|
||||||
// The returned
|
// The returned
|
||||||
// rectangle is aligned to the right edge of the last arrow encountered in
|
// rectangle is aligned to the right edge of the last arrow encountered in
|
||||||
@ -350,7 +340,7 @@ bool CallTip::UseStyleCallTip() const noexcept {
|
|||||||
|
|
||||||
// It might be better to have two access functions for this and to use
|
// It might be better to have two access functions for this and to use
|
||||||
// them for all settings of colours.
|
// them for all settings of colours.
|
||||||
void CallTip::SetForeBack(const ColourRGBA &fore, const ColourRGBA &back) noexcept {
|
void CallTip::SetForeBack(ColourRGBA fore, ColourRGBA back) noexcept {
|
||||||
colourBG = back;
|
colourBG = back;
|
||||||
colourUnSel = fore;
|
colourUnSel = fore;
|
||||||
}
|
}
|
||||||
|
@ -71,9 +71,7 @@ public:
|
|||||||
|
|
||||||
/// Setup the calltip and return a rectangle of the area required.
|
/// Setup the calltip and return a rectangle of the area required.
|
||||||
PRectangle CallTipStart(Sci::Position pos, Point pt, int textHeight, const char *defn,
|
PRectangle CallTipStart(Sci::Position pos, Point pt, int textHeight, const char *defn,
|
||||||
const char *faceName, int size, int codePage_,
|
int codePage_, Surface *surfaceMeasure, std::shared_ptr<Font> font_);
|
||||||
Scintilla::CharacterSet characterSet, Scintilla::Technology technology, const char *localeName,
|
|
||||||
const Window &wParent);
|
|
||||||
|
|
||||||
void CallTipCancel() noexcept;
|
void CallTipCancel() noexcept;
|
||||||
|
|
||||||
@ -91,7 +89,7 @@ public:
|
|||||||
bool UseStyleCallTip() const noexcept;
|
bool UseStyleCallTip() const noexcept;
|
||||||
|
|
||||||
// Modify foreground and background colours
|
// Modify foreground and background colours
|
||||||
void SetForeBack(const ColourRGBA &fore, const ColourRGBA &back) noexcept;
|
void SetForeBack(ColourRGBA fore, ColourRGBA back) noexcept;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -101,6 +101,10 @@ bool EditModel::BidirectionalR2L() const noexcept {
|
|||||||
return bidirectional == Bidirectional::R2L;
|
return bidirectional == Bidirectional::R2L;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SurfaceMode EditModel::CurrentSurfaceMode() const noexcept {
|
||||||
|
return SurfaceMode(pdoc->dbcsCodePage, BidirectionalR2L());
|
||||||
|
}
|
||||||
|
|
||||||
void EditModel::SetDefaultFoldDisplayText(const char *text) {
|
void EditModel::SetDefaultFoldDisplayText(const char *text) {
|
||||||
defaultFoldDisplayText = IsNullOrEmpty(text) ? UniqueString() : UniqueStringCopy(text);
|
defaultFoldDisplayText = IsNullOrEmpty(text) ? UniqueString() : UniqueStringCopy(text);
|
||||||
}
|
}
|
||||||
|
@ -66,6 +66,7 @@ public:
|
|||||||
virtual Sci::Line LinesOnScreen() const = 0;
|
virtual Sci::Line LinesOnScreen() const = 0;
|
||||||
bool BidirectionalEnabled() const noexcept;
|
bool BidirectionalEnabled() const noexcept;
|
||||||
bool BidirectionalR2L() const noexcept;
|
bool BidirectionalR2L() const noexcept;
|
||||||
|
SurfaceMode CurrentSurfaceMode() const noexcept;
|
||||||
void SetDefaultFoldDisplayText(const char *text);
|
void SetDefaultFoldDisplayText(const char *text);
|
||||||
const char *GetDefaultFoldDisplayText() const noexcept;
|
const char *GetDefaultFoldDisplayText() const noexcept;
|
||||||
const char *GetFoldDisplayText(Sci::Line lineDoc) const noexcept;
|
const char *GetFoldDisplayText(Sci::Line lineDoc) const noexcept;
|
||||||
|
@ -774,8 +774,8 @@ Point EditView::LocationFromPosition(Surface *surface, const EditModel &model, S
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
pt.y += (lineVisible - topLine) * vs.lineHeight;
|
pt.y += (lineVisible - topLine) * vs.lineHeight;
|
||||||
}
|
|
||||||
pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
|
pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
|
||||||
|
}
|
||||||
return pt;
|
return pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1485,7 +1485,9 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c
|
|||||||
const char *textFoldDisplay = model.GetFoldDisplayText(line);
|
const char *textFoldDisplay = model.GetFoldDisplayText(line);
|
||||||
if (textFoldDisplay) {
|
if (textFoldDisplay) {
|
||||||
const std::string_view foldDisplayText(textFoldDisplay);
|
const std::string_view foldDisplayText(textFoldDisplay);
|
||||||
rcSegment.left += (static_cast<int>(surface->WidthText(fontText, foldDisplayText)) + vsDraw.aveCharWidth);
|
rcSegment.left += static_cast<int>(
|
||||||
|
surface->WidthText(vsDraw.styles[StyleFoldDisplayText].font.get(), foldDisplayText)) +
|
||||||
|
vsDraw.aveCharWidth;
|
||||||
}
|
}
|
||||||
rcSegment.right = rcSegment.left + static_cast<XYPOSITION>(widthEOLAnnotationText);
|
rcSegment.right = rcSegment.left + static_cast<XYPOSITION>(widthEOLAnnotationText);
|
||||||
|
|
||||||
@ -2441,7 +2443,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, PRectan
|
|||||||
surface = pixmapLine.get();
|
surface = pixmapLine.get();
|
||||||
PLATFORM_ASSERT(pixmapLine->Initialised());
|
PLATFORM_ASSERT(pixmapLine->Initialised());
|
||||||
}
|
}
|
||||||
surface->SetMode(SurfaceMode(model.pdoc->dbcsCodePage, model.BidirectionalR2L()));
|
surface->SetMode(model.CurrentSurfaceMode());
|
||||||
|
|
||||||
const Point ptOrigin = model.GetVisibleOriginInMain();
|
const Point ptOrigin = model.GetVisibleOriginInMain();
|
||||||
|
|
||||||
|
@ -204,7 +204,6 @@ Editor::Editor() : durationWrapOneByte(0.000001, 0.00000001, 0.00001) {
|
|||||||
|
|
||||||
Editor::~Editor() {
|
Editor::~Editor() {
|
||||||
pdoc->RemoveWatcher(this, nullptr);
|
pdoc->RemoveWatcher(this, nullptr);
|
||||||
DropGraphics();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Editor::Finalise() {
|
void Editor::Finalise() {
|
||||||
@ -1707,6 +1706,7 @@ void Editor::PaintSelMargin(Surface *surfaceWindow, const PRectangle &rc) {
|
|||||||
} else {
|
} else {
|
||||||
surface = surfaceWindow;
|
surface = surfaceWindow;
|
||||||
}
|
}
|
||||||
|
surface->SetMode(CurrentSurfaceMode());
|
||||||
|
|
||||||
// Clip vertically to paint area to avoid drawing line numbers
|
// Clip vertically to paint area to avoid drawing line numbers
|
||||||
if (rcMargin.bottom > rc.bottom)
|
if (rcMargin.bottom > rc.bottom)
|
||||||
@ -5687,6 +5687,26 @@ int Editor::CodePage() const noexcept {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Surface> Editor::CreateMeasurementSurface() const {
|
||||||
|
if (!wMain.GetID()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::unique_ptr<Surface> surf = Surface::Allocate(technology);
|
||||||
|
surf->Init(wMain.GetID());
|
||||||
|
surf->SetMode(CurrentSurfaceMode());
|
||||||
|
return surf;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<Surface> Editor::CreateDrawingSurface(SurfaceID sid, std::optional<Scintilla::Technology> technologyOpt) const {
|
||||||
|
if (!wMain.GetID()) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
std::unique_ptr<Surface> surf = Surface::Allocate(technologyOpt ? *technologyOpt : technology);
|
||||||
|
surf->Init(sid, wMain.GetID());
|
||||||
|
surf->SetMode(CurrentSurfaceMode());
|
||||||
|
return surf;
|
||||||
|
}
|
||||||
|
|
||||||
Sci::Line Editor::WrapCount(Sci::Line line) {
|
Sci::Line Editor::WrapCount(Sci::Line line) {
|
||||||
AutoSurface surface(this);
|
AutoSurface surface(this);
|
||||||
std::shared_ptr<LineLayout> ll = view.RetrieveLineLayout(line, *this);
|
std::shared_ptr<LineLayout> ll = view.RetrieveLineLayout(line, *this);
|
||||||
@ -6464,6 +6484,12 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
|
|||||||
else
|
else
|
||||||
return pdoc->StyleAt(PositionFromUPtr(wParam));
|
return pdoc->StyleAt(PositionFromUPtr(wParam));
|
||||||
|
|
||||||
|
case Message::GetStyleIndexAt:
|
||||||
|
if (PositionFromUPtr(wParam) >= pdoc->Length())
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return pdoc->StyleIndexAt(PositionFromUPtr(wParam));
|
||||||
|
|
||||||
case Message::Redo:
|
case Message::Redo:
|
||||||
Redo();
|
Redo();
|
||||||
break;
|
break;
|
||||||
|
@ -592,6 +592,8 @@ protected: // ScintillaBase subclass needs access to much of Editor
|
|||||||
virtual bool ValidCodePage(int /* codePage */) const { return true; }
|
virtual bool ValidCodePage(int /* codePage */) const { return true; }
|
||||||
virtual std::string UTF8FromEncoded(std::string_view encoded) const = 0;
|
virtual std::string UTF8FromEncoded(std::string_view encoded) const = 0;
|
||||||
virtual std::string EncodedFromUTF8(std::string_view utf8) const = 0;
|
virtual std::string EncodedFromUTF8(std::string_view utf8) const = 0;
|
||||||
|
virtual std::unique_ptr<Surface> CreateMeasurementSurface() const;
|
||||||
|
virtual std::unique_ptr<Surface> CreateDrawingSurface(SurfaceID sid, std::optional<Scintilla::Technology> technologyOpt = {}) const;
|
||||||
|
|
||||||
Sci::Line WrapCount(Sci::Line line);
|
Sci::Line WrapCount(Sci::Line line);
|
||||||
void AddStyledText(const char *buffer, Sci::Position appendLength);
|
void AddStyledText(const char *buffer, Sci::Position appendLength);
|
||||||
@ -684,19 +686,11 @@ class AutoSurface {
|
|||||||
private:
|
private:
|
||||||
std::unique_ptr<Surface> surf;
|
std::unique_ptr<Surface> surf;
|
||||||
public:
|
public:
|
||||||
AutoSurface(const Editor *ed) {
|
AutoSurface(const Editor *ed) :
|
||||||
if (ed->wMain.GetID()) {
|
surf(ed->CreateMeasurementSurface()) {
|
||||||
surf = Surface::Allocate(ed->technology);
|
|
||||||
surf->Init(ed->wMain.GetID());
|
|
||||||
surf->SetMode(SurfaceMode(ed->CodePage(), ed->BidirectionalR2L()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
AutoSurface(SurfaceID sid, Editor *ed, std::optional<Scintilla::Technology> technology = {}) {
|
|
||||||
if (ed->wMain.GetID()) {
|
|
||||||
surf = Surface::Allocate(technology ? *technology : ed->technology);
|
|
||||||
surf->Init(sid, ed->wMain.GetID());
|
|
||||||
surf->SetMode(SurfaceMode(ed->CodePage(), ed->BidirectionalR2L()));
|
|
||||||
}
|
}
|
||||||
|
AutoSurface(SurfaceID sid, Editor *ed, std::optional<Scintilla::Technology> technology = {}) :
|
||||||
|
surf(ed->CreateDrawingSurface(sid, technology)) {
|
||||||
}
|
}
|
||||||
// Deleted so AutoSurface objects can not be copied.
|
// Deleted so AutoSurface objects can not be copied.
|
||||||
AutoSurface(const AutoSurface &) = delete;
|
AutoSurface(const AutoSurface &) = delete;
|
||||||
|
@ -465,22 +465,20 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) {
|
|||||||
// StyleDefault for the face name, size and character set. Also use it
|
// StyleDefault for the face name, size and character set. Also use it
|
||||||
// for the foreground and background colour.
|
// for the foreground and background colour.
|
||||||
const int ctStyle = ct.UseStyleCallTip() ? StyleCallTip : StyleDefault;
|
const int ctStyle = ct.UseStyleCallTip() ? StyleCallTip : StyleDefault;
|
||||||
|
const Style &style = vs.styles[ctStyle];
|
||||||
if (ct.UseStyleCallTip()) {
|
if (ct.UseStyleCallTip()) {
|
||||||
ct.SetForeBack(vs.styles[StyleCallTip].fore, vs.styles[StyleCallTip].back);
|
ct.SetForeBack(style.fore, style.back);
|
||||||
}
|
}
|
||||||
if (wMargin.Created()) {
|
if (wMargin.Created()) {
|
||||||
pt = pt + GetVisibleOriginInMain();
|
pt = pt + GetVisibleOriginInMain();
|
||||||
}
|
}
|
||||||
|
AutoSurface surfaceMeasure(this);
|
||||||
PRectangle rc = ct.CallTipStart(sel.MainCaret(), pt,
|
PRectangle rc = ct.CallTipStart(sel.MainCaret(), pt,
|
||||||
vs.lineHeight,
|
vs.lineHeight,
|
||||||
defn,
|
defn,
|
||||||
vs.styles[ctStyle].fontName,
|
|
||||||
vs.styles[ctStyle].sizeZoomed,
|
|
||||||
CodePage(),
|
CodePage(),
|
||||||
vs.styles[ctStyle].characterSet,
|
surfaceMeasure,
|
||||||
vs.technology,
|
style.font);
|
||||||
vs.localeName.c_str(),
|
|
||||||
wMain);
|
|
||||||
// If the call-tip window would be out of the client
|
// If the call-tip window would be out of the client
|
||||||
// space
|
// space
|
||||||
const PRectangle rcClient = GetClientRectangle();
|
const PRectangle rcClient = GetClientRectangle();
|
||||||
|
@ -133,7 +133,6 @@ ViewStyle::ViewStyle(size_t stylesSize_) :
|
|||||||
Element::SelectionSecondaryText,
|
Element::SelectionSecondaryText,
|
||||||
Element::SelectionSecondaryBack,
|
Element::SelectionSecondaryBack,
|
||||||
Element::SelectionInactiveText,
|
Element::SelectionInactiveText,
|
||||||
Element::SelectionBack,
|
|
||||||
Element::SelectionInactiveBack,
|
Element::SelectionInactiveBack,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -48,13 +48,16 @@ class TestSimple(unittest.TestCase):
|
|||||||
|
|
||||||
def testAddStyledText(self):
|
def testAddStyledText(self):
|
||||||
self.assertEquals(self.ed.EndStyled, 0)
|
self.assertEquals(self.ed.EndStyled, 0)
|
||||||
self.ed.AddStyledText(2, b"x\002")
|
self.ed.AddStyledText(4, b"x\002y\377")
|
||||||
self.assertEquals(self.ed.Length, 1)
|
self.assertEquals(self.ed.Length, 2)
|
||||||
self.assertEquals(self.ed.GetCharAt(0), ord("x"))
|
self.assertEquals(self.ed.GetCharAt(0), ord("x"))
|
||||||
self.assertEquals(self.ed.GetStyleAt(0), 2)
|
self.assertEquals(self.ed.GetStyleAt(0), 2)
|
||||||
|
self.assertEquals(self.ed.GetStyleIndexAt(0), 2)
|
||||||
|
self.assertEquals(self.ed.GetStyleIndexAt(1), 255)
|
||||||
self.assertEquals(self.ed.StyledTextRange(0, 1), b"x\002")
|
self.assertEquals(self.ed.StyledTextRange(0, 1), b"x\002")
|
||||||
|
self.assertEquals(self.ed.StyledTextRange(1, 2), b"y\377")
|
||||||
self.ed.ClearDocumentStyle()
|
self.ed.ClearDocumentStyle()
|
||||||
self.assertEquals(self.ed.Length, 1)
|
self.assertEquals(self.ed.Length, 2)
|
||||||
self.assertEquals(self.ed.GetCharAt(0), ord("x"))
|
self.assertEquals(self.ed.GetCharAt(0), ord("x"))
|
||||||
self.assertEquals(self.ed.GetStyleAt(0), 0)
|
self.assertEquals(self.ed.GetStyleAt(0), 0)
|
||||||
self.assertEquals(self.ed.StyledTextRange(0, 1), b"x\0")
|
self.assertEquals(self.ed.StyledTextRange(0, 1), b"x\0")
|
||||||
|
@ -1 +1 @@
|
|||||||
521
|
522
|
||||||
|
@ -19,14 +19,6 @@
|
|||||||
|
|
||||||
namespace Scintilla::Internal::HanjaDict {
|
namespace Scintilla::Internal::HanjaDict {
|
||||||
|
|
||||||
struct BSTRDeleter {
|
|
||||||
void operator()(BSTR bstr) const noexcept {
|
|
||||||
SysFreeString(bstr);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using UniqueBSTR = std::unique_ptr<OLECHAR[], BSTRDeleter>;
|
|
||||||
|
|
||||||
interface IRadical;
|
interface IRadical;
|
||||||
interface IHanja;
|
interface IHanja;
|
||||||
interface IStrokes;
|
interface IStrokes;
|
||||||
@ -66,6 +58,37 @@ interface IHanjaDic : IUnknown {
|
|||||||
extern "C" const GUID __declspec(selectany) IID_IHanjaDic =
|
extern "C" const GUID __declspec(selectany) IID_IHanjaDic =
|
||||||
{ 0xad75f3ac, 0x18cd, 0x48c6, { 0xa2, 0x7d, 0xf1, 0xe9, 0xa7, 0xdc, 0xe4, 0x32 } };
|
{ 0xad75f3ac, 0x18cd, 0x48c6, { 0xa2, 0x7d, 0xf1, 0xe9, 0xa7, 0xdc, 0xe4, 0x32 } };
|
||||||
|
|
||||||
|
class ScopedBSTR {
|
||||||
|
BSTR bstr = nullptr;
|
||||||
|
public:
|
||||||
|
ScopedBSTR() noexcept = default;
|
||||||
|
explicit ScopedBSTR(const OLECHAR *psz) noexcept :
|
||||||
|
bstr(SysAllocString(psz)) {
|
||||||
|
}
|
||||||
|
explicit ScopedBSTR(OLECHAR character) noexcept :
|
||||||
|
bstr(SysAllocStringLen(&character, 1)) {
|
||||||
|
}
|
||||||
|
// Deleted so ScopedBSTR objects can not be copied. Moves are OK.
|
||||||
|
ScopedBSTR(const ScopedBSTR &) = delete;
|
||||||
|
ScopedBSTR &operator=(const ScopedBSTR &) = delete;
|
||||||
|
// Moves are OK.
|
||||||
|
ScopedBSTR(ScopedBSTR &&) = default;
|
||||||
|
ScopedBSTR &operator=(ScopedBSTR &&) = default;
|
||||||
|
~ScopedBSTR() {
|
||||||
|
SysFreeString(bstr);
|
||||||
|
}
|
||||||
|
|
||||||
|
BSTR get() const noexcept {
|
||||||
|
return bstr;
|
||||||
|
}
|
||||||
|
void reset(BSTR value=nullptr) noexcept {
|
||||||
|
// https://en.cppreference.com/w/cpp/memory/unique_ptr/reset
|
||||||
|
BSTR const old = bstr;
|
||||||
|
bstr = value;
|
||||||
|
SysFreeString(old);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class HanjaDic {
|
class HanjaDic {
|
||||||
std::unique_ptr<IHanjaDic, UnknownReleaser> HJinterface;
|
std::unique_ptr<IHanjaDic, UnknownReleaser> HJinterface;
|
||||||
|
|
||||||
@ -77,7 +100,7 @@ class HanjaDic {
|
|||||||
hr = CoCreateInstance(CLSID_HanjaDic, nullptr,
|
hr = CoCreateInstance(CLSID_HanjaDic, nullptr,
|
||||||
CLSCTX_INPROC_SERVER, IID_IHanjaDic,
|
CLSCTX_INPROC_SERVER, IID_IHanjaDic,
|
||||||
(LPVOID *)&instance);
|
(LPVOID *)&instance);
|
||||||
if (SUCCEEDED(hr)) {
|
if (SUCCEEDED(hr) && instance) {
|
||||||
HJinterface.reset(instance);
|
HJinterface.reset(instance);
|
||||||
hr = instance->OpenMainDic();
|
hr = instance->OpenMainDic();
|
||||||
return SUCCEEDED(hr);
|
return SUCCEEDED(hr);
|
||||||
@ -102,9 +125,9 @@ public:
|
|||||||
return SUCCEEDED(hr) && hanjaType > HANJA_UNKNOWN;
|
return SUCCEEDED(hr) && hanjaType > HANJA_UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HanjaToHangul(BSTR bstrHanja, UniqueBSTR &bstrHangul) const noexcept {
|
bool HanjaToHangul(const ScopedBSTR &bstrHanja, ScopedBSTR &bstrHangul) const noexcept {
|
||||||
BSTR result = nullptr;
|
BSTR result = nullptr;
|
||||||
const HRESULT hr = HJinterface->HanjaToHangul(bstrHanja, &result);
|
const HRESULT hr = HJinterface->HanjaToHangul(bstrHanja.get(), &result);
|
||||||
bstrHangul.reset(result);
|
bstrHangul.reset(result);
|
||||||
return SUCCEEDED(hr);
|
return SUCCEEDED(hr);
|
||||||
}
|
}
|
||||||
@ -121,11 +144,10 @@ bool GetHangulOfHanja(std::wstring &inout) noexcept {
|
|||||||
if (dict.Open()) {
|
if (dict.Open()) {
|
||||||
for (wchar_t &character : inout) {
|
for (wchar_t &character : inout) {
|
||||||
if (dict.IsHanja(character)) { // Pass hanja only!
|
if (dict.IsHanja(character)) { // Pass hanja only!
|
||||||
const UniqueBSTR bstrHanja{SysAllocStringLen(&character, 1)};
|
ScopedBSTR bstrHangul;
|
||||||
UniqueBSTR bstrHangul;
|
if (dict.HanjaToHangul(ScopedBSTR(character), bstrHangul)) {
|
||||||
if (dict.HanjaToHangul(bstrHanja.get(), bstrHangul)) {
|
|
||||||
changed = true;
|
changed = true;
|
||||||
character = bstrHangul[0];
|
character = *(bstrHangul.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,9 +28,9 @@
|
|||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
#endif
|
#endif
|
||||||
#undef _WIN32_WINNT
|
#undef _WIN32_WINNT
|
||||||
#define _WIN32_WINNT 0x0500
|
#define _WIN32_WINNT 0x0A00
|
||||||
#undef WINVER
|
#undef WINVER
|
||||||
#define WINVER 0x0500
|
#define WINVER 0x0A00
|
||||||
#define WIN32_LEAN_AND_MEAN 1
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
@ -58,14 +58,6 @@
|
|||||||
#include "WinTypes.h"
|
#include "WinTypes.h"
|
||||||
#include "PlatWin.h"
|
#include "PlatWin.h"
|
||||||
|
|
||||||
#ifndef SPI_GETFONTSMOOTHINGCONTRAST
|
|
||||||
#define SPI_GETFONTSMOOTHINGCONTRAST 0x200C
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef LOAD_LIBRARY_SEARCH_SYSTEM32
|
|
||||||
#define LOAD_LIBRARY_SEARCH_SYSTEM32 0x00000800
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// __uuidof is a Microsoft extension but makes COM code neater, so disable warning
|
// __uuidof is a Microsoft extension but makes COM code neater, so disable warning
|
||||||
#if defined(__clang__)
|
#if defined(__clang__)
|
||||||
#pragma clang diagnostic ignored "-Wlanguage-extension-token"
|
#pragma clang diagnostic ignored "-Wlanguage-extension-token"
|
||||||
@ -80,8 +72,6 @@ UINT CodePageFromCharSet(CharacterSet characterSet, UINT documentCodePage) noexc
|
|||||||
#if defined(USE_D2D)
|
#if defined(USE_D2D)
|
||||||
IDWriteFactory *pIDWriteFactory = nullptr;
|
IDWriteFactory *pIDWriteFactory = nullptr;
|
||||||
ID2D1Factory *pD2DFactory = nullptr;
|
ID2D1Factory *pD2DFactory = nullptr;
|
||||||
IDWriteRenderingParams *defaultRenderingParams = nullptr;
|
|
||||||
IDWriteRenderingParams *customClearTypeRenderingParams = nullptr;
|
|
||||||
D2D1_DRAW_TEXT_OPTIONS d2dDrawTextOptions = D2D1_DRAW_TEXT_OPTIONS_NONE;
|
D2D1_DRAW_TEXT_OPTIONS d2dDrawTextOptions = D2D1_DRAW_TEXT_OPTIONS_NONE;
|
||||||
|
|
||||||
static HMODULE hDLLD2D {};
|
static HMODULE hDLLD2D {};
|
||||||
@ -131,24 +121,6 @@ void LoadD2DOnce() noexcept {
|
|||||||
reinterpret_cast<IUnknown**>(&pIDWriteFactory));
|
reinterpret_cast<IUnknown**>(&pIDWriteFactory));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pIDWriteFactory) {
|
|
||||||
const HRESULT hr = pIDWriteFactory->CreateRenderingParams(&defaultRenderingParams);
|
|
||||||
if (SUCCEEDED(hr)) {
|
|
||||||
unsigned int clearTypeContrast = 0;
|
|
||||||
if (::SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &clearTypeContrast, 0)) {
|
|
||||||
|
|
||||||
FLOAT gamma;
|
|
||||||
if (clearTypeContrast >= 1000 && clearTypeContrast <= 2200)
|
|
||||||
gamma = static_cast<FLOAT>(clearTypeContrast) / 1000.0f;
|
|
||||||
else
|
|
||||||
gamma = defaultRenderingParams->GetGamma();
|
|
||||||
|
|
||||||
pIDWriteFactory->CreateCustomRenderingParams(gamma, defaultRenderingParams->GetEnhancedContrast(), defaultRenderingParams->GetClearTypeLevel(),
|
|
||||||
defaultRenderingParams->GetPixelGeometry(), defaultRenderingParams->GetRenderingMode(), &customClearTypeRenderingParams);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadD2D() {
|
bool LoadD2D() {
|
||||||
@ -159,10 +131,6 @@ bool LoadD2D() {
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef CLEARTYPE_QUALITY
|
|
||||||
#define CLEARTYPE_QUALITY 5
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void *PointerFromWindow(HWND hWnd) noexcept {
|
void *PointerFromWindow(HWND hWnd) noexcept {
|
||||||
return reinterpret_cast<void *>(::GetWindowLongPtr(hWnd, 0));
|
return reinterpret_cast<void *>(::GetWindowLongPtr(hWnd, 0));
|
||||||
}
|
}
|
||||||
@ -1307,7 +1275,7 @@ constexpr D2D1_RECT_F RectangleInset(D2D1_RECT_F rect, FLOAT inset) noexcept {
|
|||||||
|
|
||||||
class BlobInline;
|
class BlobInline;
|
||||||
|
|
||||||
class SurfaceD2D : public Surface {
|
class SurfaceD2D : public Surface, public ISetRenderingParams {
|
||||||
SurfaceMode mode;
|
SurfaceMode mode;
|
||||||
|
|
||||||
ID2D1RenderTarget *pRenderTarget = nullptr;
|
ID2D1RenderTarget *pRenderTarget = nullptr;
|
||||||
@ -1317,8 +1285,10 @@ class SurfaceD2D : public Surface {
|
|||||||
|
|
||||||
ID2D1SolidColorBrush *pBrush = nullptr;
|
ID2D1SolidColorBrush *pBrush = nullptr;
|
||||||
|
|
||||||
FontQuality fontQuality = FontQuality::QualityMask;
|
static constexpr FontQuality invalidFontQuality = FontQuality::QualityMask;
|
||||||
|
FontQuality fontQuality = invalidFontQuality;
|
||||||
int logPixelsY = USER_DEFAULT_SCREEN_DPI;
|
int logPixelsY = USER_DEFAULT_SCREEN_DPI;
|
||||||
|
std::shared_ptr<RenderingParams> renderingParams;
|
||||||
|
|
||||||
void Clear() noexcept;
|
void Clear() noexcept;
|
||||||
void SetFontQuality(FontQuality extraFontFlag);
|
void SetFontQuality(FontQuality extraFontFlag);
|
||||||
@ -1392,6 +1362,8 @@ public:
|
|||||||
void PopClip() override;
|
void PopClip() override;
|
||||||
void FlushCachedState() override;
|
void FlushCachedState() override;
|
||||||
void FlushDrawing() override;
|
void FlushDrawing() override;
|
||||||
|
|
||||||
|
void SetRenderingParams(std::shared_ptr<RenderingParams> renderingParams_) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
SurfaceD2D::SurfaceD2D() noexcept {
|
SurfaceD2D::SurfaceD2D() noexcept {
|
||||||
@ -1443,7 +1415,7 @@ void SurfaceD2D::Release() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceD2D::SetScale(WindowID wid) noexcept {
|
void SurfaceD2D::SetScale(WindowID wid) noexcept {
|
||||||
fontQuality = FontQuality::QualityMask;
|
fontQuality = invalidFontQuality;
|
||||||
logPixelsY = DpiForWindow(wid);
|
logPixelsY = DpiForWindow(wid);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1471,7 +1443,9 @@ void SurfaceD2D::Init(SurfaceID sid, WindowID wid) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<Surface> SurfaceD2D::AllocatePixMap(int width, int height) {
|
std::unique_ptr<Surface> SurfaceD2D::AllocatePixMap(int width, int height) {
|
||||||
return std::make_unique<SurfaceD2D>(pRenderTarget, width, height, mode, logPixelsY);
|
std::unique_ptr<SurfaceD2D> surf = std::make_unique<SurfaceD2D>(pRenderTarget, width, height, mode, logPixelsY);
|
||||||
|
surf->SetRenderingParams(renderingParams);
|
||||||
|
return surf;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceD2D::SetMode(SurfaceMode mode_) {
|
void SurfaceD2D::SetMode(SurfaceMode mode_) {
|
||||||
@ -1498,15 +1472,14 @@ void SurfaceD2D::D2DPenColourAlpha(ColourRGBA fore) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void SurfaceD2D::SetFontQuality(FontQuality extraFontFlag) {
|
void SurfaceD2D::SetFontQuality(FontQuality extraFontFlag) {
|
||||||
if (fontQuality != extraFontFlag) {
|
if ((fontQuality != extraFontFlag) && renderingParams) {
|
||||||
fontQuality = extraFontFlag;
|
fontQuality = extraFontFlag;
|
||||||
const D2D1_TEXT_ANTIALIAS_MODE aaMode = DWriteMapFontQuality(extraFontFlag);
|
const D2D1_TEXT_ANTIALIAS_MODE aaMode = DWriteMapFontQuality(extraFontFlag);
|
||||||
|
if (aaMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE && renderingParams->customRenderingParams) {
|
||||||
if (aaMode == D2D1_TEXT_ANTIALIAS_MODE_CLEARTYPE && customClearTypeRenderingParams)
|
pRenderTarget->SetTextRenderingParams(renderingParams->customRenderingParams.get());
|
||||||
pRenderTarget->SetTextRenderingParams(customClearTypeRenderingParams);
|
} else if (renderingParams->defaultRenderingParams) {
|
||||||
else if (defaultRenderingParams)
|
pRenderTarget->SetTextRenderingParams(renderingParams->defaultRenderingParams.get());
|
||||||
pRenderTarget->SetTextRenderingParams(defaultRenderingParams);
|
}
|
||||||
|
|
||||||
pRenderTarget->SetTextAntialiasMode(aaMode);
|
pRenderTarget->SetTextAntialiasMode(aaMode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2642,6 +2615,10 @@ void SurfaceD2D::FlushDrawing() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SurfaceD2D::SetRenderingParams(std::shared_ptr<RenderingParams> renderingParams_) {
|
||||||
|
renderingParams = renderingParams_;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
std::unique_ptr<Surface> Surface::Allocate(Technology technology) {
|
std::unique_ptr<Surface> Surface::Allocate(Technology technology) {
|
||||||
@ -3876,8 +3853,6 @@ void Platform_Initialise(void *hInstance) noexcept {
|
|||||||
void Platform_Finalise(bool fromDllMain) noexcept {
|
void Platform_Finalise(bool fromDllMain) noexcept {
|
||||||
#if defined(USE_D2D)
|
#if defined(USE_D2D)
|
||||||
if (!fromDllMain) {
|
if (!fromDllMain) {
|
||||||
ReleaseUnknown(defaultRenderingParams);
|
|
||||||
ReleaseUnknown(customClearTypeRenderingParams);
|
|
||||||
ReleaseUnknown(pIDWriteFactory);
|
ReleaseUnknown(pIDWriteFactory);
|
||||||
ReleaseUnknown(pD2DFactory);
|
ReleaseUnknown(pD2DFactory);
|
||||||
if (hDLLDWrite) {
|
if (hDLLDWrite) {
|
||||||
|
@ -53,6 +53,15 @@ HCURSOR LoadReverseArrowCursor(UINT dpi) noexcept;
|
|||||||
extern bool LoadD2D();
|
extern bool LoadD2D();
|
||||||
extern ID2D1Factory *pD2DFactory;
|
extern ID2D1Factory *pD2DFactory;
|
||||||
extern IDWriteFactory *pIDWriteFactory;
|
extern IDWriteFactory *pIDWriteFactory;
|
||||||
|
|
||||||
|
struct RenderingParams {
|
||||||
|
std::unique_ptr<IDWriteRenderingParams, UnknownReleaser> defaultRenderingParams;
|
||||||
|
std::unique_ptr<IDWriteRenderingParams, UnknownReleaser> customRenderingParams;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ISetRenderingParams {
|
||||||
|
virtual void SetRenderingParams(std::shared_ptr<RenderingParams> renderingParams_) = 0;
|
||||||
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@
|
|||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
|
||||||
#define VERSION_SCINTILLA "5.2.1"
|
#define VERSION_SCINTILLA "5.2.2"
|
||||||
#define VERSION_WORDS 5, 2, 1, 0
|
#define VERSION_WORDS 5, 2, 2, 0
|
||||||
|
|
||||||
VS_VERSION_INFO VERSIONINFO
|
VS_VERSION_INFO VERSIONINFO
|
||||||
FILEVERSION VERSION_WORDS
|
FILEVERSION VERSION_WORDS
|
||||||
|
@ -32,9 +32,9 @@
|
|||||||
#define NOMINMAX
|
#define NOMINMAX
|
||||||
#endif
|
#endif
|
||||||
#undef _WIN32_WINNT
|
#undef _WIN32_WINNT
|
||||||
#define _WIN32_WINNT 0x0500
|
#define _WIN32_WINNT 0x0A00
|
||||||
#undef WINVER
|
#undef WINVER
|
||||||
#define WINVER 0x0500
|
#define WINVER 0x0A00
|
||||||
#define WIN32_LEAN_AND_MEAN 1
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
@ -147,12 +147,6 @@ constexpr int IndicatorTarget = IndicatorInput + 1;
|
|||||||
constexpr int IndicatorConverted = IndicatorInput + 2;
|
constexpr int IndicatorConverted = IndicatorInput + 2;
|
||||||
constexpr int IndicatorUnknown = IndicatorInput + 3;
|
constexpr int IndicatorUnknown = IndicatorInput + 3;
|
||||||
|
|
||||||
#ifndef SCS_CAP_SETRECONVERTSTRING
|
|
||||||
#define SCS_CAP_SETRECONVERTSTRING 0x00000004
|
|
||||||
#define SCS_QUERYRECONVERTSTRING 0x00020000
|
|
||||||
#define SCS_SETRECONVERTSTRING 0x00010000
|
|
||||||
#endif
|
|
||||||
|
|
||||||
typedef UINT_PTR (WINAPI *SetCoalescableTimerSig)(HWND hwnd, UINT_PTR nIDEvent,
|
typedef UINT_PTR (WINAPI *SetCoalescableTimerSig)(HWND hwnd, UINT_PTR nIDEvent,
|
||||||
UINT uElapse, TIMERPROC lpTimerFunc, ULONG uToleranceDelay);
|
UINT uElapse, TIMERPROC lpTimerFunc, ULONG uToleranceDelay);
|
||||||
|
|
||||||
@ -356,6 +350,9 @@ class ScintillaWin :
|
|||||||
#if defined(USE_D2D)
|
#if defined(USE_D2D)
|
||||||
ID2D1RenderTarget *pRenderTarget;
|
ID2D1RenderTarget *pRenderTarget;
|
||||||
bool renderTargetValid;
|
bool renderTargetValid;
|
||||||
|
// rendering parameters for current monitor
|
||||||
|
HMONITOR hCurrentMonitor;
|
||||||
|
std::shared_ptr<RenderingParams> renderingParams;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
explicit ScintillaWin(HWND hwnd);
|
explicit ScintillaWin(HWND hwnd);
|
||||||
@ -368,6 +365,7 @@ class ScintillaWin :
|
|||||||
|
|
||||||
void Finalise() override;
|
void Finalise() override;
|
||||||
#if defined(USE_D2D)
|
#if defined(USE_D2D)
|
||||||
|
bool UpdateRenderingParams(bool force) noexcept;
|
||||||
void EnsureRenderTarget(HDC hdc);
|
void EnsureRenderTarget(HDC hdc);
|
||||||
#endif
|
#endif
|
||||||
void DropRenderTarget() noexcept;
|
void DropRenderTarget() noexcept;
|
||||||
@ -392,6 +390,8 @@ class ScintillaWin :
|
|||||||
Sci::Position TargetAsUTF8(char *text) const;
|
Sci::Position TargetAsUTF8(char *text) const;
|
||||||
Sci::Position EncodedFromUTF8(const char *utf8, char *encoded) const;
|
Sci::Position EncodedFromUTF8(const char *utf8, char *encoded) const;
|
||||||
|
|
||||||
|
void SetRenderingParams(Surface *psurf) const;
|
||||||
|
|
||||||
bool PaintDC(HDC hdc);
|
bool PaintDC(HDC hdc);
|
||||||
sptr_t WndPaint();
|
sptr_t WndPaint();
|
||||||
|
|
||||||
@ -571,6 +571,7 @@ ScintillaWin::ScintillaWin(HWND hwnd) {
|
|||||||
#if defined(USE_D2D)
|
#if defined(USE_D2D)
|
||||||
pRenderTarget = nullptr;
|
pRenderTarget = nullptr;
|
||||||
renderTargetValid = true;
|
renderTargetValid = true;
|
||||||
|
hCurrentMonitor = {};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
caret.period = ::GetCaretBlinkTime();
|
caret.period = ::GetCaretBlinkTime();
|
||||||
@ -615,6 +616,38 @@ void ScintillaWin::Finalise() {
|
|||||||
|
|
||||||
#if defined(USE_D2D)
|
#if defined(USE_D2D)
|
||||||
|
|
||||||
|
bool ScintillaWin::UpdateRenderingParams(bool force) noexcept {
|
||||||
|
if (!renderingParams) {
|
||||||
|
renderingParams = std::make_shared<RenderingParams>();
|
||||||
|
}
|
||||||
|
HMONITOR monitor = ::MonitorFromWindow(MainHWND(), MONITOR_DEFAULTTONEAREST);
|
||||||
|
if (!force && monitor == hCurrentMonitor && renderingParams->defaultRenderingParams) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
IDWriteRenderingParams *monitorRenderingParams = nullptr;
|
||||||
|
IDWriteRenderingParams *customClearTypeRenderingParams = nullptr;
|
||||||
|
const HRESULT hr = pIDWriteFactory->CreateMonitorRenderingParams(monitor, &monitorRenderingParams);
|
||||||
|
UINT clearTypeContrast = 0;
|
||||||
|
if (SUCCEEDED(hr) && ::SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &clearTypeContrast, 0) != 0) {
|
||||||
|
if (clearTypeContrast >= 1000 && clearTypeContrast <= 2200) {
|
||||||
|
const FLOAT gamma = static_cast<FLOAT>(clearTypeContrast) / 1000.0f;
|
||||||
|
pIDWriteFactory->CreateCustomRenderingParams(gamma,
|
||||||
|
monitorRenderingParams->GetEnhancedContrast(),
|
||||||
|
monitorRenderingParams->GetClearTypeLevel(),
|
||||||
|
monitorRenderingParams->GetPixelGeometry(),
|
||||||
|
monitorRenderingParams->GetRenderingMode(),
|
||||||
|
&customClearTypeRenderingParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hCurrentMonitor = monitor;
|
||||||
|
renderingParams->defaultRenderingParams.reset(monitorRenderingParams);
|
||||||
|
renderingParams->customRenderingParams.reset(customClearTypeRenderingParams);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ScintillaWin::EnsureRenderTarget(HDC hdc) {
|
void ScintillaWin::EnsureRenderTarget(HDC hdc) {
|
||||||
if (!renderTargetValid) {
|
if (!renderTargetValid) {
|
||||||
DropRenderTarget();
|
DropRenderTarget();
|
||||||
@ -684,7 +717,6 @@ void ScintillaWin::EnsureRenderTarget(HDC hdc) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
void ScintillaWin::DropRenderTarget() noexcept {
|
void ScintillaWin::DropRenderTarget() noexcept {
|
||||||
#if defined(USE_D2D)
|
#if defined(USE_D2D)
|
||||||
ReleaseUnknown(pRenderTarget);
|
ReleaseUnknown(pRenderTarget);
|
||||||
@ -911,6 +943,17 @@ Sci::Position ScintillaWin::EncodedFromUTF8(const char *utf8, char *encoded) con
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScintillaWin::SetRenderingParams([[maybe_unused]] Surface *psurf) const {
|
||||||
|
#if defined(USE_D2D)
|
||||||
|
if (psurf) {
|
||||||
|
ISetRenderingParams *setDrawingParams = dynamic_cast<ISetRenderingParams *>(psurf);
|
||||||
|
if (setDrawingParams) {
|
||||||
|
setDrawingParams->SetRenderingParams(renderingParams);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
bool ScintillaWin::PaintDC(HDC hdc) {
|
bool ScintillaWin::PaintDC(HDC hdc) {
|
||||||
if (technology == Technology::Default) {
|
if (technology == Technology::Default) {
|
||||||
AutoSurface surfaceWindow(hdc, this);
|
AutoSurface surfaceWindow(hdc, this);
|
||||||
@ -924,6 +967,7 @@ bool ScintillaWin::PaintDC(HDC hdc) {
|
|||||||
if (pRenderTarget) {
|
if (pRenderTarget) {
|
||||||
AutoSurface surfaceWindow(pRenderTarget, this);
|
AutoSurface surfaceWindow(pRenderTarget, this);
|
||||||
if (surfaceWindow) {
|
if (surfaceWindow) {
|
||||||
|
SetRenderingParams(surfaceWindow);
|
||||||
pRenderTarget->BeginDraw();
|
pRenderTarget->BeginDraw();
|
||||||
Paint(surfaceWindow, rcPaint);
|
Paint(surfaceWindow, rcPaint);
|
||||||
surfaceWindow->Release();
|
surfaceWindow->Release();
|
||||||
@ -1887,9 +1931,11 @@ sptr_t ScintillaWin::SciMessage(Message iMessage, uptr_t wParam, sptr_t lParam)
|
|||||||
if (technology != technologyNew) {
|
if (technology != technologyNew) {
|
||||||
if (technologyNew > Technology::Default) {
|
if (technologyNew > Technology::Default) {
|
||||||
#if defined(USE_D2D)
|
#if defined(USE_D2D)
|
||||||
if (!LoadD2D())
|
if (!LoadD2D()) {
|
||||||
// Failed to load Direct2D or DirectWrite so no effect
|
// Failed to load Direct2D or DirectWrite so no effect
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
UpdateRenderingParams(true);
|
||||||
#else
|
#else
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
@ -1900,7 +1946,6 @@ sptr_t ScintillaWin::SciMessage(Message iMessage, uptr_t wParam, sptr_t lParam)
|
|||||||
technology = technologyNew;
|
technology = technologyNew;
|
||||||
view.bufferedDraw = technologyNew == Technology::Default;
|
view.bufferedDraw = technologyNew == Technology::Default;
|
||||||
// Invalidate all cached information including layout.
|
// Invalidate all cached information including layout.
|
||||||
DropGraphics();
|
|
||||||
InvalidateStyleRedraw();
|
InvalidateStyleRedraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1913,7 +1958,6 @@ sptr_t ScintillaWin::SciMessage(Message iMessage, uptr_t wParam, sptr_t lParam)
|
|||||||
bidirectional = static_cast<Bidirectional>(wParam);
|
bidirectional = static_cast<Bidirectional>(wParam);
|
||||||
}
|
}
|
||||||
// Invalidate all cached information including layout.
|
// Invalidate all cached information including layout.
|
||||||
DropGraphics();
|
|
||||||
InvalidateStyleRedraw();
|
InvalidateStyleRedraw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -2017,10 +2061,15 @@ sptr_t ScintillaWin::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
|
|||||||
|
|
||||||
case WM_SETTINGCHANGE:
|
case WM_SETTINGCHANGE:
|
||||||
//Platform::DebugPrintf("Setting Changed\n");
|
//Platform::DebugPrintf("Setting Changed\n");
|
||||||
|
#if defined(USE_D2D)
|
||||||
|
if (technology != Technology::Default) {
|
||||||
|
UpdateRenderingParams(true);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
UpdateBaseElements();
|
UpdateBaseElements();
|
||||||
InvalidateStyleData();
|
|
||||||
// Get Intellimouse scroll line parameters
|
// Get Intellimouse scroll line parameters
|
||||||
GetIntelliMouseParameters();
|
GetIntelliMouseParameters();
|
||||||
|
InvalidateStyleRedraw();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_GETDLGCODE:
|
case WM_GETDLGCODE:
|
||||||
@ -2081,7 +2130,17 @@ sptr_t ScintillaWin::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
|
|||||||
case WM_NCLBUTTONDOWN:
|
case WM_NCLBUTTONDOWN:
|
||||||
case WM_SYSCOMMAND:
|
case WM_SYSCOMMAND:
|
||||||
case WM_WINDOWPOSCHANGING:
|
case WM_WINDOWPOSCHANGING:
|
||||||
|
return ::DefWindowProc(MainHWND(), msg, wParam, lParam);
|
||||||
|
|
||||||
case WM_WINDOWPOSCHANGED:
|
case WM_WINDOWPOSCHANGED:
|
||||||
|
#if defined(USE_D2D)
|
||||||
|
if (technology != Technology::Default) {
|
||||||
|
if (UpdateRenderingParams(false)) {
|
||||||
|
DropGraphics();
|
||||||
|
Redraw();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return ::DefWindowProc(MainHWND(), msg, wParam, lParam);
|
return ::DefWindowProc(MainHWND(), msg, wParam, lParam);
|
||||||
|
|
||||||
case WM_GETTEXTLENGTH:
|
case WM_GETTEXTLENGTH:
|
||||||
@ -3562,11 +3621,11 @@ LRESULT PASCAL ScintillaWin::CTWndProc(
|
|||||||
#endif
|
#endif
|
||||||
RECT rc;
|
RECT rc;
|
||||||
GetClientRect(hWnd, &rc);
|
GetClientRect(hWnd, &rc);
|
||||||
// Create a Direct2D render target.
|
|
||||||
if (sciThis->technology == Technology::Default) {
|
if (sciThis->technology == Technology::Default) {
|
||||||
surfaceWindow->Init(ps.hdc, hWnd);
|
surfaceWindow->Init(ps.hdc, hWnd);
|
||||||
} else {
|
} else {
|
||||||
#if defined(USE_D2D)
|
#if defined(USE_D2D)
|
||||||
|
// Create a Direct2D render target.
|
||||||
D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp {};
|
D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp {};
|
||||||
dhrtp.hwnd = hWnd;
|
dhrtp.hwnd = hWnd;
|
||||||
dhrtp.pixelSize = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
|
dhrtp.pixelSize = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
|
||||||
@ -3595,7 +3654,8 @@ LRESULT PASCAL ScintillaWin::CTWndProc(
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
surfaceWindow->SetMode(SurfaceMode(sciThis->ct.codePage, sciThis->BidirectionalR2L()));
|
surfaceWindow->SetMode(sciThis->CurrentSurfaceMode());
|
||||||
|
sciThis->SetRenderingParams(surfaceWindow.get());
|
||||||
sciThis->ct.PaintCT(surfaceWindow.get());
|
sciThis->ct.PaintCT(surfaceWindow.get());
|
||||||
#if defined(USE_D2D)
|
#if defined(USE_D2D)
|
||||||
if (pCTRenderTarget)
|
if (pCTRenderTarget)
|
||||||
|
@ -21,7 +21,7 @@ LD=link
|
|||||||
!IFDEF SUPPORT_XP
|
!IFDEF SUPPORT_XP
|
||||||
ADD_DEFINE=-D_USING_V110_SDK71_
|
ADD_DEFINE=-D_USING_V110_SDK71_
|
||||||
# Different subsystems for 32-bit and 64-bit Windows XP so detect based on Platform
|
# Different subsystems for 32-bit and 64-bit Windows XP so detect based on Platform
|
||||||
# environment vairable set by vcvars*.bat to be either x86 or x64
|
# environment variable set by vcvars*.bat to be either x86 or x64
|
||||||
!IF "$(PLATFORM)" == "x64"
|
!IF "$(PLATFORM)" == "x64"
|
||||||
SUBSYSTEM=-SUBSYSTEM:WINDOWS,5.02
|
SUBSYSTEM=-SUBSYSTEM:WINDOWS,5.02
|
||||||
!ELSE
|
!ELSE
|
||||||
|
Loading…
x
Reference in New Issue
Block a user