aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.hgtags3
-rw-r--r--call/ScintillaCall.cxx8
-rw-r--r--cocoa/Scintilla/Info.plist2
-rw-r--r--cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj8
-rw-r--r--cppcheck.suppress3
-rw-r--r--doc/ScintillaDoc.html16
-rw-r--r--doc/ScintillaDownload.html10
-rw-r--r--doc/ScintillaHistory.html62
-rw-r--r--doc/index.html11
-rw-r--r--include/Scintilla.h3
-rw-r--r--include/Scintilla.iface8
-rw-r--r--include/ScintillaCall.h2
-rw-r--r--include/ScintillaMessages.h2
-rw-r--r--include/ScintillaTypes.h1
-rw-r--r--qt/ScintillaEdit/ScintillaDocument.cpp47
-rw-r--r--qt/ScintillaEdit/ScintillaDocument.h40
-rw-r--r--qt/ScintillaEdit/ScintillaEdit.cpp.template8
-rw-r--r--qt/ScintillaEdit/ScintillaEdit.h.template14
-rw-r--r--qt/ScintillaEdit/ScintillaEdit.pro2
-rw-r--r--qt/ScintillaEditBase/ScintillaEditBase.pro2
-rw-r--r--src/DBCS.cxx37
-rw-r--r--src/DBCS.h6
-rw-r--r--src/Document.cxx44
-rw-r--r--src/Document.h6
-rw-r--r--src/EditModel.cxx4
-rw-r--r--src/EditModel.h1
-rw-r--r--src/EditView.cxx417
-rw-r--r--src/EditView.h9
-rw-r--r--src/Editor.cxx49
-rw-r--r--src/Editor.h1
-rw-r--r--src/Geometry.h3
-rw-r--r--src/PositionCache.cxx9
-rw-r--r--src/PositionCache.h3
-rw-r--r--src/Selection.cxx28
-rw-r--r--src/Selection.h2
-rw-r--r--src/Style.cxx6
-rw-r--r--src/ViewStyle.cxx55
-rw-r--r--test/simpleTests.py29
-rw-r--r--test/unit/testSelection.cxx90
-rw-r--r--version.txt2
-rw-r--r--win32/ListBox.cxx12
-rw-r--r--win32/PlatWin.cxx24
-rw-r--r--win32/PlatWin.h5
-rw-r--r--win32/ScintRes.rc4
-rw-r--r--win32/ScintillaWin.cxx62
45 files changed, 733 insertions, 427 deletions
diff --git a/.hgtags b/.hgtags
index d465345dd..cec25cb57 100644
--- a/.hgtags
+++ b/.hgtags
@@ -216,3 +216,6 @@ c171b756efc76359f0795ca0a1bfb7eb16d4c04b rel-5-4-3
5cb9af9b3103ffa3c8c4e3c15887191486de260f rel-5-5-5
68ddcf0a91ee2763cfc148925917bf609b355948 rel-5-5-6
ba0e2f317940a65f8f16325cbe4234fd75a6d47b rel-5-5-7
+afc75d68d333f449ad52fce35ff40a5eddadf5c8 rel-5-5-8
+76c8666d51407d156417e4b4a293a5e9ed29087f rel-5-5-9
+a951931386960b1c5045652c9b93e79b669e9728 rel-5-6-0
diff --git a/call/ScintillaCall.cxx b/call/ScintillaCall.cxx
index d1d4012b2..093cf9a0d 100644
--- a/call/ScintillaCall.cxx
+++ b/call/ScintillaCall.cxx
@@ -3391,6 +3391,14 @@ Position ScintillaCall::IndexPositionFromLine(Line line, Scintilla::LineCharacte
return Call(Message::IndexPositionFromLine, line, static_cast<intptr_t>(lineCharacterIndex));
}
+bool ScintillaCall::DragDropEnabled() {
+ return Call(Message::GetDragDropEnabled);
+}
+
+void ScintillaCall::SetDragDropEnabled(bool dragDropEnabled) {
+ Call(Message::SetDragDropEnabled, dragDropEnabled);
+}
+
void ScintillaCall::StartRecord() {
Call(Message::StartRecord);
}
diff --git a/cocoa/Scintilla/Info.plist b/cocoa/Scintilla/Info.plist
index f5ce998da..195a18222 100644
--- a/cocoa/Scintilla/Info.plist
+++ b/cocoa/Scintilla/Info.plist
@@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
- <string>5.5.7</string>
+ <string>5.6.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
diff --git a/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj b/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj
index 00b77029b..eb28817b1 100644
--- a/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj
+++ b/cocoa/Scintilla/Scintilla.xcodeproj/project.pbxproj
@@ -586,7 +586,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 5.5.7;
+ CURRENT_PROJECT_VERSION = 5.6.0;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -650,7 +650,7 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
- CURRENT_PROJECT_VERSION = 5.5.7;
+ CURRENT_PROJECT_VERSION = 5.6.0;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
@@ -682,7 +682,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 5.5.7;
+ CURRENT_PROJECT_VERSION = 5.6.0;
DEAD_CODE_STRIPPING = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
@@ -717,7 +717,7 @@
CODE_SIGN_IDENTITY = "-";
CODE_SIGN_STYLE = Manual;
COMBINE_HIDPI_IMAGES = YES;
- CURRENT_PROJECT_VERSION = 5.5.7;
+ CURRENT_PROJECT_VERSION = 5.6.0;
DEAD_CODE_STRIPPING = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = "";
diff --git a/cppcheck.suppress b/cppcheck.suppress
index b8483fedf..812b65277 100644
--- a/cppcheck.suppress
+++ b/cppcheck.suppress
@@ -47,6 +47,9 @@ constParameterPointer:scintilla/win32/ScintillaWin.cxx
knownConditionTrueFalse:scintilla/src/Editor.cxx
knownConditionTrueFalse:scintilla/src/EditView.cxx
+// This makes no sense
+CastIntegerToAddressAtReturn:scintilla\src\DBCS.cxx
+
// G_DEFINE_TYPE is too complex to pass to cppcheck
unknownMacro:scintilla/gtk/PlatGTK.cxx
// G_END_DECLS
diff --git a/doc/ScintillaDoc.html b/doc/ScintillaDoc.html
index 0dfe986f4..3189a001a 100644
--- a/doc/ScintillaDoc.html
+++ b/doc/ScintillaDoc.html
@@ -482,6 +482,8 @@
*text)</a><br />
<a class="message" href="#SCI_SETREADONLY">SCI_SETREADONLY(bool readOnly)</a><br />
<a class="message" href="#SCI_GETREADONLY">SCI_GETREADONLY &rarr; bool</a><br />
+ <a class="message" href="#SCI_GETDRAGDROPENABLED">SCI_GETDRAGDROPENABLED &rarr; bool</a><br />
+ <a class="message" href="#SCI_SETDRAGDROPENABLED">SCI_SETDRAGDROPENABLED(bool dragDropEnabled)</a><br />
<a class="message" href="#SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(&lt;unused&gt;, Sci_TextRange *tr) &rarr; position</a><br />
<a class="message" href="#SCI_GETTEXTRANGEFULL">SCI_GETTEXTRANGEFULL(&lt;unused&gt;, Sci_TextRangeFull *tr) &rarr; position</a><br />
<a class="message" href="#SCI_ALLOCATE">SCI_ALLOCATE(position bytes)</a><br />
@@ -568,6 +570,10 @@
only, attempts to modify the text cause the <a class="message"
href="#SCN_MODIFYATTEMPTRO"><code>SCN_MODIFYATTEMPTRO</code></a> notification.</p>
+ <p><b id="SCI_GETDRAGDROPENABLED">SCI_GETDRAGDROPENABLED &rarr; bool</b><br />
+ <b id="SCI_SETDRAGDROPENABLED">SCI_SETDRAGDROPENABLED(bool dragDropEnabled)</b><br />
+ These messages get and set the flag controlling whether drag-and-drop is enabled or not.</p>
+
<p>
<b id="SCI_GETTEXTRANGE">SCI_GETTEXTRANGE(&lt;unused&gt;, <a class="jump" href="#Sci_TextRange">Sci_TextRange</a> *tr) &rarr; position</b><br />
<b id="SCI_GETTEXTRANGEFULL">SCI_GETTEXTRANGEFULL(&lt;unused&gt;, <a class="jump" href="#Sci_TextRangeFull">Sci_TextRangeFull</a> *tr) &rarr; position</b><br />
@@ -2884,6 +2890,16 @@ struct Sci_TextToFindFull {
<td>A horizontal line stretching until the tabstop.</td>
</tr>
+
+ <tr>
+ <th align="left"><code>SCTD_CONTROLCHAR</code></th>
+
+ <td>2</td>
+
+ <td>Will be drawn as a control code according to the configured
+ <a href="#CharacterRepresentations">character representation</a>
+ without any indentation.</td>
+ </tr>
</tbody>
</table>
diff --git a/doc/ScintillaDownload.html b/doc/ScintillaDownload.html
index 8d142b0ff..59ef4b721 100644
--- a/doc/ScintillaDownload.html
+++ b/doc/ScintillaDownload.html
@@ -26,9 +26,9 @@
<table bgcolor="#CCCCCC" width="100%" cellspacing="0" cellpadding="8" border="0">
<tr>
<td>
- <font size="4"> <a href="https://www.scintilla.org/scintilla557.zip">
+ <font size="4"> <a href="https://www.scintilla.org/scintilla560.zip">
Windows</a>&nbsp;&nbsp;
- <a href="https://www.scintilla.org/scintilla557.tgz">
+ <a href="https://www.scintilla.org/scintilla560.tgz">
GTK/Linux</a>&nbsp;&nbsp;
</font>
</td>
@@ -42,7 +42,7 @@
containing very few restrictions.
</p>
<h3>
- Release 5.5.7
+ Release 5.6.0
</h3>
<h4>
Source Code
@@ -50,8 +50,8 @@
The source code package contains all of the source code for Scintilla but no binary
executable code and is available in
<ul>
- <li><a href="https://www.scintilla.org/scintilla557.zip">zip format</a> (1.8M) commonly used on Windows</li>
- <li><a href="https://www.scintilla.org/scintilla557.tgz">tgz format</a> (1.7M) commonly used on Linux and compatible operating systems</li>
+ <li><a href="https://www.scintilla.org/scintilla560.zip">zip format</a> (1.8M) commonly used on Windows</li>
+ <li><a href="https://www.scintilla.org/scintilla560.tgz">tgz format</a> (1.7M) commonly used on Linux and compatible operating systems</li>
</ul>
Instructions for building on both Windows and Linux are included in the readme file.
<h4>
diff --git a/doc/ScintillaHistory.html b/doc/ScintillaHistory.html
index b63c9851d..26333e1be 100644
--- a/doc/ScintillaHistory.html
+++ b/doc/ScintillaHistory.html
@@ -591,15 +591,75 @@
</tr><tr>
<td>Ahmet Sait</td>
<td>Sven Ritter</td>
+ <td>Stefan Löffler</td>
+ <td>Nathaniel Braun</td>
</tr>
</table>
<h2 id="Releases">Releases</h2>
<h3>
+ <a href="https://www.scintilla.org/scintilla561.zip">Release 5.6.1</a>
+ </h3>
+ <ul>
+ <li>
+ Released 25 February 2026.
+ </li>
+ <li>
+ Add mode to draw tabs as [HT] blobs with SCI_SETTABDRAWMODE(SCTD_CONTROLCHAR).
+ </li>
+ </ul>
+ <h3>
+ <a href="https://www.scintilla.org/scintilla560.zip">Release 5.6.0</a>
+ </h3>
+ <ul>
+ <li>
+ Released 25 February 2026.
+ </li>
+ <li>
+ Fix crash when window is too narrow to show any text.
+ </li>
+ </ul>
+ <h3>
+ <a href="https://www.scintilla.org/scintilla559.zip">Release 5.5.9</a>
+ </h3>
+ <ul>
+ <li>
+ Released 25 February 2026.
+ </li>
+ <li>
+ Add option to disable drag/drop editing.
+ <a href="https://sourceforge.net/p/scintilla/feature-requests/184/">Feature #184</a>.
+ </li>
+ <li>
+ Allow Euro '&euro;' in code page 936 for 0x80.
+ <a href="https://sourceforge.net/p/scintilla/feature-requests/1575/">Feature #1575</a>.
+ </li>
+ <li>
+ Fix SCI_SETSELECTIONNSTART and SCI_SETSELECTIONNEND to behave more sensibly.
+ <a href="https://sourceforge.net/p/scintilla/bugs/2488/">Bug #2488</a>.
+ </li>
+ <li>
+ Fix lexing after undo at end of document.
+ <a href="https://sourceforge.net/p/scintilla/bugs/2491/">Bug #2491</a>.
+ </li>
+ <li>
+ When a line end is not selected, change the colour of the rectangle that indicates the line end is selected
+ to white space background instead of previous character's background except for EOL filled style.
+ </li>
+ <li>
+ On Qt, add const to ScintillaDocument and ScintillaEdit methods.
+ <a href="https://sourceforge.net/p/scintilla/bugs/2494/">Bug #2494</a>.
+ </li>
+ <li>
+ On Qt, prevent crash when using ScintillaDocument object.
+ <a href="https://sourceforge.net/p/scintilla/bugs/2495/">Bug #2495</a>.
+ </li>
+ </ul>
+ <h3>
<a href="https://www.scintilla.org/scintilla558.zip">Release 5.5.8</a>
</h3>
<ul>
<li>
- Released 8 June 2025.
+ Released 10 November 2025.
</li>
<li>
Change format for SCI_GETSELECTIONSERIALIZED.
diff --git a/doc/index.html b/doc/index.html
index aed89ac40..69fe4a270 100644
--- a/doc/index.html
+++ b/doc/index.html
@@ -9,7 +9,7 @@
<meta name="keywords" content="Scintilla, SciTE, Editing Component, Text Editor" />
<meta name="Description"
content="www.scintilla.org is the home of the Scintilla editing component and SciTE text editor application." />
- <meta name="Date.Modified" content="20250608" />
+ <meta name="Date.Modified" content="20260225" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<style type="text/css">
.logo {
@@ -61,8 +61,8 @@
GTK, and macOS</font>
</td>
<td width="40%" align="right">
- <font color="#FFCC99" size="3"> Release version 5.5.7<br />
- Site last modified June 8 2025</font>
+ <font color="#FFCC99" size="3"> Release version 5.6.0<br />
+ Site last modified February 25 2026</font>
</td>
<td width="20%">
&nbsp;
@@ -77,11 +77,12 @@
</tr>
</table>
<ul id="versionlist">
+ <li>Version 5.6.0 fixes crash when window is too narrow to show any text.</li>
+ <li>Version 5.5.9 adds an option to disable drag &amp; drop. Fixes colour after line end.</li>
+ <li>Version 5.5.8 changes format of SCI_GETSELECTIONSERIALIZED and fixes redraw after undo.</li>
<li>Version 5.5.7 can prevent storing scroll position in undo selection history and adds a wrap-aware SCI_SCROLLVERTICAL API.</li>
<li>Version 5.5.6 improves DBCS and autocompletion drawing on Win32 and improves dwell, encoding and text clipping on Qt.</li>
<li>Version 5.5.5 can remember selection with undo and redo. Update to use DirectWrite 1.1.</li>
- <li>Version 5.5.4 fixes wrapping of removed lines and edge cases for moving lines. On GTK, middle click can be repeated with one value.</li>
- <li>Version 5.5.3 fixes horizontal scrolling with a touchpad on Win32.</li>
</ul>
<ul id="menu">
<li id="remote1"><a href="https://www.scintilla.org/SciTEImage.html">Screenshot</a></li>
diff --git a/include/Scintilla.h b/include/Scintilla.h
index f7afa4f50..94a66d4f8 100644
--- a/include/Scintilla.h
+++ b/include/Scintilla.h
@@ -78,6 +78,7 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SCI_SETVIEWWS 2021
#define SCTD_LONGARROW 0
#define SCTD_STRIKEOUT 1
+#define SCTD_CONTROLCHAR 2
#define SCI_GETTABDRAWMODE 2698
#define SCI_SETTABDRAWMODE 2699
#define SCI_POSITIONFROMPOINT 2022
@@ -1194,6 +1195,8 @@ typedef sptr_t (*SciFnDirectStatus)(sptr_t ptr, unsigned int iMessage, uptr_t wP
#define SCI_RELEASELINECHARACTERINDEX 2712
#define SCI_LINEFROMINDEXPOSITION 2713
#define SCI_INDEXPOSITIONFROMLINE 2714
+#define SCI_GETDRAGDROPENABLED 2818
+#define SCI_SETDRAGDROPENABLED 2819
#define SCI_STARTRECORD 3001
#define SCI_STOPRECORD 3002
#define SCI_GETLEXER 4002
diff --git a/include/Scintilla.iface b/include/Scintilla.iface
index 9ba834aed..d98ac8358 100644
--- a/include/Scintilla.iface
+++ b/include/Scintilla.iface
@@ -196,9 +196,11 @@ set void SetViewWS=2021(WhiteSpace viewWS,)
enu TabDrawMode=SCTD_
val SCTD_LONGARROW=0
val SCTD_STRIKEOUT=1
+val SCTD_CONTROLCHAR=2
ali SCTD_LONGARROW=LONG_ARROW
ali SCTD_STRIKEOUT=STRIKE_OUT
+ali SCTD_CONTROLCHAR=CONTROL_CHAR
# Retrieve the current tab draw mode.
# Returns one of SCTD_* constants.
@@ -3258,6 +3260,12 @@ fun line LineFromIndexPosition=2713(position pos, LineCharacterIndexType lineCha
# Retrieve the position measured in index units at the start of a document line.
fun position IndexPositionFromLine=2714(line line, LineCharacterIndexType lineCharacterIndex)
+# Get whether drag-and-drop is enabled or disabled
+get bool GetDragDropEnabled=2818(,)
+
+# Enable or disable drag-and-drop
+set void SetDragDropEnabled=2819(bool dragDropEnabled,)
+
# Start notifying the container of all key presses and commands.
fun void StartRecord=3001(,)
diff --git a/include/ScintillaCall.h b/include/ScintillaCall.h
index 7a98c7e3d..2c065c03f 100644
--- a/include/ScintillaCall.h
+++ b/include/ScintillaCall.h
@@ -893,6 +893,8 @@ public:
void ReleaseLineCharacterIndex(Scintilla::LineCharacterIndexType lineCharacterIndex);
Line LineFromIndexPosition(Position pos, Scintilla::LineCharacterIndexType lineCharacterIndex);
Position IndexPositionFromLine(Line line, Scintilla::LineCharacterIndexType lineCharacterIndex);
+ bool DragDropEnabled();
+ void SetDragDropEnabled(bool dragDropEnabled);
void StartRecord();
void StopRecord();
int Lexer();
diff --git a/include/ScintillaMessages.h b/include/ScintillaMessages.h
index 6a33f5c6d..d327bf7c1 100644
--- a/include/ScintillaMessages.h
+++ b/include/ScintillaMessages.h
@@ -799,6 +799,8 @@ enum class Message {
ReleaseLineCharacterIndex = 2712,
LineFromIndexPosition = 2713,
IndexPositionFromLine = 2714,
+ GetDragDropEnabled = 2818,
+ SetDragDropEnabled = 2819,
StartRecord = 3001,
StopRecord = 3002,
GetLexer = 4002,
diff --git a/include/ScintillaTypes.h b/include/ScintillaTypes.h
index 0991a1480..a1e55c203 100644
--- a/include/ScintillaTypes.h
+++ b/include/ScintillaTypes.h
@@ -26,6 +26,7 @@ enum class WhiteSpace {
enum class TabDrawMode {
LongArrow = 0,
StrikeOut = 1,
+ ControlChar = 2,
};
enum class EndOfLine {
diff --git a/qt/ScintillaEdit/ScintillaDocument.cpp b/qt/ScintillaEdit/ScintillaDocument.cpp
index fc5ef2ec3..f532f2726 100644
--- a/qt/ScintillaEdit/ScintillaDocument.cpp
+++ b/qt/ScintillaEdit/ScintillaDocument.cpp
@@ -2,6 +2,8 @@
// Wrapper for Scintilla document object so it can be manipulated independently.
// Copyright (c) 2011 Archaeopteryx Software, Inc. d/b/a Wingware
+#include <cstdint>
+
#include <stdexcept>
#include <string_view>
#include <vector>
@@ -99,8 +101,9 @@ ScintillaDocument::ScintillaDocument(QObject *parent, void *pdoc_) :
pdoc = new Document(DocumentOption::Default);
}
docWatcher = new WatcherHelper(this);
- (static_cast<Document *>(pdoc))->AddRef();
- (static_cast<Document *>(pdoc))->AddWatcher(docWatcher, pdoc);
+ Document *doc = static_cast<Document *>(pdoc);
+ doc->AddRef();
+ doc->AddWatcher(docWatcher, doc);
}
ScintillaDocument::~ScintillaDocument() {
@@ -114,15 +117,15 @@ ScintillaDocument::~ScintillaDocument() {
docWatcher = nullptr;
}
-void *ScintillaDocument::pointer() {
+void *ScintillaDocument::pointer() const {
return pdoc;
}
-int ScintillaDocument::line_from_position(int pos) {
+int ScintillaDocument::line_from_position(int pos) const {
return (static_cast<Document *>(pdoc))->LineFromPosition(pos);
}
-bool ScintillaDocument::is_cr_lf(int pos) {
+bool ScintillaDocument::is_cr_lf(int pos) const {
return (static_cast<Document *>(pdoc))->IsCrLf(pos);
}
@@ -138,11 +141,11 @@ int ScintillaDocument::redo() {
return (static_cast<Document *>(pdoc))->Redo();
}
-bool ScintillaDocument::can_undo() {
+bool ScintillaDocument::can_undo() const {
return (static_cast<Document *>(pdoc))->CanUndo();
}
-bool ScintillaDocument::can_redo() {
+bool ScintillaDocument::can_redo() const {
return (static_cast<Document *>(pdoc))->CanRedo();
}
@@ -154,7 +157,7 @@ bool ScintillaDocument::set_undo_collection(bool collect_undo) {
return (static_cast<Document *>(pdoc))->SetUndoCollection(collect_undo);
}
-bool ScintillaDocument::is_collecting_undo() {
+bool ScintillaDocument::is_collecting_undo() const {
return (static_cast<Document *>(pdoc))->IsCollectingUndo();
}
@@ -170,7 +173,7 @@ void ScintillaDocument::set_save_point() {
(static_cast<Document *>(pdoc))->SetSavePoint();
}
-bool ScintillaDocument::is_save_point() {
+bool ScintillaDocument::is_save_point() const {
return (static_cast<Document *>(pdoc))->IsSavePoint();
}
@@ -178,15 +181,15 @@ void ScintillaDocument::set_read_only(bool read_only) {
(static_cast<Document *>(pdoc))->SetReadOnly(read_only);
}
-bool ScintillaDocument::is_read_only() {
+bool ScintillaDocument::is_read_only() const {
return (static_cast<Document *>(pdoc))->IsReadOnly();
}
-void ScintillaDocument::insert_string(int position, QByteArray &str) {
+void ScintillaDocument::insert_string(int position, const QByteArray &str) {
(static_cast<Document *>(pdoc))->InsertString(position, str.data(), str.size());
}
-QByteArray ScintillaDocument::get_char_range(int position, int length) {
+QByteArray ScintillaDocument::get_char_range(int position, int length) const {
const Document *doc = static_cast<Document *>(pdoc);
if (position < 0 || length <= 0 || position + length > doc->Length())
@@ -197,27 +200,27 @@ QByteArray ScintillaDocument::get_char_range(int position, int length) {
return ba;
}
-char ScintillaDocument::style_at(int position) {
+char ScintillaDocument::style_at(int position) const {
return (static_cast<Document *>(pdoc))->StyleAt(position);
}
-int ScintillaDocument::line_start(int lineno) {
+int ScintillaDocument::line_start(int lineno) const {
return (static_cast<Document *>(pdoc))->LineStart(lineno);
}
-int ScintillaDocument::line_end(int lineno) {
+int ScintillaDocument::line_end(int lineno) const {
return (static_cast<Document *>(pdoc))->LineEnd(lineno);
}
-int ScintillaDocument::line_end_position(int pos) {
+int ScintillaDocument::line_end_position(int pos) const {
return (static_cast<Document *>(pdoc))->LineEndPosition(pos);
}
-int ScintillaDocument::length() {
+int ScintillaDocument::length() const {
return (static_cast<Document *>(pdoc))->Length();
}
-int ScintillaDocument::lines_total() {
+int ScintillaDocument::lines_total() const {
return (static_cast<Document *>(pdoc))->LinesTotal();
}
@@ -229,7 +232,7 @@ bool ScintillaDocument::set_style_for(int length, char style) {
return (static_cast<Document *>(pdoc))->SetStyleFor(length, style);
}
-int ScintillaDocument::get_end_styled() {
+int ScintillaDocument::get_end_styled() const {
return (static_cast<Document *>(pdoc))->GetEndStyled();
}
@@ -257,7 +260,7 @@ int ScintillaDocument::decorations_end(int indic, int position) {
return (static_cast<Document *>(pdoc))->decorations->End(indic, position);
}
-int ScintillaDocument::get_code_page() {
+int ScintillaDocument::get_code_page() const {
return (static_cast<Document *>(pdoc))->CodePage();
}
@@ -265,7 +268,7 @@ void ScintillaDocument::set_code_page(int code_page) {
(static_cast<Document *>(pdoc))->dbcsCodePage = code_page;
}
-int ScintillaDocument::get_eol_mode() {
+int ScintillaDocument::get_eol_mode() const {
return static_cast<int>((static_cast<Document *>(pdoc))->eolMode);
}
@@ -277,6 +280,6 @@ int ScintillaDocument::move_position_outside_char(int pos, int move_dir, bool ch
return (static_cast<Document *>(pdoc))->MovePositionOutsideChar(pos, move_dir, check_line_end);
}
-int ScintillaDocument::get_character(int pos) {
+int ScintillaDocument::get_character(int pos) const {
return (static_cast<Document *>(pdoc))->GetCharacterAndWidth(pos, nullptr);
}
diff --git a/qt/ScintillaEdit/ScintillaDocument.h b/qt/ScintillaEdit/ScintillaDocument.h
index fa129d53b..2e68b8aa1 100644
--- a/qt/ScintillaEdit/ScintillaDocument.h
+++ b/qt/ScintillaEdit/ScintillaDocument.h
@@ -38,48 +38,48 @@ class EXPORT_IMPORT_API ScintillaDocument : public QObject
public:
explicit ScintillaDocument(QObject *parent = 0, void *pdoc_=0);
virtual ~ScintillaDocument();
- void *pointer();
+ void *pointer() const;
- int line_from_position(int pos);
- bool is_cr_lf(int pos);
+ int line_from_position(int pos) const;
+ bool is_cr_lf(int pos) const;
bool delete_chars(int pos, int len);
int undo();
int redo();
- bool can_undo();
- bool can_redo();
+ bool can_undo() const;
+ bool can_redo() const;
void delete_undo_history();
bool set_undo_collection(bool collect_undo);
- bool is_collecting_undo();
+ bool is_collecting_undo() const;
void begin_undo_action(bool coalesceWithPrior = false);
void end_undo_action();
void set_save_point();
- bool is_save_point();
+ bool is_save_point() const;
void set_read_only(bool read_only);
- bool is_read_only();
- void insert_string(int position, QByteArray &str);
- QByteArray get_char_range(int position, int length);
- char style_at(int position);
- int line_start(int lineno);
- int line_end(int lineno);
- int line_end_position(int pos);
- int length();
- int lines_total();
+ bool is_read_only() const;
+ void insert_string(int position, const QByteArray &str);
+ QByteArray get_char_range(int position, int length) const;
+ char style_at(int position) const;
+ int line_start(int lineno) const;
+ int line_end(int lineno) const;
+ int line_end_position(int pos) const;
+ int length() const;
+ int lines_total() const;
void start_styling(int position);
bool set_style_for(int length, char style);
- int get_end_styled();
+ int get_end_styled() const;
void ensure_styled_to(int position);
void set_current_indicator(int indic);
void decoration_fill_range(int position, int value, int fillLength);
int decorations_value_at(int indic, int position);
int decorations_start(int indic, int position);
int decorations_end(int indic, int position);
- int get_code_page();
+ int get_code_page() const;
void set_code_page(int code_page);
- int get_eol_mode();
+ int get_eol_mode() const;
void set_eol_mode(int eol_mode);
int move_position_outside_char(int pos, int move_dir, bool check_line_end);
- int get_character(int pos); // Calls GetCharacterAndWidth(pos, NULL)
+ int get_character(int pos) const; // Calls GetCharacterAndWidth(pos, NULL)
signals:
void modify_attempt();
diff --git a/qt/ScintillaEdit/ScintillaEdit.cpp.template b/qt/ScintillaEdit/ScintillaEdit.cpp.template
index a46a1d12d..a2deb91de 100644
--- a/qt/ScintillaEdit/ScintillaEdit.cpp.template
+++ b/qt/ScintillaEdit/ScintillaEdit.cpp.template
@@ -23,7 +23,7 @@ QByteArray ScintillaEdit::TextReturner(int message, uptr_t wParam) const {
return ba;
}
-QPair<int, int>ScintillaEdit::find_text(int flags, const char *text, int cpMin, int cpMax) {
+QPair<int, int>ScintillaEdit::find_text(int flags, const char *text, int cpMin, int cpMax) const {
struct Sci_TextToFind ft = {{0, 0}, 0, {0, 0}};
ft.chrg.cpMin = cpMin;
ft.chrg.cpMax = cpMax;
@@ -36,7 +36,7 @@ QPair<int, int>ScintillaEdit::find_text(int flags, const char *text, int cpMin,
return QPair<int,int>(start, ft.chrgText.cpMax);
}
-QByteArray ScintillaEdit::get_text_range(int start, int end) {
+QByteArray ScintillaEdit::get_text_range(int start, int end) const {
if (start > end)
start = end;
@@ -50,7 +50,7 @@ QByteArray ScintillaEdit::get_text_range(int start, int end) {
return ba;
}
-ScintillaDocument *ScintillaEdit::get_doc() {
+ScintillaDocument *ScintillaEdit::get_doc() const {
return new ScintillaDocument(0, (void *)send(SCI_GETDOCPOINTER, 0, 0));
}
@@ -60,7 +60,7 @@ void ScintillaEdit::set_doc(ScintillaDocument *pdoc_) {
long ScintillaEdit::format_range(bool draw, QPaintDevice* target, QPaintDevice* measure,
const QRect& print_rect, const QRect& page_rect,
- long range_start, long range_end)
+ long range_start, long range_end) const
{
Sci_RangeToFormat to_format;
diff --git a/qt/ScintillaEdit/ScintillaEdit.h.template b/qt/ScintillaEdit/ScintillaEdit.h.template
index 1444e907c..869788f0d 100644
--- a/qt/ScintillaEdit/ScintillaEdit.h.template
+++ b/qt/ScintillaEdit/ScintillaEdit.h.template
@@ -33,27 +33,27 @@ public:
QByteArray TextReturner(int message, uptr_t wParam) const;
- QPair<int, int>find_text(int flags, const char *text, int cpMin, int cpMax);
- QByteArray get_text_range(int start, int end);
- ScintillaDocument *get_doc();
+ QPair<int, int>find_text(int flags, const char *text, int cpMin, int cpMax) const;
+ QByteArray get_text_range(int start, int end) const;
+ ScintillaDocument *get_doc() const;
void set_doc(ScintillaDocument *pdoc_);
// Same as previous two methods but with Qt style names
- QPair<int, int>findText(int flags, const char *text, int cpMin, int cpMax) {
+ QPair<int, int>findText(int flags, const char *text, int cpMin, int cpMax) const {
return find_text(flags, text, cpMin, cpMax);
}
- QByteArray textRange(int start, int end) {
+ QByteArray textRange(int start, int end) const {
return get_text_range(start, end);
}
// Exposing the FORMATRANGE api with both underscore & qt style names
long format_range(bool draw, QPaintDevice* target, QPaintDevice* measure,
const QRect& print_rect, const QRect& page_rect,
- long range_start, long range_end);
+ long range_start, long range_end) const;
long formatRange(bool draw, QPaintDevice* target, QPaintDevice* measure,
const QRect& print_rect, const QRect& page_rect,
- long range_start, long range_end) {
+ long range_start, long range_end) const {
return format_range(draw, target, measure, print_rect, page_rect,
range_start, range_end);
}
diff --git a/qt/ScintillaEdit/ScintillaEdit.pro b/qt/ScintillaEdit/ScintillaEdit.pro
index ebfc65ebe..295678d3c 100644
--- a/qt/ScintillaEdit/ScintillaEdit.pro
+++ b/qt/ScintillaEdit/ScintillaEdit.pro
@@ -13,7 +13,7 @@ TEMPLATE = lib
CONFIG += lib_bundle
CONFIG += c++1z
-VERSION = 5.5.7
+VERSION = 5.6.0
SOURCES += \
ScintillaEdit.cpp \
diff --git a/qt/ScintillaEditBase/ScintillaEditBase.pro b/qt/ScintillaEditBase/ScintillaEditBase.pro
index 17c350f12..d2ab750df 100644
--- a/qt/ScintillaEditBase/ScintillaEditBase.pro
+++ b/qt/ScintillaEditBase/ScintillaEditBase.pro
@@ -13,7 +13,7 @@ TEMPLATE = lib
CONFIG += lib_bundle
CONFIG += c++1z
-VERSION = 5.5.7
+VERSION = 5.6.0
SOURCES += \
PlatQt.cpp \
diff --git a/src/DBCS.cxx b/src/DBCS.cxx
index f53b8e9ed..062c30a51 100644
--- a/src/DBCS.cxx
+++ b/src/DBCS.cxx
@@ -7,8 +7,10 @@
#include <cstdint>
+#include <vector>
#include <array>
#include <map>
+#include <algorithm>
#include "DBCS.h"
@@ -88,10 +90,13 @@ bool DBCSIsTrailByte(int codePage, char ch) noexcept {
bool IsDBCSValidSingleByte(int codePage, int ch) noexcept {
switch (codePage) {
case cp932:
+ // Shift_jis
return ch == 0x80
|| (ch >= 0xA0 && ch <= 0xDF)
|| (ch >= 0xFD);
-
+ case cp936:
+ // GBK
+ return ch == 0x80;
default:
return false;
}
@@ -99,25 +104,31 @@ bool IsDBCSValidSingleByte(int codePage, int ch) noexcept {
// NOLINTEND(*-magic-numbers)
-using CodePageToFoldMap = std::map<int, FoldMap>;
-CodePageToFoldMap cpToFoldMap;
+namespace {
-bool DBCSHasFoldMap(int codePage) {
- const CodePageToFoldMap::const_iterator it = cpToFoldMap.find(codePage);
- return it != cpToFoldMap.end();
-}
+struct CodePageFoldMap {
+ int codePage = 0;
+ FoldMap foldMap;
+ explicit CodePageFoldMap(int codePage_) noexcept : codePage {codePage_} {}
+};
+
+using CodePageToFoldMap = std::vector<CodePageFoldMap>;
+CodePageToFoldMap cpToFoldMap;
-void DBCSSetFoldMap(int codePage, const FoldMap &foldMap) {
- cpToFoldMap[codePage] = foldMap;
}
-FoldMap *DBCSGetMutableFoldMap(int codePage) {
- // Constructs if needed
- return &cpToFoldMap[codePage];
+FoldMap *DBCSCreateFoldMap(int codePage) {
+ cpToFoldMap.emplace_back(codePage);
+ return &(cpToFoldMap.back().foldMap);
}
const FoldMap *DBCSGetFoldMap(int codePage) {
- return &cpToFoldMap[codePage];
+ const CodePageToFoldMap::iterator it = std::find_if(cpToFoldMap.begin(), cpToFoldMap.end(),
+ [codePage](const CodePageFoldMap &cpfm) -> bool {return cpfm.codePage == codePage; });
+ if (it != cpToFoldMap.end()) {
+ return &(it->foldMap);
+ }
+ return nullptr;
}
}
diff --git a/src/DBCS.h b/src/DBCS.h
index 96d282446..466d70ec7 100644
--- a/src/DBCS.h
+++ b/src/DBCS.h
@@ -37,13 +37,11 @@ constexpr uint16_t DBCSIndex(char ch1, char ch2) noexcept {
}
struct DBCSPair {
- char chars[2];
+ char chars[2]{};
};
using FoldMap = std::array<DBCSPair, 0x8000>;
-bool DBCSHasFoldMap(int codePage);
-void DBCSSetFoldMap(int codePage, const FoldMap &foldMap);
-FoldMap *DBCSGetMutableFoldMap(int codePage);
+FoldMap *DBCSCreateFoldMap(int codePage);
const FoldMap *DBCSGetFoldMap(int codePage);
}
diff --git a/src/Document.cxx b/src/Document.cxx
index c79c5002b..458c1e93f 100644
--- a/src/Document.cxx
+++ b/src/Document.cxx
@@ -864,8 +864,9 @@ Sci::Position Document::NextPosition(Sci::Position pos, int moveDir) const noexc
const int increment = (moveDir > 0) ? 1 : -1;
if (pos + increment <= 0)
return 0;
- if (pos + increment >= cb.Length())
- return cb.Length();
+ const Sci::Position length = LengthNoExcept();
+ if (pos + increment >= length)
+ return length;
if (dbcsCodePage) {
if (CpUtf8 == dbcsCodePage) {
@@ -904,9 +905,7 @@ Sci::Position Document::NextPosition(Sci::Position pos, int moveDir) const noexc
} else {
if (moveDir > 0) {
const int mbsize = IsDBCSDualByteAt(pos) ? 2 : 1;
- pos += mbsize;
- if (pos > cb.Length())
- pos = cb.Length();
+ pos = std::min(pos + mbsize, length);
} else {
// How to Go Backward in a DBCS String
// https://msdn.microsoft.com/en-us/library/cc194792.aspx
@@ -1590,7 +1589,10 @@ Sci::Position Document::Undo() {
}
cb.PerformUndoStep();
if (action.at != ActionType::container) {
- ModifiedAt(action.position);
+ if ((action.at == ActionType::insert) && (action.position >= LengthNoExcept()) && (action.position > 0))
+ ModifiedAt(action.position - 1);
+ else
+ ModifiedAt(action.position);
newPos = action.position;
}
@@ -1761,22 +1763,23 @@ Sci::Position Document::SetLineIndentation(Sci::Line line, Sci::Position indent)
}
}
-Sci::Position Document::GetLineIndentPosition(Sci::Line line) const {
+Sci::Position Document::GetLineIndentPosition(Sci::Line line) const noexcept {
if (line < 0)
return 0;
- Sci::Position pos = LineStart(line);
- const Sci::Position length = Length();
+ Sci::Position pos = cb.LineStart(line);
+ const Sci::Position length = LengthNoExcept();
while ((pos < length) && IsSpaceOrTab(cb.CharAt(pos))) {
pos++;
}
return pos;
}
-Sci::Position Document::GetColumn(Sci::Position pos) const {
+Sci::Position Document::GetColumn(Sci::Position pos) const noexcept {
Sci::Position column = 0;
const Sci::Line line = SciLineFromPosition(pos);
if ((line >= 0) && (line < LinesTotal())) {
- for (Sci::Position i = LineStart(line); i < pos;) {
+ const Sci::Position length = LengthNoExcept();
+ for (Sci::Position i = cb.LineStart(line); i < pos;) {
const char ch = cb.CharAt(i);
if (ch == '\t') {
column = NextTab(column, tabInChars);
@@ -1785,7 +1788,7 @@ Sci::Position Document::GetColumn(Sci::Position pos) const {
return column;
} else if (ch == '\n') {
return column;
- } else if (i >= Length()) {
+ } else if (i >= length) {
return column;
} else if (UTF8IsAscii(ch)) {
column++;
@@ -1826,11 +1829,12 @@ Sci::Position Document::CountUTF16(Sci::Position startPos, Sci::Position endPos)
return count;
}
-Sci::Position Document::FindColumn(Sci::Line line, Sci::Position column) {
- Sci::Position position = LineStart(line);
+Sci::Position Document::FindColumn(Sci::Line line, Sci::Position column) const noexcept {
+ Sci::Position position = cb.LineStart(line);
if ((line >= 0) && (line < LinesTotal())) {
+ const Sci::Position length = LengthNoExcept();
Sci::Position columnCurrent = 0;
- while ((columnCurrent < column) && (position < Length())) {
+ while ((columnCurrent < column) && (position < length)) {
const char ch = cb.CharAt(position);
if (ch == '\t') {
columnCurrent = NextTab(columnCurrent, tabInChars);
@@ -1841,6 +1845,9 @@ Sci::Position Document::FindColumn(Sci::Line line, Sci::Position column) {
return position;
} else if (ch == '\n') {
return position;
+ } else if (UTF8IsAscii(ch)) {
+ columnCurrent++;
+ position++;
} else {
columnCurrent++;
position = NextPosition(position, 1);
@@ -1900,7 +1907,8 @@ std::string Document::TransformLineEnds(const char *s, size_t len, EndOfLine eol
void Document::ConvertLineEnds(EndOfLine eolModeSet) {
UndoGroup ug(this);
- for (Sci::Position pos = 0; pos < Length(); pos++) {
+ const Sci::Position length = Length();
+ for (Sci::Position pos = 0; pos < length; pos++) {
const char ch = cb.CharAt(pos);
if (ch == '\r') {
if (cb.CharAt(pos + 1) == '\n') {
@@ -2819,7 +2827,7 @@ void SCI_METHOD Document::DecorationFillRange(Sci_Position position, int value,
bool Document::AddWatcher(DocWatcher *watcher, void *userData) {
const WatcherWithUserData wwud(watcher, userData);
- std::vector<WatcherWithUserData>::iterator it =
+ const std::vector<WatcherWithUserData>::iterator it =
std::find(watchers.begin(), watchers.end(), wwud);
if (it != watchers.end())
return false;
@@ -2831,7 +2839,7 @@ bool Document::RemoveWatcher(DocWatcher *watcher, void *userData) noexcept {
try {
// This can never fail as WatcherWithUserData constructor and == are noexcept
// but std::find is not noexcept.
- std::vector<WatcherWithUserData>::iterator it =
+ const std::vector<WatcherWithUserData>::iterator it =
std::find(watchers.begin(), watchers.end(), WatcherWithUserData(watcher, userData));
if (it != watchers.end()) {
watchers.erase(it);
diff --git a/src/Document.h b/src/Document.h
index 7655d5290..7fd150f37 100644
--- a/src/Document.h
+++ b/src/Document.h
@@ -455,11 +455,11 @@ public:
int SCI_METHOD GetLineIndentation(Sci_Position line) override;
Sci::Position SetLineIndentation(Sci::Line line, Sci::Position indent);
- Sci::Position GetLineIndentPosition(Sci::Line line) const;
- Sci::Position GetColumn(Sci::Position pos) const;
+ Sci::Position GetLineIndentPosition(Sci::Line line) const noexcept;
+ Sci::Position GetColumn(Sci::Position pos) const noexcept;
Sci::Position CountCharacters(Sci::Position startPos, Sci::Position endPos) const noexcept;
Sci::Position CountUTF16(Sci::Position startPos, Sci::Position endPos) const noexcept;
- Sci::Position FindColumn(Sci::Line line, Sci::Position column);
+ Sci::Position FindColumn(Sci::Line line, Sci::Position column) const noexcept;
void Indent(bool forwards, Sci::Line lineBottom, Sci::Line lineTop);
static std::string TransformLineEnds(const char *s, size_t len, Scintilla::EndOfLine eolModeWanted);
void ConvertLineEnds(Scintilla::EndOfLine eolModeSet);
diff --git a/src/EditModel.cxx b/src/EditModel.cxx
index 65d39f9e7..cad0c3ade 100644
--- a/src/EditModel.cxx
+++ b/src/EditModel.cxx
@@ -167,6 +167,10 @@ InSelection EditModel::LineEndInSelection(Sci::Line lineDoc) const {
return sel.InSelectionForEOL(posAfterLineEnd);
}
+Sci::Position EditModel::VirtualSpaceForLine(Sci::Line lineDoc) const {
+ return sel.VirtualSpaceFor(pdoc->LineEnd(lineDoc));
+}
+
int EditModel::GetMark(Sci::Line line) const {
return pdoc->GetMark(line, FlagSet(changeHistoryOption, ChangeHistoryOption::Markers));
}
diff --git a/src/EditModel.h b/src/EditModel.h
index dcaf99613..b23169f78 100644
--- a/src/EditModel.h
+++ b/src/EditModel.h
@@ -108,6 +108,7 @@ public:
const char *GetDefaultFoldDisplayText() const noexcept;
const char *GetFoldDisplayText(Sci::Line lineDoc) const noexcept;
InSelection LineEndInSelection(Sci::Line lineDoc) const;
+ [[nodiscard]] Sci::Position VirtualSpaceForLine(Sci::Line lineDoc) const;
[[nodiscard]] int GetMark(Sci::Line line) const;
void EnsureModelState();
diff --git a/src/EditView.cxx b/src/EditView.cxx
index 3bf0a1fbb..bec07fe95 100644
--- a/src/EditView.cxx
+++ b/src/EditView.cxx
@@ -17,6 +17,7 @@
#include <string>
#include <string_view>
#include <vector>
+#include <array>
#include <map>
#include <set>
#include <forward_list>
@@ -124,8 +125,7 @@ int WidestLineWidth(Surface *surface, const ViewStyle &vs, int styleOffset, cons
const std::string_view text(st.text + start, lenLine);
widthSubLine = static_cast<int>(surface->WidthText(fontText, text));
}
- if (widthSubLine > widthMax)
- widthMax = widthSubLine;
+ widthMax = std::max(widthMax, widthSubLine);
start += lenLine + 1;
}
return widthMax;
@@ -191,7 +191,7 @@ EditView::EditView() {
imeCaretBlockOverride = false;
llc.SetLevel(LineCache::Caret);
posCache = CreatePositionCache();
- posCache->SetSize(0x400);
+ posCache->SetSize(positionCacheDefaultSize);
maxLayoutThreads = 1;
tabArrowHeight = 4;
customDrawTabArrow = nullptr;
@@ -251,9 +251,8 @@ bool EditView::AddTabstop(Sci::Line line, int x) {
int EditView::GetNextTabstop(Sci::Line line, int x) const noexcept {
if (ldTabstops) {
return ldTabstops->GetNextTabstop(line, x);
- } else {
- return 0;
}
+ return 0;
}
void EditView::LinesAddedOrRemoved(Sci::Line lineOfPos, Sci::Line linesAdded) {
@@ -353,14 +352,14 @@ void LayoutSegments(IPositionCache *pCache,
XYPOSITION representationWidth = 0.0;
// Tab is a special case of representation, taking a variable amount of space
// which will be filled in later.
- if (ll->chars[ts.start] != '\t') {
+ if (ll->chars[ts.start] != '\t' || vstyle.tabDrawMode == TabDrawMode::ControlChar) {
representationWidth = vstyle.controlCharWidth;
if (representationWidth <= 0.0) {
assert(ts.representation->stringRep.length() <= Representation::maxLength);
- XYPOSITION positionsRepr[Representation::maxLength + 1];
+ std::array<XYPOSITION, Representation::maxLength + 1> positionsRepr;
// ts.representation->stringRep is UTF-8.
pCache->MeasureWidths(surface, vstyle, StyleControlChar, true, ts.representation->stringRep,
- positionsRepr, multiThreaded);
+ positionsRepr.data(), multiThreaded);
representationWidth = positionsRepr[ts.representation->stringRep.length() - 1];
if (FlagSet(ts.representation->appearance, RepresentationAppearance::Blob)) {
representationWidth += vstyle.ctrlCharPadding;
@@ -379,9 +378,9 @@ void LayoutSegments(IPositionCache *pCache,
}
} else if (vstyle.styles[styleSegment].invisibleRepresentation[0]) {
const std::string_view text = vstyle.styles[styleSegment].invisibleRepresentation;
- XYPOSITION positionsRepr[Representation::maxLength + 1];
+ std::array<XYPOSITION, Representation::maxLength + 1> positionsRepr;
// invisibleRepresentation is UTF-8.
- pCache->MeasureWidths(surface, vstyle, styleSegment, true, text, positionsRepr, multiThreaded);
+ pCache->MeasureWidths(surface, vstyle, styleSegment, true, text, positionsRepr.data(), multiThreaded);
const XYPOSITION representationWidth = positionsRepr[text.length() - 1];
std::fill(positions, positions + ts.length, representationWidth);
}
@@ -402,13 +401,10 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
PLATFORM_ASSERT(line < model.pdoc->LinesTotal());
PLATFORM_ASSERT(ll->chars);
const Sci::Position posLineStart = model.pdoc->LineStart(line);
- Sci::Position posLineEnd = model.pdoc->LineStart(line + 1);
- // If the line is very long, limit the treatment to a length that should fit in the viewport
- if (posLineEnd >(posLineStart + ll->maxLineLength)) {
- posLineEnd = posLineStart + ll->maxLineLength;
- }
+ const Sci::Position posLineEnd = std::min(model.pdoc->LineStart(line + 1), posLineStart + ll->maxLineLength);
// Hard to cope when too narrow, so just assume there is space
- width = std::max(width, 20);
+ constexpr int minimumWidth = 20;
+ width = std::max(width, minimumWidth);
if (ll->validity == LineLayout::ValidLevel::checkTextAndStyle) {
Sci::Position lineLength = posLineEnd - posLineStart;
@@ -526,7 +522,7 @@ void EditView::LayoutLine(const EditModel &model, Surface *surface, const ViewSt
for (const TextSegment &ts : segments) {
if (vstyle.styles[ll->styles[ts.start]].visible &&
ts.representation &&
- (ll->chars[ts.start] == '\t')) {
+ ll->chars[ts.start] == '\t' && vstyle.tabDrawMode != TabDrawMode::ControlChar) {
// Simple visible tab, go to next tab stop
const XYPOSITION startTab = ll->positions[ts.start];
const XYPOSITION nextTab = NextTabstopPos(line, startTab, vstyle.tabWidth);
@@ -614,7 +610,7 @@ void EditView::UpdateBidiData(const EditModel &model, const ViewStyle &vstyle, L
const Representation *repr = model.reprs->RepresentationFromCharacter(std::string_view(&ll->chars[charsInLine], charWidth));
ll->bidiData->widthReprs[charsInLine] = 0.0f;
- if (repr && ll->chars[charsInLine] != '\t') {
+ if (repr && (ll->chars[charsInLine] != '\t' || vstyle.tabDrawMode == TabDrawMode::ControlChar)) {
ll->bidiData->widthReprs[charsInLine] = ll->positions[charsInLine + charWidth] - ll->positions[charsInLine];
}
if (charWidth > 1) {
@@ -745,7 +741,8 @@ SelectionPosition EditView::SPositionFromLocation(Surface *surface, const EditMo
const int spaceOffset = static_cast<int>(
(pt.x + subLineStart - ll->positions[rangeSubLine.end] + spaceWidth / 2) / spaceWidth);
return SelectionPosition(rangeSubLine.end + posLineStart, spaceOffset);
- } else if (canReturnInvalid) {
+ }
+ if (canReturnInvalid) {
if (pt.x < (ll->positions[rangeSubLine.end] - subLineStart)) {
return SelectionPosition(model.pdoc->MovePositionOutsideChar(rangeSubLine.end + posLineStart, 1));
}
@@ -892,11 +889,11 @@ ColourRGBA TextBackground(const EditModel &model, const ViewStyle &vsDraw, const
}
if (background && (styleMain != StyleBraceLight) && (styleMain != StyleBraceBad)) {
return *background;
- } else {
- return vsDraw.styles[styleMain].back;
}
+ return vsDraw.styles[styleMain].back;
}
+// Draw inverted text in a filled rectangle but omit the 4 corner pixels so appears rounded.
void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegment,
std::string_view text, ColourRGBA textBack, ColourRGBA textFore, bool fillBackground) {
if (rcSegment.Empty())
@@ -910,42 +907,95 @@ void DrawTextBlob(Surface *surface, const ViewStyle &vsDraw, PRectangle rcSegmen
rcCChar.left = rcCChar.left + 1;
rcCChar.top = rcSegment.top + vsDraw.maxAscent - normalCharHeight;
rcCChar.bottom = rcSegment.top + vsDraw.maxAscent + 1;
- PRectangle rcCentral = rcCChar;
- rcCentral.top++;
- rcCentral.bottom--;
+
+ // Ensure pixels to left and right coloured for central part avoiding top and bottom
+ // pixels which will be drawn by DrawTextClippedUTF8.
+ const PRectangle rcCentral = rcCChar.Inset(Point(0, 1));
surface->FillRectangleAligned(rcCentral, Fill(textFore));
- PRectangle rcChar = rcCChar;
- rcChar.left++;
- rcChar.right--;
+
+ const PRectangle rcChar = rcCChar.Inset(Point(1, 0));
+ // NOLINTNEXTLINE(readability-suspicious-call-argument) Inverted text
surface->DrawTextClippedUTF8(rcChar, ctrlCharsFont,
rcSegment.top + vsDraw.maxAscent, text,
textBack, textFore);
}
void FillLineRemainder(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line line, PRectangle rcArea, int subLine) {
+ Sci::Line line, PRectangle rcLine, XYPOSITION left, int subLine) {
+ if (rcLine.Empty()) {
+ return;
+ }
InSelection eolInSelection = InSelection::inNone;
if (vsDraw.selection.visible && (subLine == (ll->lines - 1))) {
eolInSelection = model.LineEndInSelection(line);
}
+ const bool drawEOLSelection = eolInSelection && vsDraw.selection.eolFilled && (line < model.pdoc->LinesTotal() - 1);
- if (eolInSelection && vsDraw.selection.eolFilled && (line < model.pdoc->LinesTotal() - 1) && (vsDraw.selection.layer == Layer::Base)) {
- surface->FillRectangleAligned(rcArea, Fill(SelectionBackground(model, vsDraw, eolInSelection).Opaque()));
+ const PRectangle rcArea = Clamp(rcLine, Edge::left, left); // Limit to right side of line from 'left'
+
+ const ColourRGBA selectionBack = drawEOLSelection ? SelectionBackground(model, vsDraw, eolInSelection) : ColourRGBA{};
+ ColourRGBA base = vsDraw.styles[StyleDefault].back;
+ if (drawEOLSelection && (vsDraw.selection.layer == Layer::Base)) {
+ base = selectionBack;
} else {
const ColourOptional background = vsDraw.Background(model.GetMark(line), model.caret.active, ll->containsCaret);
if (background) {
- surface->FillRectangleAligned(rcArea, Fill(*background));
- } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
- surface->FillRectangleAligned(rcArea, Fill(vsDraw.styles[ll->styles[ll->numCharsInLine]].back));
- } else {
- surface->FillRectangleAligned(rcArea, Fill(vsDraw.styles[StyleDefault].back));
+ base = *background;
+ } else if (vsDraw.styles[ll->LastStyle()].eolFilled) {
+ base = vsDraw.styles[ll->LastStyle()].back;
}
- if (eolInSelection && vsDraw.selection.eolFilled && (line < model.pdoc->LinesTotal() - 1) && (vsDraw.selection.layer != Layer::Base)) {
- surface->FillRectangleAligned(rcArea, SelectionBackground(model, vsDraw, eolInSelection));
+ }
+ surface->FillRectangleAligned(rcArea, Fill(base.Opaque()));
+ if (drawEOLSelection && (vsDraw.selection.layer != Layer::Base)) {
+ // This may be translucent
+ surface->FillRectangleAligned(rcArea, selectionBack);
+ }
+}
+
+// Stadium ends require different amounts of padding to look reasonable around text.
+constexpr XYPOSITION divisorAngle = 2.0; // <text>
+constexpr XYPOSITION divisorCircle = 3.0; // (text)
+constexpr XYPOSITION EndPadding(Surface::Ends side, XYPOSITION height) noexcept {
+ switch (side) {
+ case Surface::Ends::leftFlat:
+ case Surface::Ends::rightFlat:
+ return 1;
+ case Surface::Ends::leftAngle:
+ case Surface::Ends::rightAngle:
+ return height / divisorAngle;
+ default:
+ // semiCircles
+ return height / divisorCircle;
+ }
+}
+
+struct HorizontalPadding {
+ XYPOSITION left = 0;
+ XYPOSITION right = 0;
+};
+
+[[nodiscard]] constexpr PRectangle TextPart(const PRectangle &rc, const HorizontalPadding &padding) noexcept {
+ return PRectangle(rc.left + padding.left, rc.top, rc.right - padding.right, rc.bottom);
+}
+
+HorizontalPadding StadiumPadding(Scintilla::EOLAnnotationVisible eolAnnotationVisible, XYPOSITION height) noexcept {
+ if (eolAnnotationVisible >= EOLAnnotationVisible::Boxed) {
+ if (eolAnnotationVisible == EOLAnnotationVisible::Boxed) {
+ return { 1, 1 };
}
+ const Surface::Ends leftSide = static_cast<Surface::Ends>(static_cast<int>(eolAnnotationVisible) & 0xf);
+ const Surface::Ends rightSide = static_cast<Surface::Ends>(static_cast<int>(eolAnnotationVisible) & 0xf0);
+ const XYPOSITION leftSpace = EndPadding(leftSide, height);
+ const XYPOSITION rightSpace = EndPadding(rightSide, height);
+ return { leftSpace , rightSpace };
}
+ return {};
+}
+
}
+void EditView::UpdateMaxWidth(XYPOSITION width) noexcept {
+ lineWidthMaxSeen = std::max(lineWidthMaxSeen, static_cast<int>(width));
}
void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
@@ -955,27 +1005,23 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
PRectangle rcSegment = rcLine;
const bool lastSubLine = subLine == (ll->lines - 1);
- XYPOSITION virtualSpace = 0;
- if (lastSubLine) {
- const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- virtualSpace = static_cast<XYPOSITION>(model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line))) * spaceWidth;
- }
+ const Sci::Position virtualSpaces = lastSubLine ? model.VirtualSpaceForLine(line) : 0;
+ const XYPOSITION spaceWidth = lastSubLine ? vsDraw.styles[ll->EndLineStyle()].spaceWidth : 0;
+ const XYPOSITION virtualSpace = static_cast<XYPOSITION>(virtualSpaces) * spaceWidth;
const XYPOSITION xEol = ll->positions[lineEnd] - subLineStart;
// Fill the virtual space and show selections within it
if (virtualSpace > 0.0f) {
rcSegment.left = xEol + xStart;
rcSegment.right = xEol + xStart + virtualSpace;
- const ColourRGBA backgroundFill = background.value_or(vsDraw.styles[ll->styles[ll->numCharsInLine]].back);
+ const ColourRGBA backgroundFill = background.value_or(vsDraw.styles[ll->LastStyle()].back);
surface->FillRectangleAligned(rcSegment, backgroundFill);
if (vsDraw.selection.visible && (vsDraw.selection.layer == Layer::Base)) {
const SelectionSegment virtualSpaceRange(SelectionPosition(model.pdoc->LineEnd(line)),
- SelectionPosition(model.pdoc->LineEnd(line),
- model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line))));
+ SelectionPosition(model.pdoc->LineEnd(line), virtualSpaces));
for (size_t r = 0; r<model.sel.Count(); r++) {
const SelectionSegment portion = model.sel.Range(r).Intersect(virtualSpaceRange);
if (!portion.Empty()) {
- const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
rcSegment.left = xStart + ll->positions[portion.start.Position() - posLineStart] -
subLineStart + portion.start.VirtualSpaceWidth(spaceWidth);
rcSegment.right = xStart + ll->positions[portion.end.Position() - posLineStart] -
@@ -989,30 +1035,29 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
}
}
- InSelection eolInSelection = InSelection::inNone;
- if (vsDraw.selection.visible && lastSubLine) {
- eolInSelection = model.LineEndInSelection(line);
- }
+ const InSelection eolInSelection = (vsDraw.selection.visible && lastSubLine) ?
+ model.LineEndInSelection(line) : InSelection::inNone;
+ const bool lastLine = line >= (model.pdoc->LinesTotal() - 1);
+ const bool drawEOLSelection = eolInSelection && !lastLine;
const ColourRGBA selectionBack = SelectionBackground(model, vsDraw, eolInSelection);
// Draw the [CR], [LF], or [CR][LF] blobs if visible line ends are on
XYPOSITION blobsWidth = 0;
if (lastSubLine) {
- for (Sci::Position eolPos = ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine;) {
+ for (int eolPos = ll->numCharsBeforeEOL; eolPos<ll->numCharsInLine;) {
const int styleMain = ll->styles[eolPos];
const ColourOptional selectionFore = SelectionForeground(model, vsDraw, eolInSelection);
ColourRGBA textFore = selectionFore.value_or(vsDraw.styles[styleMain].fore);
char hexits[4] = "";
std::string_view ctrlChar;
- Sci::Position widthBytes = 1;
RepresentationAppearance appearance = RepresentationAppearance::Blob;
- const Representation *repr = model.reprs->RepresentationFromCharacter(std::string_view(&ll->chars[eolPos], ll->numCharsInLine - eolPos));
- if (repr) {
- // Representation of whole text
- widthBytes = ll->numCharsInLine - eolPos;
- } else {
- repr = model.reprs->RepresentationFromCharacter(std::string_view(&ll->chars[eolPos], 1));
+ const std::string_view rest(&ll->chars[eolPos], ll->numCharsInLine - eolPos);
+ const Representation *repr = model.reprs->RepresentationFromCharacter(rest);
+ const int widthBytes = repr ? static_cast<int>(rest.length()) : 1;
+ if (!repr) {
+ // No representation of whole line end so try first byte.
+ repr = model.reprs->RepresentationFromCharacter(rest.substr(0, 1));
}
if (repr) {
ctrlChar = repr->stringRep;
@@ -1021,7 +1066,7 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
textFore = repr->colour;
}
} else {
- const unsigned char chEOL = ll->chars[eolPos];
+ const unsigned char chEOL = rest.front();
if (UTF8IsAscii(chEOL)) {
ctrlChar = ControlCharacterString(chEOL);
} else {
@@ -1030,69 +1075,54 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
}
}
- rcSegment.left = xStart + ll->positions[eolPos] - subLineStart + virtualSpace;
- rcSegment.right = xStart + ll->positions[eolPos + widthBytes] - subLineStart + virtualSpace;
- blobsWidth += rcSegment.Width();
+ const PRectangle rcBlob = rcLine.WithHorizontalBounds(
+ ll->Span(eolPos, eolPos + widthBytes).Offset(xStart - subLineStart + virtualSpace));
+ blobsWidth += rcBlob.Width();
const ColourRGBA textBack = TextBackground(model, vsDraw, ll, background, eolInSelection, false, styleMain, eolPos);
- if (eolInSelection && (line < model.pdoc->LinesTotal() - 1)) {
- if (vsDraw.selection.layer == Layer::Base) {
- surface->FillRectangleAligned(rcSegment, Fill(selectionBack.Opaque()));
- } else {
- surface->FillRectangleAligned(rcSegment, Fill(textBack));
- }
+ if (drawEOLSelection && (vsDraw.selection.layer == Layer::Base)) {
+ surface->FillRectangleAligned(rcBlob, Fill(selectionBack.Opaque()));
} else {
- surface->FillRectangleAligned(rcSegment, Fill(textBack));
+ surface->FillRectangleAligned(rcBlob, Fill(textBack));
}
- const bool drawEOLSelection = eolInSelection && (line < model.pdoc->LinesTotal() - 1);
ColourRGBA blobText = textBack;
if (drawEOLSelection && (vsDraw.selection.layer == Layer::UnderText)) {
- surface->FillRectangleAligned(rcSegment, selectionBack);
+ surface->FillRectangleAligned(rcBlob, selectionBack);
blobText = textBack.MixedWith(selectionBack, selectionBack.GetAlphaComponent());
}
if (FlagSet(appearance, RepresentationAppearance::Blob)) {
- DrawTextBlob(surface, vsDraw, rcSegment, ctrlChar, blobText, textFore, phasesDraw == PhasesDraw::One);
+ DrawTextBlob(surface, vsDraw, rcBlob, ctrlChar, blobText, textFore, phasesDraw == PhasesDraw::One);
} else {
- surface->DrawTextTransparentUTF8(rcSegment, vsDraw.styles[StyleControlChar].font.get(),
- rcSegment.top + vsDraw.maxAscent, ctrlChar, textFore);
+ surface->DrawTextTransparentUTF8(rcBlob, vsDraw.styles[StyleControlChar].font.get(),
+ rcBlob.top + vsDraw.maxAscent, ctrlChar, textFore);
}
if (drawEOLSelection && (vsDraw.selection.layer == Layer::OverText)) {
- surface->FillRectangleAligned(rcSegment, selectionBack);
+ surface->FillRectangleAligned(rcBlob, selectionBack);
}
eolPos += widthBytes;
}
}
// Draw the eol-is-selected rectangle
- rcSegment.left = xEol + xStart + virtualSpace + blobsWidth;
- rcSegment.right = rcSegment.left + vsDraw.aveCharWidth;
-
- if (eolInSelection && (line < model.pdoc->LinesTotal() - 1) && (vsDraw.selection.layer == Layer::Base)) {
- surface->FillRectangleAligned(rcSegment, Fill(selectionBack.Opaque()));
- } else {
- if (background) {
- surface->FillRectangleAligned(rcSegment, Fill(*background));
- } else if (line < model.pdoc->LinesTotal() - 1) {
- surface->FillRectangleAligned(rcSegment, Fill(vsDraw.styles[ll->styles[ll->numCharsInLine]].back));
- } else if (vsDraw.styles[ll->styles[ll->numCharsInLine]].eolFilled) {
- surface->FillRectangleAligned(rcSegment, Fill(vsDraw.styles[ll->styles[ll->numCharsInLine]].back));
- } else {
- surface->FillRectangleAligned(rcSegment, Fill(vsDraw.styles[StyleDefault].back));
- }
- if (eolInSelection && (line < model.pdoc->LinesTotal() - 1) && (vsDraw.selection.layer != Layer::Base)) {
- surface->FillRectangleAligned(rcSegment, selectionBack);
- }
+ const PRectangle rcEOLIsSelected = rcLine.WithHorizontalBounds(
+ Interval::FromLeftAndWidth(xEol + xStart + virtualSpace + blobsWidth, vsDraw.aveCharWidth));
+ ColourRGBA base = vsDraw.styles[StyleDefault].back;
+ if (drawEOLSelection && (vsDraw.selection.layer == Layer::Base)) {
+ base = selectionBack;
+ } else if (background) {
+ base = *background;
+ } else if (const Style &styleLast = vsDraw.styles[ll->LastStyle()]; styleLast.eolFilled) {
+ base = styleLast.back;
+ }
+ surface->FillRectangleAligned(rcEOLIsSelected, Fill(base.Opaque()));
+ if (drawEOLSelection && (vsDraw.selection.layer != Layer::Base)) {
+ surface->FillRectangleAligned(rcEOLIsSelected, selectionBack);
}
-
- rcSegment.left = rcSegment.right;
- if (rcSegment.left < rcLine.left)
- rcSegment.left = rcLine.left;
- rcSegment.right = rcLine.right;
const bool drawEOLAnnotationStyledText = (vsDraw.eolAnnotationVisible != EOLAnnotationVisible::Hidden) && model.pdoc->EOLAnnotationStyledText(line).text;
const bool fillRemainder = (!lastSubLine || (!model.GetFoldDisplayText(line) && !drawEOLAnnotationStyledText));
if (fillRemainder) {
// Fill the remainder of the line
- FillLineRemainder(surface, model, vsDraw, ll, line, rcSegment, subLine);
+ FillLineRemainder(surface, model, vsDraw, ll, line, rcLine, rcEOLIsSelected.right, subLine);
}
bool drawWrapMarkEnd = false;
@@ -1109,8 +1139,8 @@ void EditView::DrawEOL(Surface *surface, const EditModel &model, const ViewStyle
}
if (drawWrapMarkEnd) {
- PRectangle rcPlace = rcSegment;
- const XYPOSITION maxLeft = rcPlace.right - vsDraw.aveCharWidth;
+ PRectangle rcPlace = rcLine;
+ const XYPOSITION maxLeft = rcLine.right - vsDraw.aveCharWidth;
if (FlagSet(vsDraw.wrap.visualFlagsLocation, WrapVisualLocation::EndByText)) {
rcPlace.left = std::min(xEol + xStart + virtualSpace, maxLeft);
@@ -1149,8 +1179,7 @@ void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, con
}
const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- const XYPOSITION virtualSpace = static_cast<XYPOSITION>(model.sel.VirtualSpaceFor(
- model.pdoc->LineEnd(line))) * spaceWidth;
+ const XYPOSITION virtualSpace = static_cast<XYPOSITION>(model.VirtualSpaceForLine(line)) * spaceWidth;
rcSegment.left = xStart + ll->positions[ll->numCharsInLine] - subLineStart + virtualSpace + vsDraw.aveCharWidth;
rcSegment.right = rcSegment.left + static_cast<XYPOSITION>(widthFoldDisplayText);
@@ -1161,22 +1190,15 @@ void EditView::DrawFoldDisplayText(Surface *surface, const EditModel &model, con
false, StyleFoldDisplayText, -1);
if (model.trackLineWidth) {
- if (rcSegment.right + 1> lineWidthMaxSeen) {
- // Fold display text border drawn on rcSegment.right with width 1 is the last visible object of the line
- lineWidthMaxSeen = static_cast<int>(rcSegment.right + 1);
- }
+ // Fold display text border drawn on rcSegment.right with width 1 is the last visible object of the line
+ UpdateMaxWidth(rcSegment.right + 1);
}
if (FlagSet(phase, DrawPhase::back)) {
surface->FillRectangleAligned(rcSegment, Fill(textBack));
// Fill Remainder of the line
- PRectangle rcRemainder = rcSegment;
- rcRemainder.left = rcRemainder.right;
- if (rcRemainder.left < rcLine.left)
- rcRemainder.left = rcLine.left;
- rcRemainder.right = rcLine.right;
- FillLineRemainder(surface, model, vsDraw, ll, line, rcRemainder, subLine);
+ FillLineRemainder(surface, model, vsDraw, ll, line, rcLine, rcSegment.right, subLine);
}
if (FlagSet(phase, DrawPhase::text)) {
@@ -1228,47 +1250,14 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c
const Font *fontText = vsDraw.styles[style].font.get();
const Surface::Ends ends = static_cast<Surface::Ends>(static_cast<int>(vsDraw.eolAnnotationVisible) & 0xff);
- const Surface::Ends leftSide = static_cast<Surface::Ends>(static_cast<int>(ends) & 0xf);
- const Surface::Ends rightSide = static_cast<Surface::Ends>(static_cast<int>(ends) & 0xf0);
-
- XYPOSITION leftBoxSpace = 0;
- XYPOSITION rightBoxSpace = 0;
- if (vsDraw.eolAnnotationVisible >= EOLAnnotationVisible::Boxed) {
- leftBoxSpace = 1;
- rightBoxSpace = 1;
- if (vsDraw.eolAnnotationVisible != EOLAnnotationVisible::Boxed) {
- switch (leftSide) {
- case Surface::Ends::leftFlat:
- leftBoxSpace = 1;
- break;
- case Surface::Ends::leftAngle:
- leftBoxSpace = rcLine.Height() / 2.0;
- break;
- case Surface::Ends::semiCircles:
- default:
- leftBoxSpace = rcLine.Height() / 3.0;
- break;
- }
- switch (rightSide) {
- case Surface::Ends::rightFlat:
- rightBoxSpace = 1;
- break;
- case Surface::Ends::rightAngle:
- rightBoxSpace = rcLine.Height() / 2.0;
- break;
- case Surface::Ends::semiCircles:
- default:
- rightBoxSpace = rcLine.Height() / 3.0;
- break;
- }
- }
- }
+
+ const HorizontalPadding padding = StadiumPadding(vsDraw.eolAnnotationVisible, rcLine.Height());
+
const int widthEOLAnnotationText = static_cast<int>(surface->WidthTextUTF8(fontText, eolAnnotationText) +
- leftBoxSpace + rightBoxSpace);
+ padding.left + padding.right);
const XYPOSITION spaceWidth = vsDraw.styles[ll->EndLineStyle()].spaceWidth;
- const XYPOSITION virtualSpace = static_cast<XYPOSITION>(model.sel.VirtualSpaceFor(
- model.pdoc->LineEnd(line))) * spaceWidth;
+ const XYPOSITION virtualSpace = static_cast<XYPOSITION>(model.VirtualSpaceForLine(line)) * spaceWidth;
rcSegment.left = xStart +
ll->positions[ll->numCharsInLine] - subLineStart
+ virtualSpace + vsDraw.aveCharWidth;
@@ -1288,10 +1277,8 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c
false, static_cast<int>(style), -1);
if (model.trackLineWidth) {
- if (rcSegment.right + 1> lineWidthMaxSeen) {
- // EOL Annotation text border drawn on rcSegment.right with width 1 is the last visible object of the line
- lineWidthMaxSeen = static_cast<int>(rcSegment.right + 1);
- }
+ // EOL Annotation text border drawn on rcSegment.right with width 1 is the last visible object of the line
+ UpdateMaxWidth(rcSegment.right + 1);
}
if (FlagSet(phase, DrawPhase::back)) {
@@ -1299,14 +1286,10 @@ void EditView::DrawEOLAnnotationText(Surface *surface, const EditModel &model, c
// it may be double drawing. This is to allow stadiums with
// curved or angled ends to have the area outside in the correct
// background colour.
- PRectangle rcRemainder = rcSegment;
- rcRemainder.right = rcLine.right;
- FillLineRemainder(surface, model, vsDraw, ll, line, rcRemainder, subLine);
+ FillLineRemainder(surface, model, vsDraw, ll, line, rcLine, rcSegment.right, subLine);
}
- PRectangle rcText = rcSegment;
- rcText.left += leftBoxSpace;
- rcText.right -= rightBoxSpace;
+ const PRectangle rcText = TextPart(rcSegment, padding);
// For single phase drawing, draw the text then any box over it
if (FlagSet(phase, DrawPhase::text)) {
@@ -1369,7 +1352,7 @@ constexpr bool AnnotationBoxedOrIndented(AnnotationVisible annotationVisible) no
}
void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) {
+ Sci::Line line, int xOrigin, PRectangle rcLine, int subLine, DrawPhase phase) {
const int indent = static_cast<int>(model.pdoc->GetLineIndentation(line) * vsDraw.spaceWidth);
PRectangle rcSegment = rcLine;
const int annotationLine = subLine - ll->lines;
@@ -1378,17 +1361,16 @@ void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const Vi
if (FlagSet(phase, DrawPhase::back)) {
surface->FillRectangleAligned(rcSegment, Fill(vsDraw.styles[0].back));
}
- rcSegment.left = static_cast<XYPOSITION>(xStart);
+ rcSegment.left = static_cast<XYPOSITION>(xOrigin);
if (model.trackLineWidth || AnnotationBoxedOrIndented(vsDraw.annotationVisible)) {
// Only care about calculating width if tracking or need to draw indented box
int widthAnnotation = WidestLineWidth(surface, vsDraw, vsDraw.annotationStyleOffset, stAnnotation);
if (AnnotationBoxedOrIndented(vsDraw.annotationVisible)) {
widthAnnotation += static_cast<int>(vsDraw.spaceWidth * 2); // Margins
- rcSegment.left = static_cast<XYPOSITION>(xStart + indent);
+ rcSegment.left = static_cast<XYPOSITION>(xOrigin + indent);
rcSegment.right = rcSegment.left + widthAnnotation;
}
- if (widthAnnotation > lineWidthMaxSeen)
- lineWidthMaxSeen = widthAnnotation;
+ UpdateMaxWidth(widthAnnotation);
}
const int annotationLines = model.pdoc->AnnotationLines(line);
size_t start = 0;
@@ -1430,7 +1412,7 @@ void EditView::DrawAnnotation(Surface *surface, const EditModel &model, const Vi
namespace {
void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- int subLine, int xStart, Sci::Position offset, Sci::Position posCaret, PRectangle rcCaret, ColourRGBA caretColour) {
+ int subLine, int xOrigin, Sci::Position offset, Sci::Position posCaret, PRectangle rcCaret, ColourRGBA caretColour) {
const Sci::Position lineStart = ll->LineStart(subLine);
Sci::Position posBefore = posCaret;
@@ -1456,8 +1438,7 @@ void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &v
// See if the next character shares horizontal space, if so we'll
// need to draw that too.
- if (offsetFirstChar < 0)
- offsetFirstChar = 0;
+ offsetFirstChar = std::max<Sci::Position>(offsetFirstChar, 0);
numCharsToDraw = offsetLastChar - offsetFirstChar;
while ((offsetLastChar < ll->LineStart(subLine + 1)) && (offsetLastChar <= ll->numCharsInLine)) {
// Update posAfter to point to the 2nd next char, this is where
@@ -1475,8 +1456,8 @@ void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &v
}
// We now know what to draw, update the caret drawing rectangle
- rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xStart;
- rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xStart;
+ rcCaret.left = ll->positions[offsetFirstChar] - ll->positions[lineStart] + xOrigin;
+ rcCaret.right = ll->positions[offsetFirstChar + numCharsToDraw] - ll->positions[lineStart] + xOrigin;
// Adjust caret position to take into account any word wrapping symbols.
if ((ll->wrapIndent != 0) && (lineStart != 0)) {
@@ -1498,7 +1479,7 @@ void DrawBlockCaret(Surface *surface, const EditModel &model, const ViewStyle &v
}
void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line lineDoc, int xStart, PRectangle rcLine, int subLine) const {
+ Sci::Line lineDoc, int xOrigin, PRectangle rcLine, int subLine) const {
// When drag is active it is the only caret drawn
const bool drawDrag = model.posDrag.IsValid();
if (!vsDraw.selection.visible && !drawDrag)
@@ -1545,7 +1526,6 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
bool canDrawBlockCaret = true;
bool drawBlockCaret = false;
XYPOSITION widthOverstrikeCaret;
- XYPOSITION caretWidthOffset = 0;
PRectangle rcCaret = rcLine;
if (posCaret.Position() == model.pdoc->Length()) { // At end of document
@@ -1558,12 +1538,15 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
const int widthChar = model.pdoc->LenChar(posCaret.Position());
widthOverstrikeCaret = ll->positions[offset + widthChar] - ll->positions[offset];
}
- if (widthOverstrikeCaret < 3) // Make sure its visible
- widthOverstrikeCaret = 3;
+ // Make sure block caret visible
+ constexpr XYPOSITION minimumBlockCaretWidth = 3.0f;
+ widthOverstrikeCaret = std::max(widthOverstrikeCaret, minimumBlockCaretWidth);
- if (xposCaret > 0)
- caretWidthOffset = 0.51f; // Move back so overlaps both character cells.
- xposCaret += xStart;
+ // Move back slightly so line caret overlaps both character cells unless at start of text area.
+ constexpr XYPOSITION justOverHalf = 0.51f;
+ const XYPOSITION caretWidthOffset = (xposCaret > 0) ? justOverHalf : 0;
+
+ xposCaret += xOrigin;
const ViewStyle::CaretShape caretShape = drawDrag ? ViewStyle::CaretShape::line :
vsDraw.CaretShapeForMode(model.inOverstrike, mainCaret);
if (drawDrag) {
@@ -1593,7 +1576,7 @@ void EditView::DrawCarets(Surface *surface, const EditModel &model, const ViewSt
const ColourRGBA caretColour = vsDraw.ElementColourForced(elementCaret);
//assert(caretColour.IsOpaque());
if (drawBlockCaret) {
- DrawBlockCaret(surface, model, vsDraw, ll, subLine, xStart, offset, posCaret.Position(), rcCaret, caretColour);
+ DrawBlockCaret(surface, model, vsDraw, ll, subLine, xOrigin, offset, posCaret.Position(), rcCaret, caretColour);
} else {
surface->FillRectangleAligned(rcCaret, Fill(caretColour));
}
@@ -1690,7 +1673,7 @@ void DrawBackground(Surface *surface, const EditModel &model, const ViewStyle &v
ColourRGBA textBack = TextBackground(model, vsDraw, ll, background, inSelection,
inHotspot, ll->styles[i], i);
if (ts.representation) {
- if (ll->chars[i] == '\t') {
+ if (ll->chars[i] == '\t' && vsDraw.tabDrawMode != TabDrawMode::ControlChar) {
// Tab display
if (drawWhitespaceBackground && vsDraw.WhiteSpaceVisible(inIndentation)) {
textBack = vsDraw.ElementColourForced(Element::WhiteSpaceBack).Opaque();
@@ -1771,10 +1754,8 @@ void DrawTranslucentSelection(Surface *surface, const EditModel &model, const Vi
const XYPOSITION subLineStart = ll->positions[lineRange.start];
const XYPOSITION horizontalOffset = xStart - subLineStart;
// For each selection draw
- Sci::Position virtualSpaces = 0;
- if (subLine == (ll->lines - 1)) {
- virtualSpaces = model.sel.VirtualSpaceFor(model.pdoc->LineEnd(line));
- }
+ const Sci::Position virtualSpaces = (subLine == (ll->lines - 1)) ?
+ model.VirtualSpaceForLine(line) : 0;
const SelectionPosition posStart(posLineStart + lineRange.start);
const SelectionPosition posEnd(posLineStart + lineRange.end, virtualSpaces);
const SelectionSegment virtualSpaceRange(posStart, posEnd);
@@ -1912,7 +1893,7 @@ void DrawTabArrow(Surface *surface, PRectangle rcTab, int ymid,
// Draw the arrow head if needed
if (vsDraw.tabDrawMode == TabDrawMode::LongArrow) {
- XYPOSITION ydiff = std::floor(rcTab.Height() / 2.0f);
+ XYPOSITION ydiff = std::floor(rcTab.Height() / 2);
XYPOSITION xhead = rightStroke - ydiff;
if (xhead <= rcTab.left) {
ydiff -= rcTab.left - xhead;
@@ -2031,7 +2012,7 @@ void DrawIndicators(Surface *surface, const EditModel &model, const ViewStyle &v
const Sci::Position endPos = std::min(rangeRun.end, posLineEnd);
const int edition = model.pdoc->EditionAt(startPos);
if (edition != 0) {
- const int indicator = (edition - 1) * 2 + indexHistory;
+ const int indicator = ((edition - 1) * 2) + indexHistory;
const Sci::Position posSecond = model.pdoc->MovePositionOutsideChar(rangeRun.First() + 1, 1);
DrawIndicator(indicator, startPos - posLineStart, endPos - posLineStart,
surface, vsDraw, ll, xStart, rcLine, posSecond - posLineStart, subLine, Indicator::State::normal,
@@ -2048,7 +2029,7 @@ void DrawIndicators(Surface *surface, const EditModel &model, const ViewStyle &v
const Sci::Position posSecond = model.pdoc->MovePositionOutsideChar(startPos + 1, 1);
for (unsigned int edition = 0; edition < 4; edition++) {
if (editions & (1 << edition)) {
- const int indicator = edition * 2 + indexHistory + 1;
+ const int indicator = (edition * 2) + indexHistory + 1;
DrawIndicator(indicator, startPos - posLineStart, posSecond - posLineStart,
surface, vsDraw, ll, xStart, rcLine, posSecond - posLineStart, subLine, Indicator::State::normal,
1, model.BidirectionalEnabled(), tabWidthMinimumPixels);
@@ -2102,12 +2083,12 @@ ColourRGBA InvertedLight(ColourRGBA orig) noexcept {
r = r * il / l;
g = g * il / l;
b = b * il / l;
- return ColourRGBA(std::min(r, 0xffu), std::min(g, 0xffu), std::min(b, 0xffu));
+ return ColourRGBA(std::min(r, maximumByte), std::min(g, maximumByte), std::min(b, maximumByte));
}
}
-void EditView::DrawIndentGuide(Surface *surface, XYPOSITION start, PRectangle rcSegment, bool highlight, bool offset) {
+void EditView::DrawIndentGuide(Surface *surface, XYPOSITION start, PRectangle rcSegment, bool highlight, bool offset) const {
const Point from = Point::FromInts(0, offset ? 1 : 0);
const PRectangle rcCopyArea(start + 1, rcSegment.top,
start + 2, rcSegment.bottom);
@@ -2197,7 +2178,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
}
ColourRGBA textBack = TextBackground(model, vsDraw, ll, background, inSelection, inHotspot, styleMain, i);
if (ts.representation) {
- if (ll->chars[i] == '\t') {
+ if (ll->chars[i] == '\t' && vsDraw.tabDrawMode != TabDrawMode::ControlChar) {
// Tab display
if (phasesDraw == PhasesDraw::One) {
if (drawWhitespaceBackground && vsDraw.WhiteSpaceVisible(inIndentation))
@@ -2219,7 +2200,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
if (vsDraw.WhiteSpaceVisible(inIndentation)) {
const PRectangle rcTab(rcSegment.left + 1, rcSegment.top + tabArrowHeight,
rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
- const int segmentTop = static_cast<int>(rcSegment.top) + vsDraw.lineHeight / 2;
+ const int segmentTop = static_cast<int>(rcSegment.top) + (vsDraw.lineHeight / 2);
const ColourRGBA whiteSpaceFore = vsDraw.ElementColour(Element::WhiteSpace).value_or(textFore);
if (!customDrawTabArrow)
DrawTabArrow(surface, rcTab, segmentTop, vsDraw, Stroke(whiteSpaceFore, 1.0f));
@@ -2229,12 +2210,13 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
}
} else {
inIndentation = false;
- if (vsDraw.controlCharSymbol >= 32) {
+ if (vsDraw.controlCharSymbol >= ' ') {
// Using one font for all control characters so it can be controlled independently to ensure
// the box goes around the characters tightly. Seems to be no way to work out what height
// is taken by an individual character - internal leading gives varying results.
const Font *ctrlCharsFont = vsDraw.styles[StyleControlChar].font.get();
const char cc[2] = { static_cast<char>(vsDraw.controlCharSymbol), '\0' };
+ // NOLINTNEXTLINE(readability-suspicious-call-argument) Inverted text
surface->DrawTextNoClip(rcSegment, ctrlCharsFont,
ybase, cc, textBack, textFore);
} else {
@@ -2286,7 +2268,7 @@ void EditView::DrawForeground(Surface *surface, const EditModel &model, const Vi
}
const int halfDotWidth = vsDraw.whitespaceSize / 2;
PRectangle rcDot(xmid - halfDotWidth,
- rcSegment.top + vsDraw.lineHeight / 2, 0.0f, 0.0f);
+ rcSegment.top + (vsDraw.lineHeight / 2), 0.0f, 0.0f);
rcDot.right = rcDot.left + vsDraw.whitespaceSize;
rcDot.bottom = rcDot.top + vsDraw.whitespaceSize;
const ColourRGBA whiteSpaceFore = vsDraw.ElementColour(Element::WhiteSpace).value_or(textFore);
@@ -2336,12 +2318,16 @@ void EditView::DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &mode
// Find the most recent line with some text
+ constexpr int largeIndent = 100000;
+
+ constexpr Sci::Line maxCheck = 20;
+
Sci::Line lineLastWithText = line;
- while (lineLastWithText > std::max(line - 20, static_cast<Sci::Line>(0)) && model.pdoc->IsWhiteLine(lineLastWithText)) {
+ while (lineLastWithText > std::max(line - maxCheck, static_cast<Sci::Line>(0)) && model.pdoc->IsWhiteLine(lineLastWithText)) {
lineLastWithText--;
}
if (lineLastWithText < line) {
- xStartText = 100000; // Don't limit to visible indentation on empty line
+ xStartText = largeIndent; // Don't limit to visible indentation on empty line
// This line is empty, so use indentation of last line with text
int indentLastWithText = model.pdoc->GetLineIndentation(lineLastWithText);
const int isFoldHeader = LevelIsHeader(model.pdoc->GetFoldLevel(lineLastWithText));
@@ -2350,21 +2336,21 @@ void EditView::DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &mode
indentLastWithText += model.pdoc->IndentSize();
}
if (vsDraw.viewIndentationGuides == IndentView::LookForward) {
- // In viLookForward mode, previous line only used if it is a fold header
+ // In LookForward mode, previous line only used if it is a fold header
if (isFoldHeader) {
indentSpace = std::max(indentSpace, indentLastWithText);
}
- } else { // viLookBoth
+ } else { // LookBoth
indentSpace = std::max(indentSpace, indentLastWithText);
}
}
Sci::Line lineNextWithText = line;
- while (lineNextWithText < std::min(line + 20, model.pdoc->LinesTotal()) && model.pdoc->IsWhiteLine(lineNextWithText)) {
+ while (lineNextWithText < std::min(line + maxCheck, model.pdoc->LinesTotal()) && model.pdoc->IsWhiteLine(lineNextWithText)) {
lineNextWithText++;
}
if (lineNextWithText > line) {
- xStartText = 100000; // Don't limit to visible indentation on empty line
+ xStartText = largeIndent; // Don't limit to visible indentation on empty line
// This line is empty, so use indentation of first next line with text
indentSpace = std::max(indentSpace,
model.pdoc->GetLineIndentation(lineNextWithText));
@@ -2381,10 +2367,10 @@ void EditView::DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &mode
}
void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line line, Sci::Line lineVisible, int xStart, PRectangle rcLine, int subLine, DrawPhase phase) {
+ Sci::Line line, Sci::Line lineVisible, int xOrigin, PRectangle rcLine, int subLine, DrawPhase phase) {
if (subLine >= ll->lines) {
- DrawAnnotation(surface, model, vsDraw, ll, line, xStart, rcLine, subLine, phase);
+ DrawAnnotation(surface, model, vsDraw, ll, line, xOrigin, rcLine, subLine, phase);
return; // No further drawing
}
@@ -2404,10 +2390,10 @@ void EditView::DrawLine(Surface *surface, const EditModel &model, const ViewStyl
if ((ll->wrapIndent != 0) && (subLine > 0)) {
if (FlagSet(phase, DrawPhase::back)) {
- DrawWrapIndentAndMarker(surface, vsDraw, ll, xStart, rcLine, background, customDrawWrapMarker, model.caret.active);
+ DrawWrapIndentAndMarker(surface, vsDraw, ll, xOrigin, rcLine, background, customDrawWrapMarker, model.caret.active);
}
- xStart += static_cast<int>(ll->wrapIndent);
}
+ const int xStart = xOrigin + ((subLine > 0) ? static_cast<int>(ll->wrapIndent) : 0);
if (phasesDraw != PhasesDraw::One) {
if (FlagSet(phase, DrawPhase::back)) {
@@ -2497,7 +2483,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V
const Point ptOrigin = model.GetVisibleOriginInMain();
const int screenLinePaintFirst = static_cast<int>(rcArea.top) / vsDraw.lineHeight;
- const int xStart = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x);
+ const int xOrigin = vsDraw.textStart - model.xOffset + static_cast<int>(ptOrigin.x);
const SelectionPosition posCaret = model.posDrag.IsValid() ? model.posDrag : model.sel.RangeMain().caret;
const Sci::Line lineCaret = model.pdoc->SciLineFromPosition(posCaret.Position());
@@ -2588,7 +2574,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V
surface->FillRectangleAligned(rcSpacer, Fill(vsDraw.styles[StyleDefault].back));
}
- DrawLine(surface, model, vsDraw, ll.get(), lineDoc, visibleLine, xStart, rcLine, subLine, phase);
+ DrawLine(surface, model, vsDraw, ll.get(), lineDoc, visibleLine, xOrigin, rcLine, subLine, phase);
#if defined(TIME_PAINTING)
durPaint += ep.Duration(true);
#endif
@@ -2600,7 +2586,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V
}
if (FlagSet(phase, DrawPhase::carets)) {
- DrawCarets(surface, model, vsDraw, ll.get(), lineDoc, xStart, rcLine, subLine);
+ DrawCarets(surface, model, vsDraw, ll.get(), lineDoc, xOrigin, rcLine, subLine);
}
if (bufferedDraw) {
@@ -2612,8 +2598,7 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V
surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
}
- lineWidthMaxSeen = std::max(
- lineWidthMaxSeen, static_cast<int>(ll->positions[ll->numCharsInLine]));
+ UpdateMaxWidth(ll->positions[ll->numCharsInLine]);
#if defined(TIME_PAINTING)
durCopy += ep.Duration(true);
#endif
@@ -2646,14 +2631,14 @@ void EditView::PaintText(Surface *surfaceWindow, const EditModel &model, const V
surfaceWindow->FillRectangleAligned(rcBeyondEOF, Fill(vsDraw.styles[StyleDefault].back));
if (vsDraw.edgeState == EdgeVisualStyle::Line) {
const int edgeX = static_cast<int>(vsDraw.theEdge.column * vsDraw.spaceWidth);
- rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xStart);
+ rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xOrigin);
rcBeyondEOF.right = rcBeyondEOF.left + 1;
surfaceWindow->FillRectangleAligned(rcBeyondEOF, Fill(vsDraw.theEdge.colour));
} else if (vsDraw.edgeState == EdgeVisualStyle::MultiLine) {
for (size_t edge = 0; edge < vsDraw.theMultiEdge.size(); edge++) {
if (vsDraw.theMultiEdge[edge].column >= 0) {
const int edgeX = static_cast<int>(vsDraw.theMultiEdge[edge].column * vsDraw.spaceWidth);
- rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xStart);
+ rcBeyondEOF.left = static_cast<XYPOSITION>(edgeX + xOrigin);
rcBeyondEOF.right = rcBeyondEOF.left + 1;
surfaceWindow->FillRectangleAligned(rcBeyondEOF, Fill(vsDraw.theMultiEdge[edge].colour));
}
@@ -2750,13 +2735,11 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl
1u << static_cast<unsigned int>(MarkerOutline::HistoryRevertedToModified);
vsPrint.maskInLine &= ~changeMarkers;
+ const int linesInArea = (rc.bottom - rc.top) / vsPrint.lineHeight;
const Sci::Line linePrintStart = model.pdoc->SciLineFromPosition(chrg.cpMin);
- Sci::Line linePrintLast = linePrintStart + (rc.bottom - rc.top) / vsPrint.lineHeight - 1;
- if (linePrintLast < linePrintStart)
- linePrintLast = linePrintStart;
const Sci::Line linePrintMax = model.pdoc->SciLineFromPosition(chrg.cpMax);
- if (linePrintLast > linePrintMax)
- linePrintLast = linePrintMax;
+ const Sci::Line linePrintLast = std::min(std::max(linePrintStart + linesInArea - 1, linePrintStart), linePrintMax);
+
//Platform::DebugPrintf("Formatting lines=[%0d,%0d,%0d] top=%0d bottom=%0d line=%0d %0d\n",
// linePrintStart, linePrintLast, linePrintMax, rc.top, rc.bottom, vsPrint.lineHeight,
// surfaceMeasure->Height(vsPrint.styles[StyleLineNumber].font));
@@ -2767,7 +2750,7 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl
// Ensure we are styled to where we are formatting.
model.pdoc->EnsureStyledTo(endPosPrint);
- const int xStart = vsPrint.fixedColumnWidth + rc.left;
+ const int xOrigin = vsPrint.fixedColumnWidth + rc.left;
int ypos = rc.top;
Sci::Line lineDoc = linePrintStart;
@@ -2841,7 +2824,7 @@ Sci::Position EditView::FormatRange(bool draw, CharacterRangeFull chrg, Rectangl
if (draw) {
rcLine.top = static_cast<XYPOSITION>(ypos);
rcLine.bottom = static_cast<XYPOSITION>(ypos + vsPrint.lineHeight);
- DrawLine(surface, model, vsPrint, &ll, lineDoc, visibleLine, xStart, rcLine, iwl, DrawPhase::all);
+ DrawLine(surface, model, vsPrint, &ll, lineDoc, visibleLine, xOrigin, rcLine, iwl, DrawPhase::all);
}
ypos += vsPrint.lineHeight;
}
diff --git a/src/EditView.h b/src/EditView.h
index 1e28d25c5..58e9c3d80 100644
--- a/src/EditView.h
+++ b/src/EditView.h
@@ -133,6 +133,7 @@ public:
Sci::Position StartEndDisplayLine(Surface *surface, const EditModel &model, Sci::Position pos, bool start, const ViewStyle &vs);
private:
+ void UpdateMaxWidth(XYPOSITION width) noexcept;
void DrawEOL(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
Sci::Line line, int xStart, PRectangle rcLine, int subLine, Sci::Position lineEnd, XYPOSITION subLineStart, ColourOptional background);
void DrawFoldDisplayText(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
@@ -140,17 +141,17 @@ private:
void DrawEOLAnnotationText(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
Sci::Line line, int xStart, PRectangle rcLine, int subLine, XYPOSITION subLineStart, DrawPhase phase);
void DrawAnnotation(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line line, int xStart, PRectangle rcLine, int subLine, DrawPhase phase);
+ Sci::Line line, int xOrigin, PRectangle rcLine, int subLine, DrawPhase phase);
void DrawCarets(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line lineDoc, int xStart, PRectangle rcLine, int subLine) const;
- void DrawIndentGuide(Surface *surface, XYPOSITION start, PRectangle rcSegment, bool highlight, bool offset);
+ Sci::Line lineDoc, int xOrigin, PRectangle rcLine, int subLine) const;
+ void DrawIndentGuide(Surface *surface, XYPOSITION start, PRectangle rcSegment, bool highlight, bool offset) const;
void DrawForeground(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
int xStart, PRectangle rcLine, int subLine, Sci::Line lineVisible, Range lineRange, Sci::Position posLineStart,
ColourOptional background);
void DrawIndentGuidesOverEmpty(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
Sci::Line line, int xStart, PRectangle rcLine, int subLine, Sci::Line lineVisible);
void DrawLine(Surface *surface, const EditModel &model, const ViewStyle &vsDraw, const LineLayout *ll,
- Sci::Line line, Sci::Line lineVisible, int xStart, PRectangle rcLine, int subLine, DrawPhase phase);
+ Sci::Line line, Sci::Line lineVisible, int xOrigin, PRectangle rcLine, int subLine, DrawPhase phase);
public:
void PaintText(Surface *surfaceWindow, const EditModel &model, const ViewStyle &vsDraw,
diff --git a/src/Editor.cxx b/src/Editor.cxx
index e7a309e67..0289fa5e5 100644
--- a/src/Editor.cxx
+++ b/src/Editor.cxx
@@ -143,6 +143,7 @@ Editor::Editor() : durationWrapOneByte(0.000001, 0.00000001, 0.00001) {
dwelling = false;
ptMouseLast.x = 0;
ptMouseLast.y = 0;
+ dragDropEnabled = true;
inDragDrop = DragDrop::none;
dropWentOutside = false;
posDrop = SelectionPosition(Sci::invalidPosition);
@@ -4167,42 +4168,37 @@ void Editor::Indent(bool forwards, bool lineIndent) {
Sci::Position caretPosition = sel.Range(r).caret.Position();
const Sci::Line lineCurrentPos = pdoc->SciLineFromPosition(caretPosition);
if (lineOfAnchor == lineCurrentPos && !lineIndent) {
+ const int indentationStep = pdoc->IndentSize();
if (forwards) {
pdoc->DeleteChars(sel.Range(r).Start().Position(), sel.Range(r).Length());
caretPosition = sel.Range(r).caret.Position();
- if (pdoc->GetColumn(caretPosition) <= pdoc->GetColumn(pdoc->GetLineIndentPosition(lineCurrentPos)) &&
- pdoc->tabIndents) {
- const int indentation = pdoc->GetLineIndentation(lineCurrentPos);
- const int indentationStep = pdoc->IndentSize();
+ const int indentation = pdoc->GetLineIndentation(lineCurrentPos);
+ const Sci::Position column = pdoc->GetColumn(caretPosition);
+ if (column <= indentation && pdoc->tabIndents) {
+ // Inside initial whitespace
const Sci::Position posSelect = pdoc->SetLineIndentation(
- lineCurrentPos, indentation + indentationStep - indentation % indentationStep);
+ lineCurrentPos, indentation + indentationStep - (indentation % indentationStep));
sel.Range(r) = SelectionRange(posSelect);
} else {
if (pdoc->useTabs) {
- const Sci::Position lengthInserted = pdoc->InsertString(caretPosition, "\t", 1);
+ const Sci::Position lengthInserted = pdoc->InsertString(caretPosition, "\t");
sel.Range(r) = SelectionRange(caretPosition + lengthInserted);
} else {
- int numSpaces = (pdoc->tabInChars) -
- static_cast<int>((pdoc->GetColumn(caretPosition) % (pdoc->tabInChars)));
- if (numSpaces < 1)
- numSpaces = pdoc->tabInChars;
+ const Sci::Position numSpaces = pdoc->tabInChars - (column % pdoc->tabInChars);
const std::string spaceText(numSpaces, ' ');
const Sci::Position lengthInserted = pdoc->InsertString(caretPosition, spaceText);
sel.Range(r) = SelectionRange(caretPosition + lengthInserted);
}
}
} else {
- if (pdoc->GetColumn(caretPosition) <= pdoc->GetLineIndentation(lineCurrentPos) &&
- pdoc->tabIndents) {
- const int indentation = pdoc->GetLineIndentation(lineCurrentPos);
- const int indentationStep = pdoc->IndentSize();
+ const int indentation = pdoc->GetLineIndentation(lineCurrentPos);
+ const Sci::Position column = pdoc->GetColumn(caretPosition);
+ if (column <= indentation && pdoc->tabIndents) {
const Sci::Position posSelect = pdoc->SetLineIndentation(lineCurrentPos, indentation - indentationStep);
sel.Range(r) = SelectionRange(posSelect);
} else {
- Sci::Position newColumn = ((pdoc->GetColumn(caretPosition) - 1) / pdoc->tabInChars) *
- pdoc->tabInChars;
- if (newColumn < 0)
- newColumn = 0;
+ const Sci::Position newColumn = std::max<Sci::Position>(0,
+ ((column - 1) / pdoc->tabInChars) * pdoc->tabInChars);
Sci::Position newPos = caretPosition;
while (pdoc->GetColumn(newPos) > newColumn)
newPos--;
@@ -5041,7 +5037,7 @@ void Editor::ButtonMoveWithModifiers(Point pt, unsigned int, KeyMod modifiers) {
AllowVirtualSpace(virtualSpaceOptions, sel.IsRectangular()));
movePos = MovePositionOutsideChar(movePos, sel.MainCaret() - movePos.Position());
- if (inDragDrop == DragDrop::initial) {
+ if (dragDropEnabled && inDragDrop == DragDrop::initial) {
if (DragThreshold(ptMouseLast, pt)) {
ChangeMouseCapture(false);
SetDragPosition(movePos);
@@ -5139,7 +5135,7 @@ void Editor::ButtonMoveWithModifiers(Point pt, unsigned int, KeyMod modifiers) {
}
}
// Display regular (drag) cursor over selection
- if (PointInSelection(pt) && !SelectionEmpty()) {
+ if (dragDropEnabled && PointInSelection(pt) && !SelectionEmpty()) {
DisplayCursor(Window::Cursor::arrow);
SetHoverIndicatorPosition(Sci::invalidPosition);
} else {
@@ -6178,11 +6174,11 @@ void Editor::SetSelectionNMessage(Message iMessage, uptr_t wParam, sptr_t lParam
break;
case Message::SetSelectionNStart:
- sel.Range(wParam).anchor.SetPosition(lParam);
+ sel.Range(wParam).StartSet(SelectionPosition(lParam));
break;
case Message::SetSelectionNEnd:
- sel.Range(wParam).caret.SetPosition(lParam);
+ sel.Range(wParam).EndSet(SelectionPosition(lParam));
break;
default:
@@ -6988,7 +6984,7 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
return static_cast<sptr_t>(vs.tabDrawMode);
case Message::SetTabDrawMode:
- vs.tabDrawMode = static_cast<TabDrawMode>(wParam);
+ SetAppearance(vs.tabDrawMode, static_cast<TabDrawMode>(wParam));
Redraw();
break;
@@ -7084,6 +7080,13 @@ sptr_t Editor::WndProc(Message iMessage, uptr_t wParam, sptr_t lParam) {
case Message::GetBufferedDraw:
return view.bufferedDraw;
+ case Message::GetDragDropEnabled:
+ return dragDropEnabled;
+
+ case Message::SetDragDropEnabled:
+ dragDropEnabled = wParam != 0;
+ break;
+
#ifdef INCLUDE_DEPRECATED_FEATURES
case SCI_GETTWOPHASEDRAW:
return view.phasesDraw == EditView::phasesTwo;
diff --git a/src/Editor.h b/src/Editor.h
index f8bc18970..95b83f1f7 100644
--- a/src/Editor.h
+++ b/src/Editor.h
@@ -238,6 +238,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
bool dwelling;
enum class TextUnit { character, word, subLine, wholeLine } selectionUnit;
Point ptMouseLast;
+ bool dragDropEnabled;
enum class DragDrop { none, initial, dragging } inDragDrop;
bool dropWentOutside;
SelectionPosition posDrop;
diff --git a/src/Geometry.h b/src/Geometry.h
index d02a25bbb..a08c5c8f0 100644
--- a/src/Geometry.h
+++ b/src/Geometry.h
@@ -69,6 +69,9 @@ public:
constexpr Interval Offset(XYPOSITION offset) const noexcept {
return {left + offset, right + offset};
}
+ [[nodiscard]] static constexpr Interval FromLeftAndWidth(XYPOSITION left_, XYPOSITION width) {
+ return {left_, left_+width};
+ }
};
/**
diff --git a/src/PositionCache.cxx b/src/PositionCache.cxx
index 16bc10f5a..1f05ca752 100644
--- a/src/PositionCache.cxx
+++ b/src/PositionCache.cxx
@@ -318,6 +318,10 @@ int LineLayout::EndLineStyle() const noexcept {
return styles[std::max(numCharsBeforeEOL - 1, 0)];
}
+int LineLayout::LastStyle() const noexcept {
+ return styles[numCharsInLine];
+}
+
void LineLayout::WrapLine(const Document *pdoc, Sci::Position posLineStart, Wrap wrapState, XYPOSITION wrapWidth) {
// Document wants document positions but simpler to work in line positions
// so take care of adding and subtracting line start in a lambda.
@@ -996,14 +1000,13 @@ public:
};
class PositionCache : public IPositionCache {
- static constexpr size_t defaultCacheSize = 0x400;
- std::vector<PositionCacheEntry> pces{ defaultCacheSize };
+ std::vector<PositionCacheEntry> pces{ positionCacheDefaultSize };
std::mutex mutex;
uint16_t clock = 1;
bool allClear = true;
public:
PositionCache();
- // Deleted so LineAnnotation objects can not be copied.
+ // Deleted so PositionCache objects can not be copied.
PositionCache(const PositionCache &) = delete;
PositionCache(PositionCache &&) = delete;
void operator=(const PositionCache &) = delete;
diff --git a/src/PositionCache.h b/src/PositionCache.h
index b912c2fcc..9138d18e7 100644
--- a/src/PositionCache.h
+++ b/src/PositionCache.h
@@ -101,6 +101,7 @@ public:
Interval Span(int start, int end) const noexcept;
Interval SpanByte(int index) const noexcept;
int EndLineStyle() const noexcept;
+ [[nodiscard]] int LastStyle() const noexcept;
void WrapLine(const Document *pdoc, Sci::Position posLineStart, Wrap wrapState, XYPOSITION wrapWidth);
};
@@ -256,6 +257,8 @@ public:
bool More() const noexcept;
};
+constexpr size_t positionCacheDefaultSize = 0x400;
+
class IPositionCache {
public:
virtual ~IPositionCache() = default;
diff --git a/src/Selection.cxx b/src/Selection.cxx
index 967033bff..e8d0148f5 100644
--- a/src/Selection.cxx
+++ b/src/Selection.cxx
@@ -182,6 +182,34 @@ SelectionSegment SelectionRange::Intersect(SelectionSegment check) const noexcep
};
}
+void SelectionRange::StartSet(SelectionPosition sp) noexcept {
+ if (anchor <= caret) {
+ anchor = sp;
+ if (caret < anchor) {
+ caret = anchor;
+ }
+ } else {
+ caret = sp;
+ if (anchor < caret) {
+ anchor = caret;
+ }
+ }
+}
+
+void SelectionRange::EndSet(SelectionPosition sp) noexcept {
+ if (caret >= anchor) {
+ caret = sp;
+ if (anchor > caret) {
+ anchor = caret;
+ }
+ } else {
+ anchor = sp;
+ if (caret > anchor) {
+ caret = anchor;
+ }
+ }
+}
+
void SelectionRange::Swap() noexcept {
std::swap(caret, anchor);
}
diff --git a/src/Selection.h b/src/Selection.h
index 1a57d2e78..0b3bb9159 100644
--- a/src/Selection.h
+++ b/src/Selection.h
@@ -156,6 +156,8 @@ struct SelectionRange {
SelectionPosition End() const noexcept {
return (anchor < caret) ? caret : anchor;
}
+ void StartSet(SelectionPosition sp) noexcept;
+ void EndSet(SelectionPosition sp) noexcept;
void Swap() noexcept;
bool Trim(SelectionRange range) noexcept;
void Truncate(Sci::Position length) noexcept;
diff --git a/src/Style.cxx b/src/Style.cxx
index 2c78c5241..a080f452e 100644
--- a/src/Style.cxx
+++ b/src/Style.cxx
@@ -62,7 +62,9 @@ int DefaultFontSize() noexcept {
try {
return Platform::DefaultFontSize();
} catch (...) {
- return 10;
+ // Should never happen
+ constexpr int sensibleFontSize = 10;
+ return sensibleFontSize;
}
}
@@ -83,5 +85,5 @@ Style::Style(const char *fontName_) noexcept :
void Style::Copy(std::shared_ptr<Font> font_, const FontMeasurements &fm_) noexcept {
font = std::move(font_);
- (FontMeasurements &)(*this) = fm_;
+ static_cast<FontMeasurements &>(*this) = fm_;
}
diff --git a/src/ViewStyle.cxx b/src/ViewStyle.cxx
index 92d084ee6..767e019f4 100644
--- a/src/ViewStyle.cxx
+++ b/src/ViewStyle.cxx
@@ -49,6 +49,8 @@ constexpr unsigned int mid = 0x80U;
constexpr unsigned int half = 0x7fU;
constexpr unsigned int quarter = 0x3fU;
+constexpr int startExtendedStyles = 0x100;
+
}
MarginStyle::MarginStyle(MarginType style_, int width_, int mask_) noexcept :
@@ -61,9 +63,8 @@ bool MarginStyle::ShowsFolding() const noexcept {
void FontRealised::Realise(Surface &surface, int zoomLevel, Technology technology, const FontSpecification &fs, const char *localeName) {
PLATFORM_ASSERT(fs.fontName);
- measurements.sizeZoomed = fs.size + zoomLevel * FontSizeMultiplier;
- if (measurements.sizeZoomed <= FontSizeMultiplier) // May fail if sizeZoomed < 1
- measurements.sizeZoomed = FontSizeMultiplier;
+ // If negative zoomLevel, ensure sizeZoomed at least minimum positive size
+ measurements.sizeZoomed = std::max(fs.size + (zoomLevel * FontSizeMultiplier), FontSizeMultiplier);
const float deviceHeight = static_cast<float>(surface.DeviceHeightFont(measurements.sizeZoomed));
const FontParameters fp(fs.fontName, deviceHeight / FontSizeMultiplier, fs.weight,
@@ -73,10 +74,11 @@ void FontRealised::Realise(Surface &surface, int zoomLevel, Technology technolog
// floor here is historical as platform layers have tweaked their values to match.
// ceil would likely be better to ensure (nearly) all of the ink of a character is seen
// but that would require platform layer changes.
- measurements.ascent = std::floor(surface.Ascent(font.get()));
+ const XYPOSITION ascent = surface.Ascent(font.get());
+ measurements.ascent = std::floor(ascent);
measurements.descent = std::floor(surface.Descent(font.get()));
- measurements.capitalHeight = surface.Ascent(font.get()) - surface.InternalLeading(font.get());
+ measurements.capitalHeight = ascent - surface.InternalLeading(font.get());
measurements.aveCharWidth = surface.AverageCharWidth(font.get());
measurements.monospaceCharacterWidth = measurements.aveCharWidth;
measurements.spaceWidth = surface.WidthText(font.get(), " ");
@@ -92,9 +94,9 @@ void FontRealised::Realise(Surface &surface, int zoomLevel, Technology technolog
const XYPOSITION maxWidth = *std::max_element(positions.begin(), positions.end());
const XYPOSITION minWidth = *std::min_element(positions.begin(), positions.end());
const XYPOSITION variance = maxWidth - minWidth;
- const XYPOSITION scaledVariance = variance / measurements.aveCharWidth;
constexpr XYPOSITION monospaceWidthEpsilon = 0.000001; // May need tweaking if monospace fonts vary more
- measurements.monospaceASCII = scaledVariance < monospaceWidthEpsilon;
+ const XYPOSITION scaledVariance = monospaceWidthEpsilon * minWidth;
+ measurements.monospaceASCII = variance < scaledVariance;
measurements.monospaceCharacterWidth = minWidth;
} else {
measurements.monospaceASCII = false;
@@ -107,7 +109,7 @@ ViewStyle::ViewStyle(size_t stylesSize_) :
indicators(static_cast<size_t>(IndicatorNumbers::Max) + 1),
ms(MaxMargin + 1) {
- nextExtendedStyle = 256;
+ nextExtendedStyle = startExtendedStyles;
ResetDefaultStyle();
// There are no image markers by default, so no need for calling CalcLargestMarkerHeight()
@@ -170,9 +172,11 @@ ViewStyle::ViewStyle(size_t stylesSize_) :
lineOverlap = 0;
maxAscent = 1;
maxDescent = 1;
- aveCharWidth = 8;
- spaceWidth = 8;
- tabWidth = spaceWidth * 8;
+ constexpr XYPOSITION defaultWidthChar = 8.F; // Reasonable initial approximation
+ aveCharWidth = defaultWidthChar;
+ spaceWidth = defaultWidthChar;
+ constexpr int defaultTabSpaces = 8;
+ tabWidth = spaceWidth * defaultTabSpaces;
// Default is for no selection foregrounds
// Shades of grey for selection backgrounds
@@ -220,7 +224,8 @@ ViewStyle::ViewStyle(size_t stylesSize_) :
leftMarginWidth = 1;
rightMarginWidth = 1;
ms[0] = MarginStyle(MarginType::Number);
- ms[1] = MarginStyle(MarginType::Symbol, 16, ~MaskFolders);
+ constexpr int widthMarks = 16;
+ ms[1] = MarginStyle(MarginType::Symbol, widthMarks, ~MaskFolders);
ms[2] = MarginStyle(MarginType::Symbol);
marginInside = true;
CalculateMarginWidthAndMask();
@@ -335,7 +340,7 @@ ViewStyle::~ViewStyle() = default;
void ViewStyle::CalculateMarginWidthAndMask() noexcept {
fixedColumnWidth = marginInside ? leftMarginWidth : 0;
- maskInLine = 0xffffffff;
+ maskInLine = UINT32_MAX;
int maskDefinedMarkers = 0;
for (const MarginStyle &m : ms) {
fixedColumnWidth += m.width;
@@ -413,11 +418,9 @@ void ViewStyle::Refresh(Surface &surface, int tabInChars) {
maxAscent = std::max(1.0, maxAscent + extraAscent);
maxDescent = std::max(0.0, maxDescent + extraDescent);
lineHeight = static_cast<int>(std::lround(maxAscent + maxDescent));
- lineOverlap = lineHeight / 10;
- if (lineOverlap < 2)
- lineOverlap = 2;
- if (lineOverlap > lineHeight)
- lineOverlap = lineHeight;
+ // lineHeight may rarely be less than 2, so can't use std::clamp
+ constexpr int overlapFraction = 10; // Allow up to a tenth of a line overlap
+ lineOverlap = std::min(std::max(lineHeight / overlapFraction, 2), lineHeight);
someStylesProtected = std::any_of(styles.cbegin(), styles.cend(),
[](const Style &style) noexcept { return style.IsProtected(); });
@@ -430,7 +433,7 @@ void ViewStyle::Refresh(Surface &surface, int tabInChars) {
tabWidth = spaceWidth * tabInChars;
controlCharWidth = 0.0;
- if (controlCharSymbol >= 32) {
+ if (controlCharSymbol >= ' ') {
const char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
controlCharWidth = surface.WidthText(styles[StyleControlChar].font.get(), cc);
}
@@ -440,7 +443,7 @@ void ViewStyle::Refresh(Surface &surface, int tabInChars) {
}
void ViewStyle::ReleaseAllExtendedStyles() noexcept {
- nextExtendedStyle = 256;
+ nextExtendedStyle = startExtendedStyles;
}
int ViewStyle::AllocateExtendedStyles(int numberStyles) {
@@ -571,9 +574,8 @@ ColourOptional ViewStyle::Background(int marksOfLine, bool caretActive, bool lin
}
if (background) {
return background->Opaque();
- } else {
- return {};
}
+ return {};
}
bool ViewStyle::SelectionBackgroundDrawn() const noexcept {
@@ -671,9 +673,8 @@ bool ViewStyle::SetElementColour(Element element, ColourRGBA colour) {
bool ViewStyle::SetElementColourOptional(Element element, uptr_t wParam, sptr_t lParam) {
if (wParam) {
return SetElementColour(element, ColourRGBA::FromIpRGB(lParam));
- } else {
- return ResetElement(element);
}
+ return ResetElement(element);
}
void ViewStyle::SetElementRGB(Element element, int rgb) {
@@ -801,9 +802,7 @@ void ViewStyle::FindMaxAscentDescent() noexcept {
const auto &style = styles[i];
- if (maxAscent < style.ascent)
- maxAscent = style.ascent;
- if (maxDescent < style.descent)
- maxDescent = style.descent;
+ maxAscent = std::max(style.ascent, maxAscent);
+ maxDescent = std::max(style.descent, maxDescent);
}
}
diff --git a/test/simpleTests.py b/test/simpleTests.py
index 020b72e99..0a14a4bdb 100644
--- a/test/simpleTests.py
+++ b/test/simpleTests.py
@@ -260,6 +260,13 @@ class TestSimple(unittest.TestCase):
self.assertEqual(self.ed.CanUndo(), 0)
self.ed.UndoCollection = 1
+ def testDragDrop(self):
+ self.assertEqual(self.ed.DragDropEnabled, 1)
+ self.ed.DragDropEnabled = 0
+ self.assertEqual(self.ed.DragDropEnabled, 0)
+ self.ed.DragDropEnabled = 1
+ self.assertEqual(self.ed.DragDropEnabled, 1)
+
def testGetColumn(self):
self.ed.AddText(1, b"x")
self.assertEqual(self.ed.GetColumn(0), 0)
@@ -1967,6 +1974,28 @@ class TestMultiSelection(unittest.TestCase):
self.assertEqual(self.ed.GetSelectionNStart(0), 2)
self.assertEqual(self.ed.GetSelectionNEnd(0), 3)
+ self.ed.SetSelectionNStart(0, 1)
+ self.assertEqual(self.ed.GetSelectionNAnchor(0), 1)
+ self.assertEqual(self.ed.GetSelectionNCaret(0), 3)
+ self.assertEqual(self.ed.GetSelectionNStart(0), 1)
+ self.assertEqual(self.ed.GetSelectionNEnd(0), 3)
+
+ self.ed.SetSelectionNAnchor(0, 2)
+ self.ed.SetSelectionNCaret(0, 2)
+ self.ed.SetSelectionNStart(0, 9)
+ self.assertEqual(self.ed.GetSelectionNAnchor(0), 9)
+ self.assertEqual(self.ed.GetSelectionNCaret(0), 9)
+ self.assertEqual(self.ed.GetSelectionNStart(0), 9)
+ self.assertEqual(self.ed.GetSelectionNEnd(0), 9)
+
+ self.ed.SetSelectionNAnchor(0, 2)
+ self.ed.SetSelectionNCaret(0, 3)
+ self.ed.SetSelectionNStart(0, 9)
+ self.assertEqual(self.ed.GetSelectionNAnchor(0), 9)
+ self.assertEqual(self.ed.GetSelectionNCaret(0), 9)
+ self.assertEqual(self.ed.GetSelectionNStart(0), 9)
+ self.assertEqual(self.ed.GetSelectionNEnd(0), 9)
+
def test2Selections(self):
self.ed.SetSelection(1, 2)
self.ed.AddSelection(4, 5)
diff --git a/test/unit/testSelection.cxx b/test/unit/testSelection.cxx
index ab0065624..76eebca21 100644
--- a/test/unit/testSelection.cxx
+++ b/test/unit/testSelection.cxx
@@ -198,6 +198,96 @@ TEST_CASE("SelectionRange") {
REQUIRE(thin == single);
}
+ SECTION("StartEndSet") {
+ {
+ SelectionRange range;
+
+ range.StartSet(SelectionPosition(2));
+ range.EndSet(SelectionPosition(3));
+ REQUIRE(range.Start() == SelectionPosition(2));
+ REQUIRE(range.End() == SelectionPosition(3));
+ REQUIRE(range == SelectionRange(3, 2));
+
+ range.StartSet(SelectionPosition(1));
+ REQUIRE(range.Start() == SelectionPosition(1));
+ REQUIRE(range.End() == SelectionPosition(3));
+ REQUIRE(range == SelectionRange(3, 1));
+ }
+
+ {
+ // Outside after
+ SelectionRange range(2, 1);
+ range.StartSet(SelectionPosition(3));
+ REQUIRE(range.Start() == SelectionPosition(3));
+ REQUIRE(range.End() == SelectionPosition(3));
+ REQUIRE(range == SelectionRange(3, 3));
+ }
+
+ {
+ // Outside after
+ SelectionRange range(2, 1);
+ range.EndSet(SelectionPosition(3));
+ REQUIRE(range.Start() == SelectionPosition(1));
+ REQUIRE(range.End() == SelectionPosition(3));
+ REQUIRE(range == SelectionRange(3, 1));
+ }
+
+ {
+ // Outside before
+ SelectionRange range(2, 1);
+ range.StartSet(SelectionPosition(0));
+ REQUIRE(range.Start() == SelectionPosition(0));
+ REQUIRE(range.End() == SelectionPosition(2));
+ REQUIRE(range == SelectionRange(2, 0));
+ }
+
+ {
+ // Outside before
+ SelectionRange range(2, 1);
+ range.EndSet(SelectionPosition(0));
+ REQUIRE(range.Start() == SelectionPosition(0));
+ REQUIRE(range.End() == SelectionPosition(0));
+ REQUIRE(range == SelectionRange(0, 0));
+ }
+
+ {
+ // Inside
+ SelectionRange range(3, 1);
+ range.EndSet(SelectionPosition(2));
+ REQUIRE(range.Start() == SelectionPosition(1));
+ REQUIRE(range.End() == SelectionPosition(2));
+ REQUIRE(range == SelectionRange(2, 1));
+ }
+
+ {
+ // Inside
+ SelectionRange range(3, 1);
+ range.StartSet(SelectionPosition(2));
+ REQUIRE(range.Start() == SelectionPosition(2));
+ REQUIRE(range.End() == SelectionPosition(3));
+ REQUIRE(range == SelectionRange(3, 2));
+ }
+
+ {
+ // Empty then outside
+ SelectionRange range(2);
+ range.StartSet(SelectionPosition(9));
+ REQUIRE(range.Start() == SelectionPosition(9));
+ REQUIRE(range.End() == SelectionPosition(9));
+ REQUIRE(range == SelectionRange(9, 9));
+ }
+
+ {
+ // Empty then outside
+ SelectionRange range(2);
+ range.StartSet(SelectionPosition(0));
+ REQUIRE(range.Start() == SelectionPosition(0));
+ REQUIRE(range.End() == SelectionPosition(2));
+ REQUIRE(range == SelectionRange(2, 0));
+ }
+
+ }
+
}
TEST_CASE("Selection") {
diff --git a/version.txt b/version.txt
index 0ee983639..c7884c020 100644
--- a/version.txt
+++ b/version.txt
@@ -1 +1 @@
-557
+560
diff --git a/win32/ListBox.cxx b/win32/ListBox.cxx
index 0548ea5bc..b5ce7782f 100644
--- a/win32/ListBox.cxx
+++ b/win32/ListBox.cxx
@@ -195,8 +195,8 @@ class ListBoxX : public ListBox {
LRESULT NcHitTest(WPARAM, LPARAM) const;
void CentreItem(int n);
void AllocateBitMap();
- LRESULT PASCAL ListProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
- static LRESULT PASCAL ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
+ LRESULT CALLBACK ListProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
+ static LRESULT CALLBACK ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
static constexpr POINT ItemInset {0, 0}; // Padding around whole item
static constexpr POINT TextInset {2, 0}; // Padding around text
@@ -237,7 +237,7 @@ public:
void SetOptions(ListOptions options_) override;
void Draw(DRAWITEMSTRUCT *pDrawItem);
LRESULT WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
- static LRESULT PASCAL StaticWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
+ static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
};
std::unique_ptr<ListBox> ListBox::Allocate() {
@@ -787,7 +787,7 @@ void ListBoxX::AllocateBitMap() {
graphics.pixmapLine->Init(graphics.bm.DC(), GetID());
}
-LRESULT PASCAL ListBoxX::ListProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
+LRESULT CALLBACK ListBoxX::ListProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
try {
switch (iMessage) {
case WM_ERASEBKGND:
@@ -831,7 +831,7 @@ LRESULT PASCAL ListBoxX::ListProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARA
return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
}
-LRESULT PASCAL ListBoxX::ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
+LRESULT CALLBACK ListBoxX::ControlWndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
if (ListBoxX *lbx = static_cast<ListBoxX *>(PointerFromWindow(::GetParent(hWnd)))) {
return lbx->ListProc(hWnd, iMessage, wParam, lParam);
}
@@ -949,7 +949,7 @@ LRESULT ListBoxX::WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam
return 0;
}
-LRESULT PASCAL ListBoxX::StaticWndProc(
+LRESULT CALLBACK ListBoxX::StaticWndProc(
HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
if (iMessage == WM_CREATE) {
CREATESTRUCT *pCreate = static_cast<CREATESTRUCT *>(PtrFromLParam(lParam));
diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx
index ff47c28ab..01b41f5cc 100644
--- a/win32/PlatWin.cxx
+++ b/win32/PlatWin.cxx
@@ -628,13 +628,14 @@ HCURSOR LoadReverseArrowCursor(UINT dpi) noexcept {
COLORREF strokeColour = RGB(0, 0, 1);
status = ::RegOpenKeyExW(HKEY_CURRENT_USER, L"Software\\Microsoft\\Accessibility", 0, KEY_QUERY_VALUE, &hKey);
if (status == ERROR_SUCCESS) {
+ constexpr DWORD customColour = 6;
if (std::optional<DWORD> cursorType = RegGetDWORD(hKey, L"CursorType")) {
switch (*cursorType) {
case 1: // black
case 4: // black
std::swap(fillColour, strokeColour);
break;
- case 6: // custom
+ case customColour: // custom
if (std::optional<DWORD> cursorColor = RegGetDWORD(hKey, L"CursorColor")) {
fillColour = *cursorColor;
}
@@ -696,6 +697,15 @@ void Menu::Show(Point pt, const Window &w) {
Destroy();
}
+namespace {
+
+bool assertionPopUps = true;
+
+constexpr int defaultFontSize = 8;
+constexpr size_t lengthDiagnostic = 2000;
+
+}
+
ColourRGBA ColourFromSys(int nIndex) noexcept {
const DWORD colourValue = ::GetSysColor(nIndex);
return ColourRGBA::FromRGB(colourValue);
@@ -714,7 +724,7 @@ const char *Platform::DefaultFont() {
}
int Platform::DefaultFontSize() {
- return 8;
+ return defaultFontSize;
}
unsigned int Platform::DoubleClickTime() {
@@ -729,7 +739,7 @@ void Platform::DebugDisplay(const char *s) noexcept {
#ifdef TRACE
void Platform::DebugPrintf(const char *format, ...) noexcept {
- char buffer[2000];
+ char buffer[lengthDiagnostic];
va_list pArguments;
va_start(pArguments, format);
vsnprintf(buffer, std::size(buffer), format, pArguments);
@@ -741,12 +751,6 @@ void Platform::DebugPrintf(const char *, ...) noexcept {
}
#endif
-namespace {
-
-bool assertionPopUps = true;
-
-}
-
bool Platform::ShowAssertionPopUps(bool assertionPopUps_) noexcept {
const bool ret = assertionPopUps;
assertionPopUps = assertionPopUps_;
@@ -754,7 +758,7 @@ bool Platform::ShowAssertionPopUps(bool assertionPopUps_) noexcept {
}
void Platform::Assert(const char *c, const char *file, int line) noexcept {
- char buffer[2000] {};
+ char buffer[lengthDiagnostic] {};
snprintf(buffer, std::size(buffer), "Assertion [%s] failed at %s %d%s", c, file, line, assertionPopUps ? "" : "\r\n");
if (assertionPopUps) {
const int idButton = ::MessageBoxA({}, buffer, "Assertion failure",
diff --git a/win32/PlatWin.h b/win32/PlatWin.h
index 2ffc4a5fb..3db343587 100644
--- a/win32/PlatWin.h
+++ b/win32/PlatWin.h
@@ -81,6 +81,11 @@ struct Painter {
explicit Painter(HWND hWnd_) noexcept : hWnd(hWnd_) {
::BeginPaint(hWnd, &ps);
}
+ // Deleted so Painter objects can not be copied.
+ Painter(const Painter &) = delete;
+ Painter(Painter &&) = delete;
+ Painter &operator=(const Painter &) = delete;
+ Painter &operator=(Painter &&) = delete;
~Painter() {
::EndPaint(hWnd, &ps);
}
diff --git a/win32/ScintRes.rc b/win32/ScintRes.rc
index 069195ea9..007b0ead9 100644
--- a/win32/ScintRes.rc
+++ b/win32/ScintRes.rc
@@ -4,8 +4,8 @@
#include <windows.h>
-#define VERSION_SCINTILLA "5.5.7"
-#define VERSION_WORDS 5, 5, 7, 0
+#define VERSION_SCINTILLA "5.6.0"
+#define VERSION_WORDS 5, 6, 0, 0
VS_VERSION_INFO VERSIONINFO
FILEVERSION VERSION_WORDS
diff --git a/win32/ScintillaWin.cxx b/win32/ScintillaWin.cxx
index fbec35f76..f59a5e28e 100644
--- a/win32/ScintillaWin.cxx
+++ b/win32/ScintillaWin.cxx
@@ -152,7 +152,7 @@ constexpr Point PointFromLParam(sptr_t lpoint) noexcept {
}
bool KeyboardIsKeyDown(int key) noexcept {
- return (::GetKeyState(key) & 0x80000000) != 0;
+ return ::GetKeyState(key) < 0;
}
// Bit 24 is the extended keyboard flag and the numeric keypad is non-extended
@@ -406,7 +406,8 @@ CLIPFORMAT RegisterClipboardType(LPCWSTR lpszFormat) noexcept {
// Registered clipboard format values are 0xC000 through 0xFFFF.
// RegisterClipboardFormatW returns 32-bit unsigned and CLIPFORMAT is 16-bit
// unsigned so choose the low 16-bits with &.
- return ::RegisterClipboardFormatW(lpszFormat) & 0xFFFF;
+ constexpr CLIPFORMAT LowBits = 0xFFFF;
+ return ::RegisterClipboardFormatW(lpszFormat) & LowBits;
}
RECT GetClientRect(HWND hwnd) noexcept {
@@ -572,12 +573,12 @@ class ScintillaWin :
sptr_t ptr, UINT iMessage, uptr_t wParam, sptr_t lParam);
static sptr_t DirectStatusFunction(
sptr_t ptr, UINT iMessage, uptr_t wParam, sptr_t lParam, int *pStatus);
- static LRESULT PASCAL SWndProc(
+ static LRESULT CALLBACK SWndProc(
HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
void CTPaint(HWND hWnd);
LRESULT CTProcessMessage(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
- static LRESULT PASCAL CTWndProc(
+ static LRESULT CALLBACK CTWndProc(
HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam);
enum : UINT_PTR { invalidTimerID, standardTimerID, idleTimerID, fineTimerStart };
@@ -856,7 +857,9 @@ bool ScintillaWin::UpdateRenderingParams(bool force) noexcept {
UINT clearTypeContrast = 0;
if (SUCCEEDED(hr) && monitorRenderingParams &&
::SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &clearTypeContrast, 0) != 0) {
- if (clearTypeContrast >= 1000 && clearTypeContrast <= 2200) {
+ constexpr UINT minContrast = 1000;
+ constexpr UINT maxContrast = 2200;
+ if (clearTypeContrast >= minContrast && clearTypeContrast <= maxContrast) {
const FLOAT gamma = static_cast<FLOAT>(clearTypeContrast) / 1000.0f;
pIDWriteFactory->CreateCustomRenderingParams(gamma,
monitorRenderingParams->GetEnhancedContrast(),
@@ -1112,7 +1115,8 @@ namespace {
int InputCodePage() noexcept {
HKL inputLocale = ::GetKeyboardLayout(0);
const LANGID inputLang = LOWORD(inputLocale);
- char sCodePage[10];
+ constexpr size_t lengthCodePage = 10;
+ char sCodePage[lengthCodePage];
const int res = ::GetLocaleInfoA(MAKELCID(inputLang, SORT_DEFAULT),
LOCALE_IDEFAULTANSICODEPAGE, sCodePage, sizeof(sCodePage));
if (!res)
@@ -1750,7 +1754,7 @@ Window::Cursor ScintillaWin::ContextCursor(Point pt) {
// Display regular (drag) cursor over selection
if (PointInSelMargin(pt)) {
return GetMarginCursor(pt);
- } else if (!SelectionEmpty() && PointInSelection(pt)) {
+ } else if (dragDropEnabled && !SelectionEmpty() && PointInSelection(pt)) {
return Window::Cursor::arrow;
} else if (PointIsHotspot(pt)) {
return Window::Cursor::hand;
@@ -2813,10 +2817,10 @@ void CreateFoldMap(int codePage, FoldMap *foldingMap) {
if (DBCSIsLeadByte(codePage, ch1)) {
for (unsigned char byte2 = highByteLast; byte2 >= minTrailByte; byte2--) {
const char ch2 = byte2;
+ const DBCSPair pair{ ch1, ch2 };
+ const uint16_t index = DBCSIndex(ch1, ch2);
+ (*foldingMap)[index] = pair;
if (DBCSIsTrailByte(codePage, ch2)) {
- const DBCSPair pair{ ch1, ch2 };
- const uint16_t index = DBCSIndex(ch1, ch2);
- (*foldingMap)[index] = pair;
const std::string_view svBytes(pair.chars, 2);
const int lenUni = WideCharLenFromMultiByte(codePage, svBytes);
if (lenUni == 1) {
@@ -2848,36 +2852,41 @@ void CreateFoldMap(int codePage, FoldMap *foldingMap) {
class CaseFolderDBCS : public CaseFolderTable {
// Allocate the expandable storage here so that it does not need to be reallocated
// for each call to Fold.
- const FoldMap *foldingMap;
- UINT cp;
+ const FoldMap *foldingMap = nullptr;
+ UINT cp = 0;
public:
explicit CaseFolderDBCS(UINT cp_) : cp(cp_) {
- if (!DBCSHasFoldMap(cp)) {
- CreateFoldMap(cp, DBCSGetMutableFoldMap(cp));
- }
foldingMap = DBCSGetFoldMap(cp);
+ if (!foldingMap) {
+ FoldMap *pfm = DBCSCreateFoldMap(cp);
+ CreateFoldMap(cp, pfm);
+ foldingMap = pfm;
+ }
}
size_t Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) override;
};
-size_t CaseFolderDBCS::Fold(char *folded, size_t sizeFolded, const char *mixed, size_t lenMixed) {
+size_t CaseFolderDBCS::Fold(char *folded, [[maybe_unused]] size_t sizeFolded, const char *mixed, size_t lenMixed) {
// This loop outputs the same length as input as for each char 1-byte -> 1-byte; 2-byte -> 2-byte
+ assert(lenMixed <= sizeFolded);
size_t lenOut = 0;
for (size_t i = 0; i < lenMixed; i++) {
- const ptrdiff_t lenLeft = lenMixed - i;
const char ch = mixed[i];
- if ((lenLeft >= 2) && DBCSIsLeadByte(cp, ch) && ((lenOut + 2) <= sizeFolded)) {
+ if (((i+1) < lenMixed) && DBCSIsLeadByte(cp, ch)) {
i++;
const char ch2 = mixed[i];
const uint16_t ind = DBCSIndex(ch, ch2);
const char *pair = foldingMap->at(ind).chars;
+ assert(pair[0]);
+ assert(pair[1]);
folded[lenOut++] = pair[0];
folded[lenOut++] = pair[1];
- } else if ((lenOut + 1) <= sizeFolded) {
+ } else {
const unsigned char uch = ch;
folded[lenOut++] = mapping[uch];
}
}
+ assert(lenOut == lenMixed);
return lenOut;
}
@@ -3712,6 +3721,10 @@ STDMETHODIMP_(ULONG) ScintillaWin::Release() {
/// Implement IDropTarget
STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
POINTL, PDWORD pdwEffect) {
+ if (!dragDropEnabled) {
+ *pdwEffect = DROPEFFECT_NONE;
+ return S_OK;
+ }
if (!pIDataSource )
return E_POINTER;
FORMATETC fmtu = {CF_UNICODETEXT, nullptr, DVASPECT_CONTENT, -1, TYMED_HGLOBAL };
@@ -3728,7 +3741,7 @@ STDMETHODIMP ScintillaWin::DragEnter(LPDATAOBJECT pIDataSource, DWORD grfKeyStat
STDMETHODIMP ScintillaWin::DragOver(DWORD grfKeyState, POINTL pt, PDWORD pdwEffect) {
try {
- if (!hasOKText || pdoc->IsReadOnly()) {
+ if (!dragDropEnabled || !hasOKText || pdoc->IsReadOnly()) {
*pdwEffect = DROPEFFECT_NONE;
return S_OK;
}
@@ -3762,6 +3775,11 @@ STDMETHODIMP ScintillaWin::Drop(LPDATAOBJECT pIDataSource, DWORD grfKeyState,
try {
*pdwEffect = EffectFromState(grfKeyState);
+ if (!dragDropEnabled) {
+ *pdwEffect = DROPEFFECT_NONE;
+ return S_OK;
+ }
+
if (!pIDataSource)
return E_POINTER;
@@ -4001,7 +4019,7 @@ LRESULT ScintillaWin::CTProcessMessage(HWND hWnd, UINT iMessage, WPARAM wParam,
return ::DefWindowProc(hWnd, iMessage, wParam, lParam);
}
-LRESULT PASCAL ScintillaWin::CTWndProc(
+LRESULT CALLBACK ScintillaWin::CTWndProc(
HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
// Find C++ object associated with window.
ScintillaWin *sciThis = static_cast<ScintillaWin *>(PointerFromWindow(hWnd));
@@ -4043,7 +4061,7 @@ sptr_t DirectFunction(
}
-LRESULT PASCAL ScintillaWin::SWndProc(
+LRESULT CALLBACK ScintillaWin::SWndProc(
HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {
//Platform::DebugPrintf("S W:%x M:%x WP:%x L:%x\n", hWnd, iMessage, wParam, lParam);