summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXhmikosR <xhmikosr@gmail.com>2015-01-20 12:10:20 +0200
committerXhmikosR <xhmikosr@gmail.com>2015-01-20 12:10:52 +0200
commit346c0695d37868c8d099cc34b29317f9862109e4 (patch)
tree95cd5afe56e98f186fdd30f4aefdfe93515f202e
parent878af2fe5c730469f009e8fe6f234509a5ffb0ac (diff)
downloadnotepad2-mod-346c0695d37868c8d099cc34b29317f9862109e4.zip
notepad2-mod-346c0695d37868c8d099cc34b29317f9862109e4.tar.gz
notepad2-mod-346c0695d37868c8d099cc34b29317f9862109e4.tar.bz2
Update Scintilla to v3.5.3.4.2.25.940
-rw-r--r--build/makefile.deps.mak3
-rw-r--r--scintilla/cppcheck.suppress1
-rw-r--r--scintilla/doc/ScintillaDoc.html13
-rw-r--r--scintilla/doc/ScintillaDownload.html10
-rw-r--r--scintilla/doc/ScintillaHistory.html71
-rw-r--r--scintilla/doc/index.html7
-rw-r--r--scintilla/include/Platform.h5
-rw-r--r--scintilla/include/SciLexer.h27
-rw-r--r--scintilla/include/Scintilla.iface33
-rw-r--r--scintilla/lexers/LexBash.cxx14
-rw-r--r--scintilla/lexers/LexCPP.cxx4
-rw-r--r--scintilla/lexers/LexHex.cxx1045
-rw-r--r--scintilla/lexers/LexVerilog.cxx876
-rw-r--r--scintilla/lexlib/LexAccessor.h3
-rw-r--r--scintilla/lexlib/WordList.cxx2
-rw-r--r--scintilla/scripts/HeaderOrder.txt1
-rw-r--r--scintilla/src/Catalogue.cxx3
-rw-r--r--scintilla/src/Document.cxx18
-rw-r--r--scintilla/src/Editor.cxx26
-rw-r--r--scintilla/src/Editor.h1
-rw-r--r--scintilla/src/MarginView.cxx18
-rw-r--r--scintilla/src/ScintillaBase.cxx4
-rw-r--r--scintilla/src/UniConversion.cxx14
-rw-r--r--scintilla/src/UniConversion.h4
-rw-r--r--scintilla/version.txt2
-rw-r--r--scintilla/win32/PlatWin.cxx89
-rw-r--r--scintilla/win32/PlatWin.h1
-rw-r--r--scintilla/win32/ScintillaWin.cxx340
28 files changed, 2232 insertions, 403 deletions
diff --git a/build/makefile.deps.mak b/build/makefile.deps.mak
index 2f3d1c2..f3f3dd4 100644
--- a/build/makefile.deps.mak
+++ b/build/makefile.deps.mak
@@ -219,7 +219,8 @@ $(SCI_SRC_OBJDIR)\Document.obj: \
$(SCI_SRC)\CaseFolder.h \
$(SCI_SRC)\Document.h \
$(SCI_SRC)\RESearch.h \
- $(SCI_SRC)\UniConversion.h
+ $(SCI_SRC)\UniConversion.h \
+ $(SCI_SRC)\UnicodeFromUTF8.h
$(SCI_SRC_OBJDIR)\EditModel.obj: \
$(SCI_SRC)\EditModel.cxx \
diff --git a/scintilla/cppcheck.suppress b/scintilla/cppcheck.suppress
index 7fded2f..81146f0 100644
--- a/scintilla/cppcheck.suppress
+++ b/scintilla/cppcheck.suppress
@@ -30,6 +30,7 @@ variableScope:scintilla/lexers/LexRuby.cxx
uninitMemberVar:scintilla/lexers/LexRuby.cxx
variableScope:scintilla/lexers/LexSpecman.cxx
unreadVariable:scintilla/lexers/LexSpice.cxx
+clarifyCalculation:scintilla/lexers/LexTADS3.cxx
invalidscanf:scintilla/lexers/LexTCMD.cxx
variableScope:scintilla/lexers/LexTeX.cxx
variableScope:scintilla/lexers/LexVHDL.cxx
diff --git a/scintilla/doc/ScintillaDoc.html b/scintilla/doc/ScintillaDoc.html
index 8b9ecb1..ed66afa 100644
--- a/scintilla/doc/ScintillaDoc.html
+++ b/scintilla/doc/ScintillaDoc.html
@@ -82,7 +82,7 @@
<h1>Scintilla Documentation</h1>
- <p>Last edited 24 November 2014 NH</p>
+ <p>Last edited 10 January 2015 NH</p>
<p>There is <a class="jump" href="Design.html">an overview of the internal design of
Scintilla</a>.<br />
@@ -2577,11 +2577,15 @@ struct Sci_TextToFind {
<b id="SCI_STYLEGETITALIC">SCI_STYLEGETITALIC(int styleNumber)</b><br />
These messages (plus <a class="message"
href="#SCI_STYLESETCHARACTERSET"><code>SCI_STYLESETCHARACTERSET</code></a>) set the font
- attributes that are used to match the fonts you request to those available. The
+ attributes that are used to match the fonts you request to those available.</p>
+ <p>The
<code>fontName</code> is a zero terminated string holding the name of a font. Under Windows,
- only the first 32 characters of the name are used and the name is not case sensitive. For
+ only the first 32 characters of the name are used, the name is decoded as UTF-8, and the name is not case sensitive. For
internal caching, Scintilla tracks fonts by name and does care about the casing of font names,
- so please be consistent. On GTK+, Pango is used to display text.</p>
+ so please be consistent.
+ On GTK+, Pango is used to display text and the name is sent directly to Pango without transformation.
+ On Qt, the name is decoded as UTF-8.
+ On Cocoa, the name is decoded as MacRoman.</p>
<p>Sizes can be set to a whole number of points with <code>SCI_STYLESETSIZE</code>
or to a fractional point size in hundredths of a point with <code>SCI_STYLESETSIZEFRACTIONAL</code>
by multiplying the size by 100 (<code>SC_FONT_SIZE_MULTIPLIER</code>).
@@ -7320,6 +7324,7 @@ for line = lineStart to lineEnd do SCI_ENSUREVISIBLE(line) next
These notifications are generated when the user clicks or double clicks on
text that is in a style with the hotspot attribute set.
This notification can be used to link to variable definitions or web pages.
+ In the notification handler, you should avoid calling any function that modifies the current selection or caret position.
The <code>position</code> field is set the text position of the click or
double click and the <code>modifiers</code> field set to the key modifiers
held down in a similar manner to <a class="message" href="#SCN_KEY">SCN_KEY</a>.
diff --git a/scintilla/doc/ScintillaDownload.html b/scintilla/doc/ScintillaDownload.html
index 4677dc9..c272a48 100644
--- a/scintilla/doc/ScintillaDownload.html
+++ b/scintilla/doc/ScintillaDownload.html
@@ -25,9 +25,9 @@
<table bgcolor="#CCCCCC" width="100%" cellspacing="0" cellpadding="8" border="0">
<tr>
<td>
- <font size="4"> <a href="http://prdownloads.sourceforge.net/scintilla/scintilla352.zip?download">
+ <font size="4"> <a href="http://prdownloads.sourceforge.net/scintilla/scintilla353.zip?download">
Windows</a>&nbsp;&nbsp;
- <a href="http://prdownloads.sourceforge.net/scintilla/scintilla352.tgz?download">
+ <a href="http://prdownloads.sourceforge.net/scintilla/scintilla353.tgz?download">
GTK+/Linux</a>&nbsp;&nbsp;
</font>
</td>
@@ -41,7 +41,7 @@
containing very few restrictions.
</p>
<h3>
- Release 3.5.2
+ Release 3.5.3
</h3>
<h4>
Source Code
@@ -49,8 +49,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="http://prdownloads.sourceforge.net/scintilla/scintilla352.zip?download">zip format</a> (1450K) commonly used on Windows</li>
- <li><a href="http://prdownloads.sourceforge.net/scintilla/scintilla352.tgz?download">tgz format</a> (1300K) commonly used on Linux and compatible operating systems</li>
+ <li><a href="http://prdownloads.sourceforge.net/scintilla/scintilla353.zip?download">zip format</a> (1450K) commonly used on Windows</li>
+ <li><a href="http://prdownloads.sourceforge.net/scintilla/scintilla353.tgz?download">tgz format</a> (1300K) 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/scintilla/doc/ScintillaHistory.html b/scintilla/doc/ScintillaHistory.html
index d1afca3..4360b28 100644
--- a/scintilla/doc/ScintillaHistory.html
+++ b/scintilla/doc/ScintillaHistory.html
@@ -463,6 +463,8 @@
</tr><tr>
<td>Erik Angelin</td>
<td>Yusuf Ramazan Karagöz</td>
+ <td>Markus Heidelberg</td>
+ <td>Joe Mueller</td>
</tr>
</table>
<p>
@@ -475,6 +477,74 @@
</li>
</ul>
<h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite353.zip?download">Release 3.5.3</a>
+ </h3>
+ <ul>
+ <li>
+ Released 20 January 2015.
+ </li>
+ <li>
+ Support removed for Windows 95, 98, and ME.
+ </li>
+ <li>
+ Lexers added for Motorola S-Record files, Intel hex files, and Tektronix extended hex files with folding for Intel hex files.
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/1091/">Feature #1091.</a>
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/1093/">Feature #1093.</a>
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/1095/">Feature #1095.</a>
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/1096/">Feature #1096.</a>
+ </li>
+ <li>
+ C++ folder allows folding on square brackets '['.
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/1087/">Feature #1087.</a>
+ </li>
+ <li>
+ Shell lexer fixes three issues with here-documents.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1672/">Bug #1672</a>.
+ </li>
+ <li>
+ Verilog lexer highlights doc comment keywords; has separate styles for input, output, and inout ports
+ (lexer.verilog.portstyling); fixes a bug in highlighting numbers; can treat upper-case identifiers as
+ keywords (lexer.verilog.allupperkeywords); and can use different styles for code that is inactive due
+ to preprocessor commands (lexer.verilog.track.preprocessor, lexer.verilog.update.preprocessor).
+ </li>
+ <li>
+ When the calltip window is taller than the Scintilla window, leave it in a
+ position that avoids overlapping the Scintilla text.
+ </li>
+ <li>
+ When a text margin is displayed, for annotation lines, use the background colour of the base line.
+ </li>
+ <li>
+ On Windows GDI, assume font names are encoded in UTF-8. This matches the Direct2D code path.
+ </li>
+ <li>
+ Fix paste for GTK+ on OS X.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1677/">Bug #1677</a>.
+ </li>
+ <li>
+ Reverted a fix on Qt where Qt 5.3 has returned to the behaviour of 4.x.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1575/">Bug #1575</a>.
+ </li>
+ <li>
+ When the mouse is on the line between margin and text changed to treat as within text.
+ This makes the PLAT_CURSES character cell platform work better.
+ </li>
+ <li>
+ Fix a crash in SciTE when the command line is just "-close:".
+ <a href="http://sourceforge.net/p/scintilla/bugs/1675/">Bug #1675</a>.
+ </li>
+ <li>
+ Fix unexpected dialog in SciTE on Windows when the command line has a quoted filename then ends with a space.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1673/">Bug #1673</a>.
+ </li>
+ <li>
+ On Windows and GTK+, use indicators for inline IME.
+ </li>
+ <li>
+ SciTE shuts down quicker when there is no user-written OnClose function and no directors are attached.
+ </li>
+ </ul>
+ <h3>
<a href="http://prdownloads.sourceforge.net/scintilla/scite352.zip?download">Release 3.5.2</a>
</h3>
<ul>
@@ -498,6 +568,7 @@
<li>
ANNOTATION_INDENTED added which is similar to ANNOTATION_BOXED in terms of positioning
but does not show a border.
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/1086/">Feature #1086.</a>
</li>
<li>
Allow platform overrides for drawing tab arrows, wrap markers, and line markers.
diff --git a/scintilla/doc/index.html b/scintilla/doc/index.html
index 89dd22c..900b1b6 100644
--- a/scintilla/doc/index.html
+++ b/scintilla/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="20141202" />
+ <meta name="Date.Modified" content="20150120" />
<style type="text/css">
#versionlist {
margin: 0;
@@ -55,8 +55,8 @@
GTK+, and OS X</font>
</td>
<td width="40%" align="right">
- <font color="#FFCC99" size="3"> Release version 3.5.2<br />
- Site last modified December 2 2014</font>
+ <font color="#FFCC99" size="3"> Release version 3.5.3<br />
+ Site last modified January 20 2015</font>
</td>
<td width="20%">
&nbsp;
@@ -71,6 +71,7 @@
</tr>
</table>
<ul id="versionlist">
+ <li>Version 3.5.3 removes support for Windows 95, 98, and ME.</li>
<li>Version 3.5.2 only supports 64-bit builds for OS X 10.7+ Cocoa. Provisional support of C++11 &lt;regex&gt;.</li>
<li>Version 3.5.1 fixes minor bugs and includes a lexer for BibTeX.</li>
<li>Version 3.5.0 can share space vertically so that extreme ascenders and descenders are not cut off.
diff --git a/scintilla/include/Platform.h b/scintilla/include/Platform.h
index 83fc9ed..5f2ba0d 100644
--- a/scintilla/include/Platform.h
+++ b/scintilla/include/Platform.h
@@ -144,6 +144,11 @@ public:
return (pt.x >= left) && (pt.x <= right) &&
(pt.y >= top) && (pt.y <= bottom);
}
+ bool ContainsWholePixel(Point pt) const {
+ // Does the rectangle contain all of the pixel to left/below the point
+ return (pt.x >= left) && ((pt.x+1) <= right) &&
+ (pt.y >= top) && ((pt.y+1) <= bottom);
+ }
bool Contains(PRectangle rc) const {
return (rc.left >= left) && (rc.right <= right) &&
(rc.top >= top) && (rc.bottom <= bottom);
diff --git a/scintilla/include/SciLexer.h b/scintilla/include/SciLexer.h
index 6ef663a..233c507 100644
--- a/scintilla/include/SciLexer.h
+++ b/scintilla/include/SciLexer.h
@@ -129,6 +129,9 @@
#define SCLEX_DMIS 114
#define SCLEX_REGISTRY 115
#define SCLEX_BIBTEX 116
+#define SCLEX_SREC 117
+#define SCLEX_IHEX 118
+#define SCLEX_TEHEX 119
#define SCLEX_AHK 200
#define SCLEX_AUTOMATIC 1000
#define SCE_P_DEFAULT 0
@@ -899,6 +902,11 @@
#define SCE_V_IDENTIFIER 11
#define SCE_V_STRINGEOL 12
#define SCE_V_USER 19
+#define SCE_V_COMMENT_WORD 20
+#define SCE_V_INPUT 21
+#define SCE_V_OUTPUT 22
+#define SCE_V_INOUT 23
+#define SCE_V_PORT_CONNECT 24
#define SCE_KIX_DEFAULT 0
#define SCE_KIX_COMMENT 1
#define SCE_KIX_STRING1 2
@@ -1763,6 +1771,25 @@
#define SCE_BIBTEX_PARAMETER 4
#define SCE_BIBTEX_VALUE 5
#define SCE_BIBTEX_COMMENT 6
+#define SCE_HEX_DEFAULT 0
+#define SCE_HEX_RECSTART 1
+#define SCE_HEX_RECTYPE 2
+#define SCE_HEX_RECTYPE_UNKNOWN 3
+#define SCE_HEX_BYTECOUNT 4
+#define SCE_HEX_BYTECOUNT_WRONG 5
+#define SCE_HEX_NOADDRESS 6
+#define SCE_HEX_DATAADDRESS 7
+#define SCE_HEX_RECCOUNT 8
+#define SCE_HEX_STARTADDRESS 9
+#define SCE_HEX_ADDRESSFIELD_UNKNOWN 10
+#define SCE_HEX_EXTENDEDADDRESS 11
+#define SCE_HEX_DATA_ODD 12
+#define SCE_HEX_DATA_EVEN 13
+#define SCE_HEX_DATA_UNKNOWN 14
+#define SCE_HEX_DATA_EMPTY 15
+#define SCE_HEX_CHECKSUM 16
+#define SCE_HEX_CHECKSUM_WRONG 17
+#define SCE_HEX_GARBAGE 18
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */
#endif
diff --git a/scintilla/include/Scintilla.iface b/scintilla/include/Scintilla.iface
index d39aa91..d300ba6 100644
--- a/scintilla/include/Scintilla.iface
+++ b/scintilla/include/Scintilla.iface
@@ -2719,6 +2719,9 @@ val SCLEX_AS=113
val SCLEX_DMIS=114
val SCLEX_REGISTRY=115
val SCLEX_BIBTEX=116
+val SCLEX_SREC=117
+val SCLEX_IHEX=118
+val SCLEX_TEHEX=119
## notepad2 custom code for the AHK lexer - start
val SCLEX_AHK=200
## notepad2 custom code for the AHK lexer - end
@@ -3602,6 +3605,11 @@ val SCE_V_OPERATOR=10
val SCE_V_IDENTIFIER=11
val SCE_V_STRINGEOL=12
val SCE_V_USER=19
+val SCE_V_COMMENT_WORD=20
+val SCE_V_INPUT=21
+val SCE_V_OUTPUT=22
+val SCE_V_INOUT=23
+val SCE_V_PORT_CONNECT=24
# Lexical states for SCLEX_KIX
lex Kix=SCLEX_KIX SCE_KIX_
val SCE_KIX_DEFAULT=0
@@ -4570,6 +4578,31 @@ val SCE_BIBTEX_KEY=3
val SCE_BIBTEX_PARAMETER=4
val SCE_BIBTEX_VALUE=5
val SCE_BIBTEX_COMMENT=6
+# Lexical state for SCLEX_SREC
+lex Srec=SCLEX_SREC SCE_HEX_
+val SCE_HEX_DEFAULT=0
+val SCE_HEX_RECSTART=1
+val SCE_HEX_RECTYPE=2
+val SCE_HEX_RECTYPE_UNKNOWN=3
+val SCE_HEX_BYTECOUNT=4
+val SCE_HEX_BYTECOUNT_WRONG=5
+val SCE_HEX_NOADDRESS=6
+val SCE_HEX_DATAADDRESS=7
+val SCE_HEX_RECCOUNT=8
+val SCE_HEX_STARTADDRESS=9
+val SCE_HEX_ADDRESSFIELD_UNKNOWN=10
+val SCE_HEX_EXTENDEDADDRESS=11
+val SCE_HEX_DATA_ODD=12
+val SCE_HEX_DATA_EVEN=13
+val SCE_HEX_DATA_UNKNOWN=14
+val SCE_HEX_DATA_EMPTY=15
+val SCE_HEX_CHECKSUM=16
+val SCE_HEX_CHECKSUM_WRONG=17
+val SCE_HEX_GARBAGE=18
+# Lexical state for SCLEX_IHEX (shared with Srec)
+lex IHex=SCLEX_IHEX SCE_HEX_
+# Lexical state for SCLEX_TEHEX (shared with Srec)
+lex TEHex=SCLEX_TEHEX SCE_HEX_
# Events
diff --git a/scintilla/lexers/LexBash.cxx b/scintilla/lexers/LexBash.cxx
index cfc214a..b495575 100644
--- a/scintilla/lexers/LexBash.cxx
+++ b/scintilla/lexers/LexBash.cxx
@@ -419,8 +419,6 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
sc.Forward();
HereDoc.Quoted = true;
HereDoc.State = 1;
- } else if (!HereDoc.Indent && sc.chNext == '-') { // <<- indent case
- HereDoc.Indent = true;
} else if (setHereDoc.Contains(sc.chNext)) {
// an unquoted here-doc delimiter, no special handling
// TODO check what exactly bash considers part of the delim
@@ -469,7 +467,7 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
if (sc.atLineStart) {
sc.SetState(SCE_SH_HERE_Q);
int prefixws = 0;
- while (IsASpace(sc.ch) && !sc.atLineEnd) { // whitespace prefix
+ while (sc.ch == '\t' && !sc.atLineEnd) { // tabulation prefix
sc.Forward();
prefixws++;
}
@@ -481,7 +479,8 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
char s[HERE_DELIM_MAX];
sc.GetCurrent(s, sizeof(s));
if (sc.LengthCurrent() == 0) { // '' or "" delimiters
- if (prefixws == 0 && HereDoc.Quoted && HereDoc.DelimiterLength == 0)
+ if ((prefixws == 0 || HereDoc.Indent) &&
+ HereDoc.Quoted && HereDoc.DelimiterLength == 0)
sc.SetState(SCE_SH_DEFAULT);
break;
}
@@ -672,7 +671,12 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
} else if (sc.Match('<', '<')) {
sc.SetState(SCE_SH_HERE_DELIM);
HereDoc.State = 0;
- HereDoc.Indent = false;
+ if (sc.GetRelative(2) == '-') { // <<- indent case
+ HereDoc.Indent = true;
+ sc.Forward();
+ } else {
+ HereDoc.Indent = false;
+ }
} else if (sc.ch == '-' && // one-char file test operators
setSingleCharOp.Contains(sc.chNext) &&
!setWord.Contains(sc.GetRelative(2)) &&
diff --git a/scintilla/lexers/LexCPP.cxx b/scintilla/lexers/LexCPP.cxx
index 5485bf2..a78fcc0 100644
--- a/scintilla/lexers/LexCPP.cxx
+++ b/scintilla/lexers/LexCPP.cxx
@@ -1344,14 +1344,14 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle,
}
}
if (options.foldSyntaxBased && (style == SCE_C_OPERATOR)) {
- if (ch == '{') {
+ if (ch == '{' || ch == '[') {
// Measure the minimum before a '{' to allow
// folding on "} else {"
if (levelMinCurrent > levelNext) {
levelMinCurrent = levelNext;
}
levelNext++;
- } else if (ch == '}') {
+ } else if (ch == '}' || ch == ']') {
levelNext--;
}
}
diff --git a/scintilla/lexers/LexHex.cxx b/scintilla/lexers/LexHex.cxx
new file mode 100644
index 0000000..fe972ff
--- /dev/null
+++ b/scintilla/lexers/LexHex.cxx
@@ -0,0 +1,1045 @@
+// Scintilla source code edit control
+/** @file LexHex.cxx
+ ** Lexers for Motorola S-Record, Intel HEX and Tektronix extended HEX.
+ **
+ ** Written by Markus Heidelberg
+ **/
+// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+/*
+ * Motorola S-Record
+ * ===============================
+ *
+ * Each record (line) is built as follows:
+ *
+ * field digits states
+ *
+ * +----------+
+ * | start | 1 ('S') SCE_HEX_RECSTART
+ * +----------+
+ * | type | 1 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN)
+ * +----------+
+ * | count | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG
+ * +----------+
+ * | address | 4/6/8 SCE_HEX_NOADDRESS, SCE_HEX_DATAADDRESS, SCE_HEX_RECCOUNT, SCE_HEX_STARTADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN)
+ * +----------+
+ * | data | 0..504/502/500 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN, SCE_HEX_DATA_EMPTY, (SCE_HEX_DATA_UNKNOWN)
+ * +----------+
+ * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG
+ * +----------+
+ *
+ *
+ * Intel HEX
+ * ===============================
+ *
+ * Each record (line) is built as follows:
+ *
+ * field digits states
+ *
+ * +----------+
+ * | start | 1 (':') SCE_HEX_RECSTART
+ * +----------+
+ * | count | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG
+ * +----------+
+ * | address | 4 SCE_HEX_NOADDRESS, SCE_HEX_DATAADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN)
+ * +----------+
+ * | type | 2 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN)
+ * +----------+
+ * | data | 0..510 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN, SCE_HEX_DATA_EMPTY, SCE_HEX_EXTENDEDADDRESS, SCE_HEX_STARTADDRESS, (SCE_HEX_DATA_UNKNOWN)
+ * +----------+
+ * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG
+ * +----------+
+ *
+ *
+ * Folding:
+ *
+ * Data records (type 0x00), which follow an extended address record (type
+ * 0x02 or 0x04), can be folded. The extended address record is the fold
+ * point at fold level 0, the corresponding data records are set to level 1.
+ *
+ * Any record, which is not a data record, sets the fold level back to 0.
+ * Any line, which is not a record (blank lines and lines starting with a
+ * character other than ':'), leaves the fold level unchanged.
+ *
+ *
+ * Tektronix extended HEX
+ * ===============================
+ *
+ * Each record (line) is built as follows:
+ *
+ * field digits states
+ *
+ * +----------+
+ * | start | 1 ('%') SCE_HEX_RECSTART
+ * +----------+
+ * | length | 2 SCE_HEX_BYTECOUNT, SCE_HEX_BYTECOUNT_WRONG
+ * +----------+
+ * | type | 1 SCE_HEX_RECTYPE, (SCE_HEX_RECTYPE_UNKNOWN)
+ * +----------+
+ * | checksum | 2 SCE_HEX_CHECKSUM, SCE_HEX_CHECKSUM_WRONG
+ * +----------+
+ * | address | 9 SCE_HEX_DATAADDRESS, SCE_HEX_STARTADDRESS, (SCE_HEX_ADDRESSFIELD_UNKNOWN)
+ * +----------+
+ * | data | 0..241 SCE_HEX_DATA_ODD, SCE_HEX_DATA_EVEN
+ * +----------+
+ *
+ *
+ * General notes for all lexers
+ * ===============================
+ *
+ * - Depending on where the helper functions are invoked, some of them have to
+ * read beyond the current position. In case of malformed data (record too
+ * short), it has to be ensured that this either does not have bad influence
+ * or will be captured deliberately.
+ *
+ * - States in parentheses in the upper format descriptions indicate that they
+ * should not appear in a valid hex file.
+ *
+ * - State SCE_HEX_GARBAGE means garbage data after the intended end of the
+ * record, the line is too long then. This state is used in all lexers.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+#include <ctype.h>
+
+#include "ILexer.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#include "WordList.h"
+#include "LexAccessor.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "CharacterSet.h"
+#include "LexerModule.h"
+
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+// prototypes for general helper functions
+static inline bool IsNewline(const int ch);
+static int GetHexaNibble(char hd);
+static int GetHexaChar(char hd1, char hd2);
+static int GetHexaChar(unsigned int pos, Accessor &styler);
+static bool ForwardWithinLine(StyleContext &sc, int nb = 1);
+static bool PosInSameRecord(unsigned int pos1, unsigned int pos2, Accessor &styler);
+static int CountByteCount(unsigned int startPos, int uncountedDigits, Accessor &styler);
+static int CalcChecksum(unsigned int startPos, int cnt, bool twosCompl, Accessor &styler);
+
+// prototypes for file format specific helper functions
+static unsigned int GetSrecRecStartPosition(unsigned int pos, Accessor &styler);
+static int GetSrecByteCount(unsigned int recStartPos, Accessor &styler);
+static int CountSrecByteCount(unsigned int recStartPos, Accessor &styler);
+static int GetSrecAddressFieldSize(unsigned int recStartPos, Accessor &styler);
+static int GetSrecAddressFieldType(unsigned int recStartPos, Accessor &styler);
+static int GetSrecDataFieldType(unsigned int recStartPos, Accessor &styler);
+static int GetSrecRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler);
+static int GetSrecChecksum(unsigned int recStartPos, Accessor &styler);
+static int CalcSrecChecksum(unsigned int recStartPos, Accessor &styler);
+
+static unsigned int GetIHexRecStartPosition(unsigned int pos, Accessor &styler);
+static int GetIHexByteCount(unsigned int recStartPos, Accessor &styler);
+static int CountIHexByteCount(unsigned int recStartPos, Accessor &styler);
+static int GetIHexAddressFieldType(unsigned int recStartPos, Accessor &styler);
+static int GetIHexDataFieldType(unsigned int recStartPos, Accessor &styler);
+static int GetIHexRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler);
+static int GetIHexChecksum(unsigned int recStartPos, Accessor &styler);
+static int CalcIHexChecksum(unsigned int recStartPos, Accessor &styler);
+
+static int GetTEHexDigitCount(unsigned int recStartPos, Accessor &styler);
+static int CountTEHexDigitCount(unsigned int recStartPos, Accessor &styler);
+static int GetTEHexAddressFieldType(unsigned int recStartPos, Accessor &styler);
+static int GetTEHexChecksum(unsigned int recStartPos, Accessor &styler);
+static int CalcTEHexChecksum(unsigned int recStartPos, Accessor &styler);
+
+static inline bool IsNewline(const int ch)
+{
+ return (ch == '\n' || ch == '\r');
+}
+
+static int GetHexaNibble(char hd)
+{
+ int hexValue = 0;
+
+ if (hd >= '0' && hd <= '9') {
+ hexValue += hd - '0';
+ } else if (hd >= 'A' && hd <= 'F') {
+ hexValue += hd - 'A' + 10;
+ } else if (hd >= 'a' && hd <= 'f') {
+ hexValue += hd - 'a' + 10;
+ } else {
+ return -1;
+ }
+
+ return hexValue;
+}
+
+static int GetHexaChar(char hd1, char hd2)
+{
+ int hexValue = 0;
+
+ if (hd1 >= '0' && hd1 <= '9') {
+ hexValue += 16 * (hd1 - '0');
+ } else if (hd1 >= 'A' && hd1 <= 'F') {
+ hexValue += 16 * (hd1 - 'A' + 10);
+ } else if (hd1 >= 'a' && hd1 <= 'f') {
+ hexValue += 16 * (hd1 - 'a' + 10);
+ } else {
+ return -1;
+ }
+
+ if (hd2 >= '0' && hd2 <= '9') {
+ hexValue += hd2 - '0';
+ } else if (hd2 >= 'A' && hd2 <= 'F') {
+ hexValue += hd2 - 'A' + 10;
+ } else if (hd2 >= 'a' && hd2 <= 'f') {
+ hexValue += hd2 - 'a' + 10;
+ } else {
+ return -1;
+ }
+
+ return hexValue;
+}
+
+static int GetHexaChar(unsigned int pos, Accessor &styler)
+{
+ char highNibble, lowNibble;
+
+ highNibble = styler.SafeGetCharAt(pos);
+ lowNibble = styler.SafeGetCharAt(pos + 1);
+
+ return GetHexaChar(highNibble, lowNibble);
+}
+
+// Forward <nb> characters, but abort (and return false) if hitting the line
+// end. Return true if forwarding within the line was possible.
+// Avoids influence on highlighting of the subsequent line if the current line
+// is malformed (too short).
+static bool ForwardWithinLine(StyleContext &sc, int nb)
+{
+ for (int i = 0; i < nb; i++) {
+ if (sc.atLineEnd) {
+ // line is too short
+ sc.SetState(SCE_HEX_DEFAULT);
+ sc.Forward();
+ return false;
+ } else {
+ sc.Forward();
+ }
+ }
+
+ return true;
+}
+
+// Checks whether the given positions are in the same record.
+static bool PosInSameRecord(unsigned int pos1, unsigned int pos2, Accessor &styler)
+{
+ return styler.GetLine(pos1) == styler.GetLine(pos2);
+}
+
+// Count the number of digit pairs from <startPos> till end of record, ignoring
+// <uncountedDigits> digits.
+// If the record is too short, a negative count may be returned.
+static int CountByteCount(unsigned int startPos, int uncountedDigits, Accessor &styler)
+{
+ int cnt;
+ unsigned int pos;
+
+ pos = startPos;
+
+ while (!IsNewline(styler.SafeGetCharAt(pos, '\n'))) {
+ pos++;
+ }
+
+ // number of digits in this line minus number of digits of uncounted fields
+ cnt = static_cast<int>(pos - startPos) - uncountedDigits;
+
+ // Prepare round up if odd (digit pair incomplete), this way the byte
+ // count is considered to be valid if the checksum is incomplete.
+ if (cnt >= 0) {
+ cnt++;
+ }
+
+ // digit pairs
+ cnt /= 2;
+
+ return cnt;
+}
+
+// Calculate the checksum of the record.
+// <startPos> is the position of the first character of the starting digit
+// pair, <cnt> is the number of digit pairs.
+static int CalcChecksum(unsigned int startPos, int cnt, bool twosCompl, Accessor &styler)
+{
+ int cs = 0;
+
+ for (unsigned int pos = startPos; pos < startPos + cnt; pos += 2) {
+ int val = GetHexaChar(pos, styler);
+
+ if (val < 0) {
+ return val;
+ }
+
+ // overflow does not matter
+ cs += val;
+ }
+
+ if (twosCompl) {
+ // low byte of two's complement
+ return -cs & 0xFF;
+ } else {
+ // low byte of one's complement
+ return ~cs & 0xFF;
+ }
+}
+
+// Get the position of the record "start" field (first character in line) in
+// the record around position <pos>.
+static unsigned int GetSrecRecStartPosition(unsigned int pos, Accessor &styler)
+{
+ while (styler.SafeGetCharAt(pos) != 'S') {
+ pos--;
+ }
+
+ return pos;
+}
+
+// Get the value of the "byte count" field, it counts the number of bytes in
+// the subsequent fields ("address", "data" and "checksum" fields).
+static int GetSrecByteCount(unsigned int recStartPos, Accessor &styler)
+{
+ int val;
+
+ val = GetHexaChar(recStartPos + 2, styler);
+ if (val < 0) {
+ val = 0;
+ }
+
+ return val;
+}
+
+// Count the number of digit pairs for the "address", "data" and "checksum"
+// fields in this record. Has to be equal to the "byte count" field value.
+// If the record is too short, a negative count may be returned.
+static int CountSrecByteCount(unsigned int recStartPos, Accessor &styler)
+{
+ return CountByteCount(recStartPos, 4, styler);
+}
+
+// Get the size of the "address" field.
+static int GetSrecAddressFieldSize(unsigned int recStartPos, Accessor &styler)
+{
+ switch (styler.SafeGetCharAt(recStartPos + 1)) {
+ case '0':
+ case '1':
+ case '5':
+ case '9':
+ return 2; // 16 bit
+
+ case '2':
+ case '6':
+ case '8':
+ return 3; // 24 bit
+
+ case '3':
+ case '7':
+ return 4; // 32 bit
+
+ default:
+ return 0;
+ }
+}
+
+// Get the type of the "address" field content.
+static int GetSrecAddressFieldType(unsigned int recStartPos, Accessor &styler)
+{
+ switch (styler.SafeGetCharAt(recStartPos + 1)) {
+ case '0':
+ return SCE_HEX_NOADDRESS;
+
+ case '1':
+ case '2':
+ case '3':
+ return SCE_HEX_DATAADDRESS;
+
+ case '5':
+ case '6':
+ return SCE_HEX_RECCOUNT;
+
+ case '7':
+ case '8':
+ case '9':
+ return SCE_HEX_STARTADDRESS;
+
+ default: // handle possible format extension in the future
+ return SCE_HEX_ADDRESSFIELD_UNKNOWN;
+ }
+}
+
+// Get the type of the "data" field content.
+static int GetSrecDataFieldType(unsigned int recStartPos, Accessor &styler)
+{
+ switch (styler.SafeGetCharAt(recStartPos + 1)) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ return SCE_HEX_DATA_ODD;
+
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return SCE_HEX_DATA_EMPTY;
+
+ default: // handle possible format extension in the future
+ return SCE_HEX_DATA_UNKNOWN;
+ }
+}
+
+// Get the required size of the "data" field. Useless for block header and
+// ordinary data records (type S0, S1, S2, S3), return the value calculated
+// from the "byte count" and "address field" size in this case.
+static int GetSrecRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler)
+{
+ switch (styler.SafeGetCharAt(recStartPos + 1)) {
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ return 0;
+
+ default:
+ return GetSrecByteCount(recStartPos, styler)
+ - GetSrecAddressFieldSize(recStartPos, styler)
+ - 1; // -1 for checksum field
+ }
+}
+
+// Get the value of the "checksum" field.
+static int GetSrecChecksum(unsigned int recStartPos, Accessor &styler)
+{
+ int byteCount;
+
+ byteCount = GetSrecByteCount(recStartPos, styler);
+
+ return GetHexaChar(recStartPos + 2 + byteCount * 2, styler);
+}
+
+// Calculate the checksum of the record.
+static int CalcSrecChecksum(unsigned int recStartPos, Accessor &styler)
+{
+ int byteCount;
+
+ byteCount = GetSrecByteCount(recStartPos, styler);
+
+ // sum over "byte count", "address" and "data" fields (6..510 digits)
+ return CalcChecksum(recStartPos + 2, byteCount * 2, false, styler);
+}
+
+// Get the position of the record "start" field (first character in line) in
+// the record around position <pos>.
+static unsigned int GetIHexRecStartPosition(unsigned int pos, Accessor &styler)
+{
+ while (styler.SafeGetCharAt(pos) != ':') {
+ pos--;
+ }
+
+ return pos;
+}
+
+// Get the value of the "byte count" field, it counts the number of bytes in
+// the "data" field.
+static int GetIHexByteCount(unsigned int recStartPos, Accessor &styler)
+{
+ int val;
+
+ val = GetHexaChar(recStartPos + 1, styler);
+ if (val < 0) {
+ val = 0;
+ }
+
+ return val;
+}
+
+// Count the number of digit pairs for the "data" field in this record. Has to
+// be equal to the "byte count" field value.
+// If the record is too short, a negative count may be returned.
+static int CountIHexByteCount(unsigned int recStartPos, Accessor &styler)
+{
+ return CountByteCount(recStartPos, 11, styler);
+}
+
+// Get the type of the "address" field content.
+static int GetIHexAddressFieldType(unsigned int recStartPos, Accessor &styler)
+{
+ if (!PosInSameRecord(recStartPos, recStartPos + 7, styler)) {
+ // malformed (record too short)
+ // type cannot be determined
+ return SCE_HEX_ADDRESSFIELD_UNKNOWN;
+ }
+
+ switch (GetHexaChar(recStartPos + 7, styler)) {
+ case 0x00:
+ return SCE_HEX_DATAADDRESS;
+
+ case 0x01:
+ case 0x02:
+ case 0x03:
+ case 0x04:
+ case 0x05:
+ return SCE_HEX_NOADDRESS;
+
+ default: // handle possible format extension in the future
+ return SCE_HEX_ADDRESSFIELD_UNKNOWN;
+ }
+}
+
+// Get the type of the "data" field content.
+static int GetIHexDataFieldType(unsigned int recStartPos, Accessor &styler)
+{
+ switch (GetHexaChar(recStartPos + 7, styler)) {
+ case 0x00:
+ return SCE_HEX_DATA_ODD;
+
+ case 0x01:
+ return SCE_HEX_DATA_EMPTY;
+
+ case 0x02:
+ case 0x04:
+ return SCE_HEX_EXTENDEDADDRESS;
+
+ case 0x03:
+ case 0x05:
+ return SCE_HEX_STARTADDRESS;
+
+ default: // handle possible format extension in the future
+ return SCE_HEX_DATA_UNKNOWN;
+ }
+}
+
+// Get the required size of the "data" field. Useless for an ordinary data
+// record (type 00), return the "byte count" in this case.
+static int GetIHexRequiredDataFieldSize(unsigned int recStartPos, Accessor &styler)
+{
+ switch (GetHexaChar(recStartPos + 7, styler)) {
+ case 0x01:
+ return 0;
+
+ case 0x02:
+ case 0x04:
+ return 2;
+
+ case 0x03:
+ case 0x05:
+ return 4;
+
+ default:
+ return GetIHexByteCount(recStartPos, styler);
+ }
+}
+
+// Get the value of the "checksum" field.
+static int GetIHexChecksum(unsigned int recStartPos, Accessor &styler)
+{
+ int byteCount;
+
+ byteCount = GetIHexByteCount(recStartPos, styler);
+
+ return GetHexaChar(recStartPos + 9 + byteCount * 2, styler);
+}
+
+// Calculate the checksum of the record.
+static int CalcIHexChecksum(unsigned int recStartPos, Accessor &styler)
+{
+ int byteCount;
+
+ byteCount = GetIHexByteCount(recStartPos, styler);
+
+ // sum over "byte count", "address", "type" and "data" fields (8..518 digits)
+ return CalcChecksum(recStartPos + 1, 8 + byteCount * 2, true, styler);
+}
+
+
+// Get the value of the "record length" field, it counts the number of digits in
+// the record excluding the percent.
+static int GetTEHexDigitCount(unsigned int recStartPos, Accessor &styler)
+{
+ int val = GetHexaChar(recStartPos + 1, styler);
+ if (val < 0)
+ val = 0;
+
+ return val;
+}
+
+// Count the number of digits in this record. Has to
+// be equal to the "record length" field value.
+static int CountTEHexDigitCount(unsigned int recStartPos, Accessor &styler)
+{
+ unsigned int pos;
+
+ pos = recStartPos+1;
+
+ while (!IsNewline(styler.SafeGetCharAt(pos, '\n'))) {
+ pos++;
+ }
+
+ return static_cast<int>(pos - (recStartPos+1));
+}
+
+// Get the type of the "address" field content.
+static int GetTEHexAddressFieldType(unsigned int recStartPos, Accessor &styler)
+{
+ switch (styler.SafeGetCharAt(recStartPos + 3)) {
+ case '6':
+ return SCE_HEX_DATAADDRESS;
+
+ case '8':
+ return SCE_HEX_STARTADDRESS;
+
+ default: // handle possible format extension in the future
+ return SCE_HEX_ADDRESSFIELD_UNKNOWN;
+ }
+}
+
+// Get the value of the "checksum" field.
+static int GetTEHexChecksum(unsigned int recStartPos, Accessor &styler)
+{
+ return GetHexaChar(recStartPos+4, styler);
+}
+
+// Calculate the checksum of the record (excluding the checksum field).
+static int CalcTEHexChecksum(unsigned int recStartPos, Accessor &styler)
+{
+ unsigned int pos = recStartPos +1;
+ unsigned int length = GetTEHexDigitCount(recStartPos, styler);
+
+ int cs = GetHexaNibble(styler.SafeGetCharAt(pos++));//length
+ cs += GetHexaNibble(styler.SafeGetCharAt(pos++));//length
+
+ cs += GetHexaNibble(styler.SafeGetCharAt(pos++));//type
+
+ pos += 2;// jump over CS field
+
+ for (; pos <= recStartPos + length; ++pos) {
+ int val = GetHexaNibble(styler.SafeGetCharAt(pos));
+
+ if (val < 0) {
+ return val;
+ }
+
+ // overflow does not matter
+ cs += val;
+ }
+
+ // low byte
+ return cs & 0xFF;
+
+}
+
+static void ColouriseSrecDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler)
+{
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ while (sc.More()) {
+ unsigned int recStartPos;
+ int byteCount, reqByteCount, addrFieldSize, addrFieldType, dataFieldSize, dataFieldType;
+ int cs1, cs2;
+
+ switch (sc.state) {
+ case SCE_HEX_DEFAULT:
+ if (sc.atLineStart && sc.Match('S')) {
+ sc.SetState(SCE_HEX_RECSTART);
+ }
+ ForwardWithinLine(sc);
+ break;
+
+ case SCE_HEX_RECSTART:
+ recStartPos = sc.currentPos - 1;
+ addrFieldType = GetSrecAddressFieldType(recStartPos, styler);
+
+ if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) {
+ sc.SetState(SCE_HEX_RECTYPE_UNKNOWN);
+ } else {
+ sc.SetState(SCE_HEX_RECTYPE);
+ }
+
+ ForwardWithinLine(sc);
+ break;
+
+ case SCE_HEX_RECTYPE:
+ case SCE_HEX_RECTYPE_UNKNOWN:
+ recStartPos = sc.currentPos - 2;
+ byteCount = GetSrecByteCount(recStartPos, styler);
+ reqByteCount = GetSrecAddressFieldSize(recStartPos, styler)
+ + GetSrecRequiredDataFieldSize(recStartPos, styler)
+ + 1; // +1 for checksum field
+
+ if (byteCount == CountSrecByteCount(recStartPos, styler)
+ && byteCount == reqByteCount) {
+ sc.SetState(SCE_HEX_BYTECOUNT);
+ } else {
+ sc.SetState(SCE_HEX_BYTECOUNT_WRONG);
+ }
+
+ ForwardWithinLine(sc, 2);
+ break;
+
+ case SCE_HEX_BYTECOUNT:
+ case SCE_HEX_BYTECOUNT_WRONG:
+ recStartPos = sc.currentPos - 4;
+ addrFieldSize = GetSrecAddressFieldSize(recStartPos, styler);
+ addrFieldType = GetSrecAddressFieldType(recStartPos, styler);
+
+ sc.SetState(addrFieldType);
+ ForwardWithinLine(sc, addrFieldSize * 2);
+ break;
+
+ case SCE_HEX_NOADDRESS:
+ case SCE_HEX_DATAADDRESS:
+ case SCE_HEX_RECCOUNT:
+ case SCE_HEX_STARTADDRESS:
+ case SCE_HEX_ADDRESSFIELD_UNKNOWN:
+ recStartPos = GetSrecRecStartPosition(sc.currentPos, styler);
+ dataFieldType = GetSrecDataFieldType(recStartPos, styler);
+
+ // Using the required size here if possible has the effect that the
+ // checksum is highlighted at a fixed position after this field for
+ // specific record types, independent on the "byte count" value.
+ dataFieldSize = GetSrecRequiredDataFieldSize(recStartPos, styler);
+
+ sc.SetState(dataFieldType);
+
+ if (dataFieldType == SCE_HEX_DATA_ODD) {
+ for (int i = 0; i < dataFieldSize * 2; i++) {
+ if ((i & 0x3) == 0) {
+ sc.SetState(SCE_HEX_DATA_ODD);
+ } else if ((i & 0x3) == 2) {
+ sc.SetState(SCE_HEX_DATA_EVEN);
+ }
+
+ if (!ForwardWithinLine(sc)) {
+ break;
+ }
+ }
+ } else {
+ ForwardWithinLine(sc, dataFieldSize * 2);
+ }
+ break;
+
+ case SCE_HEX_DATA_ODD:
+ case SCE_HEX_DATA_EVEN:
+ case SCE_HEX_DATA_EMPTY:
+ case SCE_HEX_DATA_UNKNOWN:
+ recStartPos = GetSrecRecStartPosition(sc.currentPos, styler);
+ cs1 = CalcSrecChecksum(recStartPos, styler);
+ cs2 = GetSrecChecksum(recStartPos, styler);
+
+ if (cs1 != cs2 || cs1 < 0 || cs2 < 0) {
+ sc.SetState(SCE_HEX_CHECKSUM_WRONG);
+ } else {
+ sc.SetState(SCE_HEX_CHECKSUM);
+ }
+
+ ForwardWithinLine(sc, 2);
+ break;
+
+ case SCE_HEX_CHECKSUM:
+ case SCE_HEX_CHECKSUM_WRONG:
+ case SCE_HEX_GARBAGE:
+ // record finished or line too long
+ sc.SetState(SCE_HEX_GARBAGE);
+ ForwardWithinLine(sc);
+ break;
+
+ default:
+ // prevent endless loop in faulty state
+ sc.SetState(SCE_HEX_DEFAULT);
+ break;
+ }
+ }
+ sc.Complete();
+}
+
+static void ColouriseIHexDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler)
+{
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ while (sc.More()) {
+ unsigned int recStartPos;
+ int byteCount, addrFieldType, dataFieldSize, dataFieldType;
+ int cs1, cs2;
+
+ switch (sc.state) {
+ case SCE_HEX_DEFAULT:
+ if (sc.atLineStart && sc.Match(':')) {
+ sc.SetState(SCE_HEX_RECSTART);
+ }
+ ForwardWithinLine(sc);
+ break;
+
+ case SCE_HEX_RECSTART:
+ recStartPos = sc.currentPos - 1;
+ byteCount = GetIHexByteCount(recStartPos, styler);
+ dataFieldSize = GetIHexRequiredDataFieldSize(recStartPos, styler);
+
+ if (byteCount == CountIHexByteCount(recStartPos, styler)
+ && byteCount == dataFieldSize) {
+ sc.SetState(SCE_HEX_BYTECOUNT);
+ } else {
+ sc.SetState(SCE_HEX_BYTECOUNT_WRONG);
+ }
+
+ ForwardWithinLine(sc, 2);
+ break;
+
+ case SCE_HEX_BYTECOUNT:
+ case SCE_HEX_BYTECOUNT_WRONG:
+ recStartPos = sc.currentPos - 3;
+ addrFieldType = GetIHexAddressFieldType(recStartPos, styler);
+
+ sc.SetState(addrFieldType);
+ ForwardWithinLine(sc, 4);
+ break;
+
+ case SCE_HEX_NOADDRESS:
+ case SCE_HEX_DATAADDRESS:
+ case SCE_HEX_ADDRESSFIELD_UNKNOWN:
+ recStartPos = sc.currentPos - 7;
+ addrFieldType = GetIHexAddressFieldType(recStartPos, styler);
+
+ if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) {
+ sc.SetState(SCE_HEX_RECTYPE_UNKNOWN);
+ } else {
+ sc.SetState(SCE_HEX_RECTYPE);
+ }
+
+ ForwardWithinLine(sc, 2);
+ break;
+
+ case SCE_HEX_RECTYPE:
+ case SCE_HEX_RECTYPE_UNKNOWN:
+ recStartPos = sc.currentPos - 9;
+ dataFieldType = GetIHexDataFieldType(recStartPos, styler);
+
+ // Using the required size here if possible has the effect that the
+ // checksum is highlighted at a fixed position after this field for
+ // specific record types, independent on the "byte count" value.
+ dataFieldSize = GetIHexRequiredDataFieldSize(recStartPos, styler);
+
+ sc.SetState(dataFieldType);
+
+ if (dataFieldType == SCE_HEX_DATA_ODD) {
+ for (int i = 0; i < dataFieldSize * 2; i++) {
+ if ((i & 0x3) == 0) {
+ sc.SetState(SCE_HEX_DATA_ODD);
+ } else if ((i & 0x3) == 2) {
+ sc.SetState(SCE_HEX_DATA_EVEN);
+ }
+
+ if (!ForwardWithinLine(sc)) {
+ break;
+ }
+ }
+ } else {
+ ForwardWithinLine(sc, dataFieldSize * 2);
+ }
+ break;
+
+ case SCE_HEX_DATA_ODD:
+ case SCE_HEX_DATA_EVEN:
+ case SCE_HEX_DATA_EMPTY:
+ case SCE_HEX_EXTENDEDADDRESS:
+ case SCE_HEX_STARTADDRESS:
+ case SCE_HEX_DATA_UNKNOWN:
+ recStartPos = GetIHexRecStartPosition(sc.currentPos, styler);
+ cs1 = CalcIHexChecksum(recStartPos, styler);
+ cs2 = GetIHexChecksum(recStartPos, styler);
+
+ if (cs1 != cs2 || cs1 < 0 || cs2 < 0) {
+ sc.SetState(SCE_HEX_CHECKSUM_WRONG);
+ } else {
+ sc.SetState(SCE_HEX_CHECKSUM);
+ }
+
+ ForwardWithinLine(sc, 2);
+ break;
+
+ case SCE_HEX_CHECKSUM:
+ case SCE_HEX_CHECKSUM_WRONG:
+ case SCE_HEX_GARBAGE:
+ // record finished or line too long
+ sc.SetState(SCE_HEX_GARBAGE);
+ ForwardWithinLine(sc);
+ break;
+
+ default:
+ // prevent endless loop in faulty state
+ sc.SetState(SCE_HEX_DEFAULT);
+ break;
+ }
+ }
+ sc.Complete();
+}
+
+static void FoldIHexDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
+{
+ unsigned int endPos = startPos + length;
+
+ int lineCurrent = styler.GetLine(startPos);
+ int levelCurrent = SC_FOLDLEVELBASE;
+ if (lineCurrent > 0)
+ levelCurrent = styler.LevelAt(lineCurrent - 1);
+
+ unsigned int lineStartNext = styler.LineStart(lineCurrent + 1);
+ int levelNext = SC_FOLDLEVELBASE; // default if no specific line found
+
+ for (unsigned int i = startPos; i < endPos; i++) {
+ bool atEOL = i == (lineStartNext - 1);
+ int style = styler.StyleAt(i);
+
+ // search for specific lines
+ if (style == SCE_HEX_EXTENDEDADDRESS) {
+ // extended addres record
+ levelNext = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
+ } else if (style == SCE_HEX_DATAADDRESS
+ || (style == SCE_HEX_DEFAULT
+ && i == (unsigned int)styler.LineStart(lineCurrent))) {
+ // data record or no record start code at all
+ if (levelCurrent & SC_FOLDLEVELHEADERFLAG) {
+ levelNext = SC_FOLDLEVELBASE + 1;
+ } else {
+ // continue level 0 or 1, no fold point
+ levelNext = levelCurrent;
+ }
+ }
+
+ if (atEOL || (i == endPos - 1)) {
+ styler.SetLevel(lineCurrent, levelNext);
+
+ lineCurrent++;
+ lineStartNext = styler.LineStart(lineCurrent + 1);
+ levelCurrent = levelNext;
+ levelNext = SC_FOLDLEVELBASE;
+ }
+ }
+}
+
+static void ColouriseTEHexDoc(unsigned int startPos, int length, int initStyle, WordList *[], Accessor &styler)
+{
+ StyleContext sc(startPos, length, initStyle, styler);
+
+ while (sc.More()) {
+ unsigned int recStartPos;
+ int digitCount, addrFieldType;
+ int cs1, cs2;
+
+ switch (sc.state) {
+ case SCE_HEX_DEFAULT:
+ if (sc.atLineStart && sc.Match('%')) {
+ sc.SetState(SCE_HEX_RECSTART);
+ }
+ ForwardWithinLine(sc);
+ break;
+
+ case SCE_HEX_RECSTART:
+
+ recStartPos = sc.currentPos - 1;
+
+ if (GetTEHexDigitCount(recStartPos, styler) == CountTEHexDigitCount(recStartPos, styler)) {
+ sc.SetState(SCE_HEX_BYTECOUNT);
+ } else {
+ sc.SetState(SCE_HEX_BYTECOUNT_WRONG);
+ }
+
+ ForwardWithinLine(sc, 2);
+ break;
+
+ case SCE_HEX_BYTECOUNT:
+ case SCE_HEX_BYTECOUNT_WRONG:
+ recStartPos = sc.currentPos - 3;
+ addrFieldType = GetTEHexAddressFieldType(recStartPos, styler);
+
+ if (addrFieldType == SCE_HEX_ADDRESSFIELD_UNKNOWN) {
+ sc.SetState(SCE_HEX_RECTYPE_UNKNOWN);
+ } else {
+ sc.SetState(SCE_HEX_RECTYPE);
+ }
+
+ ForwardWithinLine(sc);
+ break;
+
+ case SCE_HEX_RECTYPE:
+ case SCE_HEX_RECTYPE_UNKNOWN:
+ recStartPos = sc.currentPos - 4;
+ cs1 = CalcTEHexChecksum(recStartPos, styler);
+ cs2 = GetTEHexChecksum(recStartPos, styler);
+
+ if (cs1 != cs2 || cs1 < 0 || cs2 < 0) {
+ sc.SetState(SCE_HEX_CHECKSUM_WRONG);
+ } else {
+ sc.SetState(SCE_HEX_CHECKSUM);
+ }
+
+ ForwardWithinLine(sc, 2);
+ break;
+
+
+ case SCE_HEX_CHECKSUM:
+ case SCE_HEX_CHECKSUM_WRONG:
+ recStartPos = sc.currentPos - 6;
+ addrFieldType = GetTEHexAddressFieldType(recStartPos, styler);
+
+ sc.SetState(addrFieldType);
+ ForwardWithinLine(sc, 9);
+ break;
+
+ case SCE_HEX_DATAADDRESS:
+ case SCE_HEX_STARTADDRESS:
+ case SCE_HEX_ADDRESSFIELD_UNKNOWN:
+ recStartPos = sc.currentPos - 15;
+ digitCount = GetTEHexDigitCount(recStartPos, styler) - 14;
+
+ sc.SetState(SCE_HEX_DATA_ODD);
+
+ for (int i = 0; i < digitCount; i++) {
+ if ((i & 0x3) == 0) {
+ sc.SetState(SCE_HEX_DATA_ODD);
+ } else if ((i & 0x3) == 2) {
+ sc.SetState(SCE_HEX_DATA_EVEN);
+ }
+
+ if (!ForwardWithinLine(sc)) {
+ break;
+ }
+ }
+ break;
+
+ case SCE_HEX_DATA_ODD:
+ case SCE_HEX_DATA_EVEN:
+ case SCE_HEX_GARBAGE:
+ // record finished or line too long
+ sc.SetState(SCE_HEX_GARBAGE);
+ ForwardWithinLine(sc);
+ break;
+
+ default:
+ // prevent endless loop in faulty state
+ sc.SetState(SCE_HEX_DEFAULT);
+ break;
+ }
+ }
+ sc.Complete();
+}
+
+LexerModule lmSrec(SCLEX_SREC, ColouriseSrecDoc, "srec", 0, NULL);
+LexerModule lmIHex(SCLEX_IHEX, ColouriseIHexDoc, "ihex", FoldIHexDoc, NULL);
+LexerModule lmTEHex(SCLEX_TEHEX, ColouriseTEHexDoc, "tehex", 0, NULL);
diff --git a/scintilla/lexers/LexVerilog.cxx b/scintilla/lexers/LexVerilog.cxx
index e27de36..d41ea84 100644
--- a/scintilla/lexers/LexVerilog.cxx
+++ b/scintilla/lexers/LexVerilog.cxx
@@ -13,6 +13,11 @@
#include <assert.h>
#include <ctype.h>
+#include <string>
+#include <vector>
+#include <map>
+#include <algorithm>
+
#include "ILexer.h"
#include "Scintilla.h"
#include "SciLexer.h"
@@ -24,10 +29,309 @@
#include "CharacterSet.h"
#include "LexerModule.h"
+#include "OptionSet.h"
+#include "SubStyles.h"
+
#ifdef SCI_NAMESPACE
using namespace Scintilla;
#endif
+namespace {
+ // Use an unnamed namespace to protect the functions and classes from name conflicts
+
+struct PPDefinition {
+ int line;
+ std::string key;
+ std::string value;
+ bool isUndef;
+ std::string arguments;
+ PPDefinition(int line_, const std::string &key_, const std::string &value_, bool isUndef_ = false, std::string arguments_="") :
+ line(line_), key(key_), value(value_), isUndef(isUndef_), arguments(arguments_) {
+ }
+};
+
+class LinePPState {
+ int state;
+ int ifTaken;
+ int level;
+ bool ValidLevel() const {
+ return level >= 0 && level < 32;
+ }
+ int maskLevel() const {
+ return 1 << level;
+ }
+public:
+ LinePPState() : state(0), ifTaken(0), level(-1) {
+ }
+ bool IsInactive() const {
+ return state != 0;
+ }
+ bool CurrentIfTaken() const {
+ return (ifTaken & maskLevel()) != 0;
+ }
+ void StartSection(bool on) {
+ level++;
+ if (ValidLevel()) {
+ if (on) {
+ state &= ~maskLevel();
+ ifTaken |= maskLevel();
+ } else {
+ state |= maskLevel();
+ ifTaken &= ~maskLevel();
+ }
+ }
+ }
+ void EndSection() {
+ if (ValidLevel()) {
+ state &= ~maskLevel();
+ ifTaken &= ~maskLevel();
+ }
+ level--;
+ }
+ void InvertCurrentLevel() {
+ if (ValidLevel()) {
+ state ^= maskLevel();
+ ifTaken |= maskLevel();
+ }
+ }
+};
+
+// Hold the preprocessor state for each line seen.
+// Currently one entry per line but could become sparse with just one entry per preprocessor line.
+class PPStates {
+ std::vector<LinePPState> vlls;
+public:
+ LinePPState ForLine(int line) const {
+ if ((line > 0) && (vlls.size() > static_cast<size_t>(line))) {
+ return vlls[line];
+ } else {
+ return LinePPState();
+ }
+ }
+ void Add(int line, LinePPState lls) {
+ vlls.resize(line+1);
+ vlls[line] = lls;
+ }
+};
+
+// Options used for LexerVerilog
+struct OptionsVerilog {
+ bool foldComment;
+ bool foldPreprocessor;
+ bool foldCompact;
+ bool foldAtElse;
+ bool foldAtModule;
+ bool trackPreprocessor;
+ bool updatePreprocessor;
+ bool portStyling;
+ bool allUppercaseDocKeyword;
+ OptionsVerilog() {
+ foldComment = false;
+ foldPreprocessor = false;
+ foldCompact = false;
+ foldAtElse = false;
+ foldAtModule = false;
+ // for backwards compatibility, preprocessor functionality is disabled by default
+ trackPreprocessor = false;
+ updatePreprocessor = false;
+ // for backwards compatibility, treat input/output/inout as regular keywords
+ portStyling = false;
+ // for backwards compatibility, don't treat all uppercase identifiers as documentation keywords
+ allUppercaseDocKeyword = false;
+ }
+};
+
+struct OptionSetVerilog : public OptionSet<OptionsVerilog> {
+ OptionSetVerilog() {
+ DefineProperty("fold.comment", &OptionsVerilog::foldComment,
+ "This option enables folding multi-line comments when using the Verilog lexer.");
+ DefineProperty("fold.preprocessor", &OptionsVerilog::foldPreprocessor,
+ "This option enables folding preprocessor directives when using the Verilog lexer.");
+ DefineProperty("fold.compact", &OptionsVerilog::foldCompact);
+ DefineProperty("fold.at.else", &OptionsVerilog::foldAtElse,
+ "This option enables folding on the else line of an if statement.");
+ DefineProperty("fold.verilog.flags", &OptionsVerilog::foldAtModule,
+ "This option enables folding module definitions. Typically source files "
+ "contain only one module definition so this option is somewhat useless.");
+ DefineProperty("lexer.verilog.track.preprocessor", &OptionsVerilog::trackPreprocessor,
+ "Set to 1 to interpret `if/`else/`endif to grey out code that is not active.");
+ DefineProperty("lexer.verilog.update.preprocessor", &OptionsVerilog::updatePreprocessor,
+ "Set to 1 to update preprocessor definitions when `define, `undef, or `undefineall found.");
+ DefineProperty("lexer.verilog.portstyling", &OptionsVerilog::portStyling,
+ "Set to 1 to style input, output, and inout ports differently from regular keywords.");
+ DefineProperty("lexer.verilog.allupperkeywords", &OptionsVerilog::allUppercaseDocKeyword,
+ "Set to 1 to style identifiers that are all uppercase as documentation keyword.");
+ }
+};
+
+const char styleSubable[] = {0};
+
+}
+
+class LexerVerilog : public ILexerWithSubStyles {
+ CharacterSet setWord;
+ WordList keywords;
+ WordList keywords2;
+ WordList keywords3;
+ WordList keywords4;
+ WordList keywords5;
+ WordList ppDefinitions;
+ PPStates vlls;
+ std::vector<PPDefinition> ppDefineHistory;
+ struct SymbolValue {
+ std::string value;
+ std::string arguments;
+ SymbolValue(const std::string &value_="", const std::string &arguments_="") : value(value_), arguments(arguments_) {
+ }
+ SymbolValue &operator = (const std::string &value_) {
+ value = value_;
+ arguments.clear();
+ return *this;
+ }
+ bool IsMacro() const {
+ return !arguments.empty();
+ }
+ };
+ typedef std::map<std::string, SymbolValue> SymbolTable;
+ SymbolTable preprocessorDefinitionsStart;
+ OptionsVerilog options;
+ OptionSetVerilog osVerilog;
+ enum { activeFlag = 0x40 };
+ SubStyles subStyles;
+public:
+ LexerVerilog() :
+ setWord(CharacterSet::setAlphaNum, "._", 0x80, true),
+ subStyles(styleSubable, 0x80, 0x40, activeFlag) {
+ }
+ virtual ~LexerVerilog() {}
+ int SCI_METHOD Version() const {
+ return lvSubStyles;
+ }
+ void SCI_METHOD Release() {
+ delete this;
+ }
+ const char* SCI_METHOD PropertyNames() {
+ return osVerilog.PropertyNames();
+ }
+ int SCI_METHOD PropertyType(const char* name) {
+ return osVerilog.PropertyType(name);
+ }
+ const char* SCI_METHOD DescribeProperty(const char* name) {
+ return osVerilog.DescribeProperty(name);
+ }
+ int SCI_METHOD PropertySet(const char* key, const char* val) {
+ return osVerilog.PropertySet(&options, key, val);
+ }
+ const char* SCI_METHOD DescribeWordListSets() {
+ return osVerilog.DescribeWordListSets();
+ }
+ int SCI_METHOD WordListSet(int n, const char* wl);
+ void SCI_METHOD Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
+ void SCI_METHOD Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess);
+ void* SCI_METHOD PrivateCall(int, void*) {
+ return 0;
+ }
+ int SCI_METHOD LineEndTypesSupported() {
+ return SC_LINE_END_TYPE_UNICODE;
+ }
+ int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) {
+ return subStyles.Allocate(styleBase, numberStyles);
+ }
+ int SCI_METHOD SubStylesStart(int styleBase) {
+ return subStyles.Start(styleBase);
+ }
+ int SCI_METHOD SubStylesLength(int styleBase) {
+ return subStyles.Length(styleBase);
+ }
+ int SCI_METHOD StyleFromSubStyle(int subStyle) {
+ int styleBase = subStyles.BaseStyle(MaskActive(subStyle));
+ int active = subStyle & activeFlag;
+ return styleBase | active;
+ }
+ int SCI_METHOD PrimaryStyleFromStyle(int style) {
+ return MaskActive(style);
+ }
+ void SCI_METHOD FreeSubStyles() {
+ subStyles.Free();
+ }
+ void SCI_METHOD SetIdentifiers(int style, const char *identifiers) {
+ subStyles.SetIdentifiers(style, identifiers);
+ }
+ int SCI_METHOD DistanceToSecondaryStyles() {
+ return activeFlag;
+ }
+ const char * SCI_METHOD GetSubStyleBases() {
+ return styleSubable;
+ }
+ static ILexer* LexerFactoryVerilog() {
+ return new LexerVerilog();
+ }
+ static int MaskActive(int style) {
+ return style & ~activeFlag;
+ }
+ std::vector<std::string> Tokenize(const std::string &expr) const;
+};
+
+int SCI_METHOD LexerVerilog::WordListSet(int n, const char *wl) {
+ WordList *wordListN = 0;
+ switch (n) {
+ case 0:
+ wordListN = &keywords;
+ break;
+ case 1:
+ wordListN = &keywords2;
+ break;
+ case 2:
+ wordListN = &keywords3;
+ break;
+ case 3:
+ wordListN = &keywords4;
+ break;
+ case 4:
+ wordListN = &keywords5;
+ break;
+ case 5:
+ wordListN = &ppDefinitions;
+ break;
+ }
+ int firstModification = -1;
+ if (wordListN) {
+ WordList wlNew;
+ wlNew.Set(wl);
+ if (*wordListN != wlNew) {
+ wordListN->Set(wl);
+ firstModification = 0;
+ if (n == 5) {
+ // Rebuild preprocessorDefinitions
+ preprocessorDefinitionsStart.clear();
+ for (int nDefinition = 0; nDefinition < ppDefinitions.Length(); nDefinition++) {
+ const char *cpDefinition = ppDefinitions.WordAt(nDefinition);
+ const char *cpEquals = strchr(cpDefinition, '=');
+ if (cpEquals) {
+ std::string name(cpDefinition, cpEquals - cpDefinition);
+ std::string val(cpEquals+1);
+ size_t bracket = name.find('(');
+ size_t bracketEnd = name.find(')');
+ if ((bracket != std::string::npos) && (bracketEnd != std::string::npos)) {
+ // Macro
+ std::string args = name.substr(bracket + 1, bracketEnd - bracket - 1);
+ name = name.substr(0, bracket);
+ preprocessorDefinitionsStart[name] = SymbolValue(val, args);
+ } else {
+ preprocessorDefinitionsStart[name] = val;
+ }
+ } else {
+ std::string name(cpDefinition);
+ std::string val("1");
+ preprocessorDefinitionsStart[name] = val;
+ }
+ }
+ }
+ }
+ }
+ return firstModification;
+}
+
static inline bool IsAWordChar(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\''|| ch == '$');
}
@@ -36,116 +340,389 @@ static inline bool IsAWordStart(const int ch) {
return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '$');
}
-static void ColouriseVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
- Accessor &styler) {
+static inline bool AllUpperCase(const char *a) {
+ while (*a) {
+ if (*a >= 'a' && *a <= 'z') return false;
+ a++;
+ }
+ return true;
+}
- WordList &keywords = *keywordlists[0];
- WordList &keywords2 = *keywordlists[1];
- WordList &keywords3 = *keywordlists[2];
- WordList &keywords4 = *keywordlists[3];
+// Functor used to truncate history
+struct After {
+ int line;
+ explicit After(int line_) : line(line_) {}
+ bool operator()(PPDefinition &p) const {
+ return p.line > line;
+ }
+};
+
+static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace) {
+ std::string restOfLine;
+ int i =0;
+ char ch = styler.SafeGetCharAt(start, '\n');
+ int endLine = styler.LineEnd(styler.GetLine(start));
+ while (((start+i) < endLine) && (ch != '\r')) {
+ char chNext = styler.SafeGetCharAt(start + i + 1, '\n');
+ if (ch == '/' && (chNext == '/' || chNext == '*'))
+ break;
+ if (allowSpace || (ch != ' '))
+ restOfLine += ch;
+ i++;
+ ch = chNext;
+ }
+ return restOfLine;
+}
+
+static bool IsSpaceOrTab(int ch) {
+ return ch == ' ' || ch == '\t';
+}
+
+void SCI_METHOD LexerVerilog::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess)
+{
+ LexAccessor styler(pAccess);
+
+ const int kwOther=0, kwDot=0x100, kwInput=0x200, kwOutput=0x300, kwInout=0x400;
+ int lineState = kwOther;
+ bool continuationLine = false;
+
+ int curLine = styler.GetLine(startPos);
+ if (curLine > 0) lineState = styler.GetLineState(curLine - 1);
// Do not leak onto next line
if (initStyle == SCE_V_STRINGEOL)
initStyle = SCE_V_DEFAULT;
+ if ((MaskActive(initStyle) == SCE_V_PREPROCESSOR) ||
+ (MaskActive(initStyle) == SCE_V_COMMENTLINE) ||
+ (MaskActive(initStyle) == SCE_V_COMMENTLINEBANG)) {
+ // Set continuationLine if last character of previous line is '\'
+ if (curLine > 0) {
+ int endLinePrevious = styler.LineEnd(curLine - 1);
+ if (endLinePrevious > 0) {
+ continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\';
+ }
+ }
+ }
+
StyleContext sc(startPos, length, initStyle, styler);
+ LinePPState preproc = vlls.ForLine(curLine);
+
+ bool definitionsChanged = false;
+
+ // Truncate ppDefineHistory before current line
+
+ if (!options.updatePreprocessor)
+ ppDefineHistory.clear();
+
+ std::vector<PPDefinition>::iterator itInvalid = std::find_if(ppDefineHistory.begin(), ppDefineHistory.end(), After(curLine-1));
+ if (itInvalid != ppDefineHistory.end()) {
+ ppDefineHistory.erase(itInvalid, ppDefineHistory.end());
+ definitionsChanged = true;
+ }
+
+ SymbolTable preprocessorDefinitions = preprocessorDefinitionsStart;
+ for (std::vector<PPDefinition>::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) {
+ if (itDef->isUndef)
+ preprocessorDefinitions.erase(itDef->key);
+ else
+ preprocessorDefinitions[itDef->key] = SymbolValue(itDef->value, itDef->arguments);
+ }
+
+ int activitySet = preproc.IsInactive() ? activeFlag : 0;
+ int lineEndNext = styler.LineEnd(curLine);
for (; sc.More(); sc.Forward()) {
+ if (sc.atLineStart) {
+ if (sc.state == SCE_V_STRING) {
+ // Prevent SCE_V_STRINGEOL from leaking back to previous line
+ sc.SetState(SCE_V_STRING);
+ }
+ if ((MaskActive(sc.state) == SCE_V_PREPROCESSOR) && (!continuationLine)) {
+ sc.SetState(SCE_V_DEFAULT|activitySet);
+ }
+ if (preproc.IsInactive()) {
+ activitySet = activeFlag;
+ sc.SetState(sc.state | activitySet);
+ }
+ }
- if (sc.atLineStart && (sc.state == SCE_V_STRING)) {
- // Prevent SCE_V_STRINGEOL from leaking back to previous line
- sc.SetState(SCE_V_STRING);
+ if (sc.atLineEnd) {
+ curLine++;
+ lineEndNext = styler.LineEnd(curLine);
+ vlls.Add(curLine, preproc);
+ // Update the line state, so it can be seen by next line
+ styler.SetLineState(curLine, lineState);
}
// Handle line continuation generically.
if (sc.ch == '\\') {
- if (sc.chNext == '\n' || sc.chNext == '\r') {
+ if (static_cast<int>((sc.currentPos+1)) >= lineEndNext) {
+ curLine++;
+ lineEndNext = styler.LineEnd(curLine);
+ vlls.Add(curLine, preproc);
+ // Update the line state, so it can be seen by next line
+ styler.SetLineState(curLine, lineState);
sc.Forward();
if (sc.ch == '\r' && sc.chNext == '\n') {
+ // Even in UTF-8, \r and \n are separate
sc.Forward();
}
+ continuationLine = true;
+ sc.Forward();
continue;
}
}
- // Determine if the current state should terminate.
- if (sc.state == SCE_V_OPERATOR) {
- sc.SetState(SCE_V_DEFAULT);
- } else if (sc.state == SCE_V_NUMBER) {
- if (!IsAWordChar(sc.ch)) {
- sc.SetState(SCE_V_DEFAULT);
+ // for comment keyword
+ if (MaskActive(sc.state) == SCE_V_COMMENT_WORD && !IsAWordChar(sc.ch)) {
+ char s[100];
+ int state = lineState & 0xff;
+ sc.GetCurrent(s, sizeof(s));
+ if (keywords5.InList(s)) {
+ sc.ChangeState(SCE_V_COMMENT_WORD|activitySet);
+ } else {
+ sc.ChangeState(state|activitySet);
}
- } else if (sc.state == SCE_V_IDENTIFIER) {
- if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
- char s[100];
- sc.GetCurrent(s, sizeof(s));
- if (keywords.InList(s)) {
- sc.ChangeState(SCE_V_WORD);
- } else if (keywords2.InList(s)) {
- sc.ChangeState(SCE_V_WORD2);
- } else if (keywords3.InList(s)) {
- sc.ChangeState(SCE_V_WORD3);
- } else if (keywords4.InList(s)) {
- sc.ChangeState(SCE_V_USER);
+ sc.SetState(state|activitySet);
+ }
+
+ const bool atLineEndBeforeSwitch = sc.atLineEnd;
+
+ // Determine if the current state should terminate.
+ switch (MaskActive(sc.state)) {
+ case SCE_V_OPERATOR:
+ sc.SetState(SCE_V_DEFAULT|activitySet);
+ break;
+ case SCE_V_NUMBER:
+ if (!(IsAWordChar(sc.ch) || (sc.ch == '?'))) {
+ sc.SetState(SCE_V_DEFAULT|activitySet);
}
- sc.SetState(SCE_V_DEFAULT);
- }
- } else if (sc.state == SCE_V_PREPROCESSOR) {
- if (!IsAWordChar(sc.ch)) {
- sc.SetState(SCE_V_DEFAULT);
- }
- } else if (sc.state == SCE_V_COMMENT) {
- if (sc.Match('*', '/')) {
- sc.Forward();
- sc.ForwardSetState(SCE_V_DEFAULT);
- }
- } else if (sc.state == SCE_V_COMMENTLINE || sc.state == SCE_V_COMMENTLINEBANG) {
- if (sc.atLineStart) {
- sc.SetState(SCE_V_DEFAULT);
- }
- } else if (sc.state == SCE_V_STRING) {
- if (sc.ch == '\\') {
- if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ break;
+ case SCE_V_IDENTIFIER:
+ if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
+ char s[100];
+ lineState &= 0xff00;
+ sc.GetCurrent(s, sizeof(s));
+ if (options.portStyling && (strcmp(s, "input") == 0)) {
+ lineState = kwInput;
+ sc.ChangeState(SCE_V_INPUT|activitySet);
+ } else if (options.portStyling && (strcmp(s, "output") == 0)) {
+ lineState = kwOutput;
+ sc.ChangeState(SCE_V_OUTPUT|activitySet);
+ } else if (options.portStyling && (strcmp(s, "inout") == 0)) {
+ lineState = kwInout;
+ sc.ChangeState(SCE_V_INOUT|activitySet);
+ } else if (lineState == kwInput) {
+ sc.ChangeState(SCE_V_INPUT|activitySet);
+ } else if (lineState == kwOutput) {
+ sc.ChangeState(SCE_V_OUTPUT|activitySet);
+ } else if (lineState == kwInout) {
+ sc.ChangeState(SCE_V_INOUT|activitySet);
+ } else if (lineState == kwDot) {
+ lineState = kwOther;
+ if (options.portStyling)
+ sc.ChangeState(SCE_V_PORT_CONNECT|activitySet);
+ } else if (keywords.InList(s)) {
+ sc.ChangeState(SCE_V_WORD|activitySet);
+ } else if (keywords2.InList(s)) {
+ sc.ChangeState(SCE_V_WORD2|activitySet);
+ } else if (keywords3.InList(s)) {
+ sc.ChangeState(SCE_V_WORD3|activitySet);
+ } else if (keywords4.InList(s)) {
+ sc.ChangeState(SCE_V_USER|activitySet);
+ } else if (options.allUppercaseDocKeyword && AllUpperCase(s)) {
+ sc.ChangeState(SCE_V_USER|activitySet);
+ }
+ sc.SetState(SCE_V_DEFAULT|activitySet);
+ }
+ break;
+ case SCE_V_PREPROCESSOR:
+ if (!IsAWordChar(sc.ch) && !sc.atLineEnd) {
+ sc.SetState(SCE_V_DEFAULT|activitySet);
+ }
+ break;
+ case SCE_V_COMMENT:
+ if (sc.Match('*', '/')) {
sc.Forward();
+ sc.ForwardSetState(SCE_V_DEFAULT|activitySet);
+ } else if (IsAWordStart(sc.ch)) {
+ lineState = sc.state | (lineState & 0xff00);
+ sc.SetState(SCE_V_COMMENT_WORD|activitySet);
}
- } else if (sc.ch == '\"') {
- sc.ForwardSetState(SCE_V_DEFAULT);
- } else if (sc.atLineEnd) {
- sc.ChangeState(SCE_V_STRINGEOL);
- sc.ForwardSetState(SCE_V_DEFAULT);
- }
+ break;
+ case SCE_V_COMMENTLINE:
+ case SCE_V_COMMENTLINEBANG:
+ if (sc.atLineStart) {
+ sc.SetState(SCE_V_DEFAULT|activitySet);
+ } else if (IsAWordStart(sc.ch)) {
+ lineState = sc.state | (lineState & 0xff00);
+ sc.SetState(SCE_V_COMMENT_WORD|activitySet);
+ }
+ break;
+ case SCE_V_STRING:
+ if (sc.ch == '\\') {
+ if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+ sc.Forward();
+ }
+ } else if (sc.ch == '\"') {
+ sc.ForwardSetState(SCE_V_DEFAULT|activitySet);
+ } else if (sc.atLineEnd) {
+ sc.ChangeState(SCE_V_STRINGEOL|activitySet);
+ sc.ForwardSetState(SCE_V_DEFAULT|activitySet);
+ }
+ break;
+ }
+
+ if (sc.atLineEnd && !atLineEndBeforeSwitch) {
+ // State exit processing consumed characters up to end of line.
+ curLine++;
+ lineEndNext = styler.LineEnd(curLine);
+ vlls.Add(curLine, preproc);
+ // Update the line state, so it can be seen by next line
+ styler.SetLineState(curLine, lineState);
}
// Determine if a new state should be entered.
- if (sc.state == SCE_V_DEFAULT) {
+ if (MaskActive(sc.state) == SCE_V_DEFAULT) {
if (IsADigit(sc.ch) || (sc.ch == '\'') || (sc.ch == '.' && IsADigit(sc.chNext))) {
- sc.SetState(SCE_V_NUMBER);
+ sc.SetState(SCE_V_NUMBER|activitySet);
} else if (IsAWordStart(sc.ch)) {
- sc.SetState(SCE_V_IDENTIFIER);
+ sc.SetState(SCE_V_IDENTIFIER|activitySet);
} else if (sc.Match('/', '*')) {
- sc.SetState(SCE_V_COMMENT);
+ sc.SetState(SCE_V_COMMENT|activitySet);
sc.Forward(); // Eat the * so it isn't used for the end of the comment
} else if (sc.Match('/', '/')) {
if (sc.Match("//!")) // Nice to have a different comment style
- sc.SetState(SCE_V_COMMENTLINEBANG);
+ sc.SetState(SCE_V_COMMENTLINEBANG|activitySet);
else
- sc.SetState(SCE_V_COMMENTLINE);
+ sc.SetState(SCE_V_COMMENTLINE|activitySet);
} else if (sc.ch == '\"') {
- sc.SetState(SCE_V_STRING);
+ sc.SetState(SCE_V_STRING|activitySet);
} else if (sc.ch == '`') {
- sc.SetState(SCE_V_PREPROCESSOR);
+ sc.SetState(SCE_V_PREPROCESSOR|activitySet);
// Skip whitespace between ` and preprocessor word
do {
sc.Forward();
} while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
if (sc.atLineEnd) {
- sc.SetState(SCE_V_DEFAULT);
+ sc.SetState(SCE_V_DEFAULT|activitySet);
+ styler.SetLineState(curLine, lineState);
+ } else {
+ if (options.trackPreprocessor) {
+ if (sc.Match("ifdef") || sc.Match("ifndef")) {
+ bool isIfDef = sc.Match("ifdef");
+ int i = isIfDef ? 5 : 6;
+ std::string restOfLine = GetRestOfLine(styler, sc.currentPos + i + 1, false);
+ bool foundDef = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end();
+ preproc.StartSection(isIfDef == foundDef);
+ } else if (sc.Match("else")) {
+ if (!preproc.CurrentIfTaken()) {
+ preproc.InvertCurrentLevel();
+ activitySet = preproc.IsInactive() ? activeFlag : 0;
+ if (!activitySet) {
+ sc.ChangeState(SCE_V_PREPROCESSOR|activitySet);
+ }
+ } else if (!preproc.IsInactive()) {
+ preproc.InvertCurrentLevel();
+ activitySet = preproc.IsInactive() ? activeFlag : 0;
+ if (!activitySet) {
+ sc.ChangeState(SCE_V_PREPROCESSOR|activitySet);
+ }
+ }
+ } else if (sc.Match("elsif")) {
+ // Ensure only one chosen out of `if .. `elsif .. `elsif .. `else .. `endif
+ if (!preproc.CurrentIfTaken()) {
+ // Similar to `ifdef
+ std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true);
+ bool ifGood = preprocessorDefinitions.find(restOfLine) != preprocessorDefinitions.end();
+ if (ifGood) {
+ preproc.InvertCurrentLevel();
+ activitySet = preproc.IsInactive() ? activeFlag : 0;
+ if (!activitySet)
+ sc.ChangeState(SCE_V_PREPROCESSOR|activitySet);
+ }
+ } else if (!preproc.IsInactive()) {
+ preproc.InvertCurrentLevel();
+ activitySet = preproc.IsInactive() ? activeFlag : 0;
+ if (!activitySet)
+ sc.ChangeState(SCE_V_PREPROCESSOR|activitySet);
+ }
+ } else if (sc.Match("endif")) {
+ preproc.EndSection();
+ activitySet = preproc.IsInactive() ? activeFlag : 0;
+ sc.ChangeState(SCE_V_PREPROCESSOR|activitySet);
+ } else if (sc.Match("define")) {
+ if (options.updatePreprocessor && !preproc.IsInactive()) {
+ std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 6, true);
+ size_t startName = 0;
+ while ((startName < restOfLine.length()) && IsSpaceOrTab(restOfLine[startName]))
+ startName++;
+ size_t endName = startName;
+ while ((endName < restOfLine.length()) && setWord.Contains(static_cast<unsigned char>(restOfLine[endName])))
+ endName++;
+ std::string key = restOfLine.substr(startName, endName-startName);
+ if ((endName < restOfLine.length()) && (restOfLine.at(endName) == '(')) {
+ // Macro
+ size_t endArgs = endName;
+ while ((endArgs < restOfLine.length()) && (restOfLine[endArgs] != ')'))
+ endArgs++;
+ std::string args = restOfLine.substr(endName + 1, endArgs - endName - 1);
+ size_t startValue = endArgs+1;
+ while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue]))
+ startValue++;
+ std::string value;
+ if (startValue < restOfLine.length())
+ value = restOfLine.substr(startValue);
+ preprocessorDefinitions[key] = SymbolValue(value, args);
+ ppDefineHistory.push_back(PPDefinition(curLine, key, value, false, args));
+ definitionsChanged = true;
+ } else {
+ // Value
+ size_t startValue = endName;
+ while ((startValue < restOfLine.length()) && IsSpaceOrTab(restOfLine[startValue]))
+ startValue++;
+ std::string value = restOfLine.substr(startValue);
+ preprocessorDefinitions[key] = value;
+ ppDefineHistory.push_back(PPDefinition(curLine, key, value));
+ definitionsChanged = true;
+ }
+ }
+ } else if (sc.Match("undefineall")) {
+ if (options.updatePreprocessor && !preproc.IsInactive()) {
+ // remove all preprocessor definitions
+ std::map<std::string, SymbolValue>::iterator itDef;
+ for(itDef = preprocessorDefinitions.begin(); itDef != preprocessorDefinitions.end(); ++itDef) {
+ ppDefineHistory.push_back(PPDefinition(curLine, itDef->first, "", true));
+ }
+ preprocessorDefinitions.clear();
+ definitionsChanged = true;
+ }
+ } else if (sc.Match("undef")) {
+ if (options.updatePreprocessor && !preproc.IsInactive()) {
+ std::string restOfLine = GetRestOfLine(styler, sc.currentPos + 5, true);
+ std::vector<std::string> tokens = Tokenize(restOfLine);
+ std::string key;
+ if (tokens.size() >= 1) {
+ key = tokens[0];
+ preprocessorDefinitions.erase(key);
+ ppDefineHistory.push_back(PPDefinition(curLine, key, "", true));
+ definitionsChanged = true;
+ }
+ }
+ }
+ }
}
} else if (isoperator(static_cast<char>(sc.ch)) || sc.ch == '@' || sc.ch == '#') {
- sc.SetState(SCE_V_OPERATOR);
+ sc.SetState(SCE_V_OPERATOR|activitySet);
+ if (sc.ch == '.') lineState = kwDot;
+ if (sc.ch == ';') lineState = kwOther;
}
}
}
+ if (definitionsChanged) {
+ styler.ChangeLexerState(startPos, startPos + length);
+ }
sc.Complete();
}
@@ -153,7 +730,7 @@ static bool IsStreamCommentStyle(int style) {
return style == SCE_V_COMMENT;
}
-static bool IsCommentLine(int line, Accessor &styler) {
+static bool IsCommentLine(int line, LexAccessor &styler) {
int pos = styler.LineStart(line);
int eolPos = styler.LineStart(line + 1) - 1;
for (int i = pos; i < eolPos; i++) {
@@ -169,22 +746,13 @@ static bool IsCommentLine(int line, Accessor &styler) {
}
return false;
}
+
// Store both the current line's fold level and the next lines in the
// level store to make it easy to pick up with each increment
// and to make it possible to fiddle the current level for "} else {".
-static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle,
- Accessor &styler) {
- bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
- bool foldPreprocessor = styler.GetPropertyInt("fold.preprocessor") != 0;
- bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
- bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) != 0;
- // Verilog specific folding options:
- // fold_at_module -
- // Generally used methodology in verilog code is
- // one module per file, so folding at module definition is useless.
- // fold_at_brace/parenthese -
- // Folding of long port lists can be convenient.
- bool foldAtModule = styler.GetPropertyInt("fold.verilog.flags", 0) != 0;
+void SCI_METHOD LexerVerilog::Fold(unsigned int startPos, int length, int initStyle, IDocument *pAccess)
+{
+ LexAccessor styler(pAccess);
bool foldAtBrace = 1;
bool foldAtParenthese = 1;
@@ -197,16 +765,16 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
int levelMinCurrent = levelCurrent;
int levelNext = levelCurrent;
char chNext = styler[startPos];
- int styleNext = styler.StyleAt(startPos);
- int style = initStyle;
+ int styleNext = MaskActive(styler.StyleAt(startPos));
+ int style = MaskActive(initStyle);
for (unsigned int i = startPos; i < endPos; i++) {
char ch = chNext;
chNext = styler.SafeGetCharAt(i + 1);
int stylePrev = style;
style = styleNext;
- styleNext = styler.StyleAt(i + 1);
+ styleNext = MaskActive(styler.StyleAt(i + 1));
bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
- if (foldComment && IsStreamCommentStyle(style)) {
+ if (options.foldComment && IsStreamCommentStyle(style)) {
if (!IsStreamCommentStyle(stylePrev)) {
levelNext++;
} else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
@@ -214,7 +782,7 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
levelNext--;
}
}
- if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
+ if (options.foldComment && atEOL && IsCommentLine(lineCurrent, styler))
{
if (!IsCommentLine(lineCurrent - 1, styler)
&& IsCommentLine(lineCurrent + 1, styler))
@@ -223,7 +791,7 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
&& !IsCommentLine(lineCurrent+1, styler))
levelNext--;
}
- if (foldComment && (style == SCE_V_COMMENTLINE)) {
+ if (options.foldComment && (style == SCE_V_COMMENTLINE)) {
if ((ch == '/') && (chNext == '/')) {
char chNext2 = styler.SafeGetCharAt(i + 2);
if (chNext2 == '{') {
@@ -233,7 +801,7 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
}
}
}
- if (foldPreprocessor && (style == SCE_V_PREPROCESSOR)) {
+ if (options.foldPreprocessor && (style == SCE_V_PREPROCESSOR)) {
if (ch == '`') {
unsigned int j = i + 1;
while ((j < endPos) && IsASpaceOrTab(styler.SafeGetCharAt(j))) {
@@ -246,71 +814,71 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
}
}
}
- if (style == SCE_V_OPERATOR) {
- if (foldAtParenthese) {
- if (ch == '(') {
- levelNext++;
- } else if (ch == ')') {
- levelNext--;
+ if (style == SCE_V_OPERATOR) {
+ if (foldAtParenthese) {
+ if (ch == '(') {
+ levelNext++;
+ } else if (ch == ')') {
+ levelNext--;
+ }
}
- }
}
- if (style == SCE_V_OPERATOR) {
- if (foldAtBrace) {
- if (ch == '{') {
+ if (style == SCE_V_OPERATOR) {
+ if (foldAtBrace) {
+ if (ch == '{') {
+ levelNext++;
+ } else if (ch == '}') {
+ levelNext--;
+ }
+ }
+ }
+ if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) {
+ unsigned int j = i;
+ if (styler.Match(j, "case") ||
+ styler.Match(j, "casex") ||
+ styler.Match(j, "casez") ||
+ styler.Match(j, "class") ||
+ styler.Match(j, "function") ||
+ styler.Match(j, "generate") ||
+ styler.Match(j, "covergroup") ||
+ styler.Match(j, "package") ||
+ styler.Match(j, "primitive") ||
+ styler.Match(j, "program") ||
+ styler.Match(j, "sequence") ||
+ styler.Match(j, "specify") ||
+ styler.Match(j, "table") ||
+ styler.Match(j, "task") ||
+ styler.Match(j, "fork") ||
+ (styler.Match(j, "module") && options.foldAtModule) ||
+ styler.Match(j, "begin")) {
levelNext++;
- } else if (ch == '}') {
+ } else if (styler.Match(j, "endcase") ||
+ styler.Match(j, "endclass") ||
+ styler.Match(j, "endfunction") ||
+ styler.Match(j, "endgenerate") ||
+ styler.Match(j, "endgroup") ||
+ styler.Match(j, "endpackage") ||
+ styler.Match(j, "endprimitive") ||
+ styler.Match(j, "endprogram") ||
+ styler.Match(j, "endsequence") ||
+ styler.Match(j, "endspecify") ||
+ styler.Match(j, "endtable") ||
+ styler.Match(j, "endtask") ||
+ styler.Match(j, "join") ||
+ styler.Match(j, "join_any") ||
+ styler.Match(j, "join_none") ||
+ (styler.Match(j, "endmodule") && options.foldAtModule) ||
+ (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j + 3)))) {
levelNext--;
}
- }
- }
- if (style == SCE_V_WORD && stylePrev != SCE_V_WORD) {
- unsigned int j = i;
- if (styler.Match(j, "case") ||
- styler.Match(j, "casex") ||
- styler.Match(j, "casez") ||
- styler.Match(j, "class") ||
- styler.Match(j, "function") ||
- styler.Match(j, "generate") ||
- styler.Match(j, "covergroup") ||
- styler.Match(j, "package") ||
- styler.Match(j, "primitive") ||
- styler.Match(j, "program") ||
- styler.Match(j, "sequence") ||
- styler.Match(j, "specify") ||
- styler.Match(j, "table") ||
- styler.Match(j, "task") ||
- styler.Match(j, "fork") ||
- (styler.Match(j, "module") && foldAtModule) ||
- styler.Match(j, "begin")) {
- levelNext++;
- } else if (styler.Match(j, "endcase") ||
- styler.Match(j, "endclass") ||
- styler.Match(j, "endfunction") ||
- styler.Match(j, "endgenerate") ||
- styler.Match(j, "endgroup") ||
- styler.Match(j, "endpackage") ||
- styler.Match(j, "endprimitive") ||
- styler.Match(j, "endprogram") ||
- styler.Match(j, "endsequence") ||
- styler.Match(j, "endspecify") ||
- styler.Match(j, "endtable") ||
- styler.Match(j, "endtask") ||
- styler.Match(j, "join") ||
- styler.Match(j, "join_any") ||
- styler.Match(j, "join_none") ||
- (styler.Match(j, "endmodule") && foldAtModule) ||
- (styler.Match(j, "end") && !IsAWordChar(styler.SafeGetCharAt(j+3)))) {
- levelNext--;
- }
}
if (atEOL) {
int levelUse = levelCurrent;
- if (foldAtElse) {
+ if (options.foldAtElse) {
levelUse = levelMinCurrent;
}
int lev = levelUse | levelNext << 16;
- if (visibleChars == 0 && foldCompact)
+ if (visibleChars == 0 && options.foldCompact)
lev |= SC_FOLDLEVELWHITEFLAG;
if (levelUse < levelNext)
lev |= SC_FOLDLEVELHEADERFLAG;
@@ -327,9 +895,31 @@ static void FoldNoBoxVerilogDoc(unsigned int startPos, int length, int initStyle
}
}
-static void FoldVerilogDoc(unsigned int startPos, int length, int initStyle, WordList *[],
- Accessor &styler) {
- FoldNoBoxVerilogDoc(startPos, length, initStyle, styler);
+std::vector<std::string> LexerVerilog::Tokenize(const std::string &expr) const {
+ // Break into tokens
+ std::vector<std::string> tokens;
+ const char *cp = expr.c_str();
+ while (*cp) {
+ std::string word;
+ if (setWord.Contains(static_cast<unsigned char>(*cp))) {
+ // Identifiers and numbers
+ while (setWord.Contains(static_cast<unsigned char>(*cp))) {
+ word += *cp;
+ cp++;
+ }
+ } else if (IsSpaceOrTab(*cp)) {
+ while (IsSpaceOrTab(*cp)) {
+ cp++;
+ }
+ continue;
+ } else {
+ // Should handle strings, characters, and comments here
+ word += *cp;
+ cp++;
+ }
+ tokens.push_back(word);
+ }
+ return tokens;
}
static const char * const verilogWordLists[] = {
@@ -337,9 +927,9 @@ static const char * const verilogWordLists[] = {
"Secondary keywords and identifiers",
"System Tasks",
"User defined tasks and identifiers",
- "Unused",
+ "Documentation comment keywords",
+ "Preprocessor definitions",
0,
};
-
-LexerModule lmVerilog(SCLEX_VERILOG, ColouriseVerilogDoc, "verilog", FoldVerilogDoc, verilogWordLists);
+LexerModule lmVerilog(SCLEX_VERILOG, LexerVerilog::LexerFactoryVerilog, "verilog", verilogWordLists);
diff --git a/scintilla/lexlib/LexAccessor.h b/scintilla/lexlib/LexAccessor.h
index 248f1c5..ba4a0e2 100644
--- a/scintilla/lexlib/LexAccessor.h
+++ b/scintilla/lexlib/LexAccessor.h
@@ -58,6 +58,9 @@ public:
validLen(0),
startSeg(0), startPosStyling(0),
documentVersion(pAccess->Version()) {
+ // Prevent warnings by static analyzers about uninitialized buf and styleBuf.
+ buf[0] = 0;
+ styleBuf[0] = 0;
switch (codePage) {
case 65001:
encodingType = encUnicode;
diff --git a/scintilla/lexlib/WordList.cxx b/scintilla/lexlib/WordList.cxx
index ce94b52..7ac00ad 100644
--- a/scintilla/lexlib/WordList.cxx
+++ b/scintilla/lexlib/WordList.cxx
@@ -69,6 +69,8 @@ static char **ArrayFromWordList(char *wordlist, int *len, bool onlyLineEnds = fa
WordList::WordList(bool onlyLineEnds_) :
words(0), list(0), len(0), onlyLineEnds(onlyLineEnds_) {
+ // Prevent warnings by static analyzers about uninitialized starts.
+ starts[0] = -1;
}
WordList::~WordList() {
diff --git a/scintilla/scripts/HeaderOrder.txt b/scintilla/scripts/HeaderOrder.txt
index e9c88bb..4ab980c 100644
--- a/scintilla/scripts/HeaderOrder.txt
+++ b/scintilla/scripts/HeaderOrder.txt
@@ -20,6 +20,7 @@
#include <cstring>
#include <cctype>
#include <cstdio>
+#include <cmath>
// C++ standard library
#include <stdexcept>
diff --git a/scintilla/src/Catalogue.cxx b/scintilla/src/Catalogue.cxx
index 2d556cc..198aa22 100644
--- a/scintilla/src/Catalogue.cxx
+++ b/scintilla/src/Catalogue.cxx
@@ -124,6 +124,7 @@ int Scintilla_LinkLexers() {
//LINK_LEXER(lmGui4Cli);
//LINK_LEXER(lmHaskell);
LINK_LEXER(lmHTML);
+ //LINK_LEXER(lmIHex);
LINK_LEXER(lmInno);
//LINK_LEXER(lmKix);
//LINK_LEXER(lmKVIrc);
@@ -175,12 +176,14 @@ int Scintilla_LinkLexers() {
//LINK_LEXER(lmSpecman);
//LINK_LEXER(lmSpice);
LINK_LEXER(lmSQL);
+ //LINK_LEXER(lmSrec);
//LINK_LEXER(lmSTTXT);
//LINK_LEXER(lmTACL);
//LINK_LEXER(lmTADS3);
//LINK_LEXER(lmTAL);
LINK_LEXER(lmTCL);
//LINK_LEXER(lmTCMD);
+ //LINK_LEXER(lmTEHex);
//LINK_LEXER(lmTeX);
//LINK_LEXER(lmTxt2tags);
LINK_LEXER(lmVB);
diff --git a/scintilla/src/Document.cxx b/scintilla/src/Document.cxx
index 8bb1b7a..1770657 100644
--- a/scintilla/src/Document.cxx
+++ b/scintilla/src/Document.cxx
@@ -37,6 +37,7 @@
#include "Document.h"
#include "RESearch.h"
#include "UniConversion.h"
+#include "UnicodeFromUTF8.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
@@ -766,19 +767,6 @@ bool Document::NextCharacter(int &pos, int moveDir) const {
}
}
-static inline int UnicodeFromBytes(const unsigned char *us) {
- if (us[0] < 0xC2) {
- return us[0];
- } else if (us[0] < 0xE0) {
- return ((us[0] & 0x1F) << 6) + (us[1] & 0x3F);
- } else if (us[0] < 0xF0) {
- return ((us[0] & 0xF) << 12) + ((us[1] & 0x3F) << 6) + (us[2] & 0x3F);
- } else if (us[0] < 0xF5) {
- return ((us[0] & 0x7) << 18) + ((us[1] & 0x3F) << 12) + ((us[2] & 0x3F) << 6) + (us[3] & 0x3F);
- }
- return us[0];
-}
-
// Return -1 on out-of-bounds
int SCI_METHOD Document::GetRelativePosition(int positionStart, int characterOffset) const {
int pos = positionStart;
@@ -819,7 +807,7 @@ int SCI_METHOD Document::GetCharacterAndWidth(int position, int *pWidth) const {
character = 0xDC80 + leadByte;
} else {
bytesInCharacter = utf8status & UTF8MaskWidth;
- character = UnicodeFromBytes(charBytes);
+ character = UnicodeFromUTF8(charBytes);
}
}
} else {
@@ -1610,7 +1598,7 @@ Document::CharacterExtracted Document::ExtractCharacter(int position) const {
// Treat as invalid and use up just one byte
return CharacterExtracted(unicodeReplacementChar, 1);
} else {
- return CharacterExtracted(UnicodeFromBytes(charBytes), utf8status & UTF8MaskWidth);
+ return CharacterExtracted(UnicodeFromUTF8(charBytes), utf8status & UTF8MaskWidth);
}
}
diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx
index 3a8b2fa..99119a6 100644
--- a/scintilla/src/Editor.cxx
+++ b/scintilla/src/Editor.cxx
@@ -8,10 +8,10 @@
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
-#include <math.h>
#include <assert.h>
#include <ctype.h>
+#include <cmath>
#include <stdexcept>
#include <string>
#include <vector>
@@ -1333,7 +1333,9 @@ void Editor::ShowCaretAtCurrentPosition() {
void Editor::DropCaret() {
caret.active = false;
- FineTickerCancel(tickCaret);
+ if (FineTickerAvailable()) {
+ FineTickerCancel(tickCaret);
+ }
InvalidateCaret();
}
@@ -1898,6 +1900,13 @@ void Editor::AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS) {
}
}
+void Editor::FillVirtualSpace() {
+ const bool tmpOverstrike = inOverstrike;
+ inOverstrike = false; // not allow to be deleted twice.
+ AddCharUTF("", 0);
+ inOverstrike = tmpOverstrike;
+}
+
void Editor::InsertPaste(const char *text, int len) {
if (multiPasteMode == SC_MULTIPASTE_ONCE) {
SelectionPosition selStart = sel.Start();
@@ -3283,7 +3292,6 @@ int Editor::KeyCommand(unsigned int iMessage) {
break;
case SCI_EDITTOGGLEOVERTYPE:
inOverstrike = !inOverstrike;
- DropCaret();
ShowCaretAtCurrentPosition();
ContainerNeedsUpdate(SC_UPDATE_CONTENT);
NotifyUpdateUI();
@@ -3795,9 +3803,9 @@ void Editor::GoToLine(int lineNo) {
}
static bool Close(Point pt1, Point pt2, Point threshold) {
- if (abs(pt1.x - pt2.x) > threshold.x)
+ if (std::abs(pt1.x - pt2.x) > threshold.x)
return false;
- if (abs(pt1.y - pt2.y) > threshold.y)
+ if (std::abs(pt1.y - pt2.y) > threshold.y)
return false;
return true;
}
@@ -4016,7 +4024,7 @@ bool Editor::PointInSelMargin(Point pt) const {
PRectangle rcSelMargin = GetClientRectangle();
rcSelMargin.right = static_cast<XYPOSITION>(vs.textStart - vs.leftMarginWidth);
rcSelMargin.left = static_cast<XYPOSITION>(vs.textStart - vs.fixedColumnWidth);
- return rcSelMargin.Contains(pt);
+ return rcSelMargin.ContainsWholePixel(pt);
} else {
return false;
}
@@ -4687,12 +4695,10 @@ void Editor::FineTickerCancel(TickReason) {
void Editor::SetFocusState(bool focusState) {
hasFocus = focusState;
NotifyFocus(hasFocus);
- if (hasFocus) {
- ShowCaretAtCurrentPosition();
- } else {
+ if (!hasFocus) {
CancelModes();
- DropCaret();
}
+ ShowCaretAtCurrentPosition();
}
int Editor::PositionAfterArea(PRectangle rcArea) const {
diff --git a/scintilla/src/Editor.h b/scintilla/src/Editor.h
index 132204a..d65d0b8 100644
--- a/scintilla/src/Editor.h
+++ b/scintilla/src/Editor.h
@@ -388,6 +388,7 @@ protected: // ScintillaBase subclass needs access to much of Editor
int InsertSpace(int position, unsigned int spaces);
void AddChar(char ch);
virtual void AddCharUTF(const char *s, unsigned int len, bool treatAsDBCS=false);
+ void FillVirtualSpace();
void InsertPaste(const char *text, int len);
enum PasteShape { pasteStream=0, pasteRectangular = 1, pasteLine = 2 };
void InsertPasteShape(const char *text, int len, PasteShape shape);
diff --git a/scintilla/src/MarginView.cxx b/scintilla/src/MarginView.cxx
index b7ef485..a6fc1f4 100644
--- a/scintilla/src/MarginView.cxx
+++ b/scintilla/src/MarginView.cxx
@@ -263,8 +263,10 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect
PLATFORM_ASSERT(visibleLine < model.cs.LinesDisplayed());
const int lineDoc = model.cs.DocFromDisplay(visibleLine);
PLATFORM_ASSERT(model.cs.GetVisible(lineDoc));
- const bool firstSubLine = visibleLine == model.cs.DisplayFromDoc(lineDoc);
- const bool lastSubLine = visibleLine == model.cs.DisplayLastFromDoc(lineDoc);
+ const int firstVisibleLine = model.cs.DisplayFromDoc(lineDoc);
+ const int lastVisibleLine = model.cs.DisplayLastFromDoc(lineDoc);
+ const bool firstSubLine = visibleLine == firstVisibleLine;
+ const bool lastSubLine = visibleLine == lastVisibleLine;
int marks = model.pdoc->GetMark(lineDoc);
if (!firstSubLine)
@@ -403,9 +405,9 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect
}
}
} else if (vs.ms[margin].style == SC_MARGIN_TEXT || vs.ms[margin].style == SC_MARGIN_RTEXT) {
- if (firstSubLine) {
- const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc);
- if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
+ const StyledText stMargin = model.pdoc->MarginStyledText(lineDoc);
+ if (stMargin.text && ValidStyledText(vs, vs.marginStyleOffset, stMargin)) {
+ if (firstSubLine) {
surface->FillRectangle(rcMarker,
vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
if (vs.ms[margin].style == SC_MARGIN_RTEXT) {
@@ -414,6 +416,12 @@ void MarginView::PaintMargin(Surface *surface, int topLine, PRectangle rc, PRect
}
DrawStyledText(surface, vs, vs.marginStyleOffset, rcMarker,
stMargin, 0, stMargin.length, drawAll);
+ } else {
+ // if we're displaying annotation lines, color the margin to match the associated document line
+ const int annotationLines = model.pdoc->AnnotationLines(lineDoc);
+ if (annotationLines && (visibleLine > lastVisibleLine - annotationLines)) {
+ surface->FillRectangle(rcMarker, vs.styles[stMargin.StyleAt(0) + vs.marginStyleOffset].back);
+ }
}
}
}
diff --git a/scintilla/src/ScintillaBase.cxx b/scintilla/src/ScintillaBase.cxx
index 516a559..906f764 100644
--- a/scintilla/src/ScintillaBase.cxx
+++ b/scintilla/src/ScintillaBase.cxx
@@ -449,12 +449,12 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) {
PRectangle rcClient = GetClientRectangle();
int offset = vs.lineHeight + static_cast<int>(rc.Height());
// adjust so it displays above the text.
- if (rc.bottom > rcClient.bottom) {
+ if (rc.bottom > rcClient.bottom && rc.Height() < rcClient.Height()) {
rc.top -= offset;
rc.bottom -= offset;
}
// adjust so it displays below the text.
- if (rc.top < rcClient.top) {
+ if (rc.top < rcClient.top && rc.Height() < rcClient.Height()) {
rc.top += offset;
rc.bottom += offset;
}
diff --git a/scintilla/src/UniConversion.cxx b/scintilla/src/UniConversion.cxx
index 58651bc..f261d12 100644
--- a/scintilla/src/UniConversion.cxx
+++ b/scintilla/src/UniConversion.cxx
@@ -82,10 +82,10 @@ unsigned int UTF8CharLength(unsigned char ch) {
}
}
-unsigned int UTF16Length(const char *s, unsigned int len) {
- unsigned int ulen = 0;
- unsigned int charLen;
- for (unsigned int i=0; i<len;) {
+size_t UTF16Length(const char *s, size_t len) {
+ size_t ulen = 0;
+ size_t charLen;
+ for (size_t i = 0; i<len;) {
unsigned char ch = static_cast<unsigned char>(s[i]);
if (ch < 0x80) {
charLen = 1;
@@ -103,10 +103,10 @@ unsigned int UTF16Length(const char *s, unsigned int len) {
return ulen;
}
-unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen) {
- unsigned int ui=0;
+size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen) {
+ size_t ui = 0;
const unsigned char *us = reinterpret_cast<const unsigned char *>(s);
- unsigned int i=0;
+ size_t i = 0;
while ((i<len) && (ui<tlen)) {
unsigned char ch = us[i++];
if (ch < 0x80) {
diff --git a/scintilla/src/UniConversion.h b/scintilla/src/UniConversion.h
index 9b302b1..23dcc17 100644
--- a/scintilla/src/UniConversion.h
+++ b/scintilla/src/UniConversion.h
@@ -19,8 +19,8 @@ const int unicodeReplacementChar = 0xFFFD;
unsigned int UTF8Length(const wchar_t *uptr, unsigned int tlen);
void UTF8FromUTF16(const wchar_t *uptr, unsigned int tlen, char *putf, unsigned int len);
unsigned int UTF8CharLength(unsigned char ch);
-unsigned int UTF16Length(const char *s, unsigned int len);
-unsigned int UTF16FromUTF8(const char *s, unsigned int len, wchar_t *tbuf, unsigned int tlen);
+size_t UTF16Length(const char *s, size_t len);
+size_t UTF16FromUTF8(const char *s, size_t len, wchar_t *tbuf, size_t tlen);
unsigned int UTF32FromUTF8(const char *s, unsigned int len, unsigned int *tbuf, unsigned int tlen);
unsigned int UTF16FromUTF32Character(unsigned int val, wchar_t *tbuf);
diff --git a/scintilla/version.txt b/scintilla/version.txt
index e64cbb7..8f3487f 100644
--- a/scintilla/version.txt
+++ b/scintilla/version.txt
@@ -1 +1 @@
-352
+353
diff --git a/scintilla/win32/PlatWin.cxx b/scintilla/win32/PlatWin.cxx
index 84cdca0..c5dd835 100644
--- a/scintilla/win32/PlatWin.cxx
+++ b/scintilla/win32/PlatWin.cxx
@@ -67,7 +67,6 @@ typedef BOOL (WINAPI *GetMonitorInfoSig)(HMONITOR, LPMONITORINFO);
static CRITICAL_SECTION crPlatformLock;
static HINSTANCE hinstPlatformRes = 0;
-static bool onNT = false;
static HMODULE hDLLImage = 0;
static AlphaBlendSig AlphaBlendFn = 0;
@@ -83,10 +82,6 @@ static HCURSOR reverseArrowCursor = NULL;
namespace Scintilla {
#endif
-bool IsNT() {
- return onNT;
-}
-
Point Point::FromLong(long lpoint) {
return Point(static_cast<short>(LOWORD(lpoint)), static_cast<short>(HIWORD(lpoint)));
}
@@ -139,16 +134,17 @@ bool LoadD2D() {
HRESULT hr = pIDWriteFactory->CreateRenderingParams(&defaultRenderingParams);
if (SUCCEEDED(hr)) {
unsigned int clearTypeContrast;
- ::SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &clearTypeContrast, 0);
+ if (::SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &clearTypeContrast, 0)) {
- FLOAT gamma;
- if (clearTypeContrast >= 1000 && clearTypeContrast <= 2200)
- gamma = static_cast<FLOAT>(clearTypeContrast) / 1000.0f;
- else
- gamma = defaultRenderingParams->GetGamma();
+ FLOAT gamma;
+ if (clearTypeContrast >= 1000 && clearTypeContrast <= 2200)
+ gamma = static_cast<FLOAT>(clearTypeContrast) / 1000.0f;
+ else
+ gamma = defaultRenderingParams->GetGamma();
- pIDWriteFactory->CreateCustomRenderingParams(gamma, defaultRenderingParams->GetEnhancedContrast(), defaultRenderingParams->GetClearTypeLevel(),
- defaultRenderingParams->GetPixelGeometry(), defaultRenderingParams->GetRenderingMode(), &customClearTypeRenderingParams);
+ pIDWriteFactory->CreateCustomRenderingParams(gamma, defaultRenderingParams->GetEnhancedContrast(), defaultRenderingParams->GetClearTypeLevel(),
+ defaultRenderingParams->GetPixelGeometry(), defaultRenderingParams->GetRenderingMode(), &customClearTypeRenderingParams);
+ }
}
}
@@ -274,15 +270,15 @@ static D2D1_TEXT_ANTIALIAS_MODE DWriteMapFontQuality(int extraFontFlag) {
}
#endif
-static void SetLogFont(LOGFONTA &lf, const char *faceName, int characterSet, float size, int weight, bool italic, int extraFontFlag) {
- lf = LOGFONTA();
+static void SetLogFont(LOGFONTW &lf, const char *faceName, int characterSet, float size, int weight, bool italic, int extraFontFlag) {
+ lf = LOGFONTW();
// The negative is to allow for leading
lf.lfHeight = -(abs(static_cast<int>(size + 0.5)));
lf.lfWeight = weight;
lf.lfItalic = static_cast<BYTE>(italic ? 1 : 0);
lf.lfCharSet = static_cast<BYTE>(characterSet);
lf.lfQuality = Win32MapFontQuality(extraFontFlag);
- StringCopy(lf.lfFaceName, faceName);
+ UTF16FromUTF8(faceName, strlen(faceName)+1, lf.lfFaceName, LF_FACESIZE);
}
/**
@@ -305,7 +301,7 @@ class FontCached : Font {
FontCached *next;
int usage;
float size;
- LOGFONTA lf;
+ LOGFONTW lf;
int technology;
int hash;
explicit FontCached(const FontParameters &fp);
@@ -328,14 +324,14 @@ FontCached::FontCached(const FontParameters &fp) :
hash = HashFont(fp);
fid = 0;
if (technology == SCWIN_TECH_GDI) {
- HFONT hfont = ::CreateFontIndirectA(&lf);
+ HFONT hfont = ::CreateFontIndirectW(&lf);
fid = reinterpret_cast<void *>(new FormatAndMetrics(hfont, fp.extraFontFlag, fp.characterSet));
} else {
#if defined(USE_D2D)
IDWriteTextFormat *pTextFormat;
const int faceSize = 200;
WCHAR wszFace[faceSize];
- UTF16FromUTF8(fp.faceName, static_cast<unsigned int>(strlen(fp.faceName))+1, wszFace, faceSize);
+ UTF16FromUTF8(fp.faceName, strlen(fp.faceName)+1, wszFace, faceSize);
FLOAT fHeight = fp.size;
DWRITE_FONT_STYLE style = fp.italic ? DWRITE_FONT_STYLE_ITALIC : DWRITE_FONT_STYLE_NORMAL;
HRESULT hr = pIDWriteFactory->CreateTextFormat(wszFace, NULL,
@@ -377,14 +373,18 @@ FontCached::FontCached(const FontParameters &fp) :
}
bool FontCached::SameAs(const FontParameters &fp) {
- return
+ if (
(size == fp.size) &&
(lf.lfWeight == fp.weight) &&
(lf.lfItalic == static_cast<BYTE>(fp.italic ? 1 : 0)) &&
(lf.lfCharSet == fp.characterSet) &&
(lf.lfQuality == Win32MapFontQuality(fp.extraFontFlag)) &&
- (technology == fp.technology) &&
- 0 == strcmp(lf.lfFaceName,fp.faceName);
+ (technology == fp.technology)) {
+ wchar_t wszFace[LF_FACESIZE];
+ UTF16FromUTF8(fp.faceName, strlen(fp.faceName)+1, wszFace, LF_FACESIZE);
+ return 0 == wcscmp(lf.lfFaceName,wszFace);
+ }
+ return false;
}
void FontCached::Release() {
@@ -486,7 +486,7 @@ public:
TextWide(const char *s, int len, bool unicodeMode, int codePage=0) :
VarBuffer<wchar_t, stackBufferLength>(len) {
if (unicodeMode) {
- tlen = UTF16FromUTF8(s, len, buffer, len);
+ tlen = static_cast<int>(UTF16FromUTF8(s, len, buffer, len));
} else {
// Support Asian string display in 9x English
tlen = ::MultiByteToWideChar(codePage, 0, s, len, buffer, len);
@@ -511,8 +511,6 @@ class SurfaceGDI : public Surface {
int maxLenText;
int codePage;
- // If 9x OS and current code page is same as ANSI code page.
- bool win9xACPSame;
void BrushColor(ColourDesired back);
void SetFont(Font &font_);
@@ -574,14 +572,11 @@ SurfaceGDI::SurfaceGDI() :
brush(0), brushOld(0),
font(0), fontOld(0),
bitmap(0), bitmapOld(0) {
- // Windows 9x has only a 16 bit coordinate system so break after 30000 pixels
- maxWidthMeasure = IsNT() ? INT_MAX : 30000;
- // There appears to be a 16 bit string length limit in GDI on NT and a limit of
- // 8192 characters on Windows 95.
- maxLenText = IsNT() ? 65535 : 8192;
+ maxWidthMeasure = INT_MAX;
+ // There appears to be a 16 bit string length limit in GDI on NT.
+ maxLenText = 65535;
codePage = 0;
- win9xACPSame = false;
}
SurfaceGDI::~SurfaceGDI() {
@@ -905,7 +900,7 @@ void SurfaceGDI::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, co
// If it does fail, slice up into segments and draw each segment.
const int maxSegmentLength = 0x200;
- if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) {
+ if (!unicodeMode) {
// Use ANSI calls
int lenDraw = Platform::Minimum(len, maxLenText);
if (!::ExtTextOutA(hdc, x, yBaseInt, fuOptions, &rcw, s, lenDraw, NULL)) {
@@ -969,7 +964,7 @@ void SurfaceGDI::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybas
XYPOSITION SurfaceGDI::WidthText(Font &font_, const char *s, int len) {
SetFont(font_);
SIZE sz={0,0};
- if ((!unicodeMode) && (IsNT() || (codePage==0) || win9xACPSame)) {
+ if (!unicodeMode) {
::GetTextExtentPoint32A(hdc, s, Platform::Minimum(len, maxLenText), &sz);
} else {
const TextWide tbuf(s, len, unicodeMode, codePage);
@@ -1021,7 +1016,7 @@ void SurfaceGDI::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *
while (i<len) {
positions[i++] = lastPos;
}
- } else if (IsNT() || (codePage==0) || win9xACPSame) {
+ } else {
// Zero positions to avoid random behaviour on failure.
std::fill(positions, positions + len, 0.0f);
// len may be larger than platform supports so loop over segments small enough for platform
@@ -1047,28 +1042,6 @@ void SurfaceGDI::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *
positions += lenBlock;
s += lenBlock;
}
- } else {
- // Support Asian string display in 9x English
- const TextWide tbuf(s, len, unicodeMode, codePage);
- TextPositionsI poses(tbuf.tlen);
- for (int widthSS=0; widthSS<tbuf.tlen; widthSS++) {
- ::GetTextExtentPoint32W(hdc, tbuf.buffer, widthSS+1, &sz);
- poses.buffer[widthSS] = sz.cx;
- }
-
- int ui = 0;
- for (int i=0; i<len;) {
- if (Platform::IsDBCSLeadByte(codePage, s[i])) {
- positions[i] = static_cast<XYPOSITION>(poses.buffer[ui]);
- positions[i + 1] = static_cast<XYPOSITION>(poses.buffer[ui]);
- i += 2;
- } else {
- positions[i] = static_cast<XYPOSITION>(poses.buffer[ui]);
- i++;
- }
-
- ui++;
- }
}
}
@@ -1139,7 +1112,6 @@ void SurfaceGDI::SetUnicodeMode(bool unicodeMode_) {
void SurfaceGDI::SetDBCSMode(int codePage_) {
// No action on window as automatically handled by system.
codePage = codePage_;
- win9xACPSame = !IsNT() && ((unsigned int)codePage == ::GetACP());
}
#if defined(USE_D2D)
@@ -3254,9 +3226,6 @@ int Platform::Clamp(int val, int minVal, int maxVal) {
#endif
void Platform_Initialise(void *hInstance) {
- OSVERSIONINFO osv = {sizeof(OSVERSIONINFO),0,0,0,0,TEXT("")};
- ::GetVersionEx(&osv);
- onNT = osv.dwPlatformId == VER_PLATFORM_WIN32_NT;
::InitializeCriticalSection(&crPlatformLock);
hinstPlatformRes = reinterpret_cast<HINSTANCE>(hInstance);
// This may be called from DllMain, in which case the call to LoadLibrary
diff --git a/scintilla/win32/PlatWin.h b/scintilla/win32/PlatWin.h
index c93df4d..417c656 100644
--- a/scintilla/win32/PlatWin.h
+++ b/scintilla/win32/PlatWin.h
@@ -12,7 +12,6 @@
namespace Scintilla {
#endif
-extern bool IsNT();
extern void Platform_Initialise(void *hInstance);
extern void Platform_Finalise(bool fromDllMain);
diff --git a/scintilla/win32/ScintillaWin.cxx b/scintilla/win32/ScintillaWin.cxx
index 4eec5b4..211b8d4 100644
--- a/scintilla/win32/ScintillaWin.cxx
+++ b/scintilla/win32/ScintillaWin.cxx
@@ -103,6 +103,11 @@
#define SC_WIN_IDLE 5001
+#define SC_INDICATOR_INPUT INDIC_IME
+#define SC_INDICATOR_TARGET INDIC_IME+1
+#define SC_INDICATOR_CONVERTED INDIC_IME+2
+#define SC_INDICATOR_UNKNOWN INDIC_IME_MAX
+
typedef BOOL (WINAPI *TrackMouseEventSig)(LPTRACKMOUSEEVENT);
typedef UINT_PTR (WINAPI *SetCoalescableTimerSig)(HWND hwnd, UINT_PTR nIDEvent,
UINT uElapse, TIMERPROC lpTimerFunc, ULONG uToleranceDelay);
@@ -239,9 +244,14 @@ class ScintillaWin :
virtual bool DragThreshold(Point ptStart, Point ptNow);
virtual void StartDrag();
sptr_t WndPaint(uptr_t wParam);
- sptr_t HandleComposition(uptr_t wParam, sptr_t lParam);
+
+ sptr_t HandleCompositionWindowed(uptr_t wParam, sptr_t lParam);
+ sptr_t HandleCompositionInline(uptr_t wParam, sptr_t lParam);
static bool KoreanIME();
- sptr_t HandleCompositionKoreanIME(uptr_t wParam, sptr_t lParam);
+ void MoveImeCarets(int offset);
+ void DrawImeIndicator(int indicator, int len);
+ void SetCandidateWindowPos();
+
UINT CodePageOfDocument();
virtual bool ValidCodePage(int codePage) const;
virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam);
@@ -422,6 +432,10 @@ void ScintillaWin::Initialise() {
for (TickReason tr = tickCaret; tr <= tickDwell; tr = static_cast<TickReason>(tr + 1)) {
timers[tr] = 0;
}
+ vs.indicators[SC_INDICATOR_UNKNOWN] = Indicator(INDIC_HIDDEN, ColourDesired(0, 0, 0xff));
+ vs.indicators[SC_INDICATOR_INPUT] = Indicator(INDIC_DOTS, ColourDesired(0, 0, 0xff));
+ vs.indicators[SC_INDICATOR_CONVERTED] = Indicator(INDIC_COMPOSITIONTHICK, ColourDesired(0, 0, 0xff));
+ vs.indicators[SC_INDICATOR_TARGET] = Indicator(INDIC_STRAIGHTBOX, ColourDesired(0, 0, 0xff));
}
void ScintillaWin::Finalise() {
@@ -471,10 +485,12 @@ void ScintillaWin::EnsureRenderTarget(HDC hdc) {
ID2D1DCRenderTarget *pDCRT = NULL;
HRESULT hr = pD2DFactory->CreateDCRenderTarget(&drtp, &pDCRT);
- if (FAILED(hr)) {
+ if (SUCCEEDED(hr)) {
+ pRenderTarget = pDCRT;
+ } else {
Platform::DebugPrintf("Failed CreateDCRenderTarget 0x%x\n", hr);
+ pRenderTarget = NULL;
}
- pRenderTarget = pDCRT;
} else {
D2D1_HWND_RENDER_TARGET_PROPERTIES dhrtp;
@@ -485,10 +501,12 @@ void ScintillaWin::EnsureRenderTarget(HDC hdc) {
ID2D1HwndRenderTarget *pHwndRenderTarget = NULL;
HRESULT hr = pD2DFactory->CreateHwndRenderTarget(drtp, dhrtp, &pHwndRenderTarget);
- if (FAILED(hr)) {
+ if (SUCCEEDED(hr)) {
+ pRenderTarget = pHwndRenderTarget;
+ } else {
Platform::DebugPrintf("Failed CreateHwndRenderTarget 0x%x\n", hr);
+ pRenderTarget = NULL;
}
- pRenderTarget = pHwndRenderTarget;
}
#else
pD2DFactory->CreateHwndRenderTarget(
@@ -504,7 +522,7 @@ void ScintillaWin::EnsureRenderTarget(HDC hdc) {
DropGraphics(false);
}
- if (technology == SC_TECHNOLOGY_DIRECTWRITEDC) {
+ if ((technology == SC_TECHNOLOGY_DIRECTWRITEDC) && pRenderTarget) {
RECT rcWindow;
GetClientRect(MainHWND(), &rcWindow);
HRESULT hr = static_cast<ID2D1DCRenderTarget*>(pRenderTarget)->BindDC(hdc, &rcWindow);
@@ -705,7 +723,7 @@ LRESULT ScintillaWin::WndPaint(uptr_t wParam) {
return 0l;
}
-sptr_t ScintillaWin::HandleComposition(uptr_t wParam, sptr_t lParam) {
+sptr_t ScintillaWin::HandleCompositionWindowed(uptr_t wParam, sptr_t lParam) {
if (lParam & GCS_RESULTSTR) {
HIMC hIMC = ::ImmGetContext(MainHWND());
if (hIMC) {
@@ -746,89 +764,167 @@ bool ScintillaWin::KoreanIME() {
return codePage == 949 || codePage == 1361;
}
-sptr_t ScintillaWin::HandleCompositionKoreanIME(uptr_t, sptr_t lParam) {
+void ScintillaWin::MoveImeCarets(int offset) {
+ // Move carets relatively by bytes.
+ for (size_t r=0; r<sel.Count(); r++) {
+ int positionInsert = sel.Range(r).Start().Position();
+ sel.Range(r).caret.SetPosition(positionInsert + offset);
+ sel.Range(r).anchor.SetPosition(positionInsert + offset);
+ }
+}
+
+void ScintillaWin::DrawImeIndicator(int indicator, int len) {
+ // Emulate the visual style of IME characters with indicators.
+ // Draw an indicator on the character before caret by the character bytes of len
+ // so it should be called after addCharUTF().
+ // It does not affect caret positions.
+ if (indicator < 8 || indicator > INDIC_MAX) {
+ return;
+ }
+ pdoc->decorations.SetCurrentIndicator(indicator);
+ for (size_t r=0; r<sel.Count(); r++) {
+ int positionInsert = sel.Range(r).Start().Position();
+ pdoc->DecorationFillRange(positionInsert - len, 1, len);
+ }
+}
+
+void ScintillaWin::SetCandidateWindowPos() {
+ HIMC hIMC = ::ImmGetContext(MainHWND());
+ if (hIMC) {
+ Point pos = PointMainCaret();
+ CANDIDATEFORM CandForm;
+ CandForm.dwIndex = 0;
+ CandForm.dwStyle = CFS_CANDIDATEPOS;
+ CandForm.ptCurrentPos.x = static_cast<int>(pos.x);
+ CandForm.ptCurrentPos.y = static_cast<int>(pos.y + vs.lineHeight);
+ ::ImmSetCandidateWindow(hIMC, &CandForm);
+ ::ImmReleaseContext(MainHWND(), hIMC);
+ }
+}
- // copy & paste by johnsonj
- // Great thanks to
- // jiniya from http://www.jiniya.net/tt/494 for DBCS input with AddCharUTF()
- // BLUEnLIVE from http://zockr.tistory.com/1118 for UNDO and inOverstrike
+sptr_t ScintillaWin::HandleCompositionInline(uptr_t, sptr_t lParam) {
+ // Copy & paste by johnsonj with a lot of helps of Neil.
+ // Great thanks for my foreruners, jiniya and BLUEnLIVE.
HIMC hIMC = ::ImmGetContext(MainHWND());
if (!hIMC) {
return 0;
}
- wchar_t wcs[maxLenInputIME];
- int wides = 0;
- bool compstrExist = false;
-
if (pdoc->TentativeActive()) {
pdoc->TentativeUndo();
} else {
// No tentative undo means start of this composition so
// fill in any virtual spaces.
- bool tmpOverstrike = inOverstrike;
- inOverstrike = false; // not allow to be deleted twice.
- AddCharUTF("", 0);
- inOverstrike = tmpOverstrike;
+ FillVirtualSpace();
}
view.imeCaretBlockOverride = false;
+
if (lParam & GCS_COMPSTR) {
+ wchar_t wcs[maxLenInputIME] = { 0 };
long bytes = ::ImmGetCompositionStringW
- (hIMC, GCS_COMPSTR, wcs, maxLenInputIME);
- wides = bytes / 2;
- compstrExist = (wides != 0);
- } else if (lParam & GCS_RESULTSTR) {
- long bytes = ::ImmGetCompositionStringW
- (hIMC, GCS_RESULTSTR, wcs, maxLenInputIME);
- wides = bytes / 2;
- compstrExist = (wides == 0);
- }
+ (hIMC, GCS_COMPSTR, wcs, maxLenInputIME);
+ unsigned int wcsLen = bytes / 2;
+
+ if ((wcsLen == 0) || (wcsLen >= maxLenInputIME)) {
+ ShowCaretAtCurrentPosition();
+ ::ImmReleaseContext(MainHWND(), hIMC);
+ return 0;
+ }
- if (wides >= 1) {
+ pdoc->TentativeStart(); // TentativeActive from now on.
- char hanval[maxLenInputIME];
- unsigned int hanlen = 0;
+ // Get attribute information from composition string.
+ BYTE compAttr[maxLenInputIME] = { 0 };
+ unsigned int imeCursorPos = 0;
- if (IsUnicodeMode()) {
- hanlen = UTF8Length(wcs, wides);
- UTF8FromUTF16(wcs, wides, hanval, hanlen);
- hanval[hanlen] = '\0';
- } else {
- hanlen = ::WideCharToMultiByte(InputCodePage(), 0,
- wcs, wides, hanval, sizeof(hanval) - 1, 0, 0);
- hanval[hanlen] = '\0';
+ if (lParam & GCS_COMPATTR) {
+ ImmGetCompositionStringW(hIMC, GCS_COMPATTR, compAttr, sizeof(compAttr));
+ }
+ if (lParam & GCS_CURSORPOS) {
+ imeCursorPos = ImmGetCompositionStringW(hIMC, GCS_CURSORPOS, NULL, 0);
}
- if (compstrExist) {
- view.imeCaretBlockOverride = true;
+ // Display character by character.
+ int numBytes = 0;
+ int imeCharPos[maxLenInputIME + 1] = { 0 };
+
+ bool tmpRecordingMacro = recordingMacro;
+ recordingMacro = false;
+ for (unsigned int i = 0; i < wcsLen; i++) {
+ wchar_t uniChar[1] = { 0 };
+ char oneChar[UTF8MaxBytes + 1] = "\0\0\0\0"; // Maximum 4 bytes in utf8
+ unsigned int oneCharLen = 0;
- bool tmpRecordingMacro = recordingMacro;
- recordingMacro = false;
- pdoc->TentativeStart();
- AddCharUTF(hanval, hanlen);
- recordingMacro = tmpRecordingMacro;
+ uniChar[0] = wcs[i];
- for (size_t r = 0; r < sel.Count(); r++) { // for block caret
- int positionInsert = sel.Range(r).Start().Position();
- sel.Range(r).caret.SetPosition(positionInsert - hanlen);
- sel.Range(r).anchor.SetPosition(positionInsert - hanlen);
+ if (IsUnicodeMode()) {
+ oneCharLen = UTF8Length(uniChar, 1);
+ UTF8FromUTF16(uniChar, 1, oneChar, oneCharLen);
+ oneChar[oneCharLen] = '\0';
+ } else {
+ oneCharLen = ::WideCharToMultiByte(InputCodePage(), 0,
+ uniChar, 1, oneChar, sizeof(oneChar)-1, 0, 0);
+ oneChar[oneCharLen] = '\0';
}
- } else {
- AddCharUTF(hanval, hanlen);
+
+ // Display a character.
+ AddCharUTF(oneChar, oneCharLen);
+
+ // Record compstr character positions for moving IME carets.
+ numBytes += oneCharLen;
+ imeCharPos[i + 1] = numBytes;
+
+ // Draw an indicator on the character.
+ int indicator = SC_INDICATOR_UNKNOWN;
+ switch ((int)compAttr[i]) {
+ case ATTR_INPUT:
+ indicator = SC_INDICATOR_INPUT;
+ break;
+ case ATTR_TARGET_NOTCONVERTED:
+ case ATTR_TARGET_CONVERTED:
+ indicator = SC_INDICATOR_TARGET;
+ break;
+ case ATTR_CONVERTED:
+ indicator = SC_INDICATOR_CONVERTED;
+ break;
+ }
+ DrawImeIndicator(indicator, oneCharLen);
}
- }
+ recordingMacro = tmpRecordingMacro;
+
+ // Move IME caret position.
+ MoveImeCarets(-imeCharPos[wcsLen] + imeCharPos[imeCursorPos]);
+ if (KoreanIME()) {
+ view.imeCaretBlockOverride = true;
+ }
+ } else if (lParam & GCS_RESULTSTR) {
+ wchar_t wcs[maxLenInputIME] = { 0 };
+ long bytes = ::ImmGetCompositionStringW
+ (hIMC, GCS_RESULTSTR, wcs, maxLenInputIME);
+ unsigned int wcsLen = bytes / 2;
- // set the candidate window position for HANJA while composing.
- Point pos = PointMainCaret();
- CANDIDATEFORM CandForm;
- CandForm.dwIndex = 0;
- CandForm.dwStyle = CFS_CANDIDATEPOS;
- CandForm.ptCurrentPos.x = static_cast<int>(pos.x);
- CandForm.ptCurrentPos.y = static_cast<int>(pos.y + vs.lineHeight);
- ::ImmSetCandidateWindow(hIMC, &CandForm);
+ for (unsigned int i = 0; i < wcsLen; i++) {
+ wchar_t uniChar[1] = { 0 };
+ char oneChar[UTF8MaxBytes+1] = "\0\0\0\0"; // Maximum 4 bytes in UTF-8.
+ unsigned int oneCharLen = 0;
+ uniChar[0] = wcs[i];
+
+ if (IsUnicodeMode()) {
+ oneCharLen = UTF8Length(uniChar, 1);
+ UTF8FromUTF16(uniChar, 1, oneChar, oneCharLen);
+ oneChar[oneCharLen] = '\0';
+ } else {
+ oneCharLen = ::WideCharToMultiByte(InputCodePage(), 0,
+ uniChar, 1, oneChar, sizeof(oneChar)-1, 0, 0);
+ oneChar[oneCharLen] = '\0';
+ }
+ AddCharUTF(oneChar, oneCharLen);
+ }
+ }
+ SetCandidateWindowPos();
ShowCaretAtCurrentPosition();
::ImmReleaseContext(MainHWND(), hIMC);
return 0;
@@ -924,12 +1020,12 @@ sptr_t ScintillaWin::GetText(uptr_t wParam, sptr_t lParam) {
std::vector<char> docBytes(pdoc->Length(), '\0');
pdoc->GetCharRange(&docBytes[0], 0, pdoc->Length());
if (IsUnicodeMode()) {
- unsigned int lengthUTF16 = UTF16Length(&docBytes[0], static_cast<unsigned int>(docBytes.size()));
+ size_t lengthUTF16 = UTF16Length(&docBytes[0], static_cast<unsigned int>(docBytes.size()));
if (lParam == 0)
return lengthUTF16;
if (wParam == 0)
return 0;
- unsigned int uLen = UTF16FromUTF8(&docBytes[0], static_cast<unsigned int>(docBytes.size()),
+ size_t uLen = UTF16FromUTF8(&docBytes[0], docBytes.size(),
ptr, static_cast<int>(wParam) - 1);
ptr[uLen] = L'\0';
return uLen;
@@ -1278,21 +1374,22 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
break;
case WM_IME_STARTCOMPOSITION: // dbcs
- if (KoreanIME()) {
+ if (KoreanIME() || imeInteraction == imeInline) {
return 0;
+ } else {
+ ImeStartComposition();
+ return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
}
- ImeStartComposition();
- return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
case WM_IME_ENDCOMPOSITION: // dbcs
ImeEndComposition();
return ::DefWindowProc(MainHWND(), iMessage, wParam, lParam);
case WM_IME_COMPOSITION:
- if (KoreanIME()) {
- return HandleCompositionKoreanIME(wParam, lParam);
+ if (KoreanIME() || imeInteraction == imeInline) {
+ return HandleCompositionInline(wParam, lParam);
} else {
- return HandleComposition(wParam, lParam);
+ return HandleCompositionWindowed(wParam, lParam);
}
case WM_IME_CHAR: {
@@ -1330,7 +1427,7 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
return 0;
case WM_IME_SETCONTEXT:
- if (KoreanIME()) {
+ if (KoreanIME() || imeInteraction == imeInline) {
if (wParam) {
LPARAM NoImeWin = lParam;
NoImeWin = NoImeWin & (~ISC_SHOWUICOMPOSITIONWINDOW);
@@ -1750,8 +1847,8 @@ public:
if (foldedUTF8) {
// Maximum length of a case conversion is 6 bytes, 3 characters
wchar_t wFolded[20];
- unsigned int charsConverted = UTF16FromUTF8(foldedUTF8,
- static_cast<unsigned int>(strlen(foldedUTF8)),
+ size_t charsConverted = UTF16FromUTF8(foldedUTF8,
+ strlen(foldedUTF8),
wFolded, ELEMENTS(wFolded));
for (size_t j=0; j<charsConverted; j++)
utf16Folded[lenFlat++] = wFolded[j];
@@ -1796,13 +1893,13 @@ CaseFolder *ScintillaWin::CaseFolderForEncoding() {
const char *caseFolded = CaseConvert(wCharacter[0], CaseConversionFold);
if (caseFolded) {
wchar_t wLower[20];
- unsigned int charsConverted = UTF16FromUTF8(caseFolded,
- static_cast<unsigned int>(strlen(caseFolded)),
+ size_t charsConverted = UTF16FromUTF8(caseFolded,
+ strlen(caseFolded),
wLower, ELEMENTS(wLower));
if (charsConverted == 1) {
char sCharacterLowered[20];
unsigned int lengthConverted = ::WideCharToMultiByte(cpDoc, 0,
- wLower, charsConverted,
+ wLower, static_cast<int>(charsConverted),
sCharacterLowered, ELEMENTS(sCharacterLowered), NULL, 0);
if ((lengthConverted == 1) && (sCharacter[0] != sCharacterLowered[0])) {
pcf->SetTranslation(sCharacter[0], sCharacterLowered[0]);
@@ -1900,8 +1997,10 @@ public:
}
~GlobalMemory() {
PLATFORM_ASSERT(!ptr);
+ assert(!hand);
}
void Allocate(size_t bytes) {
+ assert(!hand);
hand = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_ZEROINIT, bytes);
if (hand) {
ptr = ::GlobalLock(hand);
@@ -2360,7 +2459,7 @@ void ScintillaWin::ImeStartComposition() {
// Since the style creation code has been made platform independent,
// The logfont for the IME is recreated here.
int styleHere = (pdoc->StyleAt(sel.MainCaret())) & 31;
- LOGFONTA lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ""};
+ LOGFONTW lf = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, L""};
int sizeZoomed = vs.styles[styleHere].size + vs.zoomLevel * SC_FONT_SIZE_MULTIPLIER;
if (sizeZoomed <= 2 * SC_FONT_SIZE_MULTIPLIER) // Hangs if sizeZoomed <= 1
sizeZoomed = 2 * SC_FONT_SIZE_MULTIPLIER;
@@ -2374,11 +2473,13 @@ void ScintillaWin::ImeStartComposition() {
lf.lfWeight = vs.styles[styleHere].weight;
lf.lfItalic = static_cast<BYTE>(vs.styles[styleHere].italic ? 1 : 0);
lf.lfCharSet = DEFAULT_CHARSET;
- lf.lfFaceName[0] = '\0';
- if (vs.styles[styleHere].fontName)
- StringCopy(lf.lfFaceName, vs.styles[styleHere].fontName);
+ lf.lfFaceName[0] = L'\0';
+ if (vs.styles[styleHere].fontName) {
+ const char* fontName = vs.styles[styleHere].fontName;
+ UTF16FromUTF8(fontName, strlen(fontName)+1, lf.lfFaceName, LF_FACESIZE);
+ }
- ::ImmSetCompositionFontA(hIMC, &lf);
+ ::ImmSetCompositionFontW(hIMC, &lf);
}
::ImmReleaseContext(MainHWND(), hIMC);
// Caret is displayed in IME window. So, caret in Scintilla is useless.
@@ -2437,11 +2538,11 @@ void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
// Default Scintilla behaviour in Unicode mode
if (IsUnicodeMode()) {
- int uchars = UTF16Length(selectedText.Data(),
+ size_t uchars = UTF16Length(selectedText.Data(),
static_cast<int>(selectedText.LengthWithTerminator()));
uniText.Allocate(2 * uchars);
if (uniText) {
- UTF16FromUTF8(selectedText.Data(), static_cast<int>(selectedText.LengthWithTerminator()),
+ UTF16FromUTF8(selectedText.Data(), selectedText.LengthWithTerminator(),
static_cast<wchar_t *>(uniText.ptr), uchars);
}
} else {
@@ -2460,20 +2561,6 @@ void ScintillaWin::CopyToClipboard(const SelectionText &selectedText) {
}
if (uniText) {
- if (!IsNT()) {
- // Copy ANSI text to clipboard on Windows 9x
- // Convert from Unicode text, so other ANSI programs can
- // paste the text
- // Windows NT, 2k, XP automatically generates CF_TEXT
- GlobalMemory ansiText;
- ansiText.Allocate(selectedText.LengthWithTerminator());
- if (ansiText) {
- ::WideCharToMultiByte(CP_ACP, 0, static_cast<wchar_t *>(uniText.ptr), -1,
- static_cast<char *>(ansiText.ptr),
- static_cast<int>(selectedText.LengthWithTerminator()), NULL, NULL);
- ansiText.SetClip(CF_TEXT);
- }
- }
uniText.SetClip(CF_UNICODETEXT);
} else {
// There was a failure - try to copy at least ANSI text
@@ -2828,10 +2915,10 @@ STDMETHODIMP ScintillaWin::GetData(FORMATETC *pFEIn, STGMEDIUM *pSTM) {
GlobalMemory text;
if (pFEIn->cfFormat == CF_UNICODETEXT) {
- int uchars = UTF16Length(drag.Data(), static_cast<int>(drag.LengthWithTerminator()));
+ size_t uchars = UTF16Length(drag.Data(), static_cast<int>(drag.LengthWithTerminator()));
text.Allocate(2 * uchars);
if (text) {
- UTF16FromUTF8(drag.Data(), static_cast<int>(drag.LengthWithTerminator()),
+ UTF16FromUTF8(drag.Data(), drag.LengthWithTerminator(),
static_cast<wchar_t *>(text.ptr), uchars);
}
} else {
@@ -2851,43 +2938,22 @@ bool ScintillaWin::Register(HINSTANCE hInstance_) {
bool result;
// Register the Scintilla class
- if (IsNT()) {
-
- // Register Scintilla as a wide character window
- WNDCLASSEXW wndclass;
- wndclass.cbSize = sizeof(wndclass);
- wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
- wndclass.lpfnWndProc = ScintillaWin::SWndProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = sizeof(ScintillaWin *);
- wndclass.hInstance = hInstance;
- wndclass.hIcon = NULL;
- wndclass.hCursor = NULL;
- wndclass.hbrBackground = NULL;
- wndclass.lpszMenuName = NULL;
- wndclass.lpszClassName = L"Scintilla";
- wndclass.hIconSm = 0;
- scintillaClassAtom = ::RegisterClassExW(&wndclass);
- result = 0 != scintillaClassAtom;
- } else {
-
- // Register Scintilla as a normal character window
- WNDCLASSEX wndclass;
- wndclass.cbSize = sizeof(wndclass);
- wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
- wndclass.lpfnWndProc = ScintillaWin::SWndProc;
- wndclass.cbClsExtra = 0;
- wndclass.cbWndExtra = sizeof(ScintillaWin *);
- wndclass.hInstance = hInstance;
- wndclass.hIcon = NULL;
- wndclass.hCursor = NULL;
- wndclass.hbrBackground = NULL;
- wndclass.lpszMenuName = NULL;
- wndclass.lpszClassName = scintillaClassName;
- wndclass.hIconSm = 0;
- scintillaClassAtom = ::RegisterClassEx(&wndclass);
- result = 0 != scintillaClassAtom;
- }
+ // Register Scintilla as a wide character window
+ WNDCLASSEXW wndclass;
+ wndclass.cbSize = sizeof(wndclass);
+ wndclass.style = CS_GLOBALCLASS | CS_HREDRAW | CS_VREDRAW;
+ wndclass.lpfnWndProc = ScintillaWin::SWndProc;
+ wndclass.cbClsExtra = 0;
+ wndclass.cbWndExtra = sizeof(ScintillaWin *);
+ wndclass.hInstance = hInstance;
+ wndclass.hIcon = NULL;
+ wndclass.hCursor = NULL;
+ wndclass.hbrBackground = NULL;
+ wndclass.lpszMenuName = NULL;
+ wndclass.lpszClassName = L"Scintilla";
+ wndclass.hIconSm = 0;
+ scintillaClassAtom = ::RegisterClassExW(&wndclass);
+ result = 0 != scintillaClassAtom;
if (result) {
// Register the CallTip class