diff options
51 files changed, 2899 insertions, 866 deletions
diff --git a/build/makefile.deps.mak b/build/makefile.deps.mak index a53304a..3a08dda 100644 --- a/build/makefile.deps.mak +++ b/build/makefile.deps.mak @@ -7,7 +7,7 @@ #*
#* See License.txt for details about distribution and modification.
#*
-#* (c) XhmikosR 2010-2012
+#* (c) XhmikosR 2010-2013
#* https://github.com/XhmikosR/notepad2-mod
#*
#*
@@ -36,10 +36,12 @@ $(SCI_LEX_OBJDIR)\LexAVS.obj: $(SCI_LEX)\LexAVS.cxx $(LEX_HEADERS) $(SCI_LEX_OBJDIR)\LexBash.obj: $(SCI_LEX)\LexBash.cxx $(LEX_HEADERS)
$(SCI_LEX_OBJDIR)\LexCmake.obj: $(SCI_LEX)\LexCmake.cxx $(LEX_HEADERS)
$(SCI_LEX_OBJDIR)\LexConf.obj: $(SCI_LEX)\LexConf.cxx $(LEX_HEADERS)
-$(SCI_LEX_OBJDIR)\LexCPP.obj: $(SCI_LEX)\LexCPP.cxx $(LEX_HEADERS) $(SCI_LIB)\OptionSet.h $(SCI_LIB)\SparseState.h
+$(SCI_LEX_OBJDIR)\LexCPP.obj: $(SCI_LEX)\LexCPP.cxx $(LEX_HEADERS) $(SCI_LIB)\OptionSet.h \
+ $(SCI_LIB)\SparseState.h $(SCI_LIB)\SubStyles.h
$(SCI_LEX_OBJDIR)\LexCSS.obj: $(SCI_LEX)\LexCSS.cxx $(LEX_HEADERS)
$(SCI_LEX_OBJDIR)\LexHTML.obj: $(SCI_LEX)\LexHTML.cxx $(LEX_HEADERS)
$(SCI_LEX_OBJDIR)\LexInno.obj: $(SCI_LEX)\LexInno.cxx $(LEX_HEADERS)
+$(SCI_LEX_OBJDIR)\LexLua.obj: $(SCI_LEX)\LexLaTeX.cxx $(LEX_HEADERS)
$(SCI_LEX_OBJDIR)\LexLua.obj: $(SCI_LEX)\LexLua.cxx $(LEX_HEADERS)
$(SCI_LEX_OBJDIR)\LexMarkdown.obj: $(SCI_LEX)\LexMarkdown.cxx $(LEX_HEADERS)
$(SCI_LEX_OBJDIR)\LexNsis.obj: $(SCI_LEX)\LexNsis.cxx $(LEX_HEADERS)
diff --git a/build/makefile.mak b/build/makefile.mak index 49f144c..efa2246 100644 --- a/build/makefile.mak +++ b/build/makefile.mak @@ -7,7 +7,7 @@ #*
#* See License.txt for details about distribution and modification.
#*
-#* (c) XhmikosR 2010-2012
+#* (c) XhmikosR 2010-2013
#* https://github.com/XhmikosR/notepad2-mod
#*
#* Use build_wdk.bat and set there your WDK directory.
@@ -132,6 +132,7 @@ SCI_LEX_OBJ = \ $(SCI_LEX_OBJDIR)\LexCSS.obj \
$(SCI_LEX_OBJDIR)\LexHTML.obj \
$(SCI_LEX_OBJDIR)\LexInno.obj \
+ $(SCI_LEX_OBJDIR)\LexLaTeX.obj \
$(SCI_LEX_OBJDIR)\LexLua.obj \
$(SCI_LEX_OBJDIR)\LexMarkdown.obj \
$(SCI_LEX_OBJDIR)\LexNsis.obj \
diff --git a/scintilla/Scintilla.vcxproj b/scintilla/Scintilla.vcxproj index 07161da..73a651b 100644 --- a/scintilla/Scintilla.vcxproj +++ b/scintilla/Scintilla.vcxproj @@ -145,6 +145,7 @@ <ClCompile Include="lexers\LexCSS.cxx" /> <ClCompile Include="lexers\LexHTML.cxx" /> <ClCompile Include="lexers\LexInno.cxx" /> + <ClCompile Include="lexers\LexLaTeX.cxx" /> <ClCompile Include="lexers\LexLua.cxx" /> <ClCompile Include="lexers\LexMarkdown.cxx" /> <ClCompile Include="lexers\LexNsis.cxx" /> @@ -209,6 +210,7 @@ <ClInclude Include="lexlib\PropSetSimple.h" /> <ClInclude Include="lexlib\SparseState.h" /> <ClInclude Include="lexlib\StyleContext.h" /> + <ClInclude Include="lexlib\SubStyles.h" /> <ClInclude Include="lexlib\WordList.h" /> <ClInclude Include="src\AutoComplete.h" /> <ClInclude Include="src\CallTip.h" /> diff --git a/scintilla/Scintilla.vcxproj.filters b/scintilla/Scintilla.vcxproj.filters index 05c1f24..07a6863 100644 --- a/scintilla/Scintilla.vcxproj.filters +++ b/scintilla/Scintilla.vcxproj.filters @@ -51,6 +51,9 @@ <ClCompile Include="lexers\LexInno.cxx"> <Filter>lexers</Filter> </ClCompile> + <ClCompile Include="lexers\LexLaTeX.cxx"> + <Filter>lexers</Filter> + </ClCompile> <ClCompile Include="lexers\LexLua.cxx"> <Filter>lexers</Filter> </ClCompile> @@ -239,6 +242,9 @@ <ClInclude Include="lexlib\StyleContext.h"> <Filter>lexlib</Filter> </ClInclude> + <ClInclude Include="lexlib\SubStyles.h"> + <Filter>lexlib</Filter> + </ClInclude> <ClInclude Include="lexlib\WordList.h"> <Filter>lexlib</Filter> </ClInclude> diff --git a/scintilla/Scintilla_icl13.vcxproj b/scintilla/Scintilla_icl13.vcxproj index 5fff968..2668912 100644 --- a/scintilla/Scintilla_icl13.vcxproj +++ b/scintilla/Scintilla_icl13.vcxproj @@ -165,6 +165,7 @@ <ClCompile Include="lexers\LexCSS.cxx" /> <ClCompile Include="lexers\LexHTML.cxx" /> <ClCompile Include="lexers\LexInno.cxx" /> + <ClCompile Include="lexers\LexLaTeX.cxx" /> <ClCompile Include="lexers\LexLua.cxx" /> <ClCompile Include="lexers\LexMarkdown.cxx" /> <ClCompile Include="lexers\LexNsis.cxx" /> @@ -229,6 +230,7 @@ <ClInclude Include="lexlib\PropSetSimple.h" /> <ClInclude Include="lexlib\SparseState.h" /> <ClInclude Include="lexlib\StyleContext.h" /> + <ClInclude Include="lexlib\SubStyles.h" /> <ClInclude Include="lexlib\WordList.h" /> <ClInclude Include="src\AutoComplete.h" /> <ClInclude Include="src\CallTip.h" /> diff --git a/scintilla/Scintilla_icl13.vcxproj.filters b/scintilla/Scintilla_icl13.vcxproj.filters index 05c1f24..07a6863 100644 --- a/scintilla/Scintilla_icl13.vcxproj.filters +++ b/scintilla/Scintilla_icl13.vcxproj.filters @@ -51,6 +51,9 @@ <ClCompile Include="lexers\LexInno.cxx"> <Filter>lexers</Filter> </ClCompile> + <ClCompile Include="lexers\LexLaTeX.cxx"> + <Filter>lexers</Filter> + </ClCompile> <ClCompile Include="lexers\LexLua.cxx"> <Filter>lexers</Filter> </ClCompile> @@ -239,6 +242,9 @@ <ClInclude Include="lexlib\StyleContext.h"> <Filter>lexlib</Filter> </ClInclude> + <ClInclude Include="lexlib\SubStyles.h"> + <Filter>lexlib</Filter> + </ClInclude> <ClInclude Include="lexlib\WordList.h"> <Filter>lexlib</Filter> </ClInclude> diff --git a/scintilla/doc/ScintillaDoc.html b/scintilla/doc/ScintillaDoc.html index b3ecf7e..d9b2d16 100644 --- a/scintilla/doc/ScintillaDoc.html +++ b/scintilla/doc/ScintillaDoc.html @@ -61,6 +61,9 @@ color: #000000;
font-size: 10pt;
}
+ .provisional {
+ background: #FFB000;
+ }
/*]]>*/
-->
</style>
@@ -79,7 +82,7 @@ <h1>Scintilla Documentation</h1>
- <p>Last edited 3/January/2013 NH</p>
+ <p>Last edited 18/January/2013 NH</p>
<p>There is <a class="jump" href="Design.html">an overview of the internal design of
Scintilla</a>.<br />
@@ -317,15 +320,18 @@ <tr>
<td>o <a class="toc" href="#GTK">GTK+</a></td>
+ <td>o <a class="toc" href="#ProvisionalMessages"><span class="provisional">Provisional messages</span></a></td>
+
<td>o <a class="toc" href="#DeprecatedMessages">Deprecated messages</a></td>
- <td>o <a class="toc" href="#EditMessagesNeverSupportedByScintilla">Edit messages never
- supported by Scintilla</a></td>
-
</tr>
<tr>
+ <td>o <a class="toc" href="#EditMessagesNeverSupportedByScintilla">Edit messages never
+ supported by Scintilla</a></td>
+
<td>o <a class="toc" href="#BuildingScintilla">Building Scintilla</a></td>
+
</tr>
</tbody>
</table>
@@ -395,6 +401,8 @@ *tr)</a><br />
<a class="message" href="#SCI_SETSTYLEBITS">SCI_SETSTYLEBITS(int bits)</a><br />
<a class="message" href="#SCI_GETSTYLEBITS">SCI_GETSTYLEBITS</a><br />
+ <a class="message" href="#SCI_RELEASEALLEXTENDEDSTYLES">SCI_RELEASEALLEXTENDEDSTYLES</a><br />
+ <a class="message" href="#SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES(int numberStyles)</a><br />
<a class="message" href="#SCI_TARGETASUTF8">SCI_TARGETASUTF8(<unused>, char *s)</a><br />
<a class="message" href="#SCI_ENCODEDFROMUTF8">SCI_ENCODEDFROMUTF8(const char *utf8, char *encoded)</a><br />
<a class="message" href="#SCI_SETLENGTHFORENCODE">SCI_SETLENGTHFORENCODE(int bytes)</a><br />
@@ -544,6 +552,18 @@ The number of styling bits needed by the current lexer can be found with
<a class="message" href="#SCI_GETSTYLEBITSNEEDED">SCI_GETSTYLEBITSNEEDED</a>.</p>
+ <p><b id="SCI_RELEASEALLEXTENDEDSTYLES">SCI_RELEASEALLEXTENDEDSTYLES</b><br />
+ <b id="SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES(int numberStyles)</b><br />
+ Extended styles are used for features like textual margins and annotations as well as internally by Scintilla.
+ They are outside the range 0..255 used for the styles bytes associated with document bytes.
+ These functions manage the use of extended styles to ensures that components cooperate in defining styles.
+ <code>SCI_RELEASEALLEXTENDEDSTYLES</code> releases any extended styles allocated by the container.
+ <code>SCI_ALLOCATEEXTENDEDSTYLES</code> allocates a range of style numbers after the byte style values and returns
+ the number of the first allocated style.
+ Ranges for margin and annotation styles should be allocated before calling
+ <a class="message" href="#SCI_MARGINSETSTYLEOFFSET">SCI_MARGINSETSTYLEOFFSET</a> or
+ <a class="message" href="#SCI_ANNOTATIONSETSTYLEOFFSET">SCI_ANNOTATIONSETSTYLEOFFSET</a>.</p>
+
<p><b id="Sci_TextRange">Sci_TextRange</b> and <b id="Sci_CharacterRange">Sci_CharacterRange</b><br />
These structures are defined to be exactly the same shape as the Win32 <code>TEXTRANGE</code>
and <code>CHARRANGE</code>, so that older code that treats Scintilla as a RichEdit will
@@ -1710,6 +1730,7 @@ struct Sci_TextToFind { <h2 id="ScrollingAndAutomaticScrolling">Scrolling and automatic scrolling</h2>
<code><a class="message" href="#SCI_LINESCROLL">SCI_LINESCROLL(int column, int line)</a><br />
<a class="message" href="#SCI_SCROLLCARET">SCI_SCROLLCARET</a><br />
+ <a class="message" href="#SCI_SCROLLRANGE">SCI_SCROLLRANGE(int secondary, int primary)</a><br />
<a class="message" href="#SCI_SETXCARETPOLICY">SCI_SETXCARETPOLICY(int caretPolicy, int
caretSlop)</a><br />
<a class="message" href="#SCI_SETYCARETPOLICY">SCI_SETYCARETPOLICY(int caretPolicy, int
@@ -1746,6 +1767,14 @@ struct Sci_TextToFind { If the current position (this is the caret if there is no selection) is not visible, the view
is scrolled to make it visible according to the current caret policy.</p>
+ <p><b id="SCI_SCROLLRANGE">SCI_SCROLLRANGE(int secondary, int primary)</b><br />
+ Scroll the argument positions and the range between them into view giving
+ priority to the primary position then the secondary position.
+ The behaviour is similar to <a class="message" href="#SCI_SCROLLCARET"><code>SCI_SCROLLCARET</code></a>
+ with the primary position used instead of the caret. An effort is then made to ensure that the secondary
+ position and range between are also visible.
+ This may be used to make a search match visible.</p>
+
<p><b id="SCI_SETXCARETPOLICY">SCI_SETXCARETPOLICY(int caretPolicy, int caretSlop)</b><br />
<b id="SCI_SETYCARETPOLICY">SCI_SETYCARETPOLICY(int caretPolicy, int caretSlop)</b><br />
These set the caret policy. The value of <code>caretPolicy</code> is a combination of
@@ -2176,17 +2205,36 @@ struct Sci_TextToFind { <h2 id="LineEndings">Line endings</h2>
- <p>Scintilla can interpret any of the three major line end conventions, Macintosh (\r), Unix
- (\n) and CP/M / DOS / Windows (\r\n). When the user presses the Enter key, one of these line
+ <p>Scintilla can handle the major line end conventions <span class="provisional">and, depending on settings and
+ the current lexer also support additional Unicode line ends</span>.</p>
+
+ <p>Scintilla can interpret any of the Macintosh (\r), Unix (\n) and Windows (\r\n)
+ line ends.
+ When the user presses the Enter key, one of these line
end strings is inserted into the buffer. The default is \r\n in Windows and \n in Unix, but
this can be changed with the <code>SCI_SETEOLMODE</code> message. You can also convert the
entire document to one of these line endings with <code>SCI_CONVERTEOLS</code>. Finally, you
can choose to display the line endings with <code>SCI_SETVIEWEOL</code>.</p>
+
+<div class="provisional">
+ <p>For the UTF-8 encoding, three additional Unicode line ends,
+ Next Line (<code>NEL=U+0085</code>), Line Separator (<code>LS=U+2028</code>), and Paragraph Separator (<code>PS=U+2029</code>)
+ may optionally be interpreted when Unicode line ends is turned on and the current lexer also supports
+ Unicode line ends.</p>
+</div>
+
<code><a class="message" href="#SCI_SETEOLMODE">SCI_SETEOLMODE(int eolMode)</a><br />
<a class="message" href="#SCI_GETEOLMODE">SCI_GETEOLMODE</a><br />
<a class="message" href="#SCI_CONVERTEOLS">SCI_CONVERTEOLS(int eolMode)</a><br />
<a class="message" href="#SCI_SETVIEWEOL">SCI_SETVIEWEOL(bool visible)</a><br />
<a class="message" href="#SCI_GETVIEWEOL">SCI_GETVIEWEOL</a><br />
+
+<div class="provisional">
+ <a class="message" href="#SCI_GETLINEENDTYPESSUPPORTED">SCI_GETLINEENDTYPESSUPPORTED</a><br />
+ <a class="message" href="#SCI_SETLINEENDTYPESALLOWED">SCI_SETLINEENDTYPESALLOWED(int lineEndBitSet)</a><br />
+ <a class="message" href="#SCI_GETLINEENDTYPESALLOWED">SCI_GETLINEENDTYPESALLOWED</a><br />
+ <a class="message" href="#SCI_GETLINEENDTYPESACTIVE">SCI_GETLINEENDTYPESACTIVE</a><br />
+</div>
</code>
<p><b id="SCI_SETEOLMODE">SCI_SETEOLMODE(int eolMode)</b><br />
@@ -2209,6 +2257,27 @@ struct Sci_TextToFind { <code>(CR)</code>, <code>(LF)</code>, or <code>(CR)(LF)</code>. <code>SCI_GETVIEWEOL</code>
returns the current state.</p>
+<div class="provisional">
+ <a href="#ProvisionalMessages">These features are provisional</a><br />
+
+ <p><b id="SCI_GETLINEENDTYPESSUPPORTED">SCI_GETLINEENDTYPESSUPPORTED</b><br />
+ <code>SCI_GETLINEENDTYPESSUPPORTED</code> reports the different types of line ends supported
+ by the current lexer. This is a bit set although there is currently only a single choice
+ with either <code>SC_LINE_END_TYPE_DEFAULT</code> (0) or <code>SC_LINE_END_TYPE_UNICODE</code> (1).
+ These values are also used by the other messages concerned with Unicode line ends.</p>
+
+ <p><b id="SCI_SETLINEENDTYPESALLOWED">SCI_SETLINEENDTYPESALLOWED(int lineEndBitSet)</b><br />
+ <b id="SCI_GETLINEENDTYPESALLOWED">SCI_GETLINEENDTYPESALLOWED</b><br />
+ By default, only the ASCII line ends are interpreted. Unicode line ends may be requested with
+ <code>SCI_SETLINEENDTYPESALLOWED(SC_LINE_END_TYPE_UNICODE)</code>
+ but this will be ineffective unless the lexer also allows you Unicode line ends.
+ <code>SCI_GETLINEENDTYPESALLOWED</code> returns the current state.</p>
+
+ <p><b id="SCI_GETLINEENDTYPESACTIVE">SCI_GETLINEENDTYPESACTIVE</b><br />
+ <code>SCI_GETLINEENDTYPESACTIVE</code> reports the set of line ends currently interpreted
+ by Scintilla. It is <code>SCI_GETLINEENDTYPESSUPPORTED & SCI_GETLINEENDTYPESALLOWED</code>.</p>
+</div>
+
<h2 id="Styling">Styling</h2>
<p>The styling messages allow you to assign styles to text. The standard Scintilla settings
@@ -2754,7 +2823,8 @@ struct Sci_TextToFind { <h2 id="Margins">Margins</h2>
- <p>There may be up to five margins to the left of the text display, plus a gap either side of
+ <p>There may be up to five margins, numbered 0 to <code>SC_MAX_MARGIN</code> (4)
+ to the left of the text display, plus a gap either side of
the text. Each margin can be set to display only symbols, line numbers, or text with <a
class="message" href="#SCI_SETMARGINTYPEN"><code>SCI_SETMARGINTYPEN</code></a>.
Textual margins may also display symbols.
@@ -2923,6 +2993,10 @@ struct Sci_TextToFind { or <code>SCI_MARGINSETSTYLES</code> has the offset added before looking up the style.
</p>
<p>
+ Always call <a class="message" href="#SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES</a>
+ before <code>SCI_MARGINSETSTYLEOFFSET</code> and use the result as the argument to <code>SCI_MARGINSETSTYLEOFFSET</code>.
+ </p>
+ <p>
<b id="SCI_SETMARGINOPTIONS">SCI_SETMARGINOPTIONS(int marginOptions)</b><br />
<b id="SCI_GETMARGINOPTIONS">SCI_GETMARGINOPTIONS</b><br />
Define margin options by enabling appropriate bit flags. At the moment, only one flag is available
@@ -2938,6 +3012,9 @@ struct Sci_TextToFind { An annotation may consist of multiple lines separated by '\n'.
Annotations can be used to display an assembler version of code for debugging or to show diagnostic messages inline or to
line up different versions of text in a merge tool.</p>
+ <p>Annotations count as display lines for the methods
+ <a class="message" href="#SCI_VISIBLEFROMDOCLINE"><code>SCI_VISIBLEFROMDOCLINE</code></a> and
+ <a class="message" href="#SCI_DOCLINEFROMVISIBLE"><code>SCI_DOCLINEFROMVISIBLE</code></a></p>
<p>Annotations used for inline diagnostics:</p>
<p><img src="annotations.png" alt="Annotations used for inline diagnostics" /></p>
@@ -3028,6 +3105,10 @@ struct Sci_TextToFind { Each style number set with <code>SCI_ANNOTATIONSETSTYLE</code>
or <code>SCI_ANNOTATIONSETSTYLES</code> has the offset added before looking up the style.
</p>
+ <p>
+ Always call <a class="message" href="#SCI_ALLOCATEEXTENDEDSTYLES">SCI_ALLOCATEEXTENDEDSTYLES</a>
+ before <code>SCI_ANNOTATIONSETSTYLEOFFSET</code> and use the result as the argument to <code>SCI_ANNOTATIONSETSTYLEOFFSET</code>.
+ </p>
<h2 id="OtherSettings">Other settings</h2>
<code><a class="message" href="#SCI_SETUSEPALETTE">SCI_SETUSEPALETTE(bool
@@ -3830,8 +3911,7 @@ struct Sci_TextToFind { <a class="message" href="#SCI_INDICSETALPHA">SCI_INDICSETALPHA</a> and
<a class="message" href="#SCI_INDICSETOUTLINEALPHA">SCI_INDICSETOUTLINEALPHA</a>
control the alpha transparency values. The default values are 30 for alpha and 50 for outline alpha.
- To avoid excessive memory allocation the maximum width of a dotted box is 4000 pixels.
- Not available for OS X Carbon.</td>
+ To avoid excessive memory allocation the maximum width of a dotted box is 4000 pixels.</td>
</tr>
<tr>
@@ -4027,6 +4107,8 @@ struct Sci_TextToFind { <a class="message" href="#SCI_AUTOCGETIGNORECASE">SCI_AUTOCGETIGNORECASE</a><br />
<a class="message" href="#SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR">SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR(int behaviour)</a><br>
<a class="message" href="#SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR">SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR</a><br>
+ <a class="message" href="#SCI_AUTOCSETORDER">SCI_AUTOCSETORDER(int order)</a><br>
+ <a class="message" href="#SCI_AUTOCGETORDER">SCI_AUTOCGETORDER</a><br>
<a class="message" href="#SCI_AUTOCSETAUTOHIDE">SCI_AUTOCSETAUTOHIDE(bool autoHide)</a><br />
<a class="message" href="#SCI_AUTOCGETAUTOHIDE">SCI_AUTOCGETAUTOHIDE</a><br />
<a class="message" href="#SCI_AUTOCSETDROPRESTOFWORD">SCI_AUTOCSETDROPRESTOFWORD(bool
@@ -4051,10 +4133,13 @@ struct Sci_TextToFind { and <a class="message"
href="#SCI_AUTOCGETSEPARATOR"><code>SCI_AUTOCGETSEPARATOR</code></a>.</p>
- <p>The list of words should be in sorted order. If set to ignore case mode with <a class="message" href="#SCI_AUTOCSETIGNORECASE"><code>SCI_AUTOCSETIGNORECASE</code></a>, then
+ <p>With default settings, the list of words should be in sorted order.
+ If set to ignore case mode with <a class="message" href="#SCI_AUTOCSETIGNORECASE"><code>SCI_AUTOCSETIGNORECASE</code></a>, then
strings are matched after being converted to upper case. One result of this is that the list
should be sorted with the punctuation characters '[', '\', ']', '^', '_', and '`' sorted after
- letters.</p>
+ letters.
+ Alternative handling of list order may be specified with <a class="message" href="#SCI_AUTOCSETORDER">SCI_AUTOCSETORDER</a>
+ </p>
<p><b id="SCI_AUTOCCANCEL">SCI_AUTOCCANCEL</b><br />
This message cancels any displayed autocompletion list. When in autocompletion mode, the list
@@ -4139,6 +4224,20 @@ struct Sci_TextToFind { This corresponds to a behaviour property of <code>SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE</code> (0).
If you want autocompletion to ignore case at all, choose <code>SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE</code> (1).</p>
+ <p><b id="SCI_AUTOCSETORDER">SCI_AUTOCSETORDER(int order)</b><br>
+ <b id="SCI_AUTOCGETORDER">SCI_AUTOCGETORDER</b><br>
+ The default setting <code>SC_ORDER_PRESORTED</code> (0) requires that the list be provided in alphabetical sorted order.
+ </p>
+ <p>Sorting the list can be done by Scintilla instead of the application with <code>SC_ORDER_PERFORMSORT</code> (1).
+ This will take additional time.
+ </p>
+ <p>Applications that wish to prioritize some values and show the list in order of priority instead
+ of alphabetical order can use <code>SC_ORDER_CUSTOM</code> (2).
+ This requires extra processing in <a class="message" href="#SCI_AUTOCSHOW">SCI_AUTOCSHOW</a> to create a sorted index.
+ </p>
+ <p>Setting the order should be done before calling <a class="message" href="#SCI_AUTOCSHOW">SCI_AUTOCSHOW</a>.
+ </p>
+
<p><b id="SCI_AUTOCSETAUTOHIDE">SCI_AUTOCSETAUTOHIDE(bool autoHide)</b><br />
<b id="SCI_AUTOCGETAUTOHIDE">SCI_AUTOCGETAUTOHIDE</b><br />
By default, the list is cancelled if there are no viable matches (the user has typed
@@ -5080,16 +5179,19 @@ sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){ </code>
<p><b id="SCI_VISIBLEFROMDOCLINE">SCI_VISIBLEFROMDOCLINE(int docLine)</b><br />
- When some lines are folded, then a particular line in the document may be displayed at a
- different position to its document position. If no lines are folded, this message returns
+ When some lines are hidden and/or annotations are displayed, then a particular line in the
+ document may be displayed at a
+ different position to its document position. If no lines are hidden and there are no annotations,
+ this message returns
<code>docLine</code>. Otherwise, this returns the display line (counting the very first visible
line as 0). The display line of an invisible line is the same as the previous visible line. The
- display line number of the first line in the document is 0. If there is folding and
+ display line number of the first line in the document is 0. If lines are hidden and
<code>docLine</code> is outside the range of lines in the document, the return value is -1.
Lines can occupy more than one display line if they wrap.</p>
<p><b id="SCI_DOCLINEFROMVISIBLE">SCI_DOCLINEFROMVISIBLE(int displayLine)</b><br />
- When some lines are hidden, then a particular line in the document may be displayed at a
+ When some lines are hidden and/or annotations are displayed, then a particular line in the
+ document may be displayed at a
different position to its document position. This message returns the document line number that
corresponds to a display line (counting the display line of the first line in the document as
0). If <code>displayLine</code> is less than or equal to 0, the result is 0. If
@@ -5632,8 +5734,18 @@ sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){ <a class="message" href="#SCI_DESCRIBEKEYWORDSETS">SCI_DESCRIBEKEYWORDSETS(<unused>, char *descriptions)</a><br />
<a class="message" href="#SCI_SETKEYWORDS">SCI_SETKEYWORDS(int keyWordSet, const char
*keyWordList)</a><br />
- <a class="message" href="#SCI_GETSTYLEBITSNEEDED">SCI_GETSTYLEBITSNEEDED</a>
- <br />
+ <a class="message" href="#SCI_GETSTYLEBITSNEEDED">SCI_GETSTYLEBITSNEEDED</a><br />
+
+<div class="provisional">
+ <a class="message" href="#SCI_GETSUBSTYLEBASES">SCI_GETSUBSTYLEBASES(<unused>, char *styles)</a><br />
+ <a class="message" href="#SCI_DISTANCETOSECONDARYSTYLES">SCI_DISTANCETOSECONDARYSTYLES</a><br />
+ <a class="message" href="#SCI_ALLOCATESUBSTYLES">SCI_ALLOCATESUBSTYLES(int styleBase, int numberStyles)</a><br />
+ <a class="message" href="#SCI_FREESUBSTYLES">SCI_FREESUBSTYLES</a><br />
+ <a class="message" href="#SCI_GETSUBSTYLESSTART">SCI_GETSUBSTYLESSTART(int styleBase)</a><br />
+ <a class="message" href="#SCI_GETSUBSTYLESLENGTH">SCI_GETSUBSTYLESLENGTH(int styleBase)</a><br />
+ <a class="message" href="#SCI_SETIDENTIFIERS">SCI_SETIDENTIFIERS(int style, const char *identifiers)</a><br />
+</div>
+
</code>
<p><b id="SCI_SETLEXER">SCI_SETLEXER(int lexer)</b><br />
@@ -5779,6 +5891,37 @@ sptr_t CallScintilla(unsigned int iMessage, uptr_t wParam, sptr_t lParam){ to <a class="message" href="#SCI_SETSTYLEBITS">SCI_SETSTYLEBITS</a>.
</p>
+<div class="provisional">
+ <h3 id="Substyles">Substyles</h3>
+ <a href="#ProvisionalMessages">These features are provisional</a><br />
+ <p>Lexers may support several different sublanguages and each sublanguage may want to style some number of
+ sets of identifiers (or similar lexemes such as documentation keywords) uniquely. Preallocating a large number for each
+ purpose would exhaust the number of allowed styles quickly.
+ This is alleviated by substyles which allow the application to determine how many sets of identifiers to allocate for
+ each purpose.
+ Lexers have to explicitly support this feature by implementing the methods in <code>ILexerWithSubStyles</code>.</p>
+
+ <p><b id="SCI_GETSUBSTYLEBASES">SCI_GETSUBSTYLEBASES(<unused>, char *styles)</b><br />
+ Fill <code>styles</code> with a byte for each style that can be split into substyles.</p>
+
+ <p><b id="SCI_DISTANCETOSECONDARYSTYLES">SCI_DISTANCETOSECONDARYSTYLES</b><br />
+ Returns the distance between a primary style and its corresponding secondary style.</p>
+
+ <p><b id="SCI_ALLOCATESUBSTYLES">SCI_ALLOCATESUBSTYLES(int styleBase, int numberStyles)</b><br />
+ Allocate some number of substyles for a particular base style returning the first substyle number allocated.
+ Substyles are allocated contiguously.</p>
+
+ <p><b id="SCI_FREESUBSTYLES">SCI_FREESUBSTYLES</b><br />
+ Free all allocated substyles.</p>
+
+ <p><b id="SCI_GETSUBSTYLESSTART">SCI_GETSUBSTYLESSTART(int styleBase)</b><br />
+ <b id="SCI_GETSUBSTYLESLENGTH">SCI_GETSUBSTYLESLENGTH(int styleBase)</b><br />
+ Return the start and length of the substyles allocated for a base style.</p>
+
+ <p><b id="SCI_SETIDENTIFIERS">SCI_SETIDENTIFIERS(int style, const char *identifiers)</b><br />
+ Similar to <code>SCI_SETKEYWORDS</code> but for substyles.</p>
+</div>
+
<h2 id="LexerObjects">Lexer Objects</h2>
<p>Lexers are programmed as objects that implement the ILexer interface and that interact
@@ -5893,6 +6036,27 @@ needs to be folded as this allowed fixing up the last line from the previous fol The new approach allows the lexer to decide whether to backtrack or to handle this
more efficiently.</p>
+<h4 class="provisional">ILexerWithSubStyles</h4>
+
+<p class="provisional">
+To allow lexers to report which line ends they support, and to support substyles,
+<code>Ilexer</code> is extended to <code>ILexerWithSubStyles</code>.
+</p>
+
+<div class="highlighted">
+<span class="S5">class</span><span class="S0"> </span>ILexerWithSubStyles<span class="S0"> </span><span class="S10">:</span><span class="S0"> </span><span class="S5">public</span><span class="S0"> </span>ILexer<span class="S0"> </span><span class="S10">{</span><br />
+<span class="S5">public</span><span class="S10">:</span><br />
+<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>LineEndTypesSupported<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
+<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>AllocateSubStyles<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>styleBase<span class="S10">,</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>numberStyles<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
+<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>SubStylesStart<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>styleBase<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
+<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>SubStylesLength<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>styleBase<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
+<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>FreeSubStyles<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
+<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">void</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>SetIdentifiers<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>style<span class="S10">,</span><span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S5">char</span><span class="S0"> </span><span class="S10">*</span>identifiers<span class="S10">)</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
+<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>DistanceToSecondaryStyles<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
+<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S5">char</span><span class="S0"> </span><span class="S10">*</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>GetSubStyleBases<span class="S10">()</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
+<span class="S10">};</span><br />
+</div>
+
<h4>IDocument</h4>
<div class="highlighted">
@@ -6041,7 +6205,22 @@ exceptions. Exceptions should not be thrown over build boundaries as the two sides may be built with different compilers or incompatible
exception options.</p>
-<p>The <code>ILexer</code> and <code>IDocument</code> interfaces may be
+<h4>IDocumentWithLineEnd</h4>
+
+<p>
+To allow lexers to determine the end position of a line and thus more easily support Unicode line ends
+<code>IDocument</code> is extended to <code>IDocumentWithLineEnd</code>.
+</p>
+
+<div class="highlighted">
+<span class="S5">class</span><span class="S0"> </span>IDocumentWithLineEnd<span class="S0"> </span><span class="S10">:</span><span class="S0"> </span><span class="S5">public</span><span class="S0"> </span>IDocument<span class="S0"> </span><span class="S10">{</span><br />
+<span class="S5">public</span><span class="S10">:</span><br />
+<span class="S0"> </span><span class="S5">virtual</span><span class="S0"> </span><span class="S5">int</span><span class="S0"> </span>SCI_METHOD<span class="S0"> </span>LineEnd<span class="S10">(</span><span class="S5">int</span><span class="S0"> </span>line<span class="S10">)</span><span class="S0"> </span><span class="S5">const</span><span class="S0"> </span><span class="S10">=</span><span class="S0"> </span><span class="S4">0</span><span class="S10">;</span><br />
+<span class="S10">};</span><br />
+</div>
+
+<p>The <code>ILexer</code>, <code>ILexerWithSubStyles</code>, <code>IDocument</code>, and
+<code>IDocumentWithLineEnd</code> interfaces may be
expanded in the future with extended versions (<code>ILexer2</code>...).
The <code>Version</code> method indicates which interface is
implemented and thus which methods may be called.</p>
@@ -6903,8 +7082,7 @@ for line = lineStart to lineEnd do SCI_ENSUREVISIBLE(line) next If there is no suitable platform support, the <a href="http://lodev.org/lodepng/">LodePNG and picoPNG</a> libraries are small libraries
for loading and decoding PNG files available under a BSD-style license.</p>
- <p>RGBA format is supported on Windows, GTK+ and OS X Cocoa.
- It is not supported on OS X Carbon.</p>
+ <p>RGBA format is supported on Windows, GTK+ and OS X Cocoa.</p>
<h3 id="XPM">XPM</h3>
@@ -6948,6 +7126,17 @@ for line = lineStart to lineEnd do SCI_ENSUREVISIBLE(line) next <p><b id="scintilla_release_resources">void scintilla_release_resources()</b><br />
Call this to free any remaining resources after all the Scintilla widgets have been destroyed.</p>
+ <h2 id="ProvisionalMessages">Provisional messages</h2>
+
+ <p>Complex new features may be added as 'provisional' to allow further changes to the API.
+ Provisional features may even be removed if experience shows they are a mistake.</p>
+
+ <p>Provisional features are displayed in this document with <span class="provisional">a distinctive background colour</span>.</p>
+
+ <p>Some developers may want to only use features that are stable and have graduated from
+ provisional status. To avoid using provisional messages compile with the symbol
+ <code>SCI_DISABLE_PROVISIONAL</code> defined.</p>
+
<h2 id="DeprecatedMessages">Deprecated messages and notifications</h2>
<p>The following messages are currently supported to emulate existing Windows controls, but
diff --git a/scintilla/doc/ScintillaDownload.html b/scintilla/doc/ScintillaDownload.html index 9b305fe..846ba81 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/scintilla323.zip?download">
+ <font size="4"> <a href="http://prdownloads.sourceforge.net/scintilla/scintilla330.zip?download">
Windows</a>
- <a href="http://prdownloads.sourceforge.net/scintilla/scintilla323.tgz?download">
+ <a href="http://prdownloads.sourceforge.net/scintilla/scintilla330.tgz?download">
GTK+/Linux</a>
</font>
</td>
@@ -41,7 +41,7 @@ containing very few restrictions.
</p>
<h3>
- Release 3.2.3
+ Release 3.3.0
</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/scintilla323.zip?download">zip format</a> (1250K) commonly used on Windows</li>
- <li><a href="http://prdownloads.sourceforge.net/scintilla/scintilla323.tgz?download">tgz format</a> (1100K) commonly used on Linux and compatible operating systems</li>
+ <li><a href="http://prdownloads.sourceforge.net/scintilla/scintilla330.zip?download">zip format</a> (1250K) commonly used on Windows</li>
+ <li><a href="http://prdownloads.sourceforge.net/scintilla/scintilla330.tgz?download">tgz format</a> (1100K) 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 032e7a0..becfb5a 100644 --- a/scintilla/doc/ScintillaHistory.html +++ b/scintilla/doc/ScintillaHistory.html @@ -415,6 +415,13 @@ <td>Joel B. Mohler</td>
<td>Isiledhel</td>
<td>Vidya Wasi</td>
+ </tr><tr>
+ <td>G. Hu</td>
+ <td>Byron Hawkins</td>
+ <td>Alpha</td>
+ <td>John Donoghue</td>
+ </tr><tr>
+ <td>kudah</td>
</tr>
</table>
<p>
@@ -427,6 +434,205 @@ </li>
</ul>
<h3>
+ 3.3.1 placeholder
+ </h3>
+ <ul>
+ <li>
+ Haskell lexer improved in several ways.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1459/">Bug #1459.</a>
+ </li>
+ <li>
+ Matlab/Octave lexer recognises block comments and ... comments.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1414/">Bug #1414.</a>
+ </li>
+ <li>
+ The PLAT_NCURSES platform now called PLAT_CURSES as may work on other implementations.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite330.zip?download">Release 3.3.0</a>
+ </h3>
+ <ul>
+ <li>
+ Released 30 March 2013.
+ </li>
+ <li>
+ Overlay scrollers and kinetic scrolling implemented on Cocoa.
+ </li>
+ <li>
+ To improve display smoothness, styling and UI Update notifications will, when possible, be performed in
+ a high-priority idle task on Cocoa instead of during painting.
+ Performing these jobs inside painting can cause paints to be abandoned and a new paint scheduled.
+ On GTK+, the high-priority idle task is used in more cases.
+ </li>
+ <li>
+ SCI_SCROLLRANGE added to scroll the view to display a range of text.
+ If the whole range can not be displayed, priority is given to one end.
+ </li>
+ <li>
+ C++ lexer no longer recognises raw (R"") strings when the first character after "
+ is invalid.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1454/">Bug #1454.</a>
+ </li>
+ <li>
+ HTML lexer recognises JavaScript RegEx literals in more contexts.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1412/">Bug #1412.</a>
+ </li>
+ <li>
+ Fixed automatic display of folded text when return pressed at end of fold header and
+ first folded line was blank.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1455/">Bug #1455.</a>
+ </li>
+ <li>
+ SCI_VISIBLEFROMDOCLINE fixed to never return a line beyond the document end.
+ </li>
+ <li>
+ SCI_LINESCROLL fixed for a negative column offset.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1450/">Bug #1450.</a>
+ </li>
+ <li>
+ On GTK+, fix tab markers so visible if indent markers are visible.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1453/">Bug #1453.</a>
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite325.zip?download">Release 3.2.5</a>
+ </h3>
+ <ul>
+ <li>
+ Released 26 February 2013.
+ </li>
+ <li>
+ To allow cooperation between different uses of extended (beyond 255) styles they should be allocated
+ using SCI_ALLOCATEEXTENDEDSTYLES.
+ </li>
+ <li>
+ For Unicode documents, lexers that use StyleContext will retrieve whole characters
+ instead of bytes.
+ LexAccessor provides a LineEnd method which can be a more efficient way to
+ handle line ends and can enable Unicode line ends.
+ </li>
+ <li>
+ The C++ lexer understands the #undef directive when determining preprocessor definitions.
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/978/">Feature #978.</a>
+ </li>
+ <li>
+ The errorlist lexer recognises gcc include path diagnostics that appear before an error.
+ </li>
+ <li>
+ Folding implemented for GetText (PO) translation language.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1437/">Bug #1437.</a>
+ </li>
+ <li>
+ HTML lexer does not interrupt comment style for processing instructions.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1447/">Bug #1447.</a>
+ </li>
+ <li>
+ Fix SciTE forgetting caret x-position when switching documents.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1442/">Bug #1442.</a>
+ </li>
+ <li>
+ Fixed bug where vertical scrollbar thumb appeared at beginning of document when
+ scrollbar shown.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1446/">Bug #1446.</a>
+ </li>
+ <li>
+ Fixed brace-highlighting bug on OS X 10.8 where matching brace is on a different line.
+ </li>
+ <li>
+ <a href="ScintillaDoc.html#ProvisionalMessages">Provisional features</a>
+ are new features that may change or be removed if they cause problems but should become
+ permanent if they work well.
+ For this release <a href="ScintillaDoc.html#SCI_GETLINEENDTYPESSUPPORTED">Unicode line ends</a> and
+ <a href="ScintillaDoc.html#Substyles">substyles</a>
+ are provisional features.
+ </li>
+ </ul>
+ <h3>
+ <a href="http://prdownloads.sourceforge.net/scintilla/scite324.zip?download">Release 3.2.4</a>
+ </h3>
+ <ul>
+ <li>
+ Released 17 January 2013.
+ </li>
+ <li>
+ Caret line highlight can optionally remain visible when window does not have focus.
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/964/">Feature #964.</a>
+ </li>
+ <li>
+ Delegate mechanism for notifications added on Cocoa.
+ </li>
+ <li>
+ NUL characters in selection are copied to clipboard as spaces to avoid truncating
+ at the NUL.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1289/">Bug #1289.</a>
+ </li>
+ <li>
+ C++ lexer fixes problem with showing inactive sections when preprocessor lines contain trailing comment.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1413/">Bug #1413.</a>
+ </li>
+ <li>
+ C++ lexer fixes problem with JavaScript regular expressions with '/' in character ranges.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1415/">Bug #1415.</a>
+ </li>
+ <li>
+ LaTeX folder added.
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/970/">Feature #970.</a>
+ </li>
+ <li>
+ LaTeX lexer improves styling of math environments.
+ <a href="http://sourceforge.net/p/scintilla/feature-requests/970/">Feature #970.</a>
+ </li>
+ <li>
+ MySQL lexer implements hidden commands.
+ </li>
+ <li>
+ Only produce a single undo step when autocompleting a single word.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1421/">Bug #1421.</a>
+ </li>
+ <li>
+ Fixed crash when printing lines longer than 8000 characters.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1430/">Bug #1430.</a>
+ </li>
+ <li>
+ Fixed problem in character movement extends selection mode where reversing
+ direction collapsed the selection.
+ </li>
+ <li>
+ Memory issues fixed on Cocoa, involving object ownership,
+ lifetime of timers, and images held by the info bar.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1436/">Bug #1436.</a>
+ </li>
+ <li>
+ Cocoa key binding for Alt+Delete changed to delete previous word to be more compatible with
+ platform standards.
+ </li>
+ <li>
+ Fixed crash on Cocoa with scrollbar when there is no scrolling possible.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1416/">Bug #1416.</a>
+ </li>
+ <li>
+ On Cocoa with retina display fixed positioning of autocompletion lists.
+ </li>
+ <li>
+ Fixed SciTE on Windows failure to run a batch file with a name containing a space by
+ quoting the path in the properties file.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1423/">Bug #1423.</a>
+ </li>
+ <li>
+ Fixed scaling bug when printing on GTK+.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1427/">Bug #1427.</a>
+ </li>
+ <li>
+ SciTE on GTK toolbar.detachable feature removed.
+ </li>
+ <li>
+ Fixed some background saving bugs in SciTE.
+ <a href="http://sourceforge.net/p/scintilla/bugs/1366/">Bug #1366.</a>
+ <a href="http://sourceforge.net/p/scintilla/bugs/1339/">Bug #1339.</a>
+ </li>
+ </ul>
+ <h3>
<a href="http://prdownloads.sourceforge.net/scintilla/scite323.zip?download">Release 3.2.3</a>
</h3>
<ul>
@@ -452,7 +658,7 @@ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3515392&group_id=2439">Bug #3515392.</a>
</li>
<li>
- For C/C++, recognize exponent in floating point hexadecimal literals.
+ For C/C++, recognise exponent in floating point hexadecimal literals.
<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3576454&group_id=2439">Bug #3576454.</a>
</li>
<li>
@@ -1306,7 +1512,7 @@ Fixed leak of document objects in SciTE.
</li>
<li>
- Recognize URL characters '?' and '%' for Open Selected command in SciTE.
+ Recognise URL characters '?' and '%' for Open Selected command in SciTE.
<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3429409&group_id=2439">Bug #3429409.</a>
</li>
</ul>
@@ -1999,7 +2205,7 @@ Performance improved when creating large rectangular selections.
</li>
<li>
- PHP folder recognizes #region and #endregion comments.
+ PHP folder recognises #region and #endregion comments.
<a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3101624&group_id=2439">Feature #3101624.</a>
</li>
<li>
@@ -2008,7 +2214,7 @@ <a href="https://sourceforge.net/tracker/?func=detail&atid=352439&aid=3098071&group_id=2439">Feature #3098071.</a>
</li>
<li>
- SQL folder recognizes case statements and understands the fold.at.else property.
+ SQL folder recognises case statements and understands the fold.at.else property.
<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3104091&group_id=2439">Bug #3104091.</a>
<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3107362&group_id=2439">Bug #3107362.</a>
</li>
@@ -2102,7 +2308,7 @@ <a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3058924&group_id=2439">Bug #3058924.</a>
</li>
<li>
- JavaScript lexer recognize regexes following return keyword.‎
+ JavaScript lexer recognise regexes following return keyword.‎
<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=3062287&group_id=2439">Bug #3062287.</a>
</li>
<li>
@@ -2565,7 +2771,7 @@ </li>
<li>
Erlang lexer extended set of numeric bases recognised; separate style for module:function_name; detects
- built-in functions, known module attributes, and known preprocessor instructions; recognizes EDoc and EDoc macros;
+ built-in functions, known module attributes, and known preprocessor instructions; recognises EDoc and EDoc macros;
separates types of comments.
<a href="https://sourceforge.net/tracker/?func=detail&atid=102439&aid=2942448&group_id=2439">Bug #2942448.</a>
</li>
@@ -3518,7 +3724,7 @@ Style changes may be made during text modification events.
</li>
<li>
- Regular expressions recognize \d, \D, \s, \S, \w, \W, and \xHH.
+ Regular expressions recognise \d, \D, \s, \S, \w, \W, and \xHH.
</li>
<li>
Support for cmake language added.
diff --git a/scintilla/doc/ScintillaToDo.html b/scintilla/doc/ScintillaToDo.html index dffd421..17b9307 100644 --- a/scintilla/doc/ScintillaToDo.html +++ b/scintilla/doc/ScintillaToDo.html @@ -29,8 +29,8 @@ Feedback
</h3>
<p>
- Issues can be reported on the <a href="https://sourceforge.net/tracker/?group_id=2439&atid=102439">Bug Tracker</a>
- and features requested on the <a href="https://sourceforge.net/tracker/?group_id=2439&atid=352439">Feature Request Tracker</a>.
+ Issues can be reported on the <a href="http://sourceforge.net/p/scintilla/bugs/">Bug Tracker</a>
+ and features requested on the <a href="http://sourceforge.net/p/scintilla/feature-requests/">Feature Request Tracker</a>.
</p>
<h3>
Scintilla Bugs
diff --git a/scintilla/doc/index.html b/scintilla/doc/index.html index 005e3ac..00ea4c1 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="20121021" />
+ <meta name="Date.Modified" content="20130330" />
<style type="text/css">
#versionlist {
margin: 0;
@@ -55,8 +55,8 @@ GTK+</font>
</td>
<td width="40%" align="right">
- <font color="#FFCC99" size="3"> Release version 3.2.3<br />
- Site last modified October 21 2012</font>
+ <font color="#FFCC99" size="3"> Release version 3.3.0<br />
+ Site last modified March 30 2013</font>
</td>
<td width="20%">
@@ -71,13 +71,13 @@ </tr>
</table>
<ul id="versionlist">
- <li>Version 3.2.3 improves speed when performing multiple searches.</li>
- <li>Version 3.2.2 supports retina displays on Cocoa.</li>
- <li>Version 3.2.1 adds some minor features and fixes bugs.</li>
- <li>Version 3.2.0 adds support for the Qt platform and PySide Python bindings.</li>
- <li>Version 3.1.0 adds an animated find indicator on Cocoa.</li>
- <li>Version 3.0.4 fixes minor problems particularly with Direct2D.</li>
- <li>Version 3.0.3 uses fractional positioning in more situations.</li>
+ <li>Version 3.3.0 implements overlay scrollers and kinetic scrolling on Cocoa.
+ Performance improved on GTK+ and Cocoa by performing more work in
+ high-priority idle tasks.</li>
+ <li>Version 3.2.5 SCI_ALLOCATEEXTENDEDSTYLES introduced so that different uses
+ of extended styles can cooperate.
+ Unicode line ends and substyles are added as provisional features which means
+ they may change before becoming permanent.</li>
</ul>
<ul id="menu">
<li id="remote1"><a href="http://www.scintilla.org/SciTEImage.html">Screenshot</a></li>
diff --git a/scintilla/include/HFacer.py b/scintilla/include/HFacer.py index 1dc25be..911b703 100644 --- a/scintilla/include/HFacer.py +++ b/scintilla/include/HFacer.py @@ -20,9 +20,13 @@ def printLexHFile(f,out): out.write("#define " + name + " " + v["Value"] + "\n")
def printHFile(f,out):
+ previousCategory = ""
for name in f.order:
v = f.features[name]
if v["Category"] != "Deprecated":
+ if v["Category"] == "Provisional" and previousCategory != "Provisional":
+ out.write("#ifndef SCI_DISABLE_PROVISIONAL\n")
+ previousCategory = v["Category"]
if v["FeatureType"] in ["fun", "get", "set"]:
featureDefineName = "SCI_" + name.upper()
out.write("#define " + featureDefineName + " " + v["Value"] + "\n")
@@ -32,6 +36,7 @@ def printHFile(f,out): elif v["FeatureType"] in ["val"]:
if not (Contains(name, "SCE_") or Contains(name, "SCLEX_")):
out.write("#define " + name + " " + v["Value"] + "\n")
+ out.write("#endif\n")
def CopyWithInsertion(input, output, genfn, definition):
copying = 1
diff --git a/scintilla/include/ILexer.h b/scintilla/include/ILexer.h index 723e8cd..795a7d7 100644 --- a/scintilla/include/ILexer.h +++ b/scintilla/include/ILexer.h @@ -18,7 +18,7 @@ namespace Scintilla { #define SCI_METHOD
#endif
-enum { dvOriginal=0 };
+enum { dvOriginal=0, dvLineEnd=1 };
class IDocument {
public:
@@ -45,7 +45,12 @@ public: virtual int SCI_METHOD GetLineIndentation(int line) = 0;
};
-enum { lvOriginal=0 };
+class IDocumentWithLineEnd : public IDocument {
+public:
+ virtual int SCI_METHOD LineEnd(int line) const = 0;
+};
+
+enum { lvOriginal=0, lvSubStyles=1 };
class ILexer {
public:
@@ -62,6 +67,18 @@ public: virtual void * SCI_METHOD PrivateCall(int operation, void *pointer) = 0;
};
+class ILexerWithSubStyles : public ILexer {
+public:
+ virtual int SCI_METHOD LineEndTypesSupported() = 0;
+ virtual int SCI_METHOD AllocateSubStyles(int styleBase, int numberStyles) = 0;
+ virtual int SCI_METHOD SubStylesStart(int styleBase) = 0;
+ virtual int SCI_METHOD SubStylesLength(int styleBase) = 0;
+ virtual void SCI_METHOD FreeSubStyles() = 0;
+ virtual void SCI_METHOD SetIdentifiers(int style, const char *identifiers) = 0;
+ virtual int SCI_METHOD DistanceToSecondaryStyles() = 0;
+ virtual const char * SCI_METHOD GetSubStyleBases() = 0;
+};
+
class ILoader {
public:
virtual int SCI_METHOD Release() = 0;
diff --git a/scintilla/include/Platform.h b/scintilla/include/Platform.h index a481595..7ce9d37 100644 --- a/scintilla/include/Platform.h +++ b/scintilla/include/Platform.h @@ -22,7 +22,7 @@ #define PLAT_WX 0
#define PLAT_QT 0
#define PLAT_FOX 0
-#define PLAT_NCURSES 0
+#define PLAT_CURSES 0
#if defined(FOX)
#undef PLAT_FOX
@@ -32,9 +32,9 @@ #undef PLAT_WX
#define PLAT_WX 1
-#elif defined(NCURSES)
-#undef PLAT_NCURSES
-#define PLAT_NCURSES 1
+#elif defined(CURSES)
+#undef PLAT_CURSES
+#define PLAT_CURSES 1
#elif defined(SCINTILLA_QT)
#undef PLAT_QT
diff --git a/scintilla/include/SciLexer.h b/scintilla/include/SciLexer.h index f2a0a64..1027a0a 100644 --- a/scintilla/include/SciLexer.h +++ b/scintilla/include/SciLexer.h @@ -478,6 +478,7 @@ #define SCE_ERR_TIDY 19
#define SCE_ERR_JAVA_STACK 20
#define SCE_ERR_VALUE 21
+#define SCE_ERR_GCC_INCLUDED_FROM 22
#define SCE_BAT_DEFAULT 0
#define SCE_BAT_COMMENT 1
#define SCE_BAT_WORD 2
@@ -1020,6 +1021,8 @@ #define SCE_HA_COMMENTBLOCK 14
#define SCE_HA_COMMENTBLOCK2 15
#define SCE_HA_COMMENTBLOCK3 16
+#define SCE_HA_PRAGMA 17
+#define SCE_HA_PREPROCESSOR 18
#define SCE_T3_DEFAULT 0
#define SCE_T3_X_DEFAULT 1
#define SCE_T3_PREPROCESSOR 2
@@ -1346,6 +1349,7 @@ #define SCE_MYSQL_USER2 19
#define SCE_MYSQL_USER3 20
#define SCE_MYSQL_HIDDENCOMMAND 21
+#define SCE_MYSQL_PLACEHOLDER 22
#define SCE_PO_DEFAULT 0
#define SCE_PO_COMMENT 1
#define SCE_PO_MSGID 2
diff --git a/scintilla/include/Scintilla.h b/scintilla/include/Scintilla.h index 053ec62..a204219 100644 --- a/scintilla/include/Scintilla.h +++ b/scintilla/include/Scintilla.h @@ -148,6 +148,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_MARKERDEFINEPIXMAP 2049
#define SCI_MARKERADDSET 2466
#define SCI_MARKERSETALPHA 2476
+#define SC_MAX_MARGIN 4
#define SC_MARGIN_SYMBOL 0
#define SC_MARGIN_NUMBER 1
#define SC_MARGIN_BACK 2
@@ -381,6 +382,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_POSITIONFROMLINE 2167
#define SCI_LINESCROLL 2168
#define SCI_SCROLLCARET 2169
+#define SCI_SCROLLRANGE 2569
#define SCI_REPLACESEL 2170
#define SCI_SETREADONLY 2171
#define SCI_NULL 2172
@@ -696,6 +698,11 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE 1
#define SCI_AUTOCSETCASEINSENSITIVEBEHAVIOUR 2634
#define SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR 2635
+#define SC_ORDER_PRESORTED 0
+#define SC_ORDER_PERFORMSORT 1
+#define SC_ORDER_CUSTOM 2
+#define SCI_AUTOCSETORDER 2660
+#define SCI_AUTOCGETORDER 2661
#define SCI_ALLOCATE 2446
#define SCI_TARGETASUTF8 2447
#define SCI_SETLENGTHFORENCODE 2448
@@ -775,6 +782,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCI_ANNOTATIONGETVISIBLE 2549
#define SCI_ANNOTATIONSETSTYLEOFFSET 2550
#define SCI_ANNOTATIONGETSTYLEOFFSET 2551
+#define SCI_RELEASEALLEXTENDEDSTYLES 2552
+#define SCI_ALLOCATEEXTENDEDSTYLES 2553
#define UNDO_MAY_COALESCE 1
#define SCI_ADDUNDOACTION 2560
#define SCI_CHARPOSITIONFROMPOINT 2561
@@ -959,6 +968,21 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam, #define SCN_AUTOCCANCELLED 2025
#define SCN_AUTOCCHARDELETED 2026
#define SCN_HOTSPOTRELEASECLICK 2027
+#ifndef SCI_DISABLE_PROVISIONAL
+#define SC_LINE_END_TYPE_DEFAULT 0
+#define SC_LINE_END_TYPE_UNICODE 1
+#define SCI_SETLINEENDTYPESALLOWED 2656
+#define SCI_GETLINEENDTYPESALLOWED 2657
+#define SCI_GETLINEENDTYPESACTIVE 2658
+#define SCI_GETLINEENDTYPESSUPPORTED 4018
+#define SCI_ALLOCATESUBSTYLES 4020
+#define SCI_GETSUBSTYLESSTART 4021
+#define SCI_GETSUBSTYLESLENGTH 4022
+#define SCI_FREESUBSTYLES 4023
+#define SCI_SETIDENTIFIERS 4024
+#define SCI_DISTANCETOSECONDARYSTYLES 4025
+#define SCI_GETSUBSTYLEBASES 4026
+#endif
/* --Autogenerated -- end of section automatically generated from Scintilla.iface */
/* These structures are defined to be exactly the same shape as the Win32
diff --git a/scintilla/include/Scintilla.iface b/scintilla/include/Scintilla.iface index 0691b1b..89c09d1 100644 --- a/scintilla/include/Scintilla.iface +++ b/scintilla/include/Scintilla.iface @@ -326,6 +326,8 @@ fun void MarkerAddSet=2466(int line, int set) # Set the alpha used for a marker that is drawn in the text area, not the margin.
set void MarkerSetAlpha=2476(int markerNumber, int alpha)
+val SC_MAX_MARGIN=4
+
enu MarginType=SC_MARGIN_
val SC_MARGIN_SYMBOL=0
val SC_MARGIN_NUMBER=1
@@ -922,6 +924,11 @@ fun void LineScroll=2168(int columns, int lines) # Ensure the caret is visible.
fun void ScrollCaret=2169(,)
+# Scroll the argument positions and the range between them into view giving
+# priority to the primary position then the secondary position.
+# This may be used to make a search match visible.
+fun void ScrollRange=2569(position secondary, position primary)
+
# Replace the selected text with the argument text.
fun void ReplaceSel=2170(, string text)
@@ -1835,6 +1842,17 @@ set void AutoCSetCaseInsensitiveBehaviour=2634(int behaviour,) # Get auto-completion case insensitive behaviour.
get int AutoCGetCaseInsensitiveBehaviour=2635(,)
+enu Ordering=SC_ORDER_
+val SC_ORDER_PRESORTED=0
+val SC_ORDER_PERFORMSORT=1
+val SC_ORDER_CUSTOM=2
+
+# Set the way autocompletion lists are ordered.
+set void AutoCSetOrder=2660(int order,)
+
+# Get the way autocompletion lists are ordered.
+get int AutoCGetOrder=2661(,)
+
# Enlarge the document to a particular size of text bytes.
fun void Allocate=2446(int bytes,)
@@ -2062,6 +2080,12 @@ set void AnnotationSetStyleOffset=2550(int style,) # Get the start of the range of style numbers used for annotations
get int AnnotationGetStyleOffset=2551(,)
+# Release all extended (>255) style numbers
+fun void ReleaseAllExtendedStyles=2552(,)
+
+# Allocate some extended (>255) style numbers and return the start of the range
+fun int AllocateExtendedStyles=2553(int numberStyles,)
+
val UNDO_MAY_COALESCE=1
# Add a container action to the undo stack
@@ -2931,6 +2955,7 @@ val SCE_ERR_ABSF=18 val SCE_ERR_TIDY=19
val SCE_ERR_JAVA_STACK=20
val SCE_ERR_VALUE=21
+val SCE_ERR_GCC_INCLUDED_FROM=22
# Lexical states for SCLEX_BATCH
lex Batch=SCLEX_BATCH SCE_BAT_
val SCE_BAT_DEFAULT=0
@@ -3559,6 +3584,8 @@ val SCE_HA_COMMENTLINE=13 val SCE_HA_COMMENTBLOCK=14
val SCE_HA_COMMENTBLOCK2=15
val SCE_HA_COMMENTBLOCK3=16
+val SCE_HA_PRAGMA=17
+val SCE_HA_PREPROCESSOR=18
# Lexical states of SCLEX_TADS3
lex TADS3=SCLEX_TADS3 SCE_T3_
val SCE_T3_DEFAULT=0
@@ -3923,6 +3950,7 @@ val SCE_MYSQL_USER1=18 val SCE_MYSQL_USER2=19
val SCE_MYSQL_USER3=20
val SCE_MYSQL_HIDDENCOMMAND=21
+val SCE_MYSQL_PLACEHOLDER=22
# Lexical state for SCLEX_PO
lex Po=SCLEX_PO SCE_PO_
val SCE_PO_DEFAULT=0
@@ -4277,6 +4305,50 @@ evt void AutoCCancelled=2025(void) evt void AutoCCharDeleted=2026(void)
evt void HotSpotReleaseClick=2027(int modifiers, int position)
+cat Provisional
+
+# Line end types which may be used in addition to LF, CR, and CRLF
+# SC_LINE_END_TYPE_UNICODE includes U+2028 Line Separator,
+# U+2029 Paragraph Separator, and U+0085 Next Line
+enu LineEndType=SC_LINE_END_TYPE_
+val SC_LINE_END_TYPE_DEFAULT=0
+val SC_LINE_END_TYPE_UNICODE=1
+
+# Set the line end types that the application wants to use. May not be used if incompatible with lexer or encoding.
+set void SetLineEndTypesAllowed=2656(int lineEndBitSet,)
+
+# Get the line end types currently allowed.
+get int GetLineEndTypesAllowed=2657(,)
+
+# Get the line end types currently recognised. May be a subset of the allowed types due to lexer limitation.
+get int GetLineEndTypesActive=2658(,)
+
+# Bit set of LineEndType enumertion for which line ends beyond the standard
+# LF, CR, and CRLF are supported by the lexer.
+get int GetLineEndTypesSupported=4018(,)
+
+# Allocate a set of sub styles for a particular base style, returning start of range
+fun int AllocateSubStyles=4020(int styleBase, int numberStyles)
+
+# The starting style number for the sub styles associated with a base style
+get int GetSubStylesStart=4021(int styleBase,)
+
+# The number of sub styles associated with a base style
+get int GetSubStylesLength=4022(int styleBase,)
+
+# Free allocated sub styles
+fun void FreeSubStyles=4023(,)
+
+# Set the identifiers that are shown in a particular style
+set void SetIdentifiers=4024(int style, string identifiers)
+
+# Where styles are duplicated by a feature such as active/inactive code
+# return the distance between the two types.
+get int DistanceToSecondaryStyles=4025(,)
+
+# Get the set of base styles that can be extended with sub styles
+get int GetSubStyleBases=4026(, stringresult styles)
+
cat Deprecated
# Deprecated in 2.21
diff --git a/scintilla/lexers/LexCPP.cxx b/scintilla/lexers/LexCPP.cxx index d08bc1b..2c00003 100644 --- a/scintilla/lexers/LexCPP.cxx +++ b/scintilla/lexers/LexCPP.cxx @@ -30,6 +30,7 @@ #include "LexerModule.h"
#include "OptionSet.h"
#include "SparseState.h"
+#include "SubStyles.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
@@ -65,9 +66,8 @@ static bool followsReturnKeyword(StyleContext &sc, LexAccessor &styler) { int pos = (int) sc.currentPos;
int currentLine = styler.GetLine(pos);
int lineStartPos = styler.LineStart(currentLine);
- char ch;
while (--pos > lineStartPos) {
- ch = styler.SafeGetCharAt(pos);
+ char ch = styler.SafeGetCharAt(pos);
if (ch != ' ' && ch != '\t') {
break;
}
@@ -87,7 +87,8 @@ static std::string GetRestOfLine(LexAccessor &styler, int start, bool allowSpace std::string restOfLine;
int i =0;
char ch = styler.SafeGetCharAt(start, '\n');
- while ((ch != '\r') && (ch != '\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;
@@ -130,8 +131,9 @@ struct PPDefinition { int line;
std::string key;
std::string value;
- PPDefinition(int line_, const std::string &key_, const std::string &value_) :
- line(line_), key(key_), value(value_) {
+ bool isUndef;
+ PPDefinition(int line_, const std::string &key_, const std::string &value_, bool isUndef_ = false) :
+ line(line_), key(key_), value(value_), isUndef(isUndef_) {
}
};
@@ -310,7 +312,9 @@ struct OptionSetCPP : public OptionSet<OptionsCPP> { }
};
-class LexerCPP : public ILexer {
+static const char styleSubable[] = {SCE_C_IDENTIFIER, SCE_C_COMMENTDOCKEYWORD, 0};
+
+class LexerCPP : public ILexerWithSubStyles {
bool caseSensitive;
CharacterSet setWord;
CharacterSet setNegationOp;
@@ -329,6 +333,8 @@ class LexerCPP : public ILexer { OptionSetCPP osCPP;
SparseState<std::string> rawStringTerminators;
enum { activeFlag = 0x40 };
+ enum { ssIdentifier, ssDocKeyword };
+ SubStyles subStyles;
public:
LexerCPP(bool caseSensitive_) :
caseSensitive(caseSensitive_),
@@ -336,7 +342,8 @@ public: setNegationOp(CharacterSet::setNone, "!"),
setArithmethicOp(CharacterSet::setNone, "+-/*%"),
setRelOp(CharacterSet::setNone, "=!<>"),
- setLogicalOp(CharacterSet::setNone, "|&") {
+ setLogicalOp(CharacterSet::setNone, "|&"),
+ subStyles(styleSubable, 0x80, 0x40, activeFlag) {
}
virtual ~LexerCPP() {
}
@@ -344,7 +351,7 @@ public: delete this;
}
int SCI_METHOD Version() const {
- return lvOriginal;
+ return lvSubStyles;
}
const char * SCI_METHOD PropertyNames() {
return osCPP.PropertyNames();
@@ -367,6 +374,32 @@ public: 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);
+ }
+ 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 *LexerFactoryCPP() {
return new LexerCPP(true);
}
@@ -460,6 +493,8 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, CharacterSet setWordStart(CharacterSet::setAlpha, "_", 0x80, true);
+ CharacterSet setInvalidRawFirst(CharacterSet::setNone, " )\\\t\v\f\n");
+
if (options.identifiersAllowDollars) {
setWordStart.Add('$');
}
@@ -479,15 +514,10 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, (MaskActive(initStyle) == SCE_C_COMMENTLINEDOC)) {
// Set continuationLine if last character of previous line is '\'
if (lineCurrent > 0) {
- int chBack = styler.SafeGetCharAt(startPos-1, 0);
- int chBack2 = styler.SafeGetCharAt(startPos-2, 0);
- int lineEndChar = '!';
- if (chBack2 == '\r' && chBack == '\n') {
- lineEndChar = styler.SafeGetCharAt(startPos-3, 0);
- } else if (chBack == '\n' || chBack == '\r') {
- lineEndChar = chBack2;
+ int endLinePrevious = styler.LineEnd(lineCurrent - 1);
+ if (endLinePrevious > 0) {
+ continuationLine = styler.SafeGetCharAt(endLinePrevious-1) == '\\';
}
- continuationLine = lineEndChar == '\\';
}
}
@@ -501,7 +531,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, }
}
- StyleContext sc(startPos, length, initStyle, styler, 0x7f);
+ StyleContext sc(startPos, length, initStyle, styler, static_cast<char>(0xff));
LinePPState preproc = vlls.ForLine(lineCurrent);
bool definitionsChanged = false;
@@ -519,7 +549,10 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, std::map<std::string, std::string> preprocessorDefinitions = preprocessorDefinitionsStart;
for (std::vector<PPDefinition>::iterator itDef = ppDefineHistory.begin(); itDef != ppDefineHistory.end(); ++itDef) {
- preprocessorDefinitions[itDef->key] = itDef->value;
+ if (itDef->isUndef)
+ preprocessorDefinitions.erase(itDef->key);
+ else
+ preprocessorDefinitions[itDef->key] = itDef->value;
}
std::string rawStringTerminator = rawStringTerminators.ValueAt(lineCurrent-1);
@@ -527,6 +560,11 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, int activitySet = preproc.IsInactive() ? activeFlag : 0;
+ const WordClassifier &classifierIdentifiers = subStyles.Classifier(SCE_C_IDENTIFIER);
+ const WordClassifier &classifierDocKeyWords = subStyles.Classifier(SCE_C_COMMENTDOCKEYWORD);
+
+ int lineEndNext = styler.LineEnd(lineCurrent);
+
for (; sc.More();) {
if (sc.atLineStart) {
@@ -554,6 +592,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, if (sc.atLineEnd) {
lineCurrent++;
+ lineEndNext = styler.LineEnd(lineCurrent);
vlls.Add(lineCurrent, preproc);
if (rawStringTerminator != "") {
rawSTNew.Set(lineCurrent-1, rawStringTerminator);
@@ -562,11 +601,13 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, // Handle line continuation generically.
if (sc.ch == '\\') {
- if (sc.chNext == '\n' || sc.chNext == '\r') {
+ if (static_cast<int>((sc.currentPos+1)) >= lineEndNext) {
lineCurrent++;
+ lineEndNext = styler.LineEnd(lineCurrent);
vlls.Add(lineCurrent, preproc);
sc.Forward();
if (sc.ch == '\r' && sc.chNext == '\n') {
+ // Even in UTF-8, \r and \n are separate
sc.Forward();
}
continuationLine = true;
@@ -591,7 +632,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, }
break;
case SCE_C_IDENTIFIER:
- if (!setWord.Contains(sc.ch) || (sc.ch == '.')) {
+ if (sc.atLineStart || sc.atLineEnd || !setWord.Contains(sc.ch) || (sc.ch == '.')) {
char s[1000];
if (caseSensitive) {
sc.GetCurrent(s, sizeof(s));
@@ -605,11 +646,16 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, sc.ChangeState(SCE_C_WORD2|activitySet);
} else if (keywords4.InList(s)) {
sc.ChangeState(SCE_C_GLOBALCLASS|activitySet);
+ } else {
+ int subStyle = classifierIdentifiers.ValueFor(s);
+ if (subStyle >= 0) {
+ sc.ChangeState(subStyle|activitySet);
+ }
}
const bool literalString = sc.ch == '\"';
if (literalString || sc.ch == '\'') {
size_t lenS = strlen(s);
- const bool raw = literalString && sc.chPrev == 'R';
+ const bool raw = literalString && sc.chPrev == 'R' && !setInvalidRawFirst.Contains(sc.chNext);
if (raw)
s[lenS--] = '\0';
bool valid =
@@ -697,8 +743,15 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } else {
sc.GetCurrentLowered(s, sizeof(s));
}
- if (!IsASpace(sc.ch) || !keywords3.InList(s + 1)) {
+ if (!IsASpace(sc.ch)) {
sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet);
+ } else if (!keywords3.InList(s + 1)) {
+ int subStyleCDKW = classifierDocKeyWords.ValueFor(s+1);
+ if (subStyleCDKW >= 0) {
+ sc.ChangeState(subStyleCDKW|activitySet);
+ } else {
+ sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR|activitySet);
+ }
}
sc.SetState(styleBeforeDCKeyword|activitySet);
}
@@ -755,7 +808,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, while ((sc.ch < 0x80) && islower(sc.ch))
sc.Forward(); // gobble regex flags
sc.SetState(SCE_C_DEFAULT|activitySet);
- } else if (sc.ch == '\\' && (sc.chNext != '\n' && sc.chNext != '\r')) {
+ } else if (sc.ch == '\\' && (static_cast<int>(sc.currentPos+1) < lineEndNext)) {
// Gobble up the escaped character
sc.Forward();
} else if (sc.ch == '[') {
@@ -787,7 +840,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, }
break;
case SCE_C_UUID:
- if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
+ if (sc.atLineEnd || sc.ch == ')') {
sc.SetState(SCE_C_DEFAULT|activitySet);
}
}
@@ -795,6 +848,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, if (sc.atLineEnd && !atLineEndBeforeSwitch) {
// State exit processing consumed characters up to end of line.
lineCurrent++;
+ lineEndNext = styler.LineEnd(lineCurrent);
vlls.Add(lineCurrent, preproc);
}
@@ -816,7 +870,7 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, } else {
sc.SetState(SCE_C_NUMBER|activitySet);
}
- } else if (setWordStart.Contains(sc.ch) || (sc.ch == '@')) {
+ } else if (!sc.atLineEnd && (setWordStart.Contains(sc.ch) || (sc.ch == '@'))) {
if (lastWordWasUUID) {
sc.SetState(SCE_C_UUID|activitySet);
lastWordWasUUID = false;
@@ -942,10 +996,22 @@ void SCI_METHOD LexerCPP::Lex(unsigned int startPos, int length, int initStyle, }
}
}
+ } 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(lineCurrent, key, "", true));
+ definitionsChanged = true;
+ }
+ }
}
}
}
- } else if (isoperator(static_cast<char>(sc.ch))) {
+ } else if (isoperator(sc.ch)) {
sc.SetState(SCE_C_OPERATOR|activitySet);
}
}
@@ -976,10 +1042,12 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, unsigned int endPos = startPos + length;
int visibleChars = 0;
+ bool inLineComment = false;
int lineCurrent = styler.GetLine(startPos);
int levelCurrent = SC_FOLDLEVELBASE;
if (lineCurrent > 0)
levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
+ unsigned int lineStartNext = styler.LineStart(lineCurrent+1);
int levelMinCurrent = levelCurrent;
int levelNext = levelCurrent;
char chNext = styler[startPos];
@@ -992,11 +1060,13 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, int stylePrev = style;
style = styleNext;
styleNext = MaskActive(styler.StyleAt(i + 1));
- bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
- if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style)) {
- if (!IsStreamCommentStyle(stylePrev) && (stylePrev != SCE_C_COMMENTLINEDOC)) {
+ bool atEOL = i == (lineStartNext-1);
+ if ((style == SCE_C_COMMENTLINE) || (style == SCE_C_COMMENTLINEDOC))
+ inLineComment = true;
+ if (options.foldComment && options.foldCommentMultiline && IsStreamCommentStyle(style) && !inLineComment) {
+ if (!IsStreamCommentStyle(stylePrev)) {
levelNext++;
- } else if (!IsStreamCommentStyle(styleNext) && (styleNext != SCE_C_COMMENTLINEDOC) && !atEOL) {
+ } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
// Comments don't end at end of line and the next character may be unstyled.
levelNext--;
}
@@ -1060,6 +1130,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, styler.SetLevel(lineCurrent, lev);
}
lineCurrent++;
+ lineStartNext = styler.LineStart(lineCurrent+1);
levelCurrent = levelNext;
levelMinCurrent = levelCurrent;
if (atEOL && (i == static_cast<unsigned int>(styler.Length()-1))) {
@@ -1067,6 +1138,7 @@ void SCI_METHOD LexerCPP::Fold(unsigned int startPos, int length, int initStyle, styler.SetLevel(lineCurrent, (levelCurrent | levelCurrent << 16) | SC_FOLDLEVELWHITEFLAG);
}
visibleChars = 0;
+ inLineComment = false;
}
}
}
diff --git a/scintilla/lexers/LexHTML.cxx b/scintilla/lexers/LexHTML.cxx index f7bbbf9..3acb896 100644 --- a/scintilla/lexers/LexHTML.cxx +++ b/scintilla/lexers/LexHTML.cxx @@ -445,11 +445,6 @@ static int StateForScript(script_type scriptLanguage) { return Result;
}
-static inline bool ishtmlwordchar(int ch) {
- return !isascii(ch) ||
- (isalnum(ch) || ch == '.' || ch == '-' || ch == '_' || ch == ':' || ch == '!' || ch == '#');
-}
-
static inline bool issgmlwordchar(int ch) {
return !isascii(ch) ||
(isalnum(ch) || ch == '.' || ch == '_' || ch == ':' || ch == '!' || ch == '#' || ch == '[');
@@ -484,10 +479,6 @@ static bool isLineEnd(int ch) { return ch == '\r' || ch == '\n';
}
-static bool isOKBeforeRE(int ch) {
- return (ch == '(') || (ch == '=') || (ch == ',');
-}
-
static bool isMakoBlockEnd(const int ch, const int chNext, const char *blockType) {
if (strlen(blockType) == 0) {
return ((ch == '%') && (chNext == '>'));
@@ -691,6 +682,8 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty const CharacterSet setHTMLWord(CharacterSet::setAlphaNum, ".-_:!#", 0x80, true);
const CharacterSet setTagContinue(CharacterSet::setAlphaNum, ".-_:!#[", 0x80, true);
const CharacterSet setAttributeContinue(CharacterSet::setAlphaNum, ".-_:!#/", 0x80, true);
+ // TODO: also handle + and - (except if they're part of ++ or --) and return keywords
+ const CharacterSet setOKBeforeJSRE(CharacterSet::setNone, "([{=,:;!%^&*|?~");
int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
int levelCurrent = levelPrev;
@@ -905,7 +898,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty !IsScriptCommentState(state)) {
beforeLanguage = scriptLanguage;
scriptLanguage = segIsScriptingIndicator(styler, i + 2, i + 6, isXml ? eScriptXML : eScriptPHP);
- if (scriptLanguage != eScriptPHP && isStringState(state)) continue;
+ if ((scriptLanguage != eScriptPHP) && (isStringState(state) || (state==SCE_H_COMMENT))) continue;
styler.ColourTo(i - 1, StateToPrint);
beforePreProc = state;
i++;
@@ -1592,7 +1585,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty } else if (ch == '/' && chNext == '/') {
styler.ColourTo(i - 1, StateToPrint);
state = SCE_HJ_COMMENTLINE;
- } else if (ch == '/' && isOKBeforeRE(chPrevNonWhite)) {
+ } else if (ch == '/' && setOKBeforeJSRE.Contains(chPrevNonWhite)) {
styler.ColourTo(i - 1, StateToPrint);
state = SCE_HJ_REGEX;
} else if (ch == '\"') {
diff --git a/scintilla/lexers/LexHaskell.cxx b/scintilla/lexers/LexHaskell.cxx index a4bc2e1..7c2a968 100644 --- a/scintilla/lexers/LexHaskell.cxx +++ b/scintilla/lexers/LexHaskell.cxx @@ -9,6 +9,8 @@ *
* Several bug fixes by Krasimir Angelov - kr.angelov at gmail.com
*
+ * Improvements by kudah - kudahkukarek at gmail.com
+ *
* TODO:
* * Implement a folder :)
* * Nice Character-lexing (stuff inside '\''), LexPython has
@@ -57,22 +59,24 @@ using namespace Scintilla; #define HA_MODE_FFI 5
#define HA_MODE_TYPE 6
-static inline bool IsNewline(const int ch) {
- return (ch == '\n' || ch == '\r');
-}
-
-static inline bool IsWhitespace(const int ch) {
- return ( ch == ' '
- || ch == '\t'
- || IsNewline(ch) );
+static inline bool IsAWordStart(const int ch) {
+ return (IsLowerCase(ch) || IsUpperCase(ch) || ch == '_');
}
-static inline bool IsAWordStart(const int ch) {
- return (ch < 0x80) && (isalnum(ch) || ch == '_');
+static inline bool IsAWordChar(const int ch, const bool magicHash) {
+ return ( IsAlphaNumeric(ch)
+ || ch == '_'
+ || ch == '\''
+ || (magicHash && ch == '#'));
}
-static inline bool IsAWordChar(const int ch) {
- return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
+static inline bool IsAnOperatorChar(const int ch) {
+ return
+ ( ch == '!' || ch == '#' || ch == '$' || ch == '%'
+ || ch == '&' || ch == '*' || ch == '+' || ch == '-'
+ || ch == '.' || ch == '/' || ch == ':' || ch == '<'
+ || ch == '=' || ch == '>' || ch == '?' || ch == '@'
+ || ch == '\\' || ch == '^' || ch == '|' || ch == '~');
}
static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
@@ -81,230 +85,293 @@ static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle, WordList &keywords = *keywordlists[0];
WordList &ffi = *keywordlists[1];
+ // property lexer.haskell.allow.hash
+ // Set to 1 to allow the # character in identifiers with the haskell lexer.
+ // (GHC -XMagicHash extension)
+ const bool magicHash = styler.GetPropertyInt("lexer.haskell.allow.hash") != 0;
+ const bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
+
StyleContext sc(startPos, length, initStyle, styler);
int lineCurrent = styler.GetLine(startPos);
int state = lineCurrent ? styler.GetLineState(lineCurrent-1)
: HA_MODE_DEFAULT;
int mode = state & 0xF;
- int xmode = state >> 4;
+ int xmode = state >> 4; // obscure parameter. Means different things in different modes.
while (sc.More()) {
// Check for state end
// Operator
if (sc.state == SCE_HA_OPERATOR) {
- if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
- sc.Forward();
- } else {
- styler.ColourTo(sc.currentPos - 1, sc.state);
- sc.ChangeState(SCE_HA_DEFAULT);
+ int style = SCE_HA_OPERATOR;
+
+ if (sc.ch == ':' &&
+ // except "::"
+ !(sc.chNext == ':' && !IsAnOperatorChar(sc.GetRelative(2)))) {
+ style = SCE_HA_CAPITAL;
}
+
+ while(IsAnOperatorChar(sc.ch))
+ sc.Forward();
+
+ styler.ColourTo(sc.currentPos - 1, style);
+ sc.ChangeState(SCE_HA_DEFAULT);
}
// String
else if (sc.state == SCE_HA_STRING) {
if (sc.ch == '\"') {
- sc.Forward();
- styler.ColourTo(sc.currentPos-1, sc.state);
- sc.ChangeState(SCE_HA_DEFAULT);
+ sc.Forward();
+ sc.SetState(SCE_HA_DEFAULT);
} else if (sc.ch == '\\') {
sc.Forward(2);
} else if (sc.atLineEnd) {
- styler.ColourTo(sc.currentPos-1, sc.state);
- sc.ChangeState(SCE_HA_DEFAULT);
- } else {
- sc.Forward();
- }
+ sc.SetState(SCE_HA_DEFAULT);
+ } else {
+ sc.Forward();
+ }
}
// Char
else if (sc.state == SCE_HA_CHARACTER) {
if (sc.ch == '\'') {
- sc.Forward();
- styler.ColourTo(sc.currentPos-1, sc.state);
- sc.ChangeState(SCE_HA_DEFAULT);
+ sc.Forward();
+ sc.SetState(SCE_HA_DEFAULT);
} else if (sc.ch == '\\') {
sc.Forward(2);
} else if (sc.atLineEnd) {
- styler.ColourTo(sc.currentPos-1, sc.state);
- sc.ChangeState(SCE_HA_DEFAULT);
- } else {
- sc.Forward();
- }
+ sc.SetState(SCE_HA_DEFAULT);
+ } else {
+ sc.Forward();
+ }
}
// Number
else if (sc.state == SCE_HA_NUMBER) {
- if (IsADigit(sc.ch, xmode)) {
+ if (IsADigit(sc.ch, xmode) ||
+ (sc.ch=='.' && IsADigit(sc.chNext, xmode))) {
sc.Forward();
} else if ((xmode == 10) &&
(sc.ch == 'e' || sc.ch == 'E') &&
(IsADigit(sc.chNext) || sc.chNext == '+' || sc.chNext == '-')) {
- sc.Forward();
- if (sc.ch == '+' || sc.ch == '-')
- sc.Forward();
+ sc.Forward();
+ if (sc.ch == '+' || sc.ch == '-')
+ sc.Forward();
} else {
- styler.ColourTo(sc.currentPos - 1, sc.state);
- sc.ChangeState(SCE_HA_DEFAULT);
+ sc.SetState(SCE_HA_DEFAULT);
}
}
- // Identifier
+ // Keyword or Identifier
else if (sc.state == SCE_HA_IDENTIFIER) {
- if (IsAWordChar(sc.ch)) {
- sc.Forward();
- } else {
- char s[100];
- sc.GetCurrent(s, sizeof(s));
- int style = sc.state;
- int new_mode = 0;
- if (keywords.InList(s)) {
- style = SCE_HA_KEYWORD;
- } else if (isupper(s[0])) {
- if (mode >= HA_MODE_IMPORT1 && mode <= HA_MODE_IMPORT3) {
- style = SCE_HA_MODULE;
- new_mode = HA_MODE_IMPORT2;
- } else if (mode == HA_MODE_MODULE)
- style = SCE_HA_MODULE;
- else
- style = SCE_HA_CAPITAL;
- } else if (mode == HA_MODE_IMPORT1 &&
- strcmp(s,"qualified") == 0) {
- style = SCE_HA_KEYWORD;
- new_mode = HA_MODE_IMPORT1;
- } else if (mode == HA_MODE_IMPORT2) {
- if (strcmp(s,"as") == 0) {
- style = SCE_HA_KEYWORD;
- new_mode = HA_MODE_IMPORT3;
- } else if (strcmp(s,"hiding") == 0) {
- style = SCE_HA_KEYWORD;
- }
- } else if (mode == HA_MODE_FFI) {
- if (ffi.InList(s)) {
- style = SCE_HA_KEYWORD;
- new_mode = HA_MODE_FFI;
+ while (sc.More()) {
+ if (IsAWordChar(sc.ch, magicHash)) {
+ sc.Forward();
+ } else if (xmode == SCE_HA_CAPITAL && sc.ch=='.') {
+ if (isupper(sc.chNext)) {
+ xmode = SCE_HA_CAPITAL;
+ sc.Forward();
+ } else if (IsAWordStart(sc.chNext)) {
+ xmode = SCE_HA_IDENTIFIER;
+ sc.Forward();
+ } else if (IsAnOperatorChar(sc.chNext)) {
+ xmode = SCE_HA_OPERATOR;
+ sc.Forward();
+ } else {
+ break;
}
+ } else if (xmode == SCE_HA_OPERATOR && IsAnOperatorChar(sc.ch)) {
+ sc.Forward();
+ } else {
+ break;
+ }
+ }
+
+ char s[100];
+ sc.GetCurrent(s, sizeof(s));
+
+ int style = xmode;
+
+ int new_mode = HA_MODE_DEFAULT;
+
+ if (keywords.InList(s)) {
+ style = SCE_HA_KEYWORD;
+ } else if (isupper(s[0])) {
+ if (mode >= HA_MODE_IMPORT1 && mode <= HA_MODE_IMPORT3) {
+ style = SCE_HA_MODULE;
+ new_mode = HA_MODE_IMPORT2;
+ } else if (mode == HA_MODE_MODULE) {
+ style = SCE_HA_MODULE;
}
- else if (mode == HA_MODE_TYPE) {
- if (strcmp(s,"family") == 0)
- style = SCE_HA_KEYWORD;
- }
- styler.ColourTo(sc.currentPos - 1, style);
- if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI)
- new_mode = HA_MODE_IMPORT1;
- else if (strcmp(s,"module") == 0)
- new_mode = HA_MODE_MODULE;
- else if (strcmp(s,"foreign") == 0)
+ } else if (mode == HA_MODE_IMPORT1 &&
+ strcmp(s,"qualified") == 0) {
+ style = SCE_HA_KEYWORD;
+ new_mode = HA_MODE_IMPORT1;
+ } else if (mode == HA_MODE_IMPORT2) {
+ if (strcmp(s,"as") == 0) {
+ style = SCE_HA_KEYWORD;
+ new_mode = HA_MODE_IMPORT3;
+ } else if (strcmp(s,"hiding") == 0) {
+ style = SCE_HA_KEYWORD;
+ }
+ } else if (mode == HA_MODE_TYPE) {
+ if (strcmp(s,"family") == 0)
+ style = SCE_HA_KEYWORD;
+ }
+
+ if (mode == HA_MODE_FFI) {
+ if (ffi.InList(s)) {
+ style = SCE_HA_KEYWORD;
new_mode = HA_MODE_FFI;
- else if (strcmp(s,"type") == 0)
- new_mode = HA_MODE_TYPE;
- sc.ChangeState(SCE_HA_DEFAULT);
- mode = new_mode;
+ }
}
+
+ styler.ColourTo(sc.currentPos - 1, style);
+
+ if (strcmp(s,"import") == 0 && mode != HA_MODE_FFI)
+ new_mode = HA_MODE_IMPORT1;
+ else if (strcmp(s,"module") == 0)
+ new_mode = HA_MODE_MODULE;
+ else if (strcmp(s,"foreign") == 0)
+ new_mode = HA_MODE_FFI;
+ else if (strcmp(s,"type") == 0
+ || strcmp(s,"data") == 0)
+ new_mode = HA_MODE_TYPE;
+
+ xmode = 0;
+ sc.ChangeState(SCE_HA_DEFAULT);
+ mode = new_mode;
}
// Comments
// Oneliner
else if (sc.state == SCE_HA_COMMENTLINE) {
- if (sc.atLineEnd) {
- styler.ColourTo(sc.currentPos - 1, sc.state);
- sc.ChangeState(SCE_HA_DEFAULT);
+ if (xmode == 1 && sc.ch != '-') {
+ xmode = 0;
+ if (IsAnOperatorChar(sc.ch))
+ sc.ChangeState(SCE_HA_OPERATOR);
+ } else if (sc.atLineEnd) {
+ sc.SetState(SCE_HA_DEFAULT);
} else {
sc.Forward();
}
}
// Nested
else if (sc.state == SCE_HA_COMMENTBLOCK) {
- if (sc.Match("{-")) {
+ if (sc.Match('{','-')) {
sc.Forward(2);
xmode++;
}
- else if (sc.Match("-}")) {
+ else if (sc.Match('-','}')) {
sc.Forward(2);
xmode--;
if (xmode == 0) {
- styler.ColourTo(sc.currentPos - 1, sc.state);
- sc.ChangeState(SCE_HA_DEFAULT);
+ sc.SetState(SCE_HA_DEFAULT);
}
} else {
if (sc.atLineEnd) {
- // Remember the line state for future incremental lexing
- styler.SetLineState(lineCurrent, (xmode << 4) | mode);
- lineCurrent++;
- }
+ // Remember the line state for future incremental lexing
+ styler.SetLineState(lineCurrent, (xmode << 4) | mode);
+ lineCurrent++;
+ }
+ sc.Forward();
+ }
+ }
+ // Pragma
+ else if (sc.state == SCE_HA_PRAGMA) {
+ if (sc.Match("#-}")) {
+ sc.Forward(3);
+ sc.SetState(SCE_HA_DEFAULT);
+ } else {
+ sc.Forward();
+ }
+ }
+ // Preprocessor
+ else if (sc.state == SCE_HA_PREPROCESSOR) {
+ if (stylingWithinPreprocessor && !IsAWordStart(sc.ch)) {
+ sc.SetState(SCE_HA_DEFAULT);
+ } else if (sc.ch == '\\' && !stylingWithinPreprocessor) {
+ sc.Forward(2);
+ } else if (sc.atLineEnd) {
+ sc.SetState(SCE_HA_DEFAULT);
+ } else {
sc.Forward();
}
}
// New state?
if (sc.state == SCE_HA_DEFAULT) {
// Digit
- if (IsADigit(sc.ch) ||
- (sc.ch == '.' && IsADigit(sc.chNext)) ||
- (sc.ch == '-' && IsADigit(sc.chNext))) {
- styler.ColourTo(sc.currentPos - 1, sc.state);
- sc.ChangeState(SCE_HA_NUMBER);
+ if (IsADigit(sc.ch)) {
+ sc.SetState(SCE_HA_NUMBER);
if (sc.ch == '0' && (sc.chNext == 'X' || sc.chNext == 'x')) {
- // Match anything starting with "0x" or "0X", too
- sc.Forward(2);
- xmode = 16;
+ // Match anything starting with "0x" or "0X", too
+ sc.Forward(2);
+ xmode = 16;
} else if (sc.ch == '0' && (sc.chNext == 'O' || sc.chNext == 'o')) {
- // Match anything starting with "0x" or "0X", too
- sc.Forward(2);
- xmode = 8;
+ // Match anything starting with "0x" or "0X", too
+ sc.Forward(2);
+ xmode = 8;
} else {
- sc.Forward();
- xmode = 10;
- }
+ sc.Forward();
+ xmode = 10;
+ }
mode = HA_MODE_DEFAULT;
}
+ // Pragma
+ else if (sc.Match("{-#")) {
+ sc.SetState(SCE_HA_PRAGMA);
+ sc.Forward(3);
+ }
// Comment line
- else if (sc.Match("--")) {
- styler.ColourTo(sc.currentPos - 1, sc.state);
+ else if (sc.Match('-','-')) {
+ sc.SetState(SCE_HA_COMMENTLINE);
sc.Forward(2);
- sc.ChangeState(SCE_HA_COMMENTLINE);
- // Comment block
+ xmode = 1;
}
- else if (sc.Match("{-")) {
- styler.ColourTo(sc.currentPos - 1, sc.state);
+ // Comment block
+ else if (sc.Match('{','-')) {
+ sc.SetState(SCE_HA_COMMENTBLOCK);
sc.Forward(2);
- sc.ChangeState(SCE_HA_COMMENTBLOCK);
xmode = 1;
}
// String
else if (sc.Match('\"')) {
- styler.ColourTo(sc.currentPos - 1, sc.state);
+ sc.SetState(SCE_HA_STRING);
sc.Forward();
- sc.ChangeState(SCE_HA_STRING);
}
// Character
else if (sc.Match('\'')) {
- styler.ColourTo(sc.currentPos - 1, sc.state);
+ sc.SetState(SCE_HA_CHARACTER);
sc.Forward();
- sc.ChangeState(SCE_HA_CHARACTER);
}
- else if (sc.ch == '(' || sc.ch == ')' ||
- sc.ch == '{' || sc.ch == '}' ||
- sc.ch == '[' || sc.ch == ']') {
- styler.ColourTo(sc.currentPos - 1, sc.state);
- sc.Forward();
- styler.ColourTo(sc.currentPos - 1, SCE_HA_OPERATOR);
- mode = HA_MODE_DEFAULT;
- }
- // Operator
- else if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
- styler.ColourTo(sc.currentPos - 1, sc.state);
+ // Preprocessor
+ else if (sc.atLineStart && sc.ch == '#') {
+ mode = HA_MODE_DEFAULT;
+ sc.SetState(SCE_HA_PREPROCESSOR);
sc.Forward();
- sc.ChangeState(SCE_HA_OPERATOR);
+ }
+ // Operator
+ else if (IsAnOperatorChar(sc.ch)) {
mode = HA_MODE_DEFAULT;
+ sc.SetState(SCE_HA_OPERATOR);
+ }
+ // Braces and punctuation
+ else if (sc.ch == ',' || sc.ch == ';'
+ || sc.ch == '(' || sc.ch == ')'
+ || sc.ch == '[' || sc.ch == ']'
+ || sc.ch == '{' || sc.ch == '}') {
+ sc.SetState(SCE_HA_OPERATOR);
+ sc.Forward();
+ sc.SetState(SCE_HA_DEFAULT);
}
- // Keyword
+ // Keyword or Identifier
else if (IsAWordStart(sc.ch)) {
- styler.ColourTo(sc.currentPos - 1, sc.state);
+ xmode = isupper(sc.ch) ? SCE_HA_CAPITAL : SCE_HA_IDENTIFIER;
+ sc.SetState(SCE_HA_IDENTIFIER);
sc.Forward();
- sc.ChangeState(SCE_HA_IDENTIFIER);
} else {
if (sc.atLineEnd) {
- // Remember the line state for future incremental lexing
- styler.SetLineState(lineCurrent, (xmode << 4) | mode);
- lineCurrent++;
- }
+ // Remember the line state for future incremental lexing
+ styler.SetLineState(lineCurrent, (xmode << 4) | mode);
+ lineCurrent++;
+ }
sc.Forward();
}
}
diff --git a/scintilla/lexers/LexLaTeX.cxx b/scintilla/lexers/LexLaTeX.cxx new file mode 100644 index 0000000..6f9612d --- /dev/null +++ b/scintilla/lexers/LexLaTeX.cxx @@ -0,0 +1,539 @@ +// Scintilla source code edit control +/** @file LexLaTeX.cxx + ** Lexer for LaTeX2e. + **/ +// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +// Modified by G. HU in 2013. Added folding, syntax highting inside math environments, and changed some minor behaviors. + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <stdarg.h> +#include <assert.h> +#include <ctype.h> +#include <vector> + +#include "ILexer.h" +#include "Scintilla.h" +#include "SciLexer.h" + +#include "PropSetSimple.h" +#include "WordList.h" +#include "LexAccessor.h" +#include "Accessor.h" +#include "StyleContext.h" +#include "CharacterSet.h" +#include "LexerModule.h" +#include "LexerBase.h" + +#ifdef SCI_NAMESPACE +using namespace Scintilla; +#endif + +using namespace std; + +struct latexFoldSave { + latexFoldSave() : structLev(0) { + for (int i = 0; i < 8; ++i) openBegins[i] = 0; + } + latexFoldSave(const latexFoldSave &save) : structLev(save.structLev) { + for (int i = 0; i < 8; ++i) openBegins[i] = save.openBegins[i]; + } + int openBegins[8]; + int structLev; +}; + +class LexerLaTeX : public LexerBase { +private: + vector<int> modes; + void setMode(int line, int mode) { + if (line >= static_cast<int>(modes.size())) modes.resize(line + 1, 0); + modes[line] = mode; + } + int getMode(int line) { + if (line >= 0 && line < static_cast<int>(modes.size())) return modes[line]; + return 0; + } + void truncModes(int numLines) { + if (static_cast<int>(modes.size()) > numLines * 2 + 256) + modes.resize(numLines + 128); + } + + vector<latexFoldSave> saves; + void setSave(int line, const latexFoldSave &save) { + if (line >= static_cast<int>(saves.size())) saves.resize(line + 1); + saves[line] = save; + } + void getSave(int line, latexFoldSave &save) { + if (line >= 0 && line < static_cast<int>(saves.size())) save = saves[line]; + else { + save.structLev = 0; + for (int i = 0; i < 8; ++i) save.openBegins[i] = 0; + } + } + void truncSaves(int numLines) { + if (static_cast<int>(saves.size()) > numLines * 2 + 256) + saves.resize(numLines + 128); + } +public: + static ILexer *LexerFactoryLaTeX() { + return new LexerLaTeX(); + } + 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); +}; + +static bool latexIsSpecial(int ch) { + return (ch == '#') || (ch == '$') || (ch == '%') || (ch == '&') || (ch == '_') || + (ch == '{') || (ch == '}') || (ch == ' '); +} + +static bool latexIsBlank(int ch) { + return (ch == ' ') || (ch == '\t'); +} + +static bool latexIsBlankAndNL(int ch) { + return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n'); +} + +static bool latexIsLetter(int ch) { + return isascii(ch) && isalpha(ch); +} + +static bool latexIsTagValid(int &i, int l, Accessor &styler) { + while (i < l) { + if (styler.SafeGetCharAt(i) == '{') { + while (i < l) { + i++; + if (styler.SafeGetCharAt(i) == '}') { + return true; + } else if (!latexIsLetter(styler.SafeGetCharAt(i)) && + styler.SafeGetCharAt(i)!='*') { + return false; + } + } + } else if (!latexIsBlank(styler.SafeGetCharAt(i))) { + return false; + } + i++; + } + return false; +} + +static bool latexNextNotBlankIs(int i, Accessor &styler, char needle) { + char ch; + while (i < styler.Length()) { + ch = styler.SafeGetCharAt(i); + if (!latexIsBlankAndNL(ch) && ch != '*') { + if (ch == needle) + return true; + else + return false; + } + i++; + } + return false; +} + +static bool latexLastWordIs(int start, Accessor &styler, const char *needle) { + unsigned int i = 0; + unsigned int l = static_cast<unsigned int>(strlen(needle)); + int ini = start-l+1; + char s[32]; + + while (i < l && i < 31) { + s[i] = styler.SafeGetCharAt(ini + i); + i++; + } + s[i] = '\0'; + + return (strcmp(s, needle) == 0); +} + +static bool latexLastWordIsMathEnv(int pos, Accessor &styler) { + int i, j; + char s[32]; + const char *mathEnvs[] = { "align", "alignat", "flalign", "gather", + "multiline", "displaymath", "eqnarray", "equation" }; + if (styler.SafeGetCharAt(pos) != '}') return false; + for (i = pos - 1; i >= 0; --i) { + if (styler.SafeGetCharAt(i) == '{') break; + if (pos - i >= 20) return false; + } + if (i < 0 || i == pos - 1) return false; + ++i; + for (j = 0; i + j < pos; ++j) + s[j] = styler.SafeGetCharAt(i + j); + s[j] = '\0'; + if (j == 0) return false; + if (s[j - 1] == '*') s[--j] = '\0'; + for (i = 0; i < static_cast<int>(sizeof(mathEnvs) / sizeof(const char *)); ++i) + if (strcmp(s, mathEnvs[i]) == 0) return true; + return false; +} + +static inline void latexStateReset(int &mode, int &state) { + switch (mode) { + case 1: state = SCE_L_MATH; break; + case 2: state = SCE_L_MATH2; break; + default: state = SCE_L_DEFAULT; break; + } +} + +// There are cases not handled correctly, like $abcd\textrm{what is $x+y$}z+w$. +// But I think it's already good enough. +void SCI_METHOD LexerLaTeX::Lex(unsigned int startPos, int length, int initStyle, IDocument *pAccess) { + // startPos is assumed to be the first character of a line + Accessor styler(pAccess, &props); + styler.StartAt(startPos); + int mode = getMode(styler.GetLine(startPos) - 1); + int state = initStyle; + if (state == SCE_L_ERROR || state == SCE_L_SHORTCMD || state == SCE_L_SPECIAL) // should not happen + latexStateReset(mode, state); + + char chNext = styler.SafeGetCharAt(startPos); + char chVerbatimDelim = '\0'; + styler.StartSegment(startPos); + int lengthDoc = startPos + length; + + for (int i = startPos; i < lengthDoc; i++) { + char ch = chNext; + chNext = styler.SafeGetCharAt(i + 1); + + if (styler.IsLeadByte(ch)) { + i++; + chNext = styler.SafeGetCharAt(i + 1); + continue; + } + + if (ch == '\r' || ch == '\n') + setMode(styler.GetLine(i), mode); + + switch (state) { + case SCE_L_DEFAULT : + switch (ch) { + case '\\' : + styler.ColourTo(i - 1, state); + if (latexIsLetter(chNext)) { + state = SCE_L_COMMAND; + } else if (latexIsSpecial(chNext)) { + styler.ColourTo(i + 1, SCE_L_SPECIAL); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else if (chNext == '\r' || chNext == '\n') { + styler.ColourTo(i, SCE_L_ERROR); + } else { + styler.ColourTo(i + 1, SCE_L_SHORTCMD); + if (chNext == '(') { + mode = 1; + state = SCE_L_MATH; + } else if (chNext == '[') { + mode = 2; + state = SCE_L_MATH2; + } + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + break; + case '$' : + styler.ColourTo(i - 1, state); + if (chNext == '$') { + styler.ColourTo(i + 1, SCE_L_SHORTCMD); + mode = 2; + state = SCE_L_MATH2; + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else { + styler.ColourTo(i, SCE_L_SHORTCMD); + mode = 1; + state = SCE_L_MATH; + } + break; + case '%' : + styler.ColourTo(i - 1, state); + state = SCE_L_COMMENT; + break; + } + break; + // These 3 will never be reached. + case SCE_L_ERROR: + case SCE_L_SPECIAL: + case SCE_L_SHORTCMD: + break; + case SCE_L_COMMAND : + if (!latexIsLetter(chNext)) { + styler.ColourTo(i, state); + if (latexNextNotBlankIs(i + 1, styler, '[' )) { + state = SCE_L_CMDOPT; + } else if (latexLastWordIs(i, styler, "\\begin")) { + state = SCE_L_TAG; + } else if (latexLastWordIs(i, styler, "\\end")) { + state = SCE_L_TAG2; + } else if (latexLastWordIs(i, styler, "\\verb") && chNext != '*' && chNext != ' ') { + chVerbatimDelim = chNext; + state = SCE_L_VERBATIM; + } else { + latexStateReset(mode, state); + } + } + break; + case SCE_L_CMDOPT : + if (ch == ']') { + styler.ColourTo(i, state); + latexStateReset(mode, state); + } + break; + case SCE_L_TAG : + if (latexIsTagValid(i, lengthDoc, styler)) { + styler.ColourTo(i, state); + latexStateReset(mode, state); + if (latexLastWordIs(i, styler, "{verbatim}")) { + state = SCE_L_VERBATIM; + } else if (latexLastWordIs(i, styler, "{comment}")) { + state = SCE_L_COMMENT2; + } else if (latexLastWordIs(i, styler, "{math}") && mode == 0) { + mode = 1; + state = SCE_L_MATH; + } else if (latexLastWordIsMathEnv(i, styler) && mode == 0) { + mode = 2; + state = SCE_L_MATH2; + } + } else { + styler.ColourTo(i, SCE_L_ERROR); + latexStateReset(mode, state); + ch = styler.SafeGetCharAt(i); + if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode); + } + chNext = styler.SafeGetCharAt(i+1); + break; + case SCE_L_TAG2 : + if (latexIsTagValid(i, lengthDoc, styler)) { + styler.ColourTo(i, state); + latexStateReset(mode, state); + } else { + styler.ColourTo(i, SCE_L_ERROR); + latexStateReset(mode, state); + ch = styler.SafeGetCharAt(i); + if (ch == '\r' || ch == '\n') setMode(styler.GetLine(i), mode); + } + chNext = styler.SafeGetCharAt(i+1); + break; + case SCE_L_MATH : + switch (ch) { + case '\\' : + styler.ColourTo(i - 1, state); + if (latexIsLetter(chNext)) { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{math}")) + mode = 0; + } + } + state = SCE_L_COMMAND; + } else if (latexIsSpecial(chNext)) { + styler.ColourTo(i + 1, SCE_L_SPECIAL); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else if (chNext == '\r' || chNext == '\n') { + styler.ColourTo(i, SCE_L_ERROR); + } else { + if (chNext == ')') { + mode = 0; + state = SCE_L_DEFAULT; + } + styler.ColourTo(i + 1, SCE_L_SHORTCMD); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + break; + case '$' : + styler.ColourTo(i - 1, state); + styler.ColourTo(i, SCE_L_SHORTCMD); + mode = 0; + state = SCE_L_DEFAULT; + break; + case '%' : + styler.ColourTo(i - 1, state); + state = SCE_L_COMMENT; + break; + } + break; + case SCE_L_MATH2 : + switch (ch) { + case '\\' : + styler.ColourTo(i - 1, state); + if (latexIsLetter(chNext)) { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIsMathEnv(match, styler)) + mode = 0; + } + } + state = SCE_L_COMMAND; + } else if (latexIsSpecial(chNext)) { + styler.ColourTo(i + 1, SCE_L_SPECIAL); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else if (chNext == '\r' || chNext == '\n') { + styler.ColourTo(i, SCE_L_ERROR); + } else { + if (chNext == ']') { + mode = 0; + state = SCE_L_DEFAULT; + } + styler.ColourTo(i + 1, SCE_L_SHORTCMD); + i++; + chNext = styler.SafeGetCharAt(i + 1); + } + break; + case '$' : + styler.ColourTo(i - 1, state); + if (chNext == '$') { + styler.ColourTo(i + 1, SCE_L_SHORTCMD); + i++; + chNext = styler.SafeGetCharAt(i + 1); + mode = 0; + state = SCE_L_DEFAULT; + } else { // This may not be an error, e.g. \begin{equation}\text{$a$}\end{equation} + styler.ColourTo(i, SCE_L_SHORTCMD); + } + break; + case '%' : + styler.ColourTo(i - 1, state); + state = SCE_L_COMMENT; + break; + } + break; + case SCE_L_COMMENT : + if (ch == '\r' || ch == '\n') { + styler.ColourTo(i - 1, state); + latexStateReset(mode, state); + } + break; + case SCE_L_COMMENT2 : + if (ch == '\\') { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{comment}")) { + styler.ColourTo(i - 1, state); + state = SCE_L_COMMAND; + } + } + } + } + break; + case SCE_L_VERBATIM : + if (ch == '\\') { + int match = i + 3; + if (latexLastWordIs(match, styler, "\\end")) { + match++; + if (latexIsTagValid(match, lengthDoc, styler)) { + if (latexLastWordIs(match, styler, "{verbatim}")) { + styler.ColourTo(i - 1, state); + state = SCE_L_COMMAND; + } + } + } + } else if (chNext == chVerbatimDelim) { + styler.ColourTo(i + 1, state); + latexStateReset(mode, state); + chVerbatimDelim = '\0'; + i++; + chNext = styler.SafeGetCharAt(i + 1); + } else if (chVerbatimDelim != '\0' && (ch == '\n' || ch == '\r')) { + styler.ColourTo(i, SCE_L_ERROR); + latexStateReset(mode, state); + chVerbatimDelim = '\0'; + } + break; + } + } + if (lengthDoc == styler.Length()) truncModes(styler.GetLine(lengthDoc - 1)); + styler.ColourTo(lengthDoc - 1, state); + styler.Flush(); +} + +static int latexFoldSaveToInt(const latexFoldSave &save) { + int sum = 0; + for (int i = 0; i <= save.structLev; ++i) + sum += save.openBegins[i]; + return ((sum + save.structLev + SC_FOLDLEVELBASE) & SC_FOLDLEVELNUMBERMASK); +} + +// Change folding state while processing a line +// Return the level before the first relevant command +void SCI_METHOD LexerLaTeX::Fold(unsigned int startPos, int length, int, IDocument *pAccess) { + const char *structWords[7] = {"part", "chapter", "section", "subsection", + "subsubsection", "paragraph", "subparagraph"}; + Accessor styler(pAccess, &props); + unsigned int endPos = startPos + length; + int curLine = styler.GetLine(startPos); + latexFoldSave save; + getSave(curLine - 1, save); + do { + char ch, buf[16]; + int i, j, lev = -1; + bool needFold = false; + for (i = static_cast<int>(startPos); i < static_cast<int>(endPos); ++i) { + ch = styler.SafeGetCharAt(i); + if (ch == '\r' || ch == '\n') break; + if (ch != '\\' || styler.StyleAt(i) != SCE_L_COMMAND) continue; + for (j = 0; j < 15 && i + 1 < static_cast<int>(endPos); ++j, ++i) { + buf[j] = styler.SafeGetCharAt(i + 1); + if (!latexIsLetter(buf[j])) break; + } + buf[j] = '\0'; + if (strcmp(buf, "begin") == 0) { + if (lev < 0) lev = latexFoldSaveToInt(save); + ++save.openBegins[save.structLev]; + needFold = true; + } + else if (strcmp(buf, "end") == 0) { + while (save.structLev > 0 && save.openBegins[save.structLev] == 0) + --save.structLev; + if (lev < 0) lev = latexFoldSaveToInt(save); + if (save.openBegins[save.structLev] > 0) --save.openBegins[save.structLev]; + } + else { + for (j = 0; j < 7; ++j) + if (strcmp(buf, structWords[j]) == 0) break; + if (j >= 7) continue; + save.structLev = j; // level before the command + for (j = save.structLev + 1; j < 8; ++j) { + save.openBegins[save.structLev] += save.openBegins[j]; + save.openBegins[j] = 0; + } + if (lev < 0) lev = latexFoldSaveToInt(save); + ++save.structLev; // level after the command + needFold = true; + } + } + if (lev < 0) lev = latexFoldSaveToInt(save); + if (needFold) lev |= SC_FOLDLEVELHEADERFLAG; + styler.SetLevel(curLine, lev); + setSave(curLine, save); + ++curLine; + startPos = styler.LineStart(curLine); + if (static_cast<int>(startPos) == styler.Length()) { + lev = latexFoldSaveToInt(save); + styler.SetLevel(curLine, lev); + setSave(curLine, save); + truncSaves(curLine); + } + } while (startPos < endPos); + styler.Flush(); +} + +static const char *const emptyWordListDesc[] = { + 0 +}; + +LexerModule lmLatex(SCLEX_LATEX, LexerLaTeX::LexerFactoryLaTeX, "latex", emptyWordListDesc); diff --git a/scintilla/lexers/LexMatlab.cxx b/scintilla/lexers/LexMatlab.cxx index 7c6019f..eb721be 100644 --- a/scintilla/lexers/LexMatlab.cxx +++ b/scintilla/lexers/LexMatlab.cxx @@ -6,6 +6,12 @@ ** Changes by Christoph Dalitz 2003/12/04:
** - added support for Octave
** - Strings can now be included both in single or double quotes
+ **
+ ** Changes by John Donoghue 2012/04/02
+ ** - added block comment (and nested block comments)
+ ** - added ... displayed as a comment
+ ** - removed unused IsAWord functions
+ ** - added some comments
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
@@ -48,14 +54,6 @@ static bool IsOctaveComment(Accessor &styler, int pos, int len) { return len > 0 && IsOctaveCommentChar(styler[pos]) ;
}
-static inline bool IsAWordChar(const int ch) {
- return (ch < 0x80) && (isalnum(ch) || ch == '_');
-}
-
-static inline bool IsAWordStart(const int ch) {
- return (ch < 0x80) && (isalnum(ch) || ch == '_');
-}
-
static void ColouriseMatlabOctaveDoc(
unsigned int startPos, int length, int initStyle,
WordList *keywordlists[], Accessor &styler,
@@ -65,12 +63,41 @@ static void ColouriseMatlabOctaveDoc( styler.StartAt(startPos);
+ // boolean for when the ' is allowed to be transpose vs the start/end
+ // of a string
bool transpose = false;
+ // approximate position of first non space character in a line
+ int nonSpaceColumn = -1;
+ // approximate column position of the current character in a line
+ int column = 0;
+
+ // use the line state of each line to store the block comment depth
+ int curLine = styler.GetLine(startPos);
+ int commentDepth = curLine > 0 ? styler.GetLineState(curLine-1) : 0;
+
+
StyleContext sc(startPos, length, initStyle, styler);
- for (; sc.More(); sc.Forward()) {
+ for (; sc.More(); sc.Forward(), column++) {
+
+ if(sc.atLineStart) {
+ // set the line state to the current commentDepth
+ curLine = styler.GetLine(sc.currentPos);
+ styler.SetLineState(curLine, commentDepth);
+ // reset the column to 0, nonSpace to -1 (not set)
+ column = 0;
+ nonSpaceColumn = -1;
+ }
+
+ // save the column position of first non space character in a line
+ if((nonSpaceColumn == -1) && (! IsASpace(sc.ch)))
+ {
+ nonSpaceColumn = column;
+ }
+
+ // check for end of states
if (sc.state == SCE_MATLAB_OPERATOR) {
if (sc.chPrev == '.') {
if (sc.ch == '*' || sc.ch == '/' || sc.ch == '\\' || sc.ch == '^') {
@@ -79,6 +106,10 @@ static void ColouriseMatlabOctaveDoc( } else if (sc.ch == '\'') {
sc.ForwardSetState(SCE_MATLAB_DEFAULT);
transpose = true;
+ } else if(sc.ch == '.' && sc.chNext == '.') {
+ // we werent an operator, but a '...'
+ sc.ChangeState(SCE_MATLAB_COMMENT);
+ transpose = false;
} else {
sc.SetState(SCE_MATLAB_DEFAULT);
}
@@ -121,15 +152,51 @@ static void ColouriseMatlabOctaveDoc( } else if (sc.ch == '\"') {
sc.ForwardSetState(SCE_MATLAB_DEFAULT);
}
- } else if (sc.state == SCE_MATLAB_COMMENT || sc.state == SCE_MATLAB_COMMAND) {
+ } else if (sc.state == SCE_MATLAB_COMMAND) {
if (sc.atLineEnd) {
sc.SetState(SCE_MATLAB_DEFAULT);
transpose = false;
}
+ } else if (sc.state == SCE_MATLAB_COMMENT) {
+ // end or start of a nested a block comment?
+ if( IsCommentChar(sc.ch) && sc.chNext == '}' && nonSpaceColumn == column) {
+ if(commentDepth > 0) commentDepth --;
+
+ curLine = styler.GetLine(sc.currentPos);
+ styler.SetLineState(curLine, commentDepth);
+ sc.Forward();
+
+ if (commentDepth == 0) {
+ sc.ForwardSetState(SCE_D_DEFAULT);
+ transpose = false;
+ }
+ }
+ else if( IsCommentChar(sc.ch) && sc.chNext == '{' && nonSpaceColumn == column)
+ {
+ commentDepth ++;
+
+ curLine = styler.GetLine(sc.currentPos);
+ styler.SetLineState(curLine, commentDepth);
+ sc.Forward();
+ transpose = false;
+
+ } else if(commentDepth == 0) {
+ // single line comment
+ if (sc.atLineEnd || sc.ch == '\r' || sc.ch == '\n') {
+ sc.SetState(SCE_MATLAB_DEFAULT);
+ transpose = false;
+ }
+ }
}
+ // check start of a new state
if (sc.state == SCE_MATLAB_DEFAULT) {
if (IsCommentChar(sc.ch)) {
+ // ncrement depth if we are a block comment
+ if(sc.chNext == '{' && nonSpaceColumn == column)
+ commentDepth ++;
+ curLine = styler.GetLine(sc.currentPos);
+ styler.SetLineState(curLine, commentDepth);
sc.SetState(SCE_MATLAB_COMMENT);
} else if (sc.ch == '!' && sc.chNext != '=' ) {
sc.SetState(SCE_MATLAB_COMMAND);
diff --git a/scintilla/lexers/LexMySQL.cxx b/scintilla/lexers/LexMySQL.cxx index dd483c1..6b9f749 100644 --- a/scintilla/lexers/LexMySQL.cxx +++ b/scintilla/lexers/LexMySQL.cxx @@ -3,7 +3,7 @@ * @file LexMySQL.cxx
* Lexer for MySQL
*
- * Improved by Mike Lischke <mike.lischke@sun.com>
+ * Improved by Mike Lischke <mike.lischke@oracle.com>
* Adopted from LexSQL.cxx by Anders Karlsson <anders@mysql.com>
* Original work by Neil Hodgson <neilh@scintilla.org>
* Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
@@ -60,74 +60,99 @@ static inline bool IsANumberChar(int ch) { /**
* Check if the current content context represent a keyword and set the context state if so.
*/
-static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[])
+static void CheckForKeyword(StyleContext& sc, WordList* keywordlists[], int activeState)
{
int length = sc.LengthCurrent() + 1; // +1 for the next char
char* s = new char[length];
sc.GetCurrentLowered(s, length);
if (keywordlists[0]->InList(s))
- sc.ChangeState(SCE_MYSQL_MAJORKEYWORD);
+ sc.ChangeState(SCE_MYSQL_MAJORKEYWORD | activeState);
else
if (keywordlists[1]->InList(s))
- sc.ChangeState(SCE_MYSQL_KEYWORD);
+ sc.ChangeState(SCE_MYSQL_KEYWORD | activeState);
else
if (keywordlists[2]->InList(s))
- sc.ChangeState(SCE_MYSQL_DATABASEOBJECT);
+ sc.ChangeState(SCE_MYSQL_DATABASEOBJECT | activeState);
else
if (keywordlists[3]->InList(s))
- sc.ChangeState(SCE_MYSQL_FUNCTION);
+ sc.ChangeState(SCE_MYSQL_FUNCTION | activeState);
else
if (keywordlists[5]->InList(s))
- sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD);
+ sc.ChangeState(SCE_MYSQL_PROCEDUREKEYWORD | activeState);
else
if (keywordlists[6]->InList(s))
- sc.ChangeState(SCE_MYSQL_USER1);
+ sc.ChangeState(SCE_MYSQL_USER1 | activeState);
else
if (keywordlists[7]->InList(s))
- sc.ChangeState(SCE_MYSQL_USER2);
+ sc.ChangeState(SCE_MYSQL_USER2 | activeState);
else
if (keywordlists[8]->InList(s))
- sc.ChangeState(SCE_MYSQL_USER3);
+ sc.ChangeState(SCE_MYSQL_USER3 | activeState);
delete [] s;
}
//--------------------------------------------------------------------------------------------------
+#define HIDDENCOMMAND_STATE 0x40 // Offset for states within a hidden command.
+#define MASKACTIVE(style) (style & ~HIDDENCOMMAND_STATE)
+
+static void SetDefaultState(StyleContext& sc, int activeState)
+{
+ if (activeState == 0)
+ sc.SetState(SCE_MYSQL_DEFAULT);
+ else
+ sc.SetState(SCE_MYSQL_HIDDENCOMMAND);
+}
+
+static void ForwardDefaultState(StyleContext& sc, int activeState)
+{
+ if (activeState == 0)
+ sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ else
+ sc.ForwardSetState(SCE_MYSQL_HIDDENCOMMAND);
+}
+
static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
Accessor &styler)
{
- StyleContext sc(startPos, length, initStyle, styler);
+ StyleContext sc(startPos, length, initStyle, styler, 127);
+ int activeState = (initStyle == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : initStyle & HIDDENCOMMAND_STATE;
for (; sc.More(); sc.Forward())
{
// Determine if the current state should terminate.
- switch (sc.state)
+ switch (MASKACTIVE(sc.state))
{
case SCE_MYSQL_OPERATOR:
- sc.SetState(SCE_MYSQL_DEFAULT);
+ SetDefaultState(sc, activeState);
break;
case SCE_MYSQL_NUMBER:
// We stop the number definition on non-numerical non-dot non-eE non-sign char.
if (!IsANumberChar(sc.ch))
- sc.SetState(SCE_MYSQL_DEFAULT);
+ SetDefaultState(sc, activeState);
break;
case SCE_MYSQL_IDENTIFIER:
// Switch from identifier to keyword state and open a new state for the new char.
if (!IsAWordChar(sc.ch))
{
- CheckForKeyword(sc, keywordlists);
+ CheckForKeyword(sc, keywordlists, activeState);
// Additional check for function keywords needed.
// A function name must be followed by an opening parenthesis.
- if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(')
- sc.ChangeState(SCE_MYSQL_DEFAULT);
+ if (MASKACTIVE(sc.state) == SCE_MYSQL_FUNCTION && sc.ch != '(')
+ {
+ if (activeState > 0)
+ sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND);
+ else
+ sc.ChangeState(SCE_MYSQL_DEFAULT);
+ }
- sc.SetState(SCE_MYSQL_DEFAULT);
+ SetDefaultState(sc, activeState);
}
break;
case SCE_MYSQL_VARIABLE:
if (!IsAWordChar(sc.ch))
- sc.SetState(SCE_MYSQL_DEFAULT);
+ SetDefaultState(sc, activeState);
break;
case SCE_MYSQL_SYSTEMVARIABLE:
if (!IsAWordChar(sc.ch))
@@ -138,10 +163,10 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, // Check for known system variables here.
if (keywordlists[4]->InList(&s[2]))
- sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE);
+ sc.ChangeState(SCE_MYSQL_KNOWNSYSTEMVARIABLE | activeState);
delete [] s;
- sc.SetState(SCE_MYSQL_DEFAULT);
+ SetDefaultState(sc, activeState);
}
break;
case SCE_MYSQL_QUOTEDIDENTIFIER:
@@ -150,20 +175,19 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, if (sc.chNext == '`')
sc.Forward(); // Ignore it
else
- sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ ForwardDefaultState(sc, activeState);
}
break;
case SCE_MYSQL_COMMENT:
- case SCE_MYSQL_HIDDENCOMMAND:
if (sc.Match('*', '/'))
{
sc.Forward();
- sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ ForwardDefaultState(sc, activeState);
}
break;
case SCE_MYSQL_COMMENTLINE:
if (sc.atLineStart)
- sc.SetState(SCE_MYSQL_DEFAULT);
+ SetDefaultState(sc, activeState);
break;
case SCE_MYSQL_SQSTRING:
if (sc.ch == '\\')
@@ -175,7 +199,7 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, if (sc.chNext == '\'')
sc.Forward();
else
- sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ ForwardDefaultState(sc, activeState);
}
break;
case SCE_MYSQL_DQSTRING:
@@ -188,76 +212,94 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, if (sc.chNext == '\"')
sc.Forward();
else
- sc.ForwardSetState(SCE_MYSQL_DEFAULT);
+ ForwardDefaultState(sc, activeState);
}
break;
+ case SCE_MYSQL_PLACEHOLDER:
+ if (sc.Match('}', '>'))
+ {
+ sc.Forward();
+ ForwardDefaultState(sc, activeState);
+ }
+ break;
+ }
+
+ if (sc.state == SCE_MYSQL_HIDDENCOMMAND && sc.Match('*', '/'))
+ {
+ activeState = 0;
+ sc.Forward();
+ ForwardDefaultState(sc, activeState);
}
// Determine if a new state should be entered.
- if (sc.state == SCE_MYSQL_DEFAULT)
+ if (sc.state == SCE_MYSQL_DEFAULT || sc.state == SCE_MYSQL_HIDDENCOMMAND)
{
switch (sc.ch)
{
case '@':
if (sc.chNext == '@')
{
- sc.SetState(SCE_MYSQL_SYSTEMVARIABLE);
+ sc.SetState(SCE_MYSQL_SYSTEMVARIABLE | activeState);
sc.Forward(2); // Skip past @@.
}
else
if (IsAWordStart(sc.ch))
{
- sc.SetState(SCE_MYSQL_VARIABLE);
+ sc.SetState(SCE_MYSQL_VARIABLE | activeState);
sc.Forward(); // Skip past @.
}
else
- sc.SetState(SCE_MYSQL_OPERATOR);
+ sc.SetState(SCE_MYSQL_OPERATOR | activeState);
break;
case '`':
- sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER);
+ sc.SetState(SCE_MYSQL_QUOTEDIDENTIFIER | activeState);
break;
case '#':
- sc.SetState(SCE_MYSQL_COMMENTLINE);
+ sc.SetState(SCE_MYSQL_COMMENTLINE | activeState);
break;
case '\'':
- sc.SetState(SCE_MYSQL_SQSTRING);
+ sc.SetState(SCE_MYSQL_SQSTRING | activeState);
break;
case '\"':
- sc.SetState(SCE_MYSQL_DQSTRING);
+ sc.SetState(SCE_MYSQL_DQSTRING | activeState);
break;
default:
if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext)))
- sc.SetState(SCE_MYSQL_NUMBER);
+ sc.SetState(SCE_MYSQL_NUMBER | activeState);
else
if (IsAWordStart(sc.ch))
- sc.SetState(SCE_MYSQL_IDENTIFIER);
+ sc.SetState(SCE_MYSQL_IDENTIFIER | activeState);
else
if (sc.Match('/', '*'))
{
- sc.SetState(SCE_MYSQL_COMMENT);
+ sc.SetState(SCE_MYSQL_COMMENT | activeState);
// Skip comment introducer and check for hidden command.
sc.Forward(2);
if (sc.ch == '!')
{
+ activeState = HIDDENCOMMAND_STATE;
sc.ChangeState(SCE_MYSQL_HIDDENCOMMAND);
- sc.Forward();
}
}
+ else if (sc.Match('<', '{'))
+ {
+ sc.SetState(SCE_MYSQL_PLACEHOLDER | activeState);
+ }
else
if (sc.Match("--"))
{
// Special MySQL single line comment.
- sc.SetState(SCE_MYSQL_COMMENTLINE);
+ sc.SetState(SCE_MYSQL_COMMENTLINE | activeState);
sc.Forward(2);
// Check the third character too. It must be a space or EOL.
if (sc.ch != ' ' && sc.ch != '\n' && sc.ch != '\r')
- sc.ChangeState(SCE_MYSQL_OPERATOR);
+ sc.ChangeState(SCE_MYSQL_OPERATOR | activeState);
}
else
if (isoperator(static_cast<char>(sc.ch)))
- sc.SetState(SCE_MYSQL_OPERATOR);
+ sc.SetState(SCE_MYSQL_OPERATOR | activeState);
}
}
}
@@ -266,12 +308,12 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, // also at the end of a line.
if (sc.state == SCE_MYSQL_IDENTIFIER)
{
- CheckForKeyword(sc, keywordlists);
+ CheckForKeyword(sc, keywordlists, activeState);
// Additional check for function keywords needed.
// A function name must be followed by an opening parenthesis.
if (sc.state == SCE_MYSQL_FUNCTION && sc.ch != '(')
- sc.ChangeState(SCE_MYSQL_DEFAULT);
+ SetDefaultState(sc, activeState);
}
sc.Complete();
@@ -284,7 +326,7 @@ static void ColouriseMySQLDoc(unsigned int startPos, int length, int initStyle, */
static bool IsStreamCommentStyle(int style)
{
- return style == SCE_MYSQL_COMMENT;
+ return MASKACTIVE(style) == SCE_MYSQL_COMMENT;
}
//--------------------------------------------------------------------------------------------------
@@ -323,6 +365,7 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL int styleNext = styler.StyleAt(startPos);
int style = initStyle;
+ int activeState = (style == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : style & HIDDENCOMMAND_STATE;
bool endPending = false;
bool whenPending = false;
@@ -332,30 +375,23 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL for (unsigned int i = startPos; length > 0; i++, length--)
{
int stylePrev = style;
+ int lastActiveState = activeState;
style = styleNext;
styleNext = styler.StyleAt(i + 1);
+ activeState = (style == SCE_MYSQL_HIDDENCOMMAND) ? HIDDENCOMMAND_STATE : style & HIDDENCOMMAND_STATE;
char currentChar = nextChar;
nextChar = styler.SafeGetCharAt(i + 1);
bool atEOL = (currentChar == '\r' && nextChar != '\n') || (currentChar == '\n');
- switch (style)
+ switch (MASKACTIVE(style))
{
case SCE_MYSQL_COMMENT:
if (foldComment)
{
- // Multiline comment style /* .. */.
- if (IsStreamCommentStyle(style))
- {
- // Increase level if we just start a foldable comment.
- if (!IsStreamCommentStyle(stylePrev))
- levelNext++;
- else
- // If we are in the middle of a foldable comment check if it ends now.
- // Don't end at the line end, though.
- if (!IsStreamCommentStyle(styleNext) && !atEOL)
- levelNext--;
- }
+ // Multiline comment style /* .. */ just started or is still in progress.
+ if (IsStreamCommentStyle(style) && !IsStreamCommentStyle(stylePrev))
+ levelNext++;
}
break;
case SCE_MYSQL_COMMENTLINE:
@@ -377,6 +413,7 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL }
break;
case SCE_MYSQL_HIDDENCOMMAND:
+ /*
if (endPending)
{
// A conditional command is not a white space so it should end the current block
@@ -386,15 +423,9 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL if (levelNext < SC_FOLDLEVELBASE)
levelNext = SC_FOLDLEVELBASE;
}
- if (style != stylePrev)
+ }*/
+ if (activeState != lastActiveState)
levelNext++;
- else
- if (style != styleNext)
- {
- levelNext--;
- if (levelNext < SC_FOLDLEVELBASE)
- levelNext = SC_FOLDLEVELBASE;
- }
break;
case SCE_MYSQL_OPERATOR:
if (endPending)
@@ -480,7 +511,7 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL break;
default:
- if (!isspace(currentChar) && endPending)
+ if (!isspacechar(currentChar) && endPending)
{
// END followed by a non-whitespace character (not covered by other cases like identifiers)
// also should end a folding block. Typical case: END followed by self defined delimiter.
@@ -490,7 +521,23 @@ static void FoldMySQLDoc(unsigned int startPos, int length, int initStyle, WordL }
break;
}
-
+
+ // Go up one level if we just ended a multi line comment.
+ if (IsStreamCommentStyle(stylePrev) && !IsStreamCommentStyle(style))
+ {
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+ }
+
+ if (activeState == 0 && lastActiveState != 0)
+ {
+ // Decrease fold level when we left a hidden command.
+ levelNext--;
+ if (levelNext < SC_FOLDLEVELBASE)
+ levelNext = SC_FOLDLEVELBASE;
+ }
+
if (atEOL)
{
// Apply the new folding level to this line.
@@ -530,4 +577,4 @@ static const char * const mysqlWordListDesc[] = { 0
};
-LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc);
+LexerModule lmMySQL(SCLEX_MYSQL, ColouriseMySQLDoc, "mysql", FoldMySQLDoc, mysqlWordListDesc, 7);
diff --git a/scintilla/lexers/LexOthers.cxx b/scintilla/lexers/LexOthers.cxx index 182cf45..b0ccb54 100644 --- a/scintilla/lexers/LexOthers.cxx +++ b/scintilla/lexers/LexOthers.cxx @@ -1,7 +1,6 @@ // Scintilla source code edit control
/** @file LexOthers.cxx
** Lexers for batch files, diff results, properties files, make files and error lists.
- ** Also lexer for LaTeX documents.
**/
// Copyright 1998-2001 by Neil Hodgson <neilh@scintilla.org>
// The License.txt file describes the conditions under which this software may be distributed.
@@ -943,6 +942,10 @@ static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLin strstr(lineBuffer, ".java:")) {
// Java stack back trace
return SCE_ERR_JAVA_STACK;
+ } else if (strstart(lineBuffer, "In file included from ") ||
+ strstart(lineBuffer, " from ")) {
+ // GCC showing include path to following error
+ return SCE_ERR_GCC_INCLUDED_FROM;
} else {
// Look for one of the following formats:
// GCC: <filename>:<line>:<message>
@@ -1109,301 +1112,6 @@ static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordLi }
}
-static bool latexIsSpecial(int ch) {
- return (ch == '#') || (ch == '$') || (ch == '%') || (ch == '&') || (ch == '_') ||
- (ch == '{') || (ch == '}') || (ch == ' ');
-}
-
-static bool latexIsBlank(int ch) {
- return (ch == ' ') || (ch == '\t');
-}
-
-static bool latexIsBlankAndNL(int ch) {
- return (ch == ' ') || (ch == '\t') || (ch == '\r') || (ch == '\n');
-}
-
-static bool latexIsLetter(int ch) {
- return isascii(ch) && isalpha(ch);
-}
-
-static bool latexIsTagValid(int &i, int l, Accessor &styler) {
- while (i < l) {
- if (styler.SafeGetCharAt(i) == '{') {
- while (i < l) {
- i++;
- if (styler.SafeGetCharAt(i) == '}') {
- return true;
- } else if (!latexIsLetter(styler.SafeGetCharAt(i)) &&
- styler.SafeGetCharAt(i)!='*') {
- return false;
- }
- }
- } else if (!latexIsBlank(styler.SafeGetCharAt(i))) {
- return false;
- }
- i++;
- }
- return false;
-}
-
-static bool latexNextNotBlankIs(int i, int l, Accessor &styler, char needle) {
- char ch;
- while (i < l) {
- ch = styler.SafeGetCharAt(i);
- if (!latexIsBlankAndNL(ch) && ch != '*') {
- if (ch == needle)
- return true;
- else
- return false;
- }
- i++;
- }
- return false;
-}
-
-static bool latexLastWordIs(int start, Accessor &styler, const char *needle) {
- unsigned int i = 0;
- unsigned int l = static_cast<unsigned int>(strlen(needle));
- int ini = start-l+1;
- char s[32];
-
- while (i < l && i < 32) {
- s[i] = styler.SafeGetCharAt(ini + i);
- i++;
- }
- s[i] = '\0';
-
- return (strcmp(s, needle) == 0);
-}
-
-static void ColouriseLatexDoc(unsigned int startPos, int length, int initStyle,
- WordList *[], Accessor &styler) {
-
- styler.StartAt(startPos);
-
- int state = initStyle;
- char chNext = styler.SafeGetCharAt(startPos);
- styler.StartSegment(startPos);
- int lengthDoc = startPos + length;
- char chVerbatimDelim = '\0';
-
- for (int i = startPos; i < lengthDoc; i++) {
- char ch = chNext;
- chNext = styler.SafeGetCharAt(i + 1);
-
- if (styler.IsLeadByte(ch)) {
- i++;
- chNext = styler.SafeGetCharAt(i + 1);
- continue;
- }
-
- switch (state) {
- case SCE_L_DEFAULT :
- switch (ch) {
- case '\\' :
- styler.ColourTo(i - 1, state);
- if (latexIsSpecial(chNext)) {
- state = SCE_L_SPECIAL;
- } else {
- if (latexIsLetter(chNext)) {
- state = SCE_L_COMMAND;
- } else {
- if (chNext == '(' || chNext == '[') {
- styler.ColourTo(i-1, state);
- styler.ColourTo(i+1, SCE_L_SHORTCMD);
- state = SCE_L_MATH;
- if (chNext == '[')
- state = SCE_L_MATH2;
- i++;
- chNext = styler.SafeGetCharAt(i+1);
- } else {
- state = SCE_L_SHORTCMD;
- }
- }
- }
- break;
- case '$' :
- styler.ColourTo(i - 1, state);
- state = SCE_L_MATH;
- if (chNext == '$') {
- state = SCE_L_MATH2;
- i++;
- chNext = styler.SafeGetCharAt(i + 1);
- }
- break;
- case '%' :
- styler.ColourTo(i - 1, state);
- state = SCE_L_COMMENT;
- break;
- }
- break;
- case SCE_L_ERROR:
- styler.ColourTo(i-1, state);
- state = SCE_L_DEFAULT;
- break;
- case SCE_L_SPECIAL:
- case SCE_L_SHORTCMD:
- styler.ColourTo(i, state);
- state = SCE_L_DEFAULT;
- break;
- case SCE_L_COMMAND :
- if (!latexIsLetter(chNext)) {
- styler.ColourTo(i, state);
- state = SCE_L_DEFAULT;
- if (latexNextNotBlankIs(i+1, lengthDoc, styler, '[' )) {
- state = SCE_L_CMDOPT;
- } else if (latexLastWordIs(i, styler, "\\begin")) {
- state = SCE_L_TAG;
- } else if (latexLastWordIs(i, styler, "\\end")) {
- state = SCE_L_TAG2;
- } else if (latexLastWordIs(i, styler, "\\verb") &&
- chNext != '*' && chNext != ' ') {
- chVerbatimDelim = chNext;
- state = SCE_L_VERBATIM;
- }
- }
- break;
- case SCE_L_CMDOPT :
- if (ch == ']') {
- styler.ColourTo(i, state);
- state = SCE_L_DEFAULT;
- }
- break;
- case SCE_L_TAG :
- if (latexIsTagValid(i, lengthDoc, styler)) {
- styler.ColourTo(i, state);
- state = SCE_L_DEFAULT;
- if (latexLastWordIs(i, styler, "{verbatim}")) {
- state = SCE_L_VERBATIM;
- } else if (latexLastWordIs(i, styler, "{comment}")) {
- state = SCE_L_COMMENT2;
- } else if (latexLastWordIs(i, styler, "{math}")) {
- state = SCE_L_MATH;
- } else if (latexLastWordIs(i, styler, "{displaymath}")) {
- state = SCE_L_MATH2;
- } else if (latexLastWordIs(i, styler, "{equation}")) {
- state = SCE_L_MATH2;
- }
- } else {
- state = SCE_L_ERROR;
- styler.ColourTo(i, state);
- state = SCE_L_DEFAULT;
- }
- chNext = styler.SafeGetCharAt(i+1);
- break;
- case SCE_L_TAG2 :
- if (latexIsTagValid(i, lengthDoc, styler)) {
- styler.ColourTo(i, state);
- state = SCE_L_DEFAULT;
- } else {
- state = SCE_L_ERROR;
- }
- chNext = styler.SafeGetCharAt(i+1);
- break;
- case SCE_L_MATH :
- if (ch == '$') {
- styler.ColourTo(i, state);
- state = SCE_L_DEFAULT;
- } else if (ch == '\\' && chNext == ')') {
- styler.ColourTo(i-1, state);
- styler.ColourTo(i+1, SCE_L_SHORTCMD);
- i++;
- chNext = styler.SafeGetCharAt(i+1);
- state = SCE_L_DEFAULT;
- } else if (ch == '\\') {
- int match = i + 3;
- if (latexLastWordIs(match, styler, "\\end")) {
- match++;
- if (latexIsTagValid(match, lengthDoc, styler)) {
- if (latexLastWordIs(match, styler, "{math}")) {
- styler.ColourTo(i-1, state);
- state = SCE_L_COMMAND;
- }
- }
- }
- }
-
- break;
- case SCE_L_MATH2 :
- if (ch == '$') {
- if (chNext == '$') {
- i++;
- chNext = styler.SafeGetCharAt(i + 1);
- styler.ColourTo(i, state);
- state = SCE_L_DEFAULT;
- } else {
- styler.ColourTo(i, SCE_L_ERROR);
- state = SCE_L_DEFAULT;
- }
- } else if (ch == '\\' && chNext == ']') {
- styler.ColourTo(i-1, state);
- styler.ColourTo(i+1, SCE_L_SHORTCMD);
- i++;
- chNext = styler.SafeGetCharAt(i+1);
- state = SCE_L_DEFAULT;
- } else if (ch == '\\') {
- int match = i + 3;
- if (latexLastWordIs(match, styler, "\\end")) {
- match++;
- if (latexIsTagValid(match, lengthDoc, styler)) {
- if (latexLastWordIs(match, styler, "{displaymath}")) {
- styler.ColourTo(i-1, state);
- state = SCE_L_COMMAND;
- } else if (latexLastWordIs(match, styler, "{equation}")) {
- styler.ColourTo(i-1, state);
- state = SCE_L_COMMAND;
- }
- }
- }
- }
- break;
- case SCE_L_COMMENT :
- if (ch == '\r' || ch == '\n') {
- styler.ColourTo(i - 1, state);
- state = SCE_L_DEFAULT;
- }
- break;
- case SCE_L_COMMENT2 :
- if (ch == '\\') {
- int match = i + 3;
- if (latexLastWordIs(match, styler, "\\end")) {
- match++;
- if (latexIsTagValid(match, lengthDoc, styler)) {
- if (latexLastWordIs(match, styler, "{comment}")) {
- styler.ColourTo(i-1, state);
- state = SCE_L_COMMAND;
- }
- }
- }
- }
- break;
- case SCE_L_VERBATIM :
- if (ch == '\\') {
- int match = i + 3;
- if (latexLastWordIs(match, styler, "\\end")) {
- match++;
- if (latexIsTagValid(match, lengthDoc, styler)) {
- if (latexLastWordIs(match, styler, "{verbatim}")) {
- styler.ColourTo(i-1, state);
- state = SCE_L_COMMAND;
- }
- }
- }
- } else if (chNext == chVerbatimDelim) {
- styler.ColourTo(i+1, state);
- state = SCE_L_DEFAULT;
- chVerbatimDelim = '\0';
- } else if (chVerbatimDelim != '\0' && (ch == '\n' || ch == '\r')) {
- styler.ColourTo(i, SCE_L_ERROR);
- state = SCE_L_DEFAULT;
- chVerbatimDelim = '\0';
- }
- break;
- }
- }
- styler.ColourTo(lengthDoc-1, state);
-}
-
static const char *const batchWordListDesc[] = {
"Internal Commands",
"External Commands",
@@ -1429,5 +1137,4 @@ LexerModule lmDiff(SCLEX_DIFF, ColouriseDiffDoc, "diff", FoldDiffDoc, emptyWordL LexerModule lmProps(SCLEX_PROPERTIES, ColourisePropsDoc, "props", FoldPropsDoc, emptyWordListDesc);
LexerModule lmMake(SCLEX_MAKEFILE, ColouriseMakeDoc, "makefile", 0, emptyWordListDesc);
LexerModule lmErrorList(SCLEX_ERRORLIST, ColouriseErrorListDoc, "errorlist", 0, emptyWordListDesc);
-LexerModule lmLatex(SCLEX_LATEX, ColouriseLatexDoc, "latex", 0, emptyWordListDesc);
LexerModule lmNull(SCLEX_NULL, ColouriseNullDoc, "null");
diff --git a/scintilla/lexers/LexPO.cxx b/scintilla/lexers/LexPO.cxx index ced58ef..7b44107 100644 --- a/scintilla/lexers/LexPO.cxx +++ b/scintilla/lexers/LexPO.cxx @@ -98,6 +98,12 @@ static void ColourisePODoc(unsigned int startPos, int length, int initStyle, Wor // forward to the first non-white character on the line bool atLineStart = sc.atLineStart; if (atLineStart) { + // reset line state if it is set to comment state so empty lines don't get + // comment line state, and the folding code folds comments separately, + // and anyway the styling don't use line state for comments + if (curLineState == SCE_PO_COMMENT) + curLineState = SCE_PO_DEFAULT; + while (sc.More() && ! sc.atLineEnd && isspacechar(sc.ch)) sc.Forward(); } @@ -142,8 +148,66 @@ static void ColourisePODoc(unsigned int startPos, int length, int initStyle, Wor sc.Complete(); } +static int FindNextNonEmptyLineState(unsigned int startPos, Accessor &styler) { + unsigned int length = styler.Length(); + for (unsigned int i = startPos; i < length; i++) { + if (! isspacechar(styler[i])) { + return styler.GetLineState(styler.GetLine(i)); + } + } + return 0; +} + +static void FoldPODoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) { + if (! styler.GetPropertyInt("fold")) + return; + bool foldCompact = styler.GetPropertyInt("fold.compact") != 0; + bool foldComment = styler.GetPropertyInt("fold.comment") != 0; + + unsigned int endPos = startPos + length; + int curLine = styler.GetLine(startPos); + int lineState = styler.GetLineState(curLine); + int nextLineState; + int level = styler.LevelAt(curLine) & SC_FOLDLEVELNUMBERMASK; + int nextLevel; + int visible = 0; + int chNext = styler[startPos]; + + for (unsigned int i = startPos; i < endPos; i++) { + int ch = chNext; + chNext = styler.SafeGetCharAt(i+1); + + if (! isspacechar(ch)) { + visible++; + } else if ((ch == '\r' && chNext != '\n') || ch == '\n' || i+1 >= endPos) { + int lvl = level; + int nextLine = curLine + 1; + + nextLineState = styler.GetLineState(nextLine); + if ((lineState != SCE_PO_COMMENT || foldComment) && + nextLineState == lineState && + FindNextNonEmptyLineState(i, styler) == lineState) + nextLevel = SC_FOLDLEVELBASE + 1; + else + nextLevel = SC_FOLDLEVELBASE; + + if (nextLevel > level) + lvl |= SC_FOLDLEVELHEADERFLAG; + if (visible == 0 && foldCompact) + lvl |= SC_FOLDLEVELWHITEFLAG; + + styler.SetLevel(curLine, lvl); + + lineState = nextLineState; + curLine = nextLine; + level = nextLevel; + visible = 0; + } + } +} + static const char *const poWordListDesc[] = { 0 }; -LexerModule lmPO(SCLEX_PO, ColourisePODoc, "po", 0, poWordListDesc); +LexerModule lmPO(SCLEX_PO, ColourisePODoc, "po", FoldPODoc, poWordListDesc); diff --git a/scintilla/lexers/LexRuby.cxx b/scintilla/lexers/LexRuby.cxx index 0930de3..b83569c 100644 --- a/scintilla/lexers/LexRuby.cxx +++ b/scintilla/lexers/LexRuby.cxx @@ -119,7 +119,7 @@ static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywor chAttr = SCE_RB_MODULE_NAME;
else if (0 == strcmp(prevWord, "def"))
chAttr = SCE_RB_DEFNAME;
- else if (keywords.InList(s) && !followsDot(start - 1, styler)) {
+ else if (keywords.InList(s) && ((start == 0) || !followsDot(start - 1, styler))) {
if (keywordIsAmbiguous(s)
&& keywordIsModifier(s, start, styler)) {
diff --git a/scintilla/lexlib/LexAccessor.h b/scintilla/lexlib/LexAccessor.h index 4072059..ed4725f 100644 --- a/scintilla/lexlib/LexAccessor.h +++ b/scintilla/lexlib/LexAccessor.h @@ -12,6 +12,8 @@ namespace Scintilla {
#endif
+enum EncodingType { enc8bit, encUnicode, encDBCS };
+
class LexAccessor {
private:
IDocument *pAccess;
@@ -25,6 +27,7 @@ private: int startPos;
int endPos;
int codePage;
+ enum EncodingType encodingType;
int lenDoc;
int mask;
char styleBuf[bufferSize];
@@ -33,6 +36,7 @@ private: char chWhile;
unsigned int startSeg;
int startPosStyling;
+ int documentVersion;
void Fill(int position) {
startPos = position - slopSize;
@@ -51,9 +55,23 @@ private: public:
LexAccessor(IDocument *pAccess_) :
pAccess(pAccess_), startPos(extremePosition), endPos(0),
- codePage(pAccess->CodePage()), lenDoc(pAccess->Length()),
+ codePage(pAccess->CodePage()),
+ encodingType(enc8bit),
+ lenDoc(pAccess->Length()),
mask(127), validLen(0), chFlags(0), chWhile(0),
- startSeg(0), startPosStyling(0) {
+ startSeg(0), startPosStyling(0),
+ documentVersion(pAccess->Version()) {
+ switch (codePage) {
+ case 65001:
+ encodingType = encUnicode;
+ break;
+ case 932:
+ case 936:
+ case 949:
+ case 950:
+ case 1361:
+ encodingType = encDBCS;
+ }
}
char operator[](int position) {
if (position < startPos || position >= endPos) {
@@ -75,7 +93,9 @@ public: bool IsLeadByte(char ch) {
return pAccess->IsDBCSLeadByte(ch);
}
-
+ EncodingType Encoding() const {
+ return encodingType;
+ }
bool Match(int pos, const char *s) {
for (int i=0; *s; i++) {
if (*s != SafeGetCharAt(pos+i))
@@ -93,6 +113,19 @@ public: int LineStart(int line) {
return pAccess->LineStart(line);
}
+ int LineEnd(int line) {
+ if (documentVersion >= dvLineEnd) {
+ return (static_cast<IDocumentWithLineEnd *>(pAccess))->LineEnd(line);
+ } else {
+ // Old interface means only '\r', '\n' and '\r\n' line ends.
+ int startNext = pAccess->LineStart(line+1);
+ char chLineEnd = SafeGetCharAt(startNext-1);
+ if (chLineEnd == '\n' && (SafeGetCharAt(startNext-2) == '\r'))
+ return startNext - 2;
+ else
+ return startNext - 1;
+ }
+ }
int LevelAt(int line) {
return pAccess->GetLevel(line);
}
diff --git a/scintilla/lexlib/LexerBase.cxx b/scintilla/lexlib/LexerBase.cxx index e2791ec..0f75851 100644 --- a/scintilla/lexlib/LexerBase.cxx +++ b/scintilla/lexlib/LexerBase.cxx @@ -1,5 +1,5 @@ // Scintilla source code edit control
-/** @file LexerSimple.cxx
+/** @file LexerBase.cxx
** A simple lexer with no state.
**/
// Copyright 1998-2010 by Neil Hodgson <neilh@scintilla.org>
diff --git a/scintilla/lexlib/LexerModule.cxx b/scintilla/lexlib/LexerModule.cxx index 4b1aa6d..853039f 100644 --- a/scintilla/lexlib/LexerModule.cxx +++ b/scintilla/lexlib/LexerModule.cxx @@ -74,11 +74,9 @@ int LexerModule::GetNumWordLists() const { }
const char *LexerModule::GetWordListDescription(int index) const {
- static const char *emptyStr = "";
-
assert(index < GetNumWordLists());
if (index >= GetNumWordLists()) {
- return emptyStr;
+ return "";
} else {
return wordListDescriptions[index];
}
diff --git a/scintilla/lexlib/StyleContext.h b/scintilla/lexlib/StyleContext.h index f57f1b9..c3194ae 100644 --- a/scintilla/lexlib/StyleContext.h +++ b/scintilla/lexlib/StyleContext.h @@ -19,6 +19,30 @@ static inline int MakeLowerCase(int ch) { return ch - 'A' + 'a';
}
+inline int UnicodeCodePoint(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];
+}
+
+inline int BytesInUnicodeCodePoint(int codePoint) {
+ if (codePoint < 0x80)
+ return 1;
+ else if (codePoint < 0x800)
+ return 2;
+ else if (codePoint < 0x10000)
+ return 3;
+ else
+ return 4;
+}
+
// All languages handled so far can treat all characters >= 0x80 as one class
// which just continues the current token or starts an identifier if in default.
// DBCS treated specially as the second character can be < 0x80 and hence
@@ -26,23 +50,42 @@ static inline int MakeLowerCase(int ch) { class StyleContext {
LexAccessor &styler;
unsigned int endPos;
+ unsigned int lengthDocument;
StyleContext &operator=(const StyleContext &);
+
void GetNextChar(unsigned int pos) {
- chNext = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1));
- if (styler.IsLeadByte(static_cast<char>(chNext))) {
- chNext = chNext << 8;
- chNext |= static_cast<unsigned char>(styler.SafeGetCharAt(pos+2));
+ chNext = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1, 0));
+ if (styler.Encoding() == encUnicode) {
+ if (chNext >= 0x80) {
+ unsigned char bytes[4] = { static_cast<unsigned char>(chNext), 0, 0, 0 };
+ for (int trail=1; trail<3; trail++) {
+ bytes[trail] = static_cast<unsigned char>(styler.SafeGetCharAt(pos+1+trail, 0));
+ if (!((bytes[trail] >= 0x80) && (bytes[trail] < 0xc0))) {
+ bytes[trail] = 0;
+ break;
+ }
+ }
+ chNext = UnicodeCodePoint(bytes);
+ }
+ } else if (styler.Encoding() == encDBCS) {
+ if (styler.IsLeadByte(static_cast<char>(chNext))) {
+ chNext = chNext << 8;
+ chNext |= static_cast<unsigned char>(styler.SafeGetCharAt(pos+2, 0));
+ }
}
// End of line?
// Trigger on CR only (Mac style) or either on LF from CR+LF (Dos/Win)
// or on LF alone (Unix). Avoid triggering two times on Dos/Win.
- atLineEnd = (ch == '\r' && chNext != '\n') ||
- (ch == '\n') ||
- (currentPos >= endPos);
+ if (lineStartNext < styler.Length())
+ atLineEnd = static_cast<int>(pos) >= (lineStartNext-1);
+ else // Last line
+ atLineEnd = static_cast<int>(pos) >= lineStartNext;
}
public:
unsigned int currentPos;
+ int currentLine;
+ int lineStartNext;
bool atLineStart;
bool atLineEnd;
int state;
@@ -55,6 +98,8 @@ public: styler(styler_),
endPos(startPos + length),
currentPos(startPos),
+ currentLine(-1),
+ lineStartNext(-1),
atLineEnd(false),
state(initStyle & chMask), // Mask off all bits which aren't in the chMask.
chPrev(0),
@@ -62,18 +107,30 @@ public: chNext(0) {
styler.StartAt(startPos, chMask);
styler.StartSegment(startPos);
- atLineStart = static_cast<unsigned int>(styler.LineStart(styler.GetLine(startPos))) == startPos;
+ currentLine = styler.GetLine(startPos);
+ lineStartNext = styler.LineStart(currentLine+1);
+ lengthDocument = static_cast<unsigned int>(styler.Length());
+ if (endPos == lengthDocument)
+ endPos++;
+ atLineStart = static_cast<unsigned int>(styler.LineStart(currentLine)) == startPos;
unsigned int pos = currentPos;
- ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos));
- if (styler.IsLeadByte(static_cast<char>(ch))) {
- pos++;
- ch = ch << 8;
- ch |= static_cast<unsigned char>(styler.SafeGetCharAt(pos));
+ ch = static_cast<unsigned char>(styler.SafeGetCharAt(pos, 0));
+ if (styler.Encoding() == encUnicode) {
+ // Get the current char
+ GetNextChar(pos-1);
+ ch = chNext;
+ pos += BytesInUnicodeCodePoint(ch) - 1;
+ } else if (styler.Encoding() == encDBCS) {
+ if (styler.IsLeadByte(static_cast<char>(ch))) {
+ pos++;
+ ch = ch << 8;
+ ch |= static_cast<unsigned char>(styler.SafeGetCharAt(pos, 0));
+ }
}
GetNextChar(pos);
}
void Complete() {
- styler.ColourTo(currentPos - 1, state);
+ styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state);
styler.Flush();
}
bool More() const {
@@ -82,12 +139,28 @@ public: void Forward() {
if (currentPos < endPos) {
atLineStart = atLineEnd;
+ if (atLineStart) {
+ currentLine++;
+ lineStartNext = styler.LineStart(currentLine+1);
+ }
chPrev = ch;
- currentPos++;
- if (ch >= 0x100)
+ if (styler.Encoding() == encUnicode) {
+ currentPos += BytesInUnicodeCodePoint(ch);
+ } else if (styler.Encoding() == encDBCS) {
+ currentPos++;
+ if (ch >= 0x100)
+ currentPos++;
+ } else {
currentPos++;
+ }
ch = chNext;
- GetNextChar(currentPos + ((ch >= 0x100) ? 1 : 0));
+ if (styler.Encoding() == encUnicode) {
+ GetNextChar(currentPos + BytesInUnicodeCodePoint(ch)-1);
+ } else if (styler.Encoding() == encDBCS) {
+ GetNextChar(currentPos + ((ch >= 0x100) ? 1 : 0));
+ } else {
+ GetNextChar(currentPos);
+ }
} else {
atLineStart = false;
chPrev = ' ';
@@ -105,19 +178,19 @@ public: state = state_;
}
void SetState(int state_) {
- styler.ColourTo(currentPos - 1, state);
+ styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state);
state = state_;
}
void ForwardSetState(int state_) {
Forward();
- styler.ColourTo(currentPos - 1, state);
+ styler.ColourTo(currentPos - ((currentPos > lengthDocument) ? 2 : 1), state);
state = state_;
}
int LengthCurrent() {
return currentPos - styler.GetStartSegment();
}
int GetRelative(int n) {
- return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n));
+ return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n, 0));
}
bool Match(char ch0) const {
return ch == static_cast<unsigned char>(ch0);
@@ -135,7 +208,7 @@ public: return false;
s++;
for (int n=2; *s; n++) {
- if (*s != styler.SafeGetCharAt(currentPos+n))
+ if (*s != styler.SafeGetCharAt(currentPos+n, 0))
return false;
s++;
}
@@ -150,7 +223,7 @@ public: s++;
for (int n=2; *s; n++) {
if (static_cast<unsigned char>(*s) !=
- MakeLowerCase(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n))))
+ MakeLowerCase(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n, 0))))
return false;
s++;
}
diff --git a/scintilla/lexlib/SubStyles.h b/scintilla/lexlib/SubStyles.h new file mode 100644 index 0000000..e6c34e0 --- /dev/null +++ b/scintilla/lexlib/SubStyles.h @@ -0,0 +1,162 @@ +// Scintilla source code edit control +/** @file SubStyles.h + ** Manage substyles for a lexer. + **/ +// Copyright 2012 by Neil Hodgson <neilh@scintilla.org> +// The License.txt file describes the conditions under which this software may be distributed. + +#ifndef SUBSTYLES_H +#define SUBSTYLES_H + +#ifdef SCI_NAMESPACE +namespace Scintilla { +#endif + +class WordClassifier { + int firstStyle; + int lenStyles; + std::map<std::string, int> wordToStyle; + +public: + + WordClassifier() : firstStyle(0), lenStyles(0) { + } + + void Allocate(int firstStyle_, int lenStyles_) { + firstStyle = firstStyle_; + lenStyles = lenStyles_; + wordToStyle.clear(); + } + + int Start() const { + return firstStyle; + } + + int Length() const { + return lenStyles; + } + + void Clear() { + firstStyle = 0; + lenStyles = 0; + wordToStyle.clear(); + } + + int ValueFor(const std::string &s) const { + std::map<std::string, int>::const_iterator it = wordToStyle.find(s); + if (it != wordToStyle.end()) + return it->second; + else + return -1; + } + + bool IncludesStyle(int style) const { + return (style >= firstStyle) && (style < (firstStyle + lenStyles)); + } + + void SetIdentifiers(int style, const char *identifiers) { + while (*identifiers) { + const char *cpSpace = identifiers; + while (*cpSpace && *cpSpace != ' ') + cpSpace++; + std::string word(identifiers, cpSpace - identifiers); + wordToStyle[word] = style; + identifiers = cpSpace; + if (*identifiers) + identifiers++; + } + } +}; + +class SubStyles { + int classifications; + const char *baseStyles; + int styleFirst; + int stylesAvailable; + int secondaryDistance; + int allocated; + std::vector<WordClassifier> classifiers; + + int BlockFromBaseStyle(int baseStyle) const { + for (int b=0; b < classifications; b++) { + if (baseStyle == baseStyles[b]) + return b; + } + return -1; + } + + int BlockFromStyle(int style) const { + int b = 0; + for (std::vector<WordClassifier>::const_iterator it=classifiers.begin(); it != classifiers.end(); ++it) { + if (it->IncludesStyle(style)) + return b; + b++; + } + return -1; + } + +public: + + SubStyles(const char *baseStyles_, int styleFirst_, int stylesAvailable_, int secondaryDistance_) : + classifications(0), + baseStyles(baseStyles_), + styleFirst(styleFirst_), + stylesAvailable(stylesAvailable_), + secondaryDistance(secondaryDistance_), + allocated(0) { + while (baseStyles[classifications]) { + classifications++; + classifiers.push_back(WordClassifier()); + } + } + + int Allocate(int styleBase, int numberStyles) { + int block = BlockFromBaseStyle(styleBase); + if (block >= 0) { + if ((allocated + numberStyles) > stylesAvailable) + return -1; + int startBlock = styleFirst + allocated; + allocated += numberStyles; + classifiers[block].Allocate(startBlock, numberStyles); + return startBlock; + } else { + return -1; + } + } + + int Start(int styleBase) { + int block = BlockFromBaseStyle(styleBase); + return (block >= 0) ? classifiers[block].Start() : -1; + } + + int Length(int styleBase) { + int block = BlockFromBaseStyle(styleBase); + return (block >= 0) ? classifiers[block].Length() : 0; + } + + int DistanceToSecondaryStyles() const { + return secondaryDistance; + } + + void SetIdentifiers(int style, const char *identifiers) { + int block = BlockFromStyle(style); + if (block >= 0) + classifiers[block].SetIdentifiers(style, identifiers); + } + + void Free() { + allocated = 0; + for (std::vector<WordClassifier>::iterator it=classifiers.begin(); it != classifiers.end(); ++it) + it->Clear(); + } + + const WordClassifier &Classifier(int baseStyle) const { + return classifiers[BlockFromBaseStyle(baseStyle)]; + } +}; + +#ifdef SCI_NAMESPACE +} +#endif + +#endif diff --git a/scintilla/src/AutoComplete.cxx b/scintilla/src/AutoComplete.cxx index f0980c7..9530808 100644 --- a/scintilla/src/AutoComplete.cxx +++ b/scintilla/src/AutoComplete.cxx @@ -10,7 +10,9 @@ #include <stdio.h>
#include <assert.h>
+#include <algorithm>
#include <string>
+#include <vector>
#include "Platform.h"
@@ -36,7 +38,8 @@ AutoComplete::AutoComplete() : dropRestOfWord(false),
ignoreCaseBehaviour(SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE),
widthLBDefault(100),
- heightLBDefault(100) {
+ heightLBDefault(100),
+ autoSort(SC_ORDER_PRESORTED) {
lb = ListBox::Allocate();
stopChars[0] = '\0';
fillUpChars[0] = '\0';
@@ -101,8 +104,91 @@ char AutoComplete::GetTypesep() const { return typesep;
}
+struct Sorter {
+ AutoComplete *ac;
+ const char *list;
+ std::vector<int> indices;
+
+ Sorter(AutoComplete *ac_, const char *list_) : ac(ac_), list(list_) {
+ int i = 0;
+ while (list[i]) {
+ indices.push_back(i); // word start
+ while (list[i] != ac->GetTypesep() && list[i] != ac->GetSeparator() && list[i])
+ ++i;
+ indices.push_back(i); // word end
+ if (list[i] == ac->GetTypesep()) {
+ while (list[i] != ac->GetSeparator() && list[i])
+ ++i;
+ }
+ if (list[i] == ac->GetSeparator()) {
+ ++i;
+ // preserve trailing separator as blank entry
+ if (!list[i]) {
+ indices.push_back(i);
+ indices.push_back(i);
+ }
+ }
+ }
+ indices.push_back(i); // index of last position
+ }
+
+ bool operator()(int a, int b) {
+ int lenA = indices[a * 2 + 1] - indices[a * 2];
+ int lenB = indices[b * 2 + 1] - indices[b * 2];
+ int len = std::min(lenA, lenB);
+ int cmp;
+ if (ac->ignoreCase)
+ cmp = CompareNCaseInsensitive(list + indices[a * 2], list + indices[b * 2], len);
+ else
+ cmp = strncmp(list + indices[a * 2], list + indices[b * 2], len);
+ if (cmp == 0)
+ cmp = lenA - lenB;
+ return cmp < 0;
+ }
+};
+
void AutoComplete::SetList(const char *list) {
- lb->SetList(list, separator, typesep);
+ if (autoSort == SC_ORDER_PRESORTED) {
+ lb->SetList(list, separator, typesep);
+ sortMatrix.clear();
+ for (int i = 0; i < lb->Length(); ++i)
+ sortMatrix.push_back(i);
+ return;
+ }
+
+ Sorter IndexSort(this, list);
+ sortMatrix.clear();
+ for (int i = 0; i < (int)IndexSort.indices.size() / 2; ++i)
+ sortMatrix.push_back(i);
+ std::sort(sortMatrix.begin(), sortMatrix.end(), IndexSort);
+ if (autoSort == SC_ORDER_CUSTOM || sortMatrix.size() < 2) {
+ lb->SetList(list, separator, typesep);
+ PLATFORM_ASSERT(lb->Length() == static_cast<int>(sortMatrix.size()));
+ return;
+ }
+
+ std::string sortedList;
+ char item[maxItemLen];
+ for (size_t i = 0; i < sortMatrix.size(); ++i) {
+ int wordLen = IndexSort.indices[sortMatrix[i] * 2 + 2] - IndexSort.indices[sortMatrix[i] * 2];
+ strncpy(item, list + IndexSort.indices[sortMatrix[i] * 2], wordLen);
+ if ((i+1) == sortMatrix.size()) {
+ // Last item so remove separator if present
+ if ((wordLen > 0) && (item[wordLen-1] == separator))
+ wordLen--;
+ } else {
+ // Item before last needs a separator
+ if ((wordLen == 0) || (item[wordLen-1] != separator)) {
+ item[wordLen] = separator;
+ wordLen++;
+ }
+ }
+ item[wordLen] = '\0';
+ sortedList += item;
+ }
+ for (int i = 0; i < (int)sortMatrix.size(); ++i)
+ sortMatrix[i] = i;
+ lb->SetList(sortedList.c_str(), separator, typesep);
}
int AutoComplete::GetSelection() const {
@@ -149,7 +235,7 @@ void AutoComplete::Select(const char *word) { while ((start <= end) && (location == -1)) { // Binary searching loop
int pivot = (start + end) / 2;
char item[maxItemLen];
- lb->GetValue(pivot, item, maxItemLen);
+ lb->GetValue(sortMatrix[pivot], item, maxItemLen);
int cond;
if (ignoreCase)
cond = CompareNCaseInsensitive(word, item, lenWord);
@@ -158,7 +244,7 @@ void AutoComplete::Select(const char *word) { if (!cond) {
// Find first match
while (pivot > start) {
- lb->GetValue(pivot-1, item, maxItemLen);
+ lb->GetValue(sortMatrix[pivot-1], item, maxItemLen);
if (ignoreCase)
cond = CompareNCaseInsensitive(word, item, lenWord);
else
@@ -172,7 +258,7 @@ void AutoComplete::Select(const char *word) { && ignoreCaseBehaviour == SC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE) {
// Check for exact-case match
for (; pivot <= end; pivot++) {
- lb->GetValue(pivot, item, maxItemLen);
+ lb->GetValue(sortMatrix[pivot], item, maxItemLen);
if (!strncmp(word, item, lenWord)) {
location = pivot;
break;
@@ -187,9 +273,24 @@ void AutoComplete::Select(const char *word) { start = pivot + 1;
}
}
- if (location == -1 && autoHide)
- Cancel();
- else
- lb->Select(location);
+ if (location == -1) {
+ if (autoHide)
+ Cancel();
+ else
+ lb->Select(-1);
+ } else {
+ if (autoSort == SC_ORDER_CUSTOM) {
+ // Check for a logically earlier match
+ char item[maxItemLen];
+ for (int i = location + 1; i <= end; ++i) {
+ lb->GetValue(sortMatrix[i], item, maxItemLen);
+ if (CompareNCaseInsensitive(word, item, lenWord))
+ break;
+ if (sortMatrix[i] < sortMatrix[location] && !strncmp(word, item, lenWord))
+ location = i;
+ }
+ }
+ lb->Select(sortMatrix[location]);
+ }
}
diff --git a/scintilla/src/AutoComplete.h b/scintilla/src/AutoComplete.h index ed215ec..c6562d2 100644 --- a/scintilla/src/AutoComplete.h +++ b/scintilla/src/AutoComplete.h @@ -21,6 +21,7 @@ class AutoComplete { char separator;
char typesep; // Type seperator
enum { maxItemLen=1000 };
+ std::vector<int> sortMatrix;
public:
@@ -36,6 +37,11 @@ public: unsigned int ignoreCaseBehaviour;
int widthLBDefault;
int heightLBDefault;
+ /** SC_ORDER_PRESORTED: Assume the list is presorted; selection will fail if it is not alphabetical<br />
+ * SC_ORDER_PERFORMSORT: Sort the list alphabetically; start up performance cost for sorting<br />
+ * SC_ORDER_CUSTOM: Handle non-alphabetical entries; start up performance cost for generating a sorted lookup table
+ */
+ int autoSort;
AutoComplete();
~AutoComplete();
diff --git a/scintilla/src/CellBuffer.cxx b/scintilla/src/CellBuffer.cxx index 003710f..7c1b42c 100644 --- a/scintilla/src/CellBuffer.cxx +++ b/scintilla/src/CellBuffer.cxx @@ -16,6 +16,7 @@ #include "SplitVector.h"
#include "Partitioning.h"
#include "CellBuffer.h"
+#include "UniConversion.h"
#ifdef SCI_NAMESPACE
using namespace Scintilla;
@@ -331,6 +332,7 @@ void UndoHistory::CompletedRedoStep() { CellBuffer::CellBuffer() {
readOnly = false;
+ utf8LineEnds = 0;
collectingUndo = true;
}
@@ -458,6 +460,13 @@ void CellBuffer::Allocate(int newSize) { style.ReAllocate(newSize);
}
+void CellBuffer::SetLineEndTypes(int utf8LineEnds_) {
+ if (utf8LineEnds != utf8LineEnds_) {
+ utf8LineEnds = utf8LineEnds_;
+ ResetLineEnds();
+ }
+}
+
void CellBuffer::SetPerLine(PerLine *pl) {
lv.SetPerLine(pl);
}
@@ -501,11 +510,63 @@ void CellBuffer::RemoveLine(int line) { lv.RemoveLine(line);
}
+bool CellBuffer::UTF8LineEndOverlaps(int position) const {
+ unsigned char bytes[] = {
+ static_cast<unsigned char>(substance.ValueAt(position-2)),
+ static_cast<unsigned char>(substance.ValueAt(position-1)),
+ static_cast<unsigned char>(substance.ValueAt(position)),
+ static_cast<unsigned char>(substance.ValueAt(position+1)),
+ };
+ return UTF8IsSeparator(bytes) || UTF8IsSeparator(bytes+1) || UTF8IsNEL(bytes+1);
+}
+
+void CellBuffer::ResetLineEnds() {
+ // Reinitialize line data -- too much work to preserve
+ lv.Init();
+
+ int position = 0;
+ int length = Length();
+ int lineInsert = 1;
+ bool atLineStart = true;
+ lv.InsertText(lineInsert-1, length);
+ unsigned char chBeforePrev = 0;
+ unsigned char chPrev = 0;
+ for (int i = 0; i < length; i++) {
+ unsigned char ch = substance.ValueAt(position + i);
+ if (ch == '\r') {
+ InsertLine(lineInsert, (position + i) + 1, atLineStart);
+ lineInsert++;
+ } else if (ch == '\n') {
+ if (chPrev == '\r') {
+ // Patch up what was end of line
+ lv.SetLineStart(lineInsert - 1, (position + i) + 1);
+ } else {
+ InsertLine(lineInsert, (position + i) + 1, atLineStart);
+ lineInsert++;
+ }
+ } else if (utf8LineEnds) {
+ unsigned char back3[3] = {chBeforePrev, chPrev, ch};
+ if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) {
+ InsertLine(lineInsert, (position + i) + 1, atLineStart);
+ lineInsert++;
+ }
+ }
+ chBeforePrev = chPrev;
+ chPrev = ch;
+ }
+}
+
void CellBuffer::BasicInsertString(int position, const char *s, int insertLength) {
if (insertLength == 0)
return;
PLATFORM_ASSERT(insertLength > 0);
+ unsigned char chAfter = substance.ValueAt(position);
+ bool breakingUTF8LineEnd = false;
+ if (utf8LineEnds && UTF8IsTrailByte(chAfter)) {
+ breakingUTF8LineEnd = UTF8LineEndOverlaps(position);
+ }
+
substance.InsertFromArray(position, s, 0, insertLength);
style.InsertValue(position, insertLength, 0);
@@ -513,14 +574,17 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength bool atLineStart = lv.LineStart(lineInsert-1) == position;
// Point all the lines after the insertion point further along in the buffer
lv.InsertText(lineInsert-1, insertLength);
- char chPrev = substance.ValueAt(position - 1);
- char chAfter = substance.ValueAt(position + insertLength);
+ unsigned char chBeforePrev = substance.ValueAt(position - 2);
+ unsigned char chPrev = substance.ValueAt(position - 1);
if (chPrev == '\r' && chAfter == '\n') {
// Splitting up a crlf pair at position
InsertLine(lineInsert, position, false);
lineInsert++;
}
- char ch = ' ';
+ if (breakingUTF8LineEnd) {
+ RemoveLine(lineInsert);
+ }
+ unsigned char ch = ' ';
for (int i = 0; i < insertLength; i++) {
ch = s[i];
if (ch == '\r') {
@@ -534,7 +598,14 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength InsertLine(lineInsert, (position + i) + 1, atLineStart);
lineInsert++;
}
+ } else if (utf8LineEnds) {
+ unsigned char back3[3] = {chBeforePrev, chPrev, ch};
+ if (UTF8IsSeparator(back3) || UTF8IsNEL(back3+1)) {
+ InsertLine(lineInsert, (position + i) + 1, atLineStart);
+ lineInsert++;
+ }
}
+ chBeforePrev = chPrev;
chPrev = ch;
}
// Joining two lines where last insertion is cr and following substance starts with lf
@@ -543,6 +614,22 @@ void CellBuffer::BasicInsertString(int position, const char *s, int insertLength // End of line already in buffer so drop the newly created one
RemoveLine(lineInsert - 1);
}
+ } else if (utf8LineEnds && !UTF8IsAscii(chAfter)) {
+ // May have end of UTF-8 line end in buffer and start in insertion
+ for (int j = 0; j < UTF8SeparatorLength-1; j++) {
+ unsigned char chAt = substance.ValueAt(position + insertLength + j);
+ unsigned char back3[3] = {chBeforePrev, chPrev, chAt};
+ if (UTF8IsSeparator(back3)) {
+ InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
+ lineInsert++;
+ }
+ if ((j == 0) && UTF8IsNEL(back3+1)) {
+ InsertLine(lineInsert, (position + insertLength + j) + 1, atLineStart);
+ lineInsert++;
+ }
+ chBeforePrev = chPrev;
+ chPrev = chAt;
+ }
}
}
@@ -560,9 +647,9 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) { int lineRemove = lv.LineFromPosition(position) + 1;
lv.InsertText(lineRemove-1, - (deleteLength));
- char chPrev = substance.ValueAt(position - 1);
- char chBefore = chPrev;
- char chNext = substance.ValueAt(position);
+ unsigned char chPrev = substance.ValueAt(position - 1);
+ unsigned char chBefore = chPrev;
+ unsigned char chNext = substance.ValueAt(position);
bool ignoreNL = false;
if (chPrev == '\r' && chNext == '\n') {
// Move back one
@@ -570,8 +657,13 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) { lineRemove++;
ignoreNL = true; // First \n is not real deletion
}
+ if (utf8LineEnds && UTF8IsTrailByte(chNext)) {
+ if (UTF8LineEndOverlaps(position)) {
+ RemoveLine(lineRemove);
+ }
+ }
- char ch = chNext;
+ unsigned char ch = chNext;
for (int i = 0; i < deleteLength; i++) {
chNext = substance.ValueAt(position + i + 1);
if (ch == '\r') {
@@ -584,6 +676,14 @@ void CellBuffer::BasicDeleteChars(int position, int deleteLength) { } else {
RemoveLine(lineRemove);
}
+ } else if (utf8LineEnds) {
+ if (!UTF8IsAscii(ch)) {
+ unsigned char next3[3] = {ch, chNext,
+ static_cast<unsigned char>(substance.ValueAt(position + i + 2))};
+ if (UTF8IsSeparator(next3) || UTF8IsNEL(next3)) {
+ RemoveLine(lineRemove);
+ }
+ }
}
ch = chNext;
diff --git a/scintilla/src/CellBuffer.h b/scintilla/src/CellBuffer.h index 29743af..86b94cb 100644 --- a/scintilla/src/CellBuffer.h +++ b/scintilla/src/CellBuffer.h @@ -98,6 +98,9 @@ class UndoHistory { void EnsureUndoRoom();
+ // Private so UndoHistory objects can not be copied
+ UndoHistory(const UndoHistory &);
+
public:
UndoHistory();
~UndoHistory();
@@ -136,12 +139,15 @@ private: SplitVector<char> substance;
SplitVector<char> style;
bool readOnly;
+ int utf8LineEnds;
bool collectingUndo;
UndoHistory uh;
LineVector lv;
+ bool UTF8LineEndOverlaps(int position) const;
+ void ResetLineEnds();
/// Actions without undo
void BasicInsertString(int position, const char *s, int insertLength);
void BasicDeleteChars(int position, int deleteLength);
@@ -162,6 +168,8 @@ public: int Length() const;
void Allocate(int newSize);
+ int GetLineEndTypes() const { return utf8LineEnds; }
+ void SetLineEndTypes(int utf8LineEnds_);
void SetPerLine(PerLine *pl);
int Lines() const;
int LineStart(int line) const;
diff --git a/scintilla/src/ContractionState.cxx b/scintilla/src/ContractionState.cxx index 3b77beb..938e16f 100644 --- a/scintilla/src/ContractionState.cxx +++ b/scintilla/src/ContractionState.cxx @@ -66,7 +66,7 @@ int ContractionState::LinesDisplayed() const { int ContractionState::DisplayFromDoc(int lineDoc) const {
if (OneToOne()) {
- return lineDoc;
+ return (lineDoc <= linesInDocument) ? lineDoc : linesInDocument;
} else {
if (lineDoc > displayLines->Partitions())
lineDoc = displayLines->Partitions();
diff --git a/scintilla/src/Document.cxx b/scintilla/src/Document.cxx index 205de27..38b931c 100644 --- a/scintilla/src/Document.cxx +++ b/scintilla/src/Document.cxx @@ -67,6 +67,17 @@ void LexInterface::Colourise(int start, int end) { }
}
+int LexInterface::LineEndTypesSupported() {
+ if (instance) {
+ int interfaceVersion = instance->Version();
+ if (interfaceVersion >= lvSubStyles) {
+ ILexerWithSubStyles *ssinstance = static_cast<ILexerWithSubStyles *>(instance);
+ return ssinstance->LineEndTypesSupported();
+ }
+ }
+ return 0;
+}
+
Document::Document() {
refCount = 0;
pcf = NULL;
@@ -76,6 +87,7 @@ Document::Document() { eolMode = SC_EOL_LF;
#endif
dbcsCodePage = 0;
+ lineEndBitSet = SC_LINE_END_TYPE_DEFAULT;
stylingBits = 5;
stylingBitsMask = 0x1F;
stylingMask = 0;
@@ -135,16 +147,40 @@ void Document::Init() { }
}
+int Document::LineEndTypesSupported() const {
+ if ((SC_CP_UTF8 == dbcsCodePage) && pli)
+ return pli->LineEndTypesSupported();
+ else
+ return 0;
+}
+
bool Document::SetDBCSCodePage(int dbcsCodePage_) {
if (dbcsCodePage != dbcsCodePage_) {
dbcsCodePage = dbcsCodePage_;
SetCaseFolder(NULL);
+ cb.SetLineEndTypes(lineEndBitSet & LineEndTypesSupported());
return true;
} else {
return false;
}
}
+bool Document::SetLineEndTypesAllowed(int lineEndBitSet_) {
+ if (lineEndBitSet != lineEndBitSet_) {
+ lineEndBitSet = lineEndBitSet_;
+ int lineEndBitSetActive = lineEndBitSet & LineEndTypesSupported();
+ if (lineEndBitSetActive != cb.GetLineEndTypes()) {
+ ModifiedAt(0);
+ cb.SetLineEndTypes(lineEndBitSetActive);
+ return true;
+ } else {
+ return false;
+ }
+ } else {
+ return false;
+ }
+}
+
void Document::InsertLine(int line) {
for (int j=0; j<ldSize; j++) {
if (perLineData[j])
@@ -245,11 +281,25 @@ int SCI_METHOD Document::LineStart(int line) const { return cb.LineStart(line);
}
-int Document::LineEnd(int line) const {
+int SCI_METHOD Document::LineEnd(int line) const {
if (line == LinesTotal() - 1) {
return LineStart(line + 1);
} else {
- int position = LineStart(line + 1) - 1;
+ int position = LineStart(line + 1);
+ if (SC_CP_UTF8 == dbcsCodePage) {
+ unsigned char bytes[] = {
+ static_cast<unsigned char>(cb.CharAt(position-3)),
+ static_cast<unsigned char>(cb.CharAt(position-2)),
+ static_cast<unsigned char>(cb.CharAt(position-1)),
+ };
+ if (UTF8IsSeparator(bytes)) {
+ return position - UTF8SeparatorLength;
+ }
+ if (UTF8IsNEL(bytes+1)) {
+ return position - UTF8NELLength;
+ }
+ }
+ position--; // Back over CR or LF
// When line terminator is CR+LF, may need to go back one more
if ((position > LineStart(line)) && (cb.CharAt(position - 1) == '\r')) {
position--;
@@ -277,6 +327,10 @@ bool Document::IsLineEndPosition(int position) const { return LineEnd(LineFromPosition(position)) == position;
}
+bool Document::IsPositionInLineEnd(int position) const {
+ return position >= LineEnd(LineFromPosition(position));
+}
+
int Document::VCHomePosition(int position) const {
int line = LineFromPosition(position);
int startPosition = LineStart(line);
diff --git a/scintilla/src/Document.h b/scintilla/src/Document.h index 1125c8a..1c6a02a 100644 --- a/scintilla/src/Document.h +++ b/scintilla/src/Document.h @@ -186,6 +186,7 @@ public: virtual ~LexInterface() {
}
void Colourise(int start, int end);
+ int LineEndTypesSupported();
bool UseContainerLexing() const {
return instance == 0;
}
@@ -193,7 +194,7 @@ public: /**
*/
-class Document : PerLine, public IDocument, public ILoader {
+class Document : PerLine, public IDocumentWithLineEnd, public ILoader {
public:
/** Used to pair watcher pointer with user data. */
@@ -240,6 +241,7 @@ public: int eolMode;
/// Can also be SC_CP_UTF8 to enable UTF-8 mode
int dbcsCodePage;
+ int lineEndBitSet;
int tabInChars;
int indentInChars;
int actualIndentInChars;
@@ -256,12 +258,16 @@ public: int SCI_METHOD Release();
virtual void Init();
+ int LineEndTypesSupported() const;
bool SetDBCSCodePage(int dbcsCodePage_);
+ int GetLineEndTypesAllowed() { return cb.GetLineEndTypes(); }
+ bool SetLineEndTypesAllowed(int lineEndBitSet_);
+ int GetLineEndTypesActive() { return cb.GetLineEndTypes(); }
virtual void InsertLine(int line);
virtual void RemoveLine(int line);
int SCI_METHOD Version() const {
- return dvOriginal;
+ return dvLineEnd;
}
void SCI_METHOD SetErrorStatus(int status);
@@ -338,9 +344,10 @@ public: void DeleteAllMarks(int markerNum);
int LineFromHandle(int markerHandle);
int SCI_METHOD LineStart(int line) const;
- int LineEnd(int line) const;
+ int SCI_METHOD LineEnd(int line) const;
int LineEndPosition(int position) const;
bool IsLineEndPosition(int position) const;
+ bool IsPositionInLineEnd(int position) const;
int VCHomePosition(int position) const;
int SCI_METHOD SetLevel(int line, int level);
diff --git a/scintilla/src/Editor.cxx b/scintilla/src/Editor.cxx index ceb2fa7..ff05228 100644 --- a/scintilla/src/Editor.cxx +++ b/scintilla/src/Editor.cxx @@ -9,6 +9,7 @@ #include <string.h>
#include <stdio.h>
#include <ctype.h>
+#include <math.h>
#include <assert.h>
#include <string>
@@ -174,6 +175,7 @@ Editor::Editor() { pixmapLine = 0;
pixmapSelMargin = 0;
pixmapSelPattern = 0;
+ pixmapSelPatternOffset1 = 0;
pixmapIndentGuide = 0;
pixmapIndentGuideHighlight = 0;
@@ -249,6 +251,8 @@ void Editor::DropGraphics(bool freeObjects) { pixmapSelMargin = 0;
delete pixmapSelPattern;
pixmapSelPattern = 0;
+ delete pixmapSelPatternOffset1;
+ pixmapSelPatternOffset1 = 0;
delete pixmapIndentGuide;
pixmapIndentGuide = 0;
delete pixmapIndentGuideHighlight;
@@ -260,6 +264,8 @@ void Editor::DropGraphics(bool freeObjects) { pixmapSelMargin->Release();
if (pixmapSelPattern)
pixmapSelPattern->Release();
+ if (pixmapSelPatternOffset1)
+ pixmapSelPatternOffset1->Release();
if (pixmapIndentGuide)
pixmapIndentGuide->Release();
if (pixmapIndentGuideHighlight)
@@ -274,6 +280,8 @@ void Editor::AllocateGraphics() { pixmapSelMargin = Surface::Allocate(technology);
if (!pixmapSelPattern)
pixmapSelPattern = Surface::Allocate(technology);
+ if (!pixmapSelPatternOffset1)
+ pixmapSelPatternOffset1 = Surface::Allocate(technology);
if (!pixmapIndentGuide)
pixmapIndentGuide = Surface::Allocate(technology);
if (!pixmapIndentGuideHighlight)
@@ -307,13 +315,37 @@ void Editor::RefreshStyleData() { }
}
+Point Editor::GetVisibleOriginInMain() {
+ return Point(0,0);
+}
+
+Point Editor::DocumentPointFromView(Point ptView) {
+ Point ptDocument = ptView;
+ if (wMargin.GetID()) {
+ Point ptOrigin = GetVisibleOriginInMain();
+ ptDocument.x += ptOrigin.x;
+ ptDocument.y += ptOrigin.y;
+ } else {
+ ptDocument.x += xOffset;
+ ptDocument.y += topLine * vs.lineHeight;
+ }
+ return ptDocument;
+}
+
+int Editor::TopLineOfMain() {
+ if (wMargin.GetID())
+ return 0;
+ else
+ return topLine;
+}
+
PRectangle Editor::GetClientRectangle() {
return wMain.GetClientPosition();
}
PRectangle Editor::GetTextRectangle() {
PRectangle rc = GetClientRectangle();
- rc.left += vs.fixedColumnWidth;
+ rc.left += vs.textStart;
rc.right -= vs.rightMarginWidth;
return rc;
}
@@ -436,7 +468,7 @@ Point Editor::LocationFromPosition(SelectionPosition pos) { pt.y += vs.lineHeight;
}
}
- pt.x += vs.fixedColumnWidth - xOffset;
+ pt.x += vs.textStart - xOffset;
}
pt.x += pos.VirtualSpace() * vs.styles[ll->EndLineStyle()].spaceWidth;
return pt;
@@ -448,12 +480,12 @@ Point Editor::LocationFromPosition(int pos) { int Editor::XFromPosition(int pos) {
Point pt = LocationFromPosition(pos);
- return pt.x - vs.fixedColumnWidth + xOffset;
+ return pt.x - vs.textStart + xOffset;
}
int Editor::XFromPosition(SelectionPosition sp) {
Point pt = LocationFromPosition(sp);
- return pt.x - vs.fixedColumnWidth + xOffset;
+ return pt.x - vs.textStart + xOffset;
}
int Editor::LineFromLocation(Point pt) {
@@ -461,7 +493,7 @@ int Editor::LineFromLocation(Point pt) { }
void Editor::SetTopLine(int topLineNew) {
- if (topLine != topLineNew) {
+ if ((topLine != topLineNew) && (topLineNew >= 0)) {
topLine = topLineNew;
ContainerNeedsUpdate(SC_UPDATE_V_SCROLL);
}
@@ -474,16 +506,14 @@ SelectionPosition Editor::SPositionFromLocation(Point pt, bool canReturnInvalid, PRectangle rcClient = GetTextRectangle();
if (!rcClient.Contains(pt))
return SelectionPosition(INVALID_POSITION);
- if (pt.x < vs.fixedColumnWidth)
+ if (pt.x < vs.textStart)
return SelectionPosition(INVALID_POSITION);
if (pt.y < 0)
return SelectionPosition(INVALID_POSITION);
}
- pt.x = pt.x - vs.fixedColumnWidth + xOffset;
- int visibleLine = pt.y / vs.lineHeight + topLine;
- if (pt.y < 0) { // Division rounds towards 0
- visibleLine = (static_cast<int>(pt.y) - (vs.lineHeight - 1)) / vs.lineHeight + topLine;
- }
+ pt = DocumentPointFromView(pt);
+ pt.x = pt.x - vs.textStart;
+ int visibleLine = floor(pt.y / vs.lineHeight);
if (!canReturnInvalid && (visibleLine < 0))
visibleLine = 0;
int lineDoc = cs.DocFromDisplay(visibleLine);
@@ -622,6 +652,8 @@ void Editor::Redraw() { //Platform::DebugPrintf("Redraw all\n");
PRectangle rcClient = GetClientRectangle();
wMain.InvalidateRectangle(rcClient);
+ if (wMargin.GetID())
+ wMargin.InvalidateAll();
//wMain.InvalidateAll();
}
@@ -631,7 +663,7 @@ void Editor::RedrawSelMargin(int line, bool allAfter) { Redraw();
} else {
PRectangle rcSelMargin = GetClientRectangle();
- rcSelMargin.right = vs.fixedColumnWidth;
+ rcSelMargin.right = rcSelMargin.left + vs.fixedColumnWidth;
if (line != -1) {
int position = pdoc->LineStart(line);
PRectangle rcLine = RectangleFromRange(position, position);
@@ -651,7 +683,13 @@ void Editor::RedrawSelMargin(int line, bool allAfter) { if (!allAfter)
rcSelMargin.bottom = rcLine.bottom;
}
- wMain.InvalidateRectangle(rcSelMargin);
+ if (wMargin.GetID()) {
+ Point ptOrigin = GetVisibleOriginInMain();
+ rcSelMargin.Move(-ptOrigin.x, -ptOrigin.y);
+ wMargin.InvalidateRectangle(rcSelMargin);
+ } else {
+ wMain.InvalidateRectangle(rcSelMargin);
+ }
}
}
}
@@ -669,15 +707,12 @@ PRectangle Editor::RectangleFromRange(int start, int end) { PRectangle rcClient = GetTextRectangle();
PRectangle rc;
const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;
- rc.left = vs.fixedColumnWidth - leftTextOverlap;
- rc.top = (minLine - topLine) * vs.lineHeight;
- if (rc.top < 0)
- rc.top = 0;
+ rc.left = vs.textStart - leftTextOverlap;
+ rc.top = (minLine - TopLineOfMain()) * vs.lineHeight;
+ if (rc.top < rcClient.top)
+ rc.top = rcClient.top;
rc.right = rcClient.right;
- rc.bottom = (maxLine - topLine + 1) * vs.lineHeight;
- // Ensure PRectangle is within 16 bit space
- rc.top = Platform::Clamp(rc.top, -32000, 32000);
- rc.bottom = Platform::Clamp(rc.bottom, -32000, 32000);
+ rc.bottom = (maxLine - TopLineOfMain() + 1) * vs.lineHeight;
return rc;
}
@@ -782,6 +817,7 @@ void Editor::SetSelection(SelectionPosition currentPos_, SelectionPosition ancho if (highlightDelimiter.NeedsDrawing(currentLine)) {
RedrawSelMargin();
}
+ QueueIdleWork(WorkNeeded::workUpdateUI);
}
void Editor::SetSelection(int currentPos_, int anchor_) {
@@ -808,6 +844,7 @@ void Editor::SetSelection(SelectionPosition currentPos_) { if (highlightDelimiter.NeedsDrawing(currentLine)) {
RedrawSelMargin();
}
+ QueueIdleWork(WorkNeeded::workUpdateUI);
}
void Editor::SetSelection(int currentPos_) {
@@ -828,6 +865,7 @@ void Editor::SetEmptySelection(SelectionPosition currentPos_) { if (highlightDelimiter.NeedsDrawing(currentLine)) {
RedrawSelMargin();
}
+ QueueIdleWork(WorkNeeded::workUpdateUI);
}
void Editor::SetEmptySelection(int currentPos_) {
@@ -924,7 +962,8 @@ int Editor::MovePositionTo(SelectionPosition newPos, Selection::selTypes selt, b // In case in need of wrapping to ensure DisplayFromDoc works.
if (currentLine >= wrapStart)
WrapLines(true, -1);
- XYScrollPosition newXY = XYScrollToMakeVisible(true, true, true);
+ XYScrollPosition newXY = XYScrollToMakeVisible(
+ SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret), xysDefault);
if (simpleCaret && (newXY.xOffset == xOffset)) {
// simple vertical scroll then invalidate
ScrollTo(newXY.topLine);
@@ -1195,17 +1234,22 @@ slop | strict | jumps | even | Caret can go to the margin | When 1 | 1 | 1 | 1 | No, kept out of UZ | moved to put caret at 3UZ of the margin
*/
-Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, const bool vert, const bool horiz) {
+Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options) {
PRectangle rcClient = GetTextRectangle();
- const SelectionPosition posCaret = posDrag.IsValid() ? posDrag : sel.RangeMain().caret;
- const Point pt = LocationFromPosition(posCaret);
+ Point pt = LocationFromPosition(range.caret);
+ Point ptAnchor = LocationFromPosition(range.anchor);
+ const Point ptOrigin = GetVisibleOriginInMain();
+ pt.x += ptOrigin.x;
+ pt.y += ptOrigin.y;
+ ptAnchor.x += ptOrigin.x;
+ ptAnchor.y += ptOrigin.y;
const Point ptBottomCaret(pt.x, pt.y + vs.lineHeight - 1);
- const int lineCaret = DisplayFromPosition(posCaret.Position());
XYScrollPosition newXY(xOffset, topLine);
// Vertical positioning
- if (vert && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) {
+ if ((options & xysVertical) && (pt.y < rcClient.top || ptBottomCaret.y >= rcClient.bottom || (caretYPolicy & CARET_STRICT) != 0)) {
+ const int lineCaret = DisplayFromPosition(range.caret.Position());
const int linesOnScreen = LinesOnScreen();
const int halfScreen = Platform::Maximum(linesOnScreen - 1, 2) / 2;
const bool bSlop = (caretYPolicy & CARET_SLOP) != 0;
@@ -1219,7 +1263,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con int yMoveT, yMoveB;
if (bStrict) {
int yMarginT, yMarginB;
- if (!useMargin) {
+ if (!(options & xysUseMargin)) {
// In drag mode, avoid moves
// otherwise, a double click will select several lines.
yMarginT = yMarginB = 0;
@@ -1289,11 +1333,23 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con }
}
}
+ if (!(range.caret == range.anchor)) {
+ const int lineAnchor = DisplayFromPosition(range.anchor.Position());
+ if (lineAnchor < lineCaret) {
+ // Shift up to show anchor or as much of range as possible
+ newXY.topLine = std::min(newXY.topLine, lineAnchor);
+ newXY.topLine = std::max(newXY.topLine, lineCaret - LinesOnScreen());
+ } else {
+ // Shift down to show anchor or as much of range as possible
+ newXY.topLine = std::max(newXY.topLine, lineAnchor - LinesOnScreen());
+ newXY.topLine = std::min(newXY.topLine, lineCaret);
+ }
+ }
newXY.topLine = Platform::Clamp(newXY.topLine, 0, MaxScrollPos());
}
// Horizontal positioning
- if (horiz && (wrapState == eWrapNone)) {
+ if ((options & xysHorizontal) && (wrapState == eWrapNone)) {
const int halfScreen = Platform::Maximum(rcClient.Width() - 4, 4) / 2;
const bool bSlop = (caretXPolicy & CARET_SLOP) != 0;
const bool bStrict = (caretXPolicy & CARET_STRICT) != 0;
@@ -1304,7 +1360,7 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con int xMoveL, xMoveR;
if (bStrict) {
int xMarginL, xMarginR;
- if (!useMargin) {
+ if (!(options & xysUseMargin)) {
// In drag mode, avoid moves unless very near of the margin
// otherwise, a simple click will select text.
xMarginL = xMarginR = 2;
@@ -1393,6 +1449,21 @@ Editor::XYScrollPosition Editor::XYScrollToMakeVisible(const bool useMargin, con newXY.xOffset += static_cast<int>(vs.aveCharWidth);
}
}
+ if (!(range.caret == range.anchor)) {
+ if (ptAnchor.x < pt.x) {
+ // Shift to left to show anchor or as much of range as possible
+ int maxOffset = ptAnchor.x + xOffset - rcClient.left - 1;
+ int minOffset = pt.x + xOffset - rcClient.right + 1;
+ newXY.xOffset = std::min(newXY.xOffset, maxOffset);
+ newXY.xOffset = std::max(newXY.xOffset, minOffset);
+ } else {
+ // Shift to right to show anchor or as much of range as possible
+ int minOffset = ptAnchor.x + xOffset - rcClient.right + 1;
+ int maxOffset = pt.x + xOffset - rcClient.left - 1;
+ newXY.xOffset = std::max(newXY.xOffset, minOffset);
+ newXY.xOffset = std::min(newXY.xOffset, maxOffset);
+ }
+ }
if (newXY.xOffset < 0) {
newXY.xOffset = 0;
}
@@ -1425,8 +1496,13 @@ void Editor::SetXYScroll(XYScrollPosition newXY) { }
}
+void Editor::ScrollRange(SelectionRange range) {
+ SetXYScroll(XYScrollToMakeVisible(range, xysDefault));
+}
+
void Editor::EnsureCaretVisible(bool useMargin, bool vert, bool horiz) {
- SetXYScroll(XYScrollToMakeVisible(useMargin, vert, horiz));
+ SetXYScroll(XYScrollToMakeVisible(SelectionRange(posDrag.IsValid() ? posDrag : sel.RangeMain().caret),
+ static_cast<XYScrollOptions>((useMargin?xysUseMargin:0)|(vert?xysVertical:0)|(horiz?xysHorizontal:0))));
}
void Editor::ShowCaretAtCurrentPosition() {
@@ -1542,8 +1618,8 @@ bool Editor::WrapLines(bool fullWrap, int priorityWrapLineStart) { int lineDocTop = cs.DocFromDisplay(topLine);
int subLineTop = topLine - cs.DisplayFromDoc(lineDocTop);
PRectangle rcTextArea = GetClientRectangle();
- rcTextArea.left = vs.fixedColumnWidth;
- rcTextArea.right -= vs.rightMarginWidth;
+ rcTextArea.left = vs.textStart;
+ rcTextArea.right -= vs.textStart;
wrapWidth = rcTextArea.Width();
RefreshStyleData();
AutoSurface surface(this);
@@ -1606,7 +1682,7 @@ void Editor::LinesJoin() { UndoGroup ug(pdoc);
bool prevNonWS = true;
for (int pos = targetStart; pos < targetEnd; pos++) {
- if (IsEOLChar(pdoc->CharAt(pos))) {
+ if (pdoc->IsPositionInLineEnd(pos)) {
targetEnd -= pdoc->LenChar(pos);
pdoc->DelChar(pos);
if (prevNonWS) {
@@ -1753,7 +1829,12 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { if (vs.fixedColumnWidth == 0)
return;
+ RefreshPixMaps(surfWindow);
+
PRectangle rcMargin = GetClientRectangle();
+ Point ptOrigin = GetVisibleOriginInMain();
+ rcMargin.Move(0, -ptOrigin.y);
+ rcMargin.left = 0;
rcMargin.right = vs.fixedColumnWidth;
if (!rc.Intersects(rcMargin))
@@ -1774,18 +1855,24 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { PRectangle rcSelMargin = rcMargin;
rcSelMargin.right = rcMargin.left;
+ if (rcSelMargin.bottom < rc.bottom)
+ rcSelMargin.bottom = rc.bottom;
- for (int margin = 0; margin < vs.margins; margin++) {
+ for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
if (vs.ms[margin].width > 0) {
rcSelMargin.left = rcSelMargin.right;
rcSelMargin.right = rcSelMargin.left + vs.ms[margin].width;
if (vs.ms[margin].style != SC_MARGIN_NUMBER) {
- if (vs.ms[margin].mask & SC_MASK_FOLDERS)
+ if (vs.ms[margin].mask & SC_MASK_FOLDERS) {
// Required because of special way brush is created for selection margin
- surface->FillRectangle(rcSelMargin, *pixmapSelPattern);
- else {
+ // Ensure patterns line up when scrolling with separate margin view
+ // by choosing correctly aligned variant.
+ bool invertPhase = static_cast<int>(ptOrigin.y) & 1;
+ surface->FillRectangle(rcSelMargin,
+ invertPhase ? *pixmapSelPattern : *pixmapSelPatternOffset1);
+ } else {
ColourDesired colour;
switch (vs.ms[margin].style) {
case SC_MARGIN_BACK:
@@ -1804,9 +1891,9 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { surface->FillRectangle(rcSelMargin, vs.styles[STYLE_LINENUMBER].back);
}
- const int lineStartPaint = rcMargin.top / vs.lineHeight;
- int visibleLine = topLine + lineStartPaint;
- int yposScreen = lineStartPaint * vs.lineHeight;
+ const int lineStartPaint = (rcMargin.top + ptOrigin.y) / vs.lineHeight;
+ int visibleLine = TopLineOfMain() + lineStartPaint;
+ int yposScreen = lineStartPaint * vs.lineHeight - ptOrigin.y;
// Work out whether the top line is whitespace located after a
// lessening of fold level which implies a 'fold tail' but which should not
// be displayed until the last of a sequence of whitespace.
@@ -1837,7 +1924,7 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { int folderEnd = SubstituteMarkerIfEmpty(SC_MARKNUM_FOLDEREND,
SC_MARKNUM_FOLDER);
- while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rcMargin.bottom) {
+ while ((visibleLine < cs.LinesDisplayed()) && yposScreen < rc.bottom) {
PLATFORM_ASSERT(visibleLine < cs.LinesDisplayed());
int lineDoc = cs.DocFromDisplay(visibleLine);
@@ -1947,8 +2034,9 @@ void Editor::PaintSelMargin(Surface *surfWindow, PRectangle &rc) { rcMarker.bottom = yposScreen + vs.lineHeight;
if (vs.ms[margin].style == SC_MARGIN_NUMBER) {
if (firstSubLine) {
- char number[100];
- sprintf(number, "%d", lineDoc + 1);
+ char number[100] = "";
+ if (lineDoc >= 0)
+ sprintf(number, "%d", lineDoc + 1);
if (foldFlags & SC_FOLDFLAG_LEVELNUMBERS) {
int lev = pdoc->GetLevel(lineDoc);
sprintf(number, "%c%c %03X %03X",
@@ -2193,7 +2281,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou bool isBadUTF = isBadUTFNext;
isBadUTFNext = IsUnicodeMode() && BadUTF(ll->chars + charInLine + 1, numCharsInLine - charInLine - 1, trailBytes);
if ((ll->styles[charInLine] != ll->styles[charInLine + 1]) ||
- isControl || isControlNext || isBadUTF || isBadUTFNext) {
+ isControl || isControlNext || isBadUTF || isBadUTFNext || ((charInLine+1) >= numCharsBeforeEOL)) {
ll->positions[startseg] = 0;
if (vstyle.styles[ll->styles[charInLine]].visible) {
if (isControl) {
@@ -2213,7 +2301,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou ll->positions + startseg + 1);
}
lastSegItalics = false;
- } else if (isBadUTF) {
+ } else if ((isBadUTF) || (charInLine >= numCharsBeforeEOL)) {
char hexits[4];
sprintf(hexits, "x%2X", ll->chars[charInLine] & 0xff);
ll->positions[charInLine + 1] =
@@ -2504,7 +2592,15 @@ void Editor::DrawEOL(Surface *surface, ViewStyle &vsDraw, PRectangle rcLine, Lin rcSegment.left = xStart + ll->positions[eolPos] - subLineStart + virtualSpace;
rcSegment.right = xStart + ll->positions[eolPos+1] - subLineStart + virtualSpace;
blobsWidth += rcSegment.Width();
- const char *ctrlChar = ControlCharacterString(ll->chars[eolPos]);
+ char hexits[4];
+ const char *ctrlChar;
+ unsigned char chEOL = ll->chars[eolPos];
+ if (UTF8IsAscii(chEOL)) {
+ ctrlChar = ControlCharacterString(chEOL);
+ } else {
+ sprintf(hexits, "x%2X", chEOL);
+ ctrlChar = hexits;
+ }
int styleMain = ll->styles[eolPos];
ColourDesired textBack = TextBackground(vsDraw, overrideBackground, background, eolInSelection, false, styleMain, eolPos, ll);
ColourDesired textFore = vsDraw.styles[styleMain].fore;
@@ -2989,12 +3085,6 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis textBack = vsDraw.whitespaceBackground;
surface->FillRectangle(rcSegment, textBack);
}
- if ((vsDraw.viewWhitespace != wsInvisible) ||
- (inIndentation && vsDraw.viewIndentationGuides != ivNone)) {
- if (vsDraw.whitespaceForegroundSet)
- textFore = vsDraw.whitespaceForeground;
- surface->PenColour(textFore);
- }
if (inIndentation && vsDraw.viewIndentationGuides == ivReal) {
for (int indentCount = (ll->positions[i] + epsilon) / indentWidth;
indentCount <= (ll->positions[i + 1] - epsilon) / indentWidth;
@@ -3008,6 +3098,9 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis }
if (vsDraw.viewWhitespace != wsInvisible) {
if (!inIndentation || vsDraw.viewWhitespace == wsVisibleAlways) {
+ if (vsDraw.whitespaceForegroundSet)
+ textFore = vsDraw.whitespaceForeground;
+ surface->PenColour(textFore);
PRectangle rcTab(rcSegment.left + 1, rcSegment.top + 4,
rcSegment.right - 1, rcSegment.bottom - vsDraw.maxDescent);
DrawTabArrow(surface, rcTab, rcSegment.top + vsDraw.lineHeight / 2);
@@ -3289,6 +3382,7 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) { if (!pixmapSelPattern->Initialised()) {
const int patternSize = 8;
pixmapSelPattern->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
+ pixmapSelPatternOffset1->InitPixMap(patternSize, patternSize, surfaceWindow, wMain.GetID());
// This complex procedure is to reproduce the checkerboard dithered pattern used by windows
// for scroll bars and Visual Studio for its selection margin. The colour of this pattern is half
// way between the chrome colour and the chrome highlight colour making a nice transition
@@ -3315,10 +3409,12 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) { }
pixmapSelPattern->FillRectangle(rcPattern, colourFMFill);
+ pixmapSelPatternOffset1->FillRectangle(rcPattern, colourFMStripes);
for (int y = 0; y < patternSize; y++) {
for (int x = y % 2; x < patternSize; x+=2) {
PRectangle rcPixel(x, y, x+1, y+1);
pixmapSelPattern->FillRectangle(rcPixel, colourFMStripes);
+ pixmapSelPatternOffset1->FillRectangle(rcPixel, colourFMFill);
}
}
}
@@ -3446,22 +3542,20 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { StyleToPositionInView(PositionAfterArea(rcArea));
PRectangle rcClient = GetClientRectangle();
+ Point ptOrigin = GetVisibleOriginInMain();
//Platform::DebugPrintf("Client: (%3d,%3d) ... (%3d,%3d) %d\n",
// rcClient.left, rcClient.top, rcClient.right, rcClient.bottom);
int screenLinePaintFirst = rcArea.top / vs.lineHeight;
- int xStart = vs.fixedColumnWidth - xOffset;
+ int xStart = vs.textStart - xOffset + ptOrigin.x;
int ypos = 0;
if (!bufferedDraw)
ypos += screenLinePaintFirst * vs.lineHeight;
int yposScreen = screenLinePaintFirst * vs.lineHeight;
bool paintAbandonedByStyling = paintState == paintAbandoned;
- if (needUpdateUI) {
- NotifyUpdateUI();
- needUpdateUI = 0;
-
+ if (NotifyUpdateUI()) {
RefreshStyleData();
RefreshPixMaps(surfaceWindow);
}
@@ -3486,12 +3580,20 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { surfaceWindow->SetClip(rcArea);
if (paintState != paintAbandoned) {
- PaintSelMargin(surfaceWindow, rcArea);
-
- PRectangle rcRightMargin = rcClient;
- rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
- if (rcArea.Intersects(rcRightMargin)) {
- surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back);
+ if (vs.marginInside) {
+ PaintSelMargin(surfaceWindow, rcArea);
+ PRectangle rcRightMargin = rcClient;
+ rcRightMargin.left = rcRightMargin.right - vs.rightMarginWidth;
+ if (rcArea.Intersects(rcRightMargin)) {
+ surfaceWindow->FillRectangle(rcRightMargin, vs.styles[STYLE_DEFAULT].back);
+ }
+ } else { // Else separate view so separate paint event but leftMargin included to allow overlap
+ PRectangle rcLeftMargin = rcArea;
+ rcLeftMargin.left = 0;
+ rcLeftMargin.right = rcLeftMargin.left + vs.leftMarginWidth;
+ if (rcArea.Intersects(rcLeftMargin)) {
+ surfaceWindow->FillRectangle(rcLeftMargin, vs.styles[STYLE_DEFAULT].back);
+ }
}
}
@@ -3515,7 +3617,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { const int leftTextOverlap = ((xOffset == 0) && (vs.leftMarginWidth > 0)) ? 1 : 0;
// Do the painting
- if (rcArea.right > vs.fixedColumnWidth - leftTextOverlap) {
+ if (rcArea.right > vs.textStart - leftTextOverlap) {
Surface *surface = surfaceWindow;
if (bufferedDraw) {
@@ -3525,7 +3627,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { surface->SetUnicodeMode(IsUnicodeMode());
surface->SetDBCSMode(CodePage());
- int visibleLine = topLine + screenLinePaintFirst;
+ int visibleLine = TopLineOfMain() + screenLinePaintFirst;
SelectionPosition posCaret = sel.RangeMain().caret;
if (posDrag.IsValid())
@@ -3533,12 +3635,16 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { int lineCaret = pdoc->LineFromPosition(posCaret.Position());
PRectangle rcTextArea = rcClient;
- rcTextArea.left = vs.fixedColumnWidth;
- rcTextArea.right -= vs.rightMarginWidth;
+ if (vs.marginInside) {
+ rcTextArea.left += vs.textStart;
+ rcTextArea.right -= vs.rightMarginWidth;
+ } else {
+ rcTextArea = rcArea;
+ }
// Remove selection margin from drawing area so text will not be drawn
// on it in unbuffered mode.
- if (!bufferedDraw) {
+ if (!bufferedDraw && vs.marginInside) {
PRectangle rcClipText = rcTextArea;
rcClipText.left -= leftTextOverlap;
surfaceWindow->SetClip(rcClipText);
@@ -3632,8 +3738,8 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { DrawCarets(surface, vs, lineDoc, xStart, rcLine, ll, subLine);
if (bufferedDraw) {
- Point from(vs.fixedColumnWidth-leftTextOverlap, 0);
- PRectangle rcCopyArea(vs.fixedColumnWidth-leftTextOverlap, yposScreen,
+ Point from(vs.textStart-leftTextOverlap, 0);
+ PRectangle rcCopyArea(vs.textStart-leftTextOverlap, yposScreen,
rcClient.right - vs.rightMarginWidth, yposScreen + vs.lineHeight);
surfaceWindow->Copy(rcCopyArea, from, *pixmapLine);
}
@@ -3657,10 +3763,10 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) { // durPaint = 0.00000001;
// Right column limit indicator
- PRectangle rcBeyondEOF = rcClient;
- rcBeyondEOF.left = vs.fixedColumnWidth;
- rcBeyondEOF.right = rcBeyondEOF.right - vs.rightMarginWidth;
- rcBeyondEOF.top = (cs.LinesDisplayed() - topLine) * vs.lineHeight;
+ PRectangle rcBeyondEOF = (vs.marginInside) ? rcClient : rcArea;
+ rcBeyondEOF.left = vs.textStart;
+ rcBeyondEOF.right = rcBeyondEOF.right - ((vs.marginInside) ? vs.rightMarginWidth : 0);
+ rcBeyondEOF.top = (cs.LinesDisplayed() - TopLineOfMain()) * vs.lineHeight;
if (rcBeyondEOF.top < rcBeyondEOF.bottom) {
surfaceWindow->FillRectangle(rcBeyondEOF, vs.styles[STYLE_DEFAULT].back);
if (vs.edgeState == EDGE_LINE) {
@@ -3718,7 +3824,7 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { // Modify the view style for printing as do not normally want any of the transient features to be printed
// Printing supports only the line number margin.
int lineNumberIndex = -1;
- for (int margin = 0; margin < ViewStyle::margins; margin++) {
+ for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
if ((vsPrint.ms[margin].style == SC_MARGIN_NUMBER) && (vsPrint.ms[margin].width > 0)) {
lineNumberIndex = margin;
} else {
@@ -3814,7 +3920,7 @@ long Editor::FormatRange(bool draw, Sci_RangeToFormat *pfr) { // Copy this line and its styles from the document into local arrays
// and determine the x position at which each character starts.
- LineLayout ll(8000);
+ LineLayout ll(pdoc->LineStart(lineDoc+1)-pdoc->LineStart(lineDoc)+1);
LayoutLine(lineDoc, surfaceMeasure, vsPrint, &ll, widthPrint);
ll.containsCaret = false;
@@ -3930,7 +4036,7 @@ void Editor::ChangeSize() { SetScrollBars();
if (wrapState != eWrapNone) {
PRectangle rcTextArea = GetClientRectangle();
- rcTextArea.left = vs.fixedColumnWidth;
+ rcTextArea.left = vs.textStart;
rcTextArea.right -= vs.rightMarginWidth;
if (wrapWidth != rcTextArea.Width()) {
NeedWrapping();
@@ -3995,7 +4101,7 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) { }
} else if (inOverstrike) {
if (positionInsert < pdoc->Length()) {
- if (!IsEOLChar(pdoc->CharAt(positionInsert))) {
+ if (!pdoc->IsPositionInLineEnd(positionInsert)) {
pdoc->DelChar(positionInsert);
currentSel->ClearVirtualSpace();
}
@@ -4240,7 +4346,7 @@ void Editor::Clear() { else
sel.Range(r) = SelectionPosition(InsertSpace(sel.Range(r).caret.Position(), sel.Range(r).caret.VirtualSpace()));
}
- if ((sel.Count() == 1) || !IsEOLChar(pdoc->CharAt(sel.Range(r).caret.Position()))) {
+ if ((sel.Count() == 1) || !pdoc->IsPositionInLineEnd(sel.Range(r).caret.Position())) {
pdoc->DelChar(sel.Range(r).caret.Position());
sel.Range(r).ClearVirtualSpace();
} // else multiple selection so don't eat line ends
@@ -4418,11 +4524,16 @@ void Editor::NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool NotifyParent(scn);
}
-void Editor::NotifyUpdateUI() {
- SCNotification scn = {0};
- scn.nmhdr.code = SCN_UPDATEUI;
- scn.updated = needUpdateUI;
- NotifyParent(scn);
+bool Editor::NotifyUpdateUI() {
+ if (needUpdateUI) {
+ SCNotification scn = {0};
+ scn.nmhdr.code = SCN_UPDATEUI;
+ scn.updated = needUpdateUI;
+ NotifyParent(scn);
+ needUpdateUI = 0;
+ return true;
+ }
+ return false;
}
void Editor::NotifyPainted() {
@@ -4445,8 +4556,8 @@ void Editor::NotifyIndicatorClick(bool click, int position, bool shift, bool ctr bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
int marginClicked = -1;
- int x = 0;
- for (int margin = 0; margin < ViewStyle::margins; margin++) {
+ int x = vs.textStart - vs.fixedColumnWidth;
+ for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width))
marginClicked = margin;
x += vs.ms[margin].width;
@@ -4630,18 +4741,13 @@ void Editor::NotifyModified(Document *, DocModification mh, void *) { }
}
- //Platform::DebugPrintf("** %x Doc Changed\n", this);
- // TODO: could invalidate from mh.startModification to end of screen
- //InvalidateRange(mh.position, mh.position + mh.length);
if (paintState == notPainting && !CanDeferToLastStep(mh)) {
- QueueStyling(pdoc->Length());
+ QueueIdleWork(WorkNeeded::workStyle, pdoc->Length());
Redraw();
}
} else {
- //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this,
- // mh.position, mh.position + mh.length);
if (paintState == notPainting && mh.length && !CanEliminate(mh)) {
- QueueStyling(mh.position + mh.length);
+ QueueIdleWork(WorkNeeded::workStyle, mh.position + mh.length);
InvalidateRange(mh.position, mh.position + mh.length);
}
}
@@ -6121,7 +6227,8 @@ bool Editor::PointInSelMargin(Point pt) { // Really means: "Point in a margin"
if (vs.fixedColumnWidth > 0) { // There is a margin
PRectangle rcSelMargin = GetClientRectangle();
- rcSelMargin.right = vs.fixedColumnWidth - vs.leftMarginWidth;
+ rcSelMargin.right = vs.textStart - vs.leftMarginWidth;
+ rcSelMargin.left = vs.textStart - vs.fixedColumnWidth;
return rcSelMargin.Contains(pt);
} else {
return false;
@@ -6130,7 +6237,7 @@ bool Editor::PointInSelMargin(Point pt) { Window::Cursor Editor::GetMarginCursor(Point pt) {
int x = 0;
- for (int margin = 0; margin < ViewStyle::margins; margin++) {
+ for (int margin = 0; margin <= SC_MAX_MARGIN; margin++) {
if ((pt.x >= x) && (pt.x < x + vs.ms[margin].width))
return static_cast<Window::Cursor>(vs.ms[margin].cursor);
x += vs.ms[margin].width;
@@ -6511,6 +6618,8 @@ void Editor::ButtonMove(Point pt) { // Autoscroll
PRectangle rcClient = GetClientRectangle();
+ Point ptOrigin = GetVisibleOriginInMain();
+ rcClient.Move(0, -ptOrigin.y);
int lineMove = DisplayFromPosition(movePos.Position());
if (pt.y > rcClient.bottom) {
ScrollTo(lineMove - LinesOnScreen() + 1);
@@ -6710,7 +6819,7 @@ int Editor::PositionAfterArea(PRectangle rcArea) { // Style to a position within the view. If this causes a change at end of last line then
// affects later lines so style all the viewed text.
void Editor::StyleToPositionInView(Position pos) {
- int endWindow = PositionAfterArea(GetClientRectangle());
+ int endWindow = (vs.marginInside) ? (PositionAfterArea(GetClientRectangle())) : (pdoc->Length());
if (pos > endWindow)
pos = endWindow;
int styleAtEnd = pdoc->StyleAt(pos-1);
@@ -6722,20 +6831,18 @@ void Editor::StyleToPositionInView(Position pos) { }
}
-void Editor::IdleStyling() {
+void Editor::IdleWork() {
// Style the line after the modification as this allows modifications that change just the
// line of the modification to heal instead of propagating to the rest of the window.
- StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(styleNeeded.upTo) + 2));
+ if (workNeeded.items & WorkNeeded::workStyle)
+ StyleToPositionInView(pdoc->LineStart(pdoc->LineFromPosition(workNeeded.upTo) + 2));
- if (needUpdateUI) {
- NotifyUpdateUI();
- needUpdateUI = 0;
- }
- styleNeeded.Reset();
+ NotifyUpdateUI();
+ workNeeded.Reset();
}
-void Editor::QueueStyling(int upTo) {
- styleNeeded.NeedUpTo(upTo);
+void Editor::QueueIdleWork(WorkNeeded::workItems items, int upTo) {
+ workNeeded.Need(items, upTo);
}
bool Editor::PaintContains(PRectangle rc) {
@@ -6747,8 +6854,13 @@ bool Editor::PaintContains(PRectangle rc) { }
bool Editor::PaintContainsMargin() {
+ if (wMargin.GetID()) {
+ // With separate margin view, paint of text view
+ // never contains margin.
+ return false;
+ }
PRectangle rcSelMargin = GetClientRectangle();
- rcSelMargin.right = vs.fixedColumnWidth;
+ rcSelMargin.right = vs.textStart;
return PaintContains(rcSelMargin);
}
@@ -6833,6 +6945,8 @@ void Editor::SetDocPointer(Document *document) { braces[0] = invalidPosition;
braces[1] = invalidPosition;
+ vs.ReleaseAllExtendedStyles();
+
// Reset the contraction state to fully shown.
cs.Clear();
cs.InsertLines(0, pdoc->LinesTotal() - 1);
@@ -6944,12 +7058,17 @@ void Editor::EnsureLineVisible(int lineDoc, bool enforcePolicy) { WrapLines(true, -1);
if (!cs.GetVisible(lineDoc)) {
+ // Back up to find a non-blank line
int lookLine = lineDoc;
int lookLineLevel = pdoc->GetLevel(lookLine);
while ((lookLine > 0) && (lookLineLevel & SC_FOLDLEVELWHITEFLAG)) {
lookLineLevel = pdoc->GetLevel(--lookLine);
}
int lineParent = pdoc->GetFoldParent(lookLine);
+ if (lineParent < 0) {
+ // Backed up to a top level line, so try to find parent of initial line
+ lineParent = pdoc->GetFoldParent(lineDoc);
+ }
if (lineParent >= 0) {
if (lineDoc != lineParent)
EnsureLineVisible(lineParent, enforcePolicy);
@@ -7062,7 +7181,7 @@ void Editor::AddStyledText(char *buffer, int appendLength) { }
static bool ValidMargin(unsigned long wParam) {
- return wParam < ViewStyle::margins;
+ return wParam <= SC_MAX_MARGIN;
}
static char *CharPtrFromSPtr(sptr_t lParam) {
@@ -7420,7 +7539,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_LINESCROLL:
ScrollTo(topLine + lParam);
- HorizontalScrollTo(xOffset + wParam * vs.spaceWidth);
+ HorizontalScrollTo(xOffset + static_cast<int>(wParam) * vs.spaceWidth);
return 1;
case SCI_SETXOFFSET:
@@ -7456,7 +7575,8 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { return 0;
} else {
Point pt = LocationFromPosition(lParam);
- return pt.x;
+ // Convert to view-relative
+ return pt.x - vs.textStart + vs.fixedColumnWidth;
}
case SCI_POINTYFROMPOSITION:
@@ -7793,6 +7913,21 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { pdoc->eolMode = wParam;
break;
+ case SCI_SETLINEENDTYPESALLOWED:
+ if (pdoc->SetLineEndTypesAllowed(wParam)) {
+ cs.Clear();
+ cs.InsertLines(0, pdoc->LinesTotal() - 1);
+ SetAnnotationHeights(0, pdoc->LinesTotal());
+ InvalidateStyleRedraw();
+ }
+ break;
+
+ case SCI_GETLINEENDTYPESALLOWED:
+ return pdoc->GetLineEndTypesAllowed();
+
+ case SCI_GETLINEENDTYPESACTIVE:
+ return pdoc->GetLineEndTypesActive();
+
case SCI_STARTSTYLING:
pdoc->StartStyling(wParam, static_cast<char>(lParam));
break;
@@ -8059,6 +8194,8 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { verticalScrollBarVisible = wParam != 0;
SetScrollBars();
ReconfigureScrollBars();
+ if (verticalScrollBarVisible)
+ SetVerticalScrollPos();
}
break;
@@ -8089,6 +8226,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_SETCODEPAGE:
if (ValidCodePage(wParam)) {
if (pdoc->SetDBCSCodePage(wParam)) {
+ cs.Clear();
+ cs.InsertLines(0, pdoc->LinesTotal() - 1);
+ SetAnnotationHeights(0, pdoc->LinesTotal());
InvalidateStyleRedraw();
}
}
@@ -8438,6 +8578,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { EnsureLineVisible(wParam, true);
break;
+ case SCI_SCROLLRANGE:
+ ScrollRange(SelectionRange(lParam, wParam));
+ break;
+
case SCI_SEARCHANCHOR:
SearchAnchor();
break;
@@ -9152,6 +9296,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) { case SCI_ANNOTATIONGETSTYLEOFFSET:
return vs.annotationStyleOffset;
+ case SCI_RELEASEALLEXTENDEDSTYLES:
+ vs.ReleaseAllExtendedStyles();
+ break;
+
+ case SCI_ALLOCATEEXTENDEDSTYLES:
+ return vs.AllocateExtendedStyles(wParam);
+
case SCI_ADDUNDOACTION:
pdoc->AddUndoAction(wParam, lParam & UNDO_MAY_COALESCE);
break;
diff --git a/scintilla/src/Editor.h b/scintilla/src/Editor.h index 8d300d6..a6f0355 100644 --- a/scintilla/src/Editor.h +++ b/scintilla/src/Editor.h @@ -47,21 +47,30 @@ public: /**
* When platform has a way to generate an event before painting,
- * accumulate needed styling range in StyleNeeded to avoid unnecessary work.
+ * accumulate needed styling range and other work items in
+ * WorkNeeded to avoid unnecessary work inside paint handler
*/
-class StyleNeeded {
+class WorkNeeded {
public:
+ enum workItems {
+ workNone=0,
+ workStyle=1,
+ workUpdateUI=2
+ };
bool active;
+ enum workItems items;
Position upTo;
- StyleNeeded() : active(false), upTo(0) {}
+ WorkNeeded() : active(false), items(workNone), upTo(0) {}
void Reset() {
active = false;
+ items = workNone;
upTo = 0;
}
- void NeedUpTo(Position pos) {
- if (upTo < pos)
+ void Need(workItems items_, Position pos) {
+ if ((items_ & workStyle) && (upTo < pos))
upTo = pos;
+ items = static_cast<workItems>(items | items_);
}
};
@@ -95,6 +104,7 @@ public: characterSet = characterSet_;
rectangular = rectangular_;
lineCopy = lineCopy_;
+ FixSelectionForClipboard();
}
void Copy(const char *s_, int len_, int codePage_, int characterSet_, bool rectangular_, bool lineCopy_) {
delete []s;
@@ -108,10 +118,22 @@ public: characterSet = characterSet_;
rectangular = rectangular_;
lineCopy = lineCopy_;
+ FixSelectionForClipboard();
}
void Copy(const SelectionText &other) {
Copy(other.s, other.len, other.codePage, other.characterSet, other.rectangular, other.lineCopy);
}
+
+private:
+ void FixSelectionForClipboard() {
+ // Replace null characters by spaces.
+ // To avoid that the content of the clipboard is truncated in the paste operation
+ // when the clipboard contains null characters.
+ for (int i = 0; i < len - 1; ++i) {
+ if (s[i] == '\0')
+ s[i] = ' ';
+ }
+ }
};
/**
@@ -126,6 +148,7 @@ protected: // ScintillaBase subclass needs access to much of Editor /** On GTK+, Scintilla is a container widget holding two scroll bars
* whereas on Windows there is just one window with both scroll bars turned on. */
Window wMain; ///< The Scintilla parent window
+ Window wMargin; ///< May be separate when using a scroll view for wMain
/** Style resources may be expensive to allocate so are cached between uses.
* When a style attribute is changed, this cache is flushed. */
@@ -177,6 +200,7 @@ protected: // ScintillaBase subclass needs access to much of Editor Surface *pixmapLine;
Surface *pixmapSelMargin;
Surface *pixmapSelPattern;
+ Surface *pixmapSelPatternOffset1;
Surface *pixmapIndentGuide;
Surface *pixmapIndentGuideHighlight;
@@ -228,7 +252,7 @@ protected: // ScintillaBase subclass needs access to much of Editor PRectangle rcPaint;
bool paintingAllText;
bool willRedrawAll;
- StyleNeeded styleNeeded;
+ WorkNeeded workNeeded;
int modEventMask;
@@ -286,6 +310,11 @@ protected: // ScintillaBase subclass needs access to much of Editor void DropGraphics(bool freeObjects);
void AllocateGraphics();
+ // The top left visible point in main window coordinates. Will be 0,0 except for
+ // scroll views where it will be equivalent to the current scroll position.
+ virtual Point GetVisibleOriginInMain();
+ Point DocumentPointFromView(Point ptView); // Convert a point from view space to document
+ int TopLineOfMain(); // Return the line at Main's y coordinate 0
virtual PRectangle GetClientRectangle();
PRectangle GetTextRectangle();
@@ -352,10 +381,19 @@ protected: // ScintillaBase subclass needs access to much of Editor int xOffset;
int topLine;
XYScrollPosition(int xOffset_, int topLine_) : xOffset(xOffset_), topLine(topLine_) {}
+ bool operator==(const XYScrollPosition &other) const {
+ return (xOffset == other.xOffset) && (topLine == other.topLine);
+ }
};
- XYScrollPosition XYScrollToMakeVisible(const bool useMargin, const bool vert, const bool horiz);
+ enum XYScrollOptions {
+ xysUseMargin=0x1,
+ xysVertical=0x2,
+ xysHorizontal=0x4,
+ xysDefault=xysUseMargin|xysVertical|xysHorizontal};
+ XYScrollPosition XYScrollToMakeVisible(const SelectionRange range, const XYScrollOptions options);
void SetXYScroll(XYScrollPosition newXY);
void EnsureCaretVisible(bool useMargin=true, bool vert=true, bool horiz=true);
+ void ScrollRange(SelectionRange range);
void ShowCaretAtCurrentPosition();
void DropCaret();
void InvalidateCaret();
@@ -439,7 +477,7 @@ protected: // ScintillaBase subclass needs access to much of Editor void NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt);
void NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt);
void NotifyHotSpotReleaseClick(int position, bool shift, bool ctrl, bool alt);
- void NotifyUpdateUI();
+ bool NotifyUpdateUI();
void NotifyPainted();
void NotifyIndicatorClick(bool click, int position, bool shift, bool ctrl, bool alt);
bool NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt);
@@ -518,8 +556,8 @@ protected: // ScintillaBase subclass needs access to much of Editor int PositionAfterArea(PRectangle rcArea);
void StyleToPositionInView(Position pos);
- void IdleStyling();
- virtual void QueueStyling(int upTo);
+ virtual void IdleWork();
+ virtual void QueueIdleWork(WorkNeeded::workItems items, int upTo=0);
virtual bool PaintContains(PRectangle rc);
bool PaintContainsMargin();
diff --git a/scintilla/src/LineMarker.cxx b/scintilla/src/LineMarker.cxx index de88f07..33690ac 100644 --- a/scintilla/src/LineMarker.cxx +++ b/scintilla/src/LineMarker.cxx @@ -6,6 +6,7 @@ // The License.txt file describes the conditions under which this software may be distributed.
#include <string.h>
+#include <math.h>
#include <vector>
#include <map>
@@ -112,8 +113,8 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac rc.bottom--;
int minDim = Platform::Minimum(rc.Width(), rc.Height());
minDim--; // Ensure does not go beyond edge
- int centreX = (rc.right + rc.left) / 2;
- int centreY = (rc.bottom + rc.top) / 2;
+ int centreX = floor((rc.right + rc.left) / 2.0);
+ int centreY = floor((rc.bottom + rc.top) / 2.0);
int dimOn2 = minDim / 2;
int dimOn4 = minDim / 4;
int blobSize = dimOn2-1;
diff --git a/scintilla/src/PositionCache.h b/scintilla/src/PositionCache.h index 232a097..1b909fd 100644 --- a/scintilla/src/PositionCache.h +++ b/scintilla/src/PositionCache.h @@ -130,6 +130,8 @@ class BreakFinder { int subBreak;
Document *pdoc;
void Insert(int val);
+ // Private so BreakFinder objects can not be copied
+ BreakFinder(const BreakFinder &);
public:
// If a whole run is longer than lengthStartSubdivision then subdivide
// into smaller runs at spaces or punctuation.
@@ -148,6 +150,8 @@ class PositionCache { size_t size;
unsigned int clock;
bool allClear;
+ // Private so PositionCache objects can not be copied
+ PositionCache(const PositionCache &);
public:
PositionCache();
~PositionCache();
diff --git a/scintilla/src/RunStyles.h b/scintilla/src/RunStyles.h index c94ca3c..25f9752 100644 --- a/scintilla/src/RunStyles.h +++ b/scintilla/src/RunStyles.h @@ -23,6 +23,8 @@ private: void RemoveRun(int run);
void RemoveRunIfEmpty(int run);
void RemoveRunIfSameAsPrevious(int run);
+ // Private so RunStyles objects can not be copied
+ RunStyles(const RunStyles &);
public:
RunStyles();
~RunStyles();
diff --git a/scintilla/src/ScintillaBase.cxx b/scintilla/src/ScintillaBase.cxx index 4a88411..c751790 100644 --- a/scintilla/src/ScintillaBase.cxx +++ b/scintilla/src/ScintillaBase.cxx @@ -193,6 +193,13 @@ void ScintillaBase::AutoCompleteDoubleClick(void *p) { sci->AutoCompleteCompleted();
}
+void ScintillaBase::AutoCompleteInsert(Position startPos, int removeLen, const char *text, int textLen) {
+ UndoGroup ug(pdoc);
+ pdoc->DeleteChars(startPos, removeLen);
+ pdoc->InsertString(startPos, text, textLen);
+ SetEmptySelection(startPos + textLen);
+}
+
void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
//Platform::DebugPrintf("AutoComplete %s\n", list);
ct.CallTipCancel();
@@ -202,17 +209,11 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { const char *typeSep = strchr(list, ac.GetTypesep());
int lenInsert = typeSep ?
static_cast<int>(typeSep-list) : static_cast<int>(strlen(list));
- UndoGroup ug(pdoc);
if (ac.ignoreCase) {
- SetEmptySelection(sel.MainCaret() - lenEntered);
- pdoc->DeleteChars(sel.MainCaret(), lenEntered);
- SetEmptySelection(sel.MainCaret());
- pdoc->InsertString(sel.MainCaret(), list, lenInsert);
- SetEmptySelection(sel.MainCaret() + lenInsert);
+ // May need to convert the case before invocation, so remove lenEntered characters
+ AutoCompleteInsert(sel.MainCaret() - lenEntered, lenEntered, list, lenInsert);
} else {
- SetEmptySelection(sel.MainCaret());
- pdoc->InsertString(sel.MainCaret(), list + lenEntered, lenInsert - lenEntered);
- SetEmptySelection(sel.MainCaret() + lenInsert - lenEntered);
+ AutoCompleteInsert(sel.MainCaret(), 0, list + lenEntered, lenInsert - lenEntered);
}
ac.Cancel();
return;
@@ -234,6 +235,11 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) { Redraw();
pt = PointMainCaret();
}
+ if (wMargin.GetID()) {
+ Point ptOrigin = GetVisibleOriginInMain();
+ pt.x += ptOrigin.x;
+ pt.y += ptOrigin.y;
+ }
PRectangle rcac;
rcac.left = pt.x - ac.lb->CaretFromEdge();
if (pt.y >= rcPopupBounds.bottom - heightLB && // Wont fit below.
@@ -357,15 +363,7 @@ void ScintillaBase::AutoCompleteCompleted() { endPos = pdoc->ExtendWordSelect(endPos, 1, true);
if (endPos < firstPos)
return;
- UndoGroup ug(pdoc);
- if (endPos != firstPos) {
- pdoc->DeleteChars(firstPos, endPos - firstPos);
- }
- SetEmptySelection(ac.posStart);
- if (item != -1) {
- pdoc->InsertCString(firstPos, selected.c_str());
- SetEmptySelection(firstPos + static_cast<int>(selected.length()));
- }
+ AutoCompleteInsert(firstPos, endPos - firstPos, selected.c_str(), static_cast<int>(selected.length()));
SetLastXChosen();
}
@@ -399,6 +397,11 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) { if (ct.UseStyleCallTip()) {
ct.SetForeBack(vs.styles[STYLE_CALLTIP].fore, vs.styles[STYLE_CALLTIP].back);
}
+ if (wMargin.GetID()) {
+ Point ptOrigin = GetVisibleOriginInMain();
+ pt.x += ptOrigin.x;
+ pt.y += ptOrigin.y;
+ }
PRectangle rc = ct.CallTipStart(sel.MainCaret(), pt,
vs.lineHeight,
defn,
@@ -473,6 +476,7 @@ class LexState : public LexInterface { const LexerModule *lexCurrent;
void SetLexerModule(const LexerModule *lex);
PropSetSimple props;
+ int interfaceVersion;
public:
int lexLanguage;
@@ -492,6 +496,15 @@ public: const char *PropGet(const char *key) const;
int PropGetInt(const char *key, int defaultValue=0) const;
int PropGetExpanded(const char *key, char *result) const;
+
+ int LineEndTypesSupported();
+ int AllocateSubStyles(int styleBase, int numberStyles);
+ int SubStylesStart(int styleBase);
+ int SubStylesLength(int styleBase);
+ void FreeSubStyles();
+ void SetIdentifiers(int style, const char *identifiers);
+ int DistanceToSecondaryStyles();
+ const char *GetSubStyleBases();
};
#ifdef SCI_NAMESPACE
@@ -501,6 +514,7 @@ public: LexState::LexState(Document *pdoc_) : LexInterface(pdoc_) {
lexCurrent = 0;
performingStyle = false;
+ interfaceVersion = lvOriginal;
lexLanguage = SCLEX_CONTAINER;
}
@@ -524,9 +538,12 @@ void LexState::SetLexerModule(const LexerModule *lex) { instance->Release();
instance = 0;
}
+ interfaceVersion = lvOriginal;
lexCurrent = lex;
- if (lexCurrent)
+ if (lexCurrent) {
instance = lexCurrent->Create();
+ interfaceVersion = instance->Version();
+ }
pdoc->LexerChanged();
}
}
@@ -631,6 +648,60 @@ int LexState::PropGetExpanded(const char *key, char *result) const { return props.GetExpanded(key, result);
}
+int LexState::LineEndTypesSupported() {
+ if (instance && (interfaceVersion >= lvSubStyles)) {
+ return static_cast<ILexerWithSubStyles *>(instance)->LineEndTypesSupported();
+ }
+ return 0;
+}
+
+int LexState::AllocateSubStyles(int styleBase, int numberStyles) {
+ if (instance && (interfaceVersion >= lvSubStyles)) {
+ return static_cast<ILexerWithSubStyles *>(instance)->AllocateSubStyles(styleBase, numberStyles);
+ }
+ return -1;
+}
+
+int LexState::SubStylesStart(int styleBase) {
+ if (instance && (interfaceVersion >= lvSubStyles)) {
+ return static_cast<ILexerWithSubStyles *>(instance)->SubStylesStart(styleBase);
+ }
+ return -1;
+}
+
+int LexState::SubStylesLength(int styleBase) {
+ if (instance && (interfaceVersion >= lvSubStyles)) {
+ return static_cast<ILexerWithSubStyles *>(instance)->SubStylesLength(styleBase);
+ }
+ return 0;
+}
+
+void LexState::FreeSubStyles() {
+ if (instance && (interfaceVersion >= lvSubStyles)) {
+ static_cast<ILexerWithSubStyles *>(instance)->FreeSubStyles();
+ }
+}
+
+void LexState::SetIdentifiers(int style, const char *identifiers) {
+ if (instance && (interfaceVersion >= lvSubStyles)) {
+ static_cast<ILexerWithSubStyles *>(instance)->SetIdentifiers(style, identifiers);
+ }
+}
+
+int LexState::DistanceToSecondaryStyles() {
+ if (instance && (interfaceVersion >= lvSubStyles)) {
+ return static_cast<ILexerWithSubStyles *>(instance)->DistanceToSecondaryStyles();
+ }
+ return 0;
+}
+
+const char *LexState::GetSubStyleBases() {
+ if (instance && (interfaceVersion >= lvSubStyles)) {
+ return static_cast<ILexerWithSubStyles *>(instance)->GetSubStyleBases();
+ }
+ return "";
+}
+
#endif
void ScintillaBase::NotifyStyleToNeeded(int endStyleNeeded) {
@@ -726,6 +797,13 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara case SCI_AUTOCGETCASEINSENSITIVEBEHAVIOUR:
return ac.ignoreCaseBehaviour;
+ case SCI_AUTOCSETORDER:
+ ac.autoSort = wParam;
+ break;
+
+ case SCI_AUTOCGETORDER:
+ return ac.autoSort;
+
case SCI_USERLISTSHOW:
listType = wParam;
AutoCompleteStart(0, reinterpret_cast<const char *>(lParam));
@@ -891,6 +969,31 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara case SCI_DESCRIBEKEYWORDSETS:
return StringResult(lParam, DocumentLexState()->DescribeWordListSets());
+ case SCI_GETLINEENDTYPESSUPPORTED:
+ return DocumentLexState()->LineEndTypesSupported();
+
+ case SCI_ALLOCATESUBSTYLES:
+ return DocumentLexState()->AllocateSubStyles(wParam, lParam);
+
+ case SCI_GETSUBSTYLESSTART:
+ return DocumentLexState()->SubStylesStart(wParam);
+
+ case SCI_GETSUBSTYLESLENGTH:
+ return DocumentLexState()->SubStylesLength(wParam);
+
+ case SCI_FREESUBSTYLES:
+ DocumentLexState()->FreeSubStyles();
+ break;
+
+ case SCI_SETIDENTIFIERS:
+ DocumentLexState()->SetIdentifiers(wParam, reinterpret_cast<const char *>(lParam));
+ break;
+
+ case SCI_DISTANCETOSECONDARYSTYLES:
+ return DocumentLexState()->DistanceToSecondaryStyles();
+
+ case SCI_GETSUBSTYLEBASES:
+ return StringResult(lParam, DocumentLexState()->GetSubStyleBases());
#endif
default:
diff --git a/scintilla/src/ScintillaBase.h b/scintilla/src/ScintillaBase.h index f34e04e..4c9271c 100644 --- a/scintilla/src/ScintillaBase.h +++ b/scintilla/src/ScintillaBase.h @@ -64,6 +64,7 @@ protected: virtual void CancelModes();
virtual int KeyCommand(unsigned int iMessage);
+ void AutoCompleteInsert(Position startPos, int removeLen, const char *text, int textLen);
void AutoCompleteStart(int lenEntered, const char *list);
void AutoCompleteCancel();
void AutoCompleteMove(int delta);
diff --git a/scintilla/src/UniConversion.h b/scintilla/src/UniConversion.h index 28b491c..1f1e537 100644 --- a/scintilla/src/UniConversion.h +++ b/scintilla/src/UniConversion.h @@ -26,3 +26,16 @@ inline bool UTF8IsAscii(int ch) { enum { UTF8MaskWidth=0x7, UTF8MaskInvalid=0x8 };
int UTF8Classify(const unsigned char *us, int len);
+
+// Line separator is U+2028 \xe2\x80\xa8
+// Paragraph separator is U+2029 \xe2\x80\xa9
+const int UTF8SeparatorLength = 3;
+inline bool UTF8IsSeparator(const unsigned char *us) {
+ return (us[0] == 0xe2) && (us[1] == 0x80) && ((us[2] == 0xa8) || (us[2] == 0xa9));
+}
+
+// NEL is U+0085 \xc2\x85
+const int UTF8NELLength = 2;
+inline bool UTF8IsNEL(const unsigned char *us) {
+ return (us[0] == 0xc2) && (us[1] == 0x85);
+}
diff --git a/scintilla/src/ViewStyle.cxx b/scintilla/src/ViewStyle.cxx index cdad268..e1eafcc 100644 --- a/scintilla/src/ViewStyle.cxx +++ b/scintilla/src/ViewStyle.cxx @@ -6,6 +6,7 @@ // The License.txt file describes the conditions under which this software may be distributed.
#include <string.h>
+#include <assert.h>
#include <vector>
#include <map>
@@ -140,6 +141,7 @@ ViewStyle::ViewStyle(const ViewStyle &source) { // Can't just copy fontname as its lifetime is relative to its owning ViewStyle
styles[sty].fontName = fontNames.Save(source.styles[sty].fontName);
}
+ nextExtendedStyle = source.nextExtendedStyle;
for (int mrk=0; mrk<=MARKER_MAX; mrk++) {
markers[mrk] = source.markers[mrk];
}
@@ -191,11 +193,13 @@ ViewStyle::ViewStyle(const ViewStyle &source) { someStylesForceCase = false;
leftMarginWidth = source.leftMarginWidth;
rightMarginWidth = source.rightMarginWidth;
- for (int i=0; i < margins; i++) {
- ms[i] = source.ms[i];
+ for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
+ ms[margin] = source.ms[margin];
}
maskInLine = source.maskInLine;
fixedColumnWidth = source.fixedColumnWidth;
+ marginInside = source.marginInside;
+ textStart = source.textStart;
zoomLevel = source.zoomLevel;
viewWhitespace = source.viewWhitespace;
whitespaceSize = source.whitespaceSize;
@@ -225,6 +229,7 @@ void ViewStyle::Init(size_t stylesSize_) { stylesSize = 0;
styles = NULL;
AllocStyles(stylesSize_);
+ nextExtendedStyle = 256;
fontNames.Clear();
ResetDefaultStyle();
@@ -303,13 +308,15 @@ void ViewStyle::Init(size_t stylesSize_) { ms[2].style = SC_MARGIN_SYMBOL;
ms[2].width = 0;
ms[2].mask = 0;
- fixedColumnWidth = leftMarginWidth;
+ marginInside = true;
+ fixedColumnWidth = marginInside ? leftMarginWidth : 0;
maskInLine = 0xffffffff;
- for (int margin=0; margin < margins; margin++) {
+ for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
fixedColumnWidth += ms[margin].width;
if (ms[margin].width > 0)
maskInLine &= ~ms[margin].mask;
}
+ textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
zoomLevel = 0;
viewWhitespace = wsInvisible;
whitespaceSize = 1;
@@ -356,6 +363,7 @@ void ViewStyle::Refresh(Surface &surface) { CreateFont(styles[j]);
}
+ assert(frFirst);
frFirst->Realise(surface, zoomLevel, technology);
for (unsigned int k=0; k<stylesSize; k++) {
@@ -383,13 +391,14 @@ void ViewStyle::Refresh(Surface &surface) { aveCharWidth = styles[STYLE_DEFAULT].aveCharWidth;
spaceWidth = styles[STYLE_DEFAULT].spaceWidth;
- fixedColumnWidth = leftMarginWidth;
+ fixedColumnWidth = marginInside ? leftMarginWidth : 0;
maskInLine = 0xffffffff;
- for (int margin=0; margin < margins; margin++) {
+ for (int margin=0; margin <= SC_MAX_MARGIN; margin++) {
fixedColumnWidth += ms[margin].width;
if (ms[margin].width > 0)
maskInLine &= ~ms[margin].mask;
}
+ textStart = marginInside ? fixedColumnWidth : leftMarginWidth;
}
void ViewStyle::AllocStyles(size_t sizeNew) {
@@ -411,6 +420,16 @@ void ViewStyle::AllocStyles(size_t sizeNew) { stylesSize = sizeNew;
}
+void ViewStyle::ReleaseAllExtendedStyles() {
+ nextExtendedStyle = 256;
+}
+
+int ViewStyle::AllocateExtendedStyles(int numberStyles) {
+ int startRange = static_cast<int>(nextExtendedStyle);
+ nextExtendedStyle += numberStyles;
+ return startRange;
+}
+
void ViewStyle::EnsureStyle(size_t index) {
if (index >= stylesSize) {
size_t sizeNew = stylesSize * 2;
@@ -469,4 +488,3 @@ void ViewStyle::CalcLargestMarkerHeight() { }
}
}
-
diff --git a/scintilla/src/ViewStyle.h b/scintilla/src/ViewStyle.h index c54448d..1830ae8 100644 --- a/scintilla/src/ViewStyle.h +++ b/scintilla/src/ViewStyle.h @@ -32,6 +32,8 @@ private: int size;
int max;
+ // Private so FontNames objects can not be copied
+ FontNames(const FontNames &);
public:
FontNames();
~FontNames();
@@ -65,6 +67,7 @@ public: FontRealised *frFirst;
size_t stylesSize;
Style *styles;
+ size_t nextExtendedStyle;
LineMarker markers[MARKER_MAX + 1];
int largestMarkerHeight;
Indicator indicators[INDIC_MAX + 1];
@@ -101,12 +104,13 @@ public: bool hotspotUnderline;
bool hotspotSingleLine;
/// Margins are ordered: Line Numbers, Selection Margin, Spacing Margin
- enum { margins=5 };
int leftMarginWidth; ///< Spacing margin on left of text
int rightMarginWidth; ///< Spacing margin on right of text
int maskInLine; ///< Mask for markers to be put into text because there is nowhere for them to go in margin
- MarginStyle ms[margins];
- int fixedColumnWidth;
+ MarginStyle ms[SC_MAX_MARGIN+1];
+ int fixedColumnWidth; ///< Total width of margins
+ bool marginInside; ///< true: margin included in text view, false: separate views
+ int textStart; ///< Starting x position of text within the view
int zoomLevel;
WhiteSpaceVisibility viewWhitespace;
int whitespaceSize;
@@ -142,6 +146,8 @@ public: void CreateFont(const FontSpecification &fs);
void Refresh(Surface &surface);
void AllocStyles(size_t sizeNew);
+ void ReleaseAllExtendedStyles();
+ int AllocateExtendedStyles(int numberStyles);
void EnsureStyle(size_t index);
void ResetDefaultStyle();
void ClearStyles();
diff --git a/scintilla/version.txt b/scintilla/version.txt index 88d2442..7f72ddf 100644 --- a/scintilla/version.txt +++ b/scintilla/version.txt @@ -1 +1 @@ -323
+330
diff --git a/scintilla/win32/PlatWin.cxx b/scintilla/win32/PlatWin.cxx index c9ec34e..0fb0951 100644 --- a/scintilla/win32/PlatWin.cxx +++ b/scintilla/win32/PlatWin.cxx @@ -81,6 +81,8 @@ static LONG_PTR GetWindowLongPtr(HWND hWnd, int nIndex) { }
#endif
+extern UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage);
+
// Declarations needed for functions dynamically loaded as not available on all Windows versions.
typedef BOOL (WINAPI *AlphaBlendSig)(HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION);
typedef HMONITOR (WINAPI *MonitorFromPointSig)(POINT, DWORD);
@@ -125,15 +127,13 @@ ID2D1Factory *pD2DFactory = 0; bool LoadD2D() {
static bool triedLoadingD2D = false;
- static HMODULE hDLLD2D = 0;
- static HMODULE hDLLDWrite = 0;
if (!triedLoadingD2D) {
typedef HRESULT (WINAPI *D2D1CFSig)(D2D1_FACTORY_TYPE factoryType, REFIID riid,
CONST D2D1_FACTORY_OPTIONS *pFactoryOptions, IUnknown **factory);
typedef HRESULT (WINAPI *DWriteCFSig)(DWRITE_FACTORY_TYPE factoryType, REFIID iid,
IUnknown **factory);
- hDLLD2D = ::LoadLibraryEx(TEXT("D2D1.DLL"), 0, 0x00000800 /*LOAD_LIBRARY_SEARCH_SYSTEM32*/);
+ HMODULE hDLLD2D = ::LoadLibraryEx(TEXT("D2D1.DLL"), 0, 0x00000800 /*LOAD_LIBRARY_SEARCH_SYSTEM32*/);
if (hDLLD2D) {
D2D1CFSig fnD2DCF = (D2D1CFSig)::GetProcAddress(hDLLD2D, "D2D1CreateFactory");
if (fnD2DCF) {
@@ -144,7 +144,7 @@ bool LoadD2D() { reinterpret_cast<IUnknown**>(&pD2DFactory));
}
}
- hDLLDWrite = ::LoadLibraryEx(TEXT("DWRITE.DLL"), 0, 0x00000800 /*LOAD_LIBRARY_SEARCH_SYSTEM32*/);
+ HMODULE hDLLDWrite = ::LoadLibraryEx(TEXT("DWRITE.DLL"), 0, 0x00000800 /*LOAD_LIBRARY_SEARCH_SYSTEM32*/);
if (hDLLDWrite) {
DWriteCFSig fnDWCF = (DWriteCFSig)::GetProcAddress(hDLLDWrite, "DWriteCreateFactory");
if (fnDWCF) {
@@ -166,19 +166,32 @@ struct FormatAndMetrics { IDWriteTextFormat *pTextFormat;
#endif
int extraFontFlag;
+ int characterSet;
FLOAT yAscent;
FLOAT yDescent;
FLOAT yInternalLeading;
- FormatAndMetrics(HFONT hfont_, int extraFontFlag_) :
- technology(SCWIN_TECH_GDI), hfont(hfont_),
+ FormatAndMetrics(HFONT hfont_, int extraFontFlag_, int characterSet_) :
+ technology(SCWIN_TECH_GDI), hfont(hfont_),
#if defined(USE_D2D)
pTextFormat(0),
#endif
- extraFontFlag(extraFontFlag_), yAscent(2), yDescent(1), yInternalLeading(0) {
+ extraFontFlag(extraFontFlag_), characterSet(characterSet_), yAscent(2), yDescent(1), yInternalLeading(0) {
}
#if defined(USE_D2D)
- FormatAndMetrics(IDWriteTextFormat *pTextFormat_, int extraFontFlag_, FLOAT yAscent_, FLOAT yDescent_, FLOAT yInternalLeading_) :
- technology(SCWIN_TECH_DIRECTWRITE), hfont(0), pTextFormat(pTextFormat_), extraFontFlag(extraFontFlag_), yAscent(yAscent_), yDescent(yDescent_), yInternalLeading(yInternalLeading_) {
+ FormatAndMetrics(IDWriteTextFormat *pTextFormat_,
+ int extraFontFlag_,
+ int characterSet_,
+ FLOAT yAscent_,
+ FLOAT yDescent_,
+ FLOAT yInternalLeading_) :
+ technology(SCWIN_TECH_DIRECTWRITE),
+ hfont(0),
+ pTextFormat(pTextFormat_),
+ extraFontFlag(extraFontFlag_),
+ characterSet(characterSet_),
+ yAscent(yAscent_),
+ yDescent(yDescent_),
+ yInternalLeading(yInternalLeading_) {
}
#endif
~FormatAndMetrics() {
@@ -190,6 +203,7 @@ struct FormatAndMetrics { pTextFormat = 0;
#endif
extraFontFlag = 0;
+ characterSet = 0;
yAscent = 2;
yDescent = 1;
yInternalLeading = 0;
@@ -317,7 +331,7 @@ FontCached::FontCached(const FontParameters &fp) : fid = 0;
if (technology == SCWIN_TECH_GDI) {
HFONT hfont = ::CreateFontIndirectA(&lf);
- fid = reinterpret_cast<void *>(new FormatAndMetrics(hfont, fp.extraFontFlag));
+ fid = reinterpret_cast<void *>(new FormatAndMetrics(hfont, fp.extraFontFlag, fp.characterSet));
} else {
#if defined(USE_D2D)
IDWriteTextFormat *pTextFormat;
@@ -356,7 +370,7 @@ FontCached::FontCached(const FontParameters &fp) : }
pTextLayout->Release();
}
- fid = reinterpret_cast<void *>(new FormatAndMetrics(pTextFormat, fp.extraFontFlag, yAscent, yDescent, yInternalLeading));
+ fid = reinterpret_cast<void *>(new FormatAndMetrics(pTextFormat, fp.extraFontFlag, fp.characterSet, yAscent, yDescent, yInternalLeading));
}
#endif
}
@@ -448,6 +462,9 @@ void Font::Release() { template<typename T, int lengthStandard>
class VarBuffer {
T bufferStandard[lengthStandard];
+ // Private so VarBuffer objects can not be copied
+ VarBuffer(const VarBuffer &);
+ VarBuffer &operator=(const VarBuffer &);
public:
T *buffer;
VarBuffer(size_t length) : buffer(0) {
@@ -1045,7 +1062,7 @@ void SurfaceGDI::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION * int ui = 0;
for (int i=0;i<len;) {
- if (::IsDBCSLeadByteEx(codePage, s[i])) {
+ if (Platform::IsDBCSLeadByte(codePage, s[i])) {
positions[i] = poses.buffer[ui];
positions[i+1] = poses.buffer[ui];
i += 2;
@@ -1139,6 +1156,7 @@ class SurfaceD2D : public Surface { int x, y;
int codePage;
+ int codePageText;
ID2D1RenderTarget *pRenderTarget;
bool ownRenderTarget;
@@ -1221,6 +1239,7 @@ SurfaceD2D::SurfaceD2D() : x(0), y(0) {
codePage = 0;
+ codePageText = 0;
pRenderTarget = NULL;
ownRenderTarget = false;
@@ -1334,6 +1353,10 @@ void SurfaceD2D::SetFont(Font &font_) { yAscent = pfm->yAscent;
yDescent = pfm->yDescent;
yInternalLeading = pfm->yInternalLeading;
+ codePageText = codePage;
+ if (pfm->characterSet) {
+ codePageText = CodePageFromCharSet(pfm->characterSet, codePage);
+ }
if (pRenderTarget) {
pRenderTarget->SetTextAntialiasMode(DWriteMapFontQuality(pfm->extraFontFlag));
}
@@ -1581,7 +1604,7 @@ void SurfaceD2D::DrawTextCommon(PRectangle rc, Font &font_, XYPOSITION ybase, co SetFont(font_);
// Use Unicode calls
- const TextWide tbuf(s, len, unicodeMode, codePage);
+ const TextWide tbuf(s, len, unicodeMode, codePageText);
if (pRenderTarget && pTextFormat && pBrush) {
if (fuOptions & ETO_CLIPPED) {
D2D1_RECT_F rcClip = {rc.left, rc.top, rc.right, rc.bottom};
@@ -1639,7 +1662,7 @@ void SurfaceD2D::DrawTextTransparent(PRectangle rc, Font &font_, XYPOSITION ybas XYPOSITION SurfaceD2D::WidthText(Font &font_, const char *s, int len) {
FLOAT width = 1.0;
SetFont(font_);
- const TextWide tbuf(s, len, unicodeMode, codePage);
+ const TextWide tbuf(s, len, unicodeMode, codePageText);
if (pIDWriteFactory && pTextFormat) {
// Create a layout
IDWriteTextLayout *pTextLayout = 0;
@@ -1657,7 +1680,7 @@ XYPOSITION SurfaceD2D::WidthText(Font &font_, const char *s, int len) { void SurfaceD2D::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION *positions) {
SetFont(font_);
int fit = 0;
- const TextWide tbuf(s, len, unicodeMode, codePage);
+ const TextWide tbuf(s, len, unicodeMode, codePageText);
TextPositions poses(tbuf.tlen);
fit = tbuf.tlen;
const int clusters = 1000;
@@ -1711,7 +1734,7 @@ void SurfaceD2D::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION * while (i<len) {
positions[i++] = lastPos;
}
- } else if (codePage == 0) {
+ } else if (codePageText == 0) {
// One character per position
PLATFORM_ASSERT(len == tbuf.tlen);
@@ -1724,7 +1747,7 @@ void SurfaceD2D::MeasureWidths(Font &font_, const char *s, int len, XYPOSITION * // May be more than one byte per position
int ui = 0;
for (int i=0;i<len;) {
- if (::IsDBCSLeadByteEx(codePage, s[i])) {
+ if (Platform::IsDBCSLeadByte(codePageText, s[i])) {
positions[i] = poses.buffer[ui];
positions[i+1] = poses.buffer[ui];
i += 2;
@@ -2459,20 +2482,22 @@ void ListBoxX::Draw(DRAWITEMSTRUCT *pDrawItem) { );
ID2D1DCRenderTarget *pDCRT = 0;
HRESULT hr = pD2DFactory->CreateDCRenderTarget(&props, &pDCRT);
- RECT rcWindow;
- GetClientRect(pDrawItem->hwndItem, &rcWindow);
- hr = pDCRT->BindDC(pDrawItem->hDC, &rcWindow);
if (SUCCEEDED(hr)) {
- surfaceItem->Init(pDCRT, pDrawItem->hwndItem);
- pDCRT->BeginDraw();
- int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
- PRectangle rcImage(left, pDrawItem->rcItem.top,
- left + images.GetWidth(), pDrawItem->rcItem.bottom);
- surfaceItem->DrawRGBAImage(rcImage,
- pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
- delete surfaceItem;
- pDCRT->EndDraw();
- pDCRT->Release();
+ RECT rcWindow;
+ GetClientRect(pDrawItem->hwndItem, &rcWindow);
+ hr = pDCRT->BindDC(pDrawItem->hDC, &rcWindow);
+ if (SUCCEEDED(hr)) {
+ surfaceItem->Init(pDCRT, pDrawItem->hwndItem);
+ pDCRT->BeginDraw();
+ int left = pDrawItem->rcItem.left + ItemInset.x + ImageInset.x;
+ PRectangle rcImage(left, pDrawItem->rcItem.top,
+ left + images.GetWidth(), pDrawItem->rcItem.bottom);
+ surfaceItem->DrawRGBAImage(rcImage,
+ pimage->GetWidth(), pimage->GetHeight(), pimage->Pixels());
+ delete surfaceItem;
+ pDCRT->EndDraw();
+ pDCRT->Release();
+ }
}
#endif
}
@@ -3138,11 +3163,39 @@ long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long }
bool Platform::IsDBCSLeadByte(int codePage, char ch) {
- return ::IsDBCSLeadByteEx(codePage, ch) != 0;
+ // Byte ranges found in Wikipedia articles with relevant search strings in each case
+ unsigned char uch = static_cast<unsigned char>(ch);
+ switch (codePage) {
+ case 932:
+ // Shift_jis
+ return ((uch >= 0x81) && (uch <= 0x9F)) ||
+ ((uch >= 0xE0) && (uch <= 0xEF));
+ case 936:
+ // GBK
+ return (uch >= 0x81) && (uch <= 0xFE);
+ case 949:
+ // Korean Wansung KS C-5601-1987
+ return (uch >= 0x81) && (uch <= 0xFE);
+ case 950:
+ // Big5
+ return (uch >= 0x81) && (uch <= 0xFE);
+ case 1361:
+ // Korean Johab KS C-5601-1992
+ return
+ ((uch >= 0x84) && (uch <= 0xD3)) ||
+ ((uch >= 0xD8) && (uch <= 0xDE)) ||
+ ((uch >= 0xE0) && (uch <= 0xF9));
+ }
+ return false;
}
int Platform::DBCSCharLength(int codePage, const char *s) {
- return (::IsDBCSLeadByteEx(codePage, s[0]) != 0) ? 2 : 1;
+ if (codePage == 932 || codePage == 936 || codePage == 949 ||
+ codePage == 950 || codePage == 1361) {
+ return Platform::IsDBCSLeadByte(codePage, s[0]) ? 2 : 1;
+ } else {
+ return 1;
+ }
}
int Platform::DBCSCharMaxLength() {
diff --git a/scintilla/win32/ScintillaWin.cxx b/scintilla/win32/ScintillaWin.cxx index e434810..76b387b 100644 --- a/scintilla/win32/ScintillaWin.cxx +++ b/scintilla/win32/ScintillaWin.cxx @@ -688,26 +688,35 @@ static unsigned int SciMessageFromEM(unsigned int iMessage) { return iMessage;
}
-static UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) {
+UINT CodePageFromCharSet(DWORD characterSet, UINT documentCodePage) {
if (documentCodePage == SC_CP_UTF8) {
- // The system calls here are a little slow so avoid if known case.
return SC_CP_UTF8;
}
- CHARSETINFO ci = { 0, 0, { { 0, 0, 0, 0 }, { 0, 0 } } };
- BOOL bci = ::TranslateCharsetInfo((DWORD*)characterSet,
- &ci, TCI_SRCCHARSET);
-
- UINT cp;
- if (bci)
- cp = ci.ciACP;
- else
- cp = documentCodePage;
-
- CPINFO cpi;
- if (!IsValidCodePage(cp) && !GetCPInfo(cp, &cpi))
- cp = CP_ACP;
-
- return cp;
+ switch (characterSet) {
+ case SC_CHARSET_ANSI: return 1252;
+ case SC_CHARSET_DEFAULT: return 0;
+ case SC_CHARSET_BALTIC: return 1257;
+ case SC_CHARSET_CHINESEBIG5: return 950;
+ case SC_CHARSET_EASTEUROPE: return 1250;
+ case SC_CHARSET_GB2312: return 936;
+ case SC_CHARSET_GREEK: return 1253;
+ case SC_CHARSET_HANGUL: return 949;
+ case SC_CHARSET_MAC: return 10000;
+ case SC_CHARSET_OEM: return 437;
+ case SC_CHARSET_RUSSIAN: return 1251;
+ case SC_CHARSET_SHIFTJIS: return 932;
+ case SC_CHARSET_TURKISH: return 1254;
+ case SC_CHARSET_JOHAB: return 1361;
+ case SC_CHARSET_HEBREW: return 1255;
+ case SC_CHARSET_ARABIC: return 1256;
+ case SC_CHARSET_VIETNAMESE: return 1258;
+ case SC_CHARSET_THAI: return 874;
+ case SC_CHARSET_8859_15: return 28605;
+ // Not supported
+ case SC_CHARSET_CYRILLIC: return documentCodePage;
+ case SC_CHARSET_SYMBOL: return documentCodePage;
+ }
+ return documentCodePage;
}
UINT ScintillaWin::CodePageOfDocument() {
|