]> git.saurik.com Git - wxWidgets.git/commitdiff
Updated to Scintilla 1.67
authorRobin Dunn <robin@alldunn.com>
Wed, 8 Mar 2006 01:48:03 +0000 (01:48 +0000)
committerRobin Dunn <robin@alldunn.com>
Wed, 8 Mar 2006 01:48:03 +0000 (01:48 +0000)
git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@37898 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775

149 files changed:
contrib/build/stc/makefile.bcc
contrib/build/stc/makefile.gcc
contrib/build/stc/makefile.vc
contrib/build/stc/makefile.wat
contrib/build/stc/stc.bkl
contrib/build/stc/stc.dsp
contrib/include/wx/stc/stc.h
contrib/src/stc/Makefile.in
contrib/src/stc/PlatWX.cpp
contrib/src/stc/gen_iface.py
contrib/src/stc/scintilla/README.txt
contrib/src/stc/scintilla/include/KeyWords.h
contrib/src/stc/scintilla/include/Platform.h
contrib/src/stc/scintilla/include/PropSet.h
contrib/src/stc/scintilla/include/SString.h
contrib/src/stc/scintilla/include/SciLexer.h
contrib/src/stc/scintilla/include/Scintilla.h
contrib/src/stc/scintilla/include/Scintilla.iface
contrib/src/stc/scintilla/include/ScintillaWidget.h
contrib/src/stc/scintilla/src/AutoComplete.cxx
contrib/src/stc/scintilla/src/AutoComplete.h
contrib/src/stc/scintilla/src/CallTip.cxx
contrib/src/stc/scintilla/src/CallTip.h
contrib/src/stc/scintilla/src/CellBuffer.cxx
contrib/src/stc/scintilla/src/CellBuffer.h
contrib/src/stc/scintilla/src/Document.cxx
contrib/src/stc/scintilla/src/Document.h
contrib/src/stc/scintilla/src/DocumentAccessor.cxx
contrib/src/stc/scintilla/src/DocumentAccessor.h
contrib/src/stc/scintilla/src/Editor.cxx
contrib/src/stc/scintilla/src/Editor.h
contrib/src/stc/scintilla/src/KeyMap.cxx
contrib/src/stc/scintilla/src/KeyWords.cxx
contrib/src/stc/scintilla/src/LexAU3.cxx
contrib/src/stc/scintilla/src/LexAVE.cxx
contrib/src/stc/scintilla/src/LexAsn1.cxx
contrib/src/stc/scintilla/src/LexBash.cxx
contrib/src/stc/scintilla/src/LexBasic.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/LexCLW.cxx
contrib/src/stc/scintilla/src/LexCPP.cxx
contrib/src/stc/scintilla/src/LexCSS.cxx
contrib/src/stc/scintilla/src/LexCaml.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/LexCsound.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/LexEiffel.cxx
contrib/src/stc/scintilla/src/LexFlagship.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/LexFortran.cxx
contrib/src/stc/scintilla/src/LexGui4Cli.cxx
contrib/src/stc/scintilla/src/LexHTML.cxx
contrib/src/stc/scintilla/src/LexHaskell.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/LexLisp.cxx
contrib/src/stc/scintilla/src/LexLua.cxx
contrib/src/stc/scintilla/src/LexMSSQL.cxx
contrib/src/stc/scintilla/src/LexMetapost.cxx
contrib/src/stc/scintilla/src/LexNsis.cxx
contrib/src/stc/scintilla/src/LexOthers.cxx
contrib/src/stc/scintilla/src/LexPOV.cxx
contrib/src/stc/scintilla/src/LexPS.cxx
contrib/src/stc/scintilla/src/LexPerl.cxx
contrib/src/stc/scintilla/src/LexPython.cxx
contrib/src/stc/scintilla/src/LexRebol.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/LexRuby.cxx
contrib/src/stc/scintilla/src/LexSQL.cxx
contrib/src/stc/scintilla/src/LexSmalltalk.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/LexTADS3.cxx [new file with mode: 0644]
contrib/src/stc/scintilla/src/LexTeX.cxx
contrib/src/stc/scintilla/src/LexVB.cxx
contrib/src/stc/scintilla/src/LineMarker.cxx
contrib/src/stc/scintilla/src/PropSet.cxx
contrib/src/stc/scintilla/src/RESearch.h
contrib/src/stc/scintilla/src/ScintillaBase.cxx
contrib/src/stc/scintilla/src/ScintillaBase.h
contrib/src/stc/scintilla/src/StyleContext.h
contrib/src/stc/scintilla/src/XPM.cxx
contrib/src/stc/stc.cpp
contrib/src/stc/stc.cpp.in
contrib/src/stc/stc.h.in
include/wx/stc/stc.h
src/stc/Makefile.in
src/stc/PlatWX.cpp
src/stc/gen_iface.py
src/stc/scintilla/README.txt
src/stc/scintilla/include/KeyWords.h
src/stc/scintilla/include/Platform.h
src/stc/scintilla/include/PropSet.h
src/stc/scintilla/include/SString.h
src/stc/scintilla/include/SciLexer.h
src/stc/scintilla/include/Scintilla.h
src/stc/scintilla/include/Scintilla.iface
src/stc/scintilla/include/ScintillaWidget.h
src/stc/scintilla/src/AutoComplete.cxx
src/stc/scintilla/src/AutoComplete.h
src/stc/scintilla/src/CallTip.cxx
src/stc/scintilla/src/CallTip.h
src/stc/scintilla/src/CellBuffer.cxx
src/stc/scintilla/src/CellBuffer.h
src/stc/scintilla/src/Document.cxx
src/stc/scintilla/src/Document.h
src/stc/scintilla/src/DocumentAccessor.cxx
src/stc/scintilla/src/DocumentAccessor.h
src/stc/scintilla/src/Editor.cxx
src/stc/scintilla/src/Editor.h
src/stc/scintilla/src/KeyMap.cxx
src/stc/scintilla/src/KeyWords.cxx
src/stc/scintilla/src/LexAU3.cxx
src/stc/scintilla/src/LexAVE.cxx
src/stc/scintilla/src/LexAsn1.cxx
src/stc/scintilla/src/LexBash.cxx
src/stc/scintilla/src/LexBasic.cxx [new file with mode: 0644]
src/stc/scintilla/src/LexCLW.cxx
src/stc/scintilla/src/LexCPP.cxx
src/stc/scintilla/src/LexCSS.cxx
src/stc/scintilla/src/LexCaml.cxx [new file with mode: 0644]
src/stc/scintilla/src/LexCsound.cxx [new file with mode: 0644]
src/stc/scintilla/src/LexEiffel.cxx
src/stc/scintilla/src/LexFlagship.cxx [new file with mode: 0644]
src/stc/scintilla/src/LexFortran.cxx
src/stc/scintilla/src/LexGui4Cli.cxx
src/stc/scintilla/src/LexHTML.cxx
src/stc/scintilla/src/LexHaskell.cxx [new file with mode: 0644]
src/stc/scintilla/src/LexLisp.cxx
src/stc/scintilla/src/LexLua.cxx
src/stc/scintilla/src/LexMSSQL.cxx
src/stc/scintilla/src/LexMetapost.cxx
src/stc/scintilla/src/LexNsis.cxx
src/stc/scintilla/src/LexOthers.cxx
src/stc/scintilla/src/LexPOV.cxx
src/stc/scintilla/src/LexPS.cxx
src/stc/scintilla/src/LexPerl.cxx
src/stc/scintilla/src/LexPython.cxx
src/stc/scintilla/src/LexRebol.cxx [new file with mode: 0644]
src/stc/scintilla/src/LexRuby.cxx
src/stc/scintilla/src/LexSQL.cxx
src/stc/scintilla/src/LexSmalltalk.cxx [new file with mode: 0644]
src/stc/scintilla/src/LexTADS3.cxx [new file with mode: 0644]
src/stc/scintilla/src/LexTeX.cxx
src/stc/scintilla/src/LexVB.cxx
src/stc/scintilla/src/LineMarker.cxx
src/stc/scintilla/src/PropSet.cxx
src/stc/scintilla/src/RESearch.h
src/stc/scintilla/src/ScintillaBase.cxx
src/stc/scintilla/src/ScintillaBase.h
src/stc/scintilla/src/StyleContext.h
src/stc/scintilla/src/XPM.cxx
src/stc/stc.cpp
src/stc/stc.cpp.in
src/stc/stc.h.in
wxPython/contrib/stc/_stc_gendocs.i
wxPython/contrib/stc/_stc_rename.i
wxPython/contrib/stc/stc.i

index 9312ecbf827e93dcfe5cd5661c9208287b8b5502..4f248ea7c5ee621a9119d49c8fc609b4190ebcc1 100644 (file)
@@ -59,19 +59,24 @@ STCDLL_OBJECTS =  \
        $(OBJS)\stcdll_LexAsn1.obj \
        $(OBJS)\stcdll_LexBaan.obj \
        $(OBJS)\stcdll_LexBash.obj \
+       $(OBJS)\stcdll_LexBasic.obj \
        $(OBJS)\stcdll_LexBullant.obj \
        $(OBJS)\stcdll_LexCLW.obj \
        $(OBJS)\stcdll_LexCPP.obj \
        $(OBJS)\stcdll_LexCSS.obj \
+       $(OBJS)\stcdll_LexCaml.obj \
+       $(OBJS)\stcdll_LexCsound.obj \
        $(OBJS)\stcdll_LexConf.obj \
        $(OBJS)\stcdll_LexCrontab.obj \
        $(OBJS)\stcdll_LexEScript.obj \
        $(OBJS)\stcdll_LexEiffel.obj \
        $(OBJS)\stcdll_LexErlang.obj \
+       $(OBJS)\stcdll_LexFlagship.obj \
        $(OBJS)\stcdll_LexForth.obj \
        $(OBJS)\stcdll_LexFortran.obj \
        $(OBJS)\stcdll_LexGui4Cli.obj \
        $(OBJS)\stcdll_LexHTML.obj \
+       $(OBJS)\stcdll_LexHaskell.obj \
        $(OBJS)\stcdll_LexKix.obj \
        $(OBJS)\stcdll_LexLisp.obj \
        $(OBJS)\stcdll_LexLout.obj \
@@ -89,8 +94,11 @@ STCDLL_OBJECTS =  \
        $(OBJS)\stcdll_LexPascal.obj \
        $(OBJS)\stcdll_LexPerl.obj \
        $(OBJS)\stcdll_LexPython.obj \
+       $(OBJS)\stcdll_LexRebol.obj \
        $(OBJS)\stcdll_LexRuby.obj \
        $(OBJS)\stcdll_LexSQL.obj \
+       $(OBJS)\stcdll_LexSmalltalk.obj \
+       $(OBJS)\stcdll_LexTADS3.obj \
        $(OBJS)\stcdll_LexScriptol.obj \
        $(OBJS)\stcdll_LexSpecman.obj \
        $(OBJS)\stcdll_LexTeX.obj \
@@ -139,19 +147,24 @@ STCLIB_OBJECTS =  \
        $(OBJS)\stclib_LexAsn1.obj \
        $(OBJS)\stclib_LexBaan.obj \
        $(OBJS)\stclib_LexBash.obj \
+       $(OBJS)\stclib_LexBasic.obj \
        $(OBJS)\stclib_LexBullant.obj \
        $(OBJS)\stclib_LexCLW.obj \
        $(OBJS)\stclib_LexCPP.obj \
        $(OBJS)\stclib_LexCSS.obj \
+       $(OBJS)\stclib_LexCaml.obj \
+       $(OBJS)\stclib_LexCsound.obj \
        $(OBJS)\stclib_LexConf.obj \
        $(OBJS)\stclib_LexCrontab.obj \
        $(OBJS)\stclib_LexEScript.obj \
        $(OBJS)\stclib_LexEiffel.obj \
        $(OBJS)\stclib_LexErlang.obj \
+       $(OBJS)\stclib_LexFlagship.obj \
        $(OBJS)\stclib_LexForth.obj \
        $(OBJS)\stclib_LexFortran.obj \
        $(OBJS)\stclib_LexGui4Cli.obj \
        $(OBJS)\stclib_LexHTML.obj \
+       $(OBJS)\stclib_LexHaskell.obj \
        $(OBJS)\stclib_LexKix.obj \
        $(OBJS)\stclib_LexLisp.obj \
        $(OBJS)\stclib_LexLout.obj \
@@ -169,8 +182,11 @@ STCLIB_OBJECTS =  \
        $(OBJS)\stclib_LexPascal.obj \
        $(OBJS)\stclib_LexPerl.obj \
        $(OBJS)\stclib_LexPython.obj \
+       $(OBJS)\stclib_LexRebol.obj \
        $(OBJS)\stclib_LexRuby.obj \
        $(OBJS)\stclib_LexSQL.obj \
+       $(OBJS)\stclib_LexSmalltalk.obj \
+       $(OBJS)\stclib_LexTADS3.obj \
        $(OBJS)\stclib_LexScriptol.obj \
        $(OBJS)\stclib_LexSpecman.obj \
        $(OBJS)\stclib_LexTeX.obj \
@@ -460,6 +476,9 @@ $(OBJS)\stcdll_LexBaan.obj: ../../src/stc\scintilla\src\LexBaan.cxx
 $(OBJS)\stcdll_LexBash.obj: ../../src/stc\scintilla\src\LexBash.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexBasic.obj: ../../src/stc\scintilla\src\LexBasic.cxx
+       $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexBullant.obj: ../../src/stc\scintilla\src\LexBullant.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
@@ -472,6 +491,12 @@ $(OBJS)\stcdll_LexCPP.obj: ../../src/stc\scintilla\src\LexCPP.cxx
 $(OBJS)\stcdll_LexCSS.obj: ../../src/stc\scintilla\src\LexCSS.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexCaml.obj: ../../src/stc\scintilla\src\LexCaml.cxx
+       $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
+
+$(OBJS)\stcdll_LexCsound.obj: ../../src/stc\scintilla\src\LexCsound.cxx
+       $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexConf.obj: ../../src/stc\scintilla\src\LexConf.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
@@ -487,6 +512,9 @@ $(OBJS)\stcdll_LexEiffel.obj: ../../src/stc\scintilla\src\LexEiffel.cxx
 $(OBJS)\stcdll_LexErlang.obj: ../../src/stc\scintilla\src\LexErlang.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexFlagship.obj: ../../src/stc\scintilla\src\LexFlagship.cxx
+       $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexForth.obj: ../../src/stc\scintilla\src\LexForth.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
@@ -499,6 +527,9 @@ $(OBJS)\stcdll_LexGui4Cli.obj: ../../src/stc\scintilla\src\LexGui4Cli.cxx
 $(OBJS)\stcdll_LexHTML.obj: ../../src/stc\scintilla\src\LexHTML.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexHaskell.obj: ../../src/stc\scintilla\src\LexHaskell.cxx
+       $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexKix.obj: ../../src/stc\scintilla\src\LexKix.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
@@ -550,12 +581,21 @@ $(OBJS)\stcdll_LexPerl.obj: ../../src/stc\scintilla\src\LexPerl.cxx
 $(OBJS)\stcdll_LexPython.obj: ../../src/stc\scintilla\src\LexPython.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexRebol.obj: ../../src/stc\scintilla\src\LexRebol.cxx
+       $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexRuby.obj: ../../src/stc\scintilla\src\LexRuby.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
 $(OBJS)\stcdll_LexSQL.obj: ../../src/stc\scintilla\src\LexSQL.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexSmalltalk.obj: ../../src/stc\scintilla\src\LexSmalltalk.cxx
+       $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
+
+$(OBJS)\stcdll_LexTADS3.obj: ../../src/stc\scintilla\src\LexTADS3.cxx
+       $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexScriptol.obj: ../../src/stc\scintilla\src\LexScriptol.cxx
        $(CXX) -q -c -P -o$@ $(STCDLL_CXXFLAGS) $**
 
@@ -673,6 +713,9 @@ $(OBJS)\stclib_LexBaan.obj: ../../src/stc\scintilla\src\LexBaan.cxx
 $(OBJS)\stclib_LexBash.obj: ../../src/stc\scintilla\src\LexBash.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexBasic.obj: ../../src/stc\scintilla\src\LexBasic.cxx
+       $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexBullant.obj: ../../src/stc\scintilla\src\LexBullant.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
@@ -685,6 +728,12 @@ $(OBJS)\stclib_LexCPP.obj: ../../src/stc\scintilla\src\LexCPP.cxx
 $(OBJS)\stclib_LexCSS.obj: ../../src/stc\scintilla\src\LexCSS.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexCaml.obj: ../../src/stc\scintilla\src\LexCaml.cxx
+       $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
+
+$(OBJS)\stclib_LexCsound.obj: ../../src/stc\scintilla\src\LexCsound.cxx
+       $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexConf.obj: ../../src/stc\scintilla\src\LexConf.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
@@ -700,6 +749,9 @@ $(OBJS)\stclib_LexEiffel.obj: ../../src/stc\scintilla\src\LexEiffel.cxx
 $(OBJS)\stclib_LexErlang.obj: ../../src/stc\scintilla\src\LexErlang.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexFlagship.obj: ../../src/stc\scintilla\src\LexFlagship.cxx
+       $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexForth.obj: ../../src/stc\scintilla\src\LexForth.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
@@ -712,6 +764,9 @@ $(OBJS)\stclib_LexGui4Cli.obj: ../../src/stc\scintilla\src\LexGui4Cli.cxx
 $(OBJS)\stclib_LexHTML.obj: ../../src/stc\scintilla\src\LexHTML.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexHaskell.obj: ../../src/stc\scintilla\src\LexHaskell.cxx
+       $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexKix.obj: ../../src/stc\scintilla\src\LexKix.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
@@ -763,12 +818,21 @@ $(OBJS)\stclib_LexPerl.obj: ../../src/stc\scintilla\src\LexPerl.cxx
 $(OBJS)\stclib_LexPython.obj: ../../src/stc\scintilla\src\LexPython.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexRebol.obj: ../../src/stc\scintilla\src\LexRebol.cxx
+       $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexRuby.obj: ../../src/stc\scintilla\src\LexRuby.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
 $(OBJS)\stclib_LexSQL.obj: ../../src/stc\scintilla\src\LexSQL.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexSmalltalk.obj: ../../src/stc\scintilla\src\LexSmalltalk.cxx
+       $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
+
+$(OBJS)\stclib_LexTADS3.obj: ../../src/stc\scintilla\src\LexTADS3.cxx
+       $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexScriptol.obj: ../../src/stc\scintilla\src\LexScriptol.cxx
        $(CXX) -q -c -P -o$@ $(STCLIB_CXXFLAGS) $**
 
index e50ecf38306d238637b1472fbb103f9ed3afb17a..8627eda8dd7ed27f7d4d3d7e15ec07b5cb211253 100644 (file)
@@ -52,19 +52,24 @@ STCDLL_OBJECTS =  \
        $(OBJS)\stcdll_LexAsn1.o \
        $(OBJS)\stcdll_LexBaan.o \
        $(OBJS)\stcdll_LexBash.o \
+       $(OBJS)\stcdll_LexBasic.o \
        $(OBJS)\stcdll_LexBullant.o \
        $(OBJS)\stcdll_LexCLW.o \
        $(OBJS)\stcdll_LexCPP.o \
        $(OBJS)\stcdll_LexCSS.o \
+       $(OBJS)\stcdll_LexCaml.o \
+       $(OBJS)\stcdll_LexCsound.o \
        $(OBJS)\stcdll_LexConf.o \
        $(OBJS)\stcdll_LexCrontab.o \
        $(OBJS)\stcdll_LexEScript.o \
        $(OBJS)\stcdll_LexEiffel.o \
        $(OBJS)\stcdll_LexErlang.o \
+       $(OBJS)\stcdll_LexFlagship.o \
        $(OBJS)\stcdll_LexForth.o \
        $(OBJS)\stcdll_LexFortran.o \
        $(OBJS)\stcdll_LexGui4Cli.o \
        $(OBJS)\stcdll_LexHTML.o \
+       $(OBJS)\stcdll_LexHaskell.o \
        $(OBJS)\stcdll_LexKix.o \
        $(OBJS)\stcdll_LexLisp.o \
        $(OBJS)\stcdll_LexLout.o \
@@ -82,8 +87,11 @@ STCDLL_OBJECTS =  \
        $(OBJS)\stcdll_LexPascal.o \
        $(OBJS)\stcdll_LexPerl.o \
        $(OBJS)\stcdll_LexPython.o \
+       $(OBJS)\stcdll_LexRebol.o \
        $(OBJS)\stcdll_LexRuby.o \
        $(OBJS)\stcdll_LexSQL.o \
+       $(OBJS)\stcdll_LexSmalltalk.o \
+       $(OBJS)\stcdll_LexTADS3.o \
        $(OBJS)\stcdll_LexScriptol.o \
        $(OBJS)\stcdll_LexSpecman.o \
        $(OBJS)\stcdll_LexTeX.o \
@@ -132,19 +140,24 @@ STCLIB_OBJECTS =  \
        $(OBJS)\stclib_LexAsn1.o \
        $(OBJS)\stclib_LexBaan.o \
        $(OBJS)\stclib_LexBash.o \
+       $(OBJS)\stclib_LexBasic.o \
        $(OBJS)\stclib_LexBullant.o \
        $(OBJS)\stclib_LexCLW.o \
        $(OBJS)\stclib_LexCPP.o \
        $(OBJS)\stclib_LexCSS.o \
+       $(OBJS)\stclib_LexCaml.o \
+       $(OBJS)\stclib_LexCsound.o \
        $(OBJS)\stclib_LexConf.o \
        $(OBJS)\stclib_LexCrontab.o \
        $(OBJS)\stclib_LexEScript.o \
        $(OBJS)\stclib_LexEiffel.o \
        $(OBJS)\stclib_LexErlang.o \
+       $(OBJS)\stclib_LexFlagship.o \
        $(OBJS)\stclib_LexForth.o \
        $(OBJS)\stclib_LexFortran.o \
        $(OBJS)\stclib_LexGui4Cli.o \
        $(OBJS)\stclib_LexHTML.o \
+       $(OBJS)\stclib_LexHaskell.o \
        $(OBJS)\stclib_LexKix.o \
        $(OBJS)\stclib_LexLisp.o \
        $(OBJS)\stclib_LexLout.o \
@@ -162,8 +175,11 @@ STCLIB_OBJECTS =  \
        $(OBJS)\stclib_LexPascal.o \
        $(OBJS)\stclib_LexPerl.o \
        $(OBJS)\stclib_LexPython.o \
+       $(OBJS)\stclib_LexRebol.o \
        $(OBJS)\stclib_LexRuby.o \
        $(OBJS)\stclib_LexSQL.o \
+       $(OBJS)\stclib_LexSmalltalk.o \
+       $(OBJS)\stclib_LexTADS3.o \
        $(OBJS)\stclib_LexScriptol.o \
        $(OBJS)\stclib_LexSpecman.o \
        $(OBJS)\stclib_LexTeX.o \
@@ -450,6 +466,9 @@ $(OBJS)\stcdll_LexBaan.o: ../../src/stc/scintilla/src/LexBaan.cxx
 $(OBJS)\stcdll_LexBash.o: ../../src/stc/scintilla/src/LexBash.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stcdll_LexBasic.o: ../../src/stc/scintilla/src/LexBasic.cxx
+       $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stcdll_LexBullant.o: ../../src/stc/scintilla/src/LexBullant.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
@@ -462,6 +481,12 @@ $(OBJS)\stcdll_LexCPP.o: ../../src/stc/scintilla/src/LexCPP.cxx
 $(OBJS)\stcdll_LexCSS.o: ../../src/stc/scintilla/src/LexCSS.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stcdll_LexCaml.o: ../../src/stc/scintilla/src/LexCaml.cxx
+       $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
+
+$(OBJS)\stcdll_LexCsound.o: ../../src/stc/scintilla/src/LexCsound.cxx
+       $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stcdll_LexConf.o: ../../src/stc/scintilla/src/LexConf.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
@@ -477,6 +502,9 @@ $(OBJS)\stcdll_LexEiffel.o: ../../src/stc/scintilla/src/LexEiffel.cxx
 $(OBJS)\stcdll_LexErlang.o: ../../src/stc/scintilla/src/LexErlang.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stcdll_LexFlagship.o: ../../src/stc/scintilla/src/LexFlagship.cxx
+       $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stcdll_LexForth.o: ../../src/stc/scintilla/src/LexForth.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
@@ -489,6 +517,9 @@ $(OBJS)\stcdll_LexGui4Cli.o: ../../src/stc/scintilla/src/LexGui4Cli.cxx
 $(OBJS)\stcdll_LexHTML.o: ../../src/stc/scintilla/src/LexHTML.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stcdll_LexHaskell.o: ../../src/stc/scintilla/src/LexHaskell.cxx
+       $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stcdll_LexKix.o: ../../src/stc/scintilla/src/LexKix.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
@@ -540,12 +571,21 @@ $(OBJS)\stcdll_LexPerl.o: ../../src/stc/scintilla/src/LexPerl.cxx
 $(OBJS)\stcdll_LexPython.o: ../../src/stc/scintilla/src/LexPython.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stcdll_LexRebol.o: ../../src/stc/scintilla/src/LexRebol.cxx
+       $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stcdll_LexRuby.o: ../../src/stc/scintilla/src/LexRuby.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
 $(OBJS)\stcdll_LexSQL.o: ../../src/stc/scintilla/src/LexSQL.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stcdll_LexSmalltalk.o: ../../src/stc/scintilla/src/LexSmalltalk.cxx
+       $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
+
+$(OBJS)\stcdll_LexTADS3.o: ../../src/stc/scintilla/src/LexTADS3.cxx
+       $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stcdll_LexScriptol.o: ../../src/stc/scintilla/src/LexScriptol.cxx
        $(CXX) -c -o $@ $(STCDLL_CXXFLAGS) $(CPPDEPS) $<
 
@@ -663,6 +703,9 @@ $(OBJS)\stclib_LexBaan.o: ../../src/stc/scintilla/src/LexBaan.cxx
 $(OBJS)\stclib_LexBash.o: ../../src/stc/scintilla/src/LexBash.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stclib_LexBasic.o: ../../src/stc/scintilla/src/LexBasic.cxx
+       $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stclib_LexBullant.o: ../../src/stc/scintilla/src/LexBullant.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
@@ -675,6 +718,12 @@ $(OBJS)\stclib_LexCPP.o: ../../src/stc/scintilla/src/LexCPP.cxx
 $(OBJS)\stclib_LexCSS.o: ../../src/stc/scintilla/src/LexCSS.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stclib_LexCaml.o: ../../src/stc/scintilla/src/LexCaml.cxx
+       $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
+
+$(OBJS)\stclib_LexCsound.o: ../../src/stc/scintilla/src/LexCsound.cxx
+       $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stclib_LexConf.o: ../../src/stc/scintilla/src/LexConf.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
@@ -690,6 +739,9 @@ $(OBJS)\stclib_LexEiffel.o: ../../src/stc/scintilla/src/LexEiffel.cxx
 $(OBJS)\stclib_LexErlang.o: ../../src/stc/scintilla/src/LexErlang.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stclib_LexFlagship.o: ../../src/stc/scintilla/src/LexFlagship.cxx
+       $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stclib_LexForth.o: ../../src/stc/scintilla/src/LexForth.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
@@ -702,6 +754,9 @@ $(OBJS)\stclib_LexGui4Cli.o: ../../src/stc/scintilla/src/LexGui4Cli.cxx
 $(OBJS)\stclib_LexHTML.o: ../../src/stc/scintilla/src/LexHTML.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stclib_LexHaskell.o: ../../src/stc/scintilla/src/LexHaskell.cxx
+       $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stclib_LexKix.o: ../../src/stc/scintilla/src/LexKix.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
@@ -753,12 +808,21 @@ $(OBJS)\stclib_LexPerl.o: ../../src/stc/scintilla/src/LexPerl.cxx
 $(OBJS)\stclib_LexPython.o: ../../src/stc/scintilla/src/LexPython.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stclib_LexRebol.o: ../../src/stc/scintilla/src/LexRebol.cxx
+       $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stclib_LexRuby.o: ../../src/stc/scintilla/src/LexRuby.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
 $(OBJS)\stclib_LexSQL.o: ../../src/stc/scintilla/src/LexSQL.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
+$(OBJS)\stclib_LexSmalltalk.o: ../../src/stc/scintilla/src/LexSmalltalk.cxx
+       $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
+
+$(OBJS)\stclib_LexTADS3.o: ../../src/stc/scintilla/src/LexTADS3.cxx
+       $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
+
 $(OBJS)\stclib_LexScriptol.o: ../../src/stc/scintilla/src/LexScriptol.cxx
        $(CXX) -c -o $@ $(STCLIB_CXXFLAGS) $(CPPDEPS) $<
 
index 7f7da0796f61eb742573635f4b79a5c887c9cc3a..5a1cdd1e901f76fd82db8e1faf48b43a67ea73b0 100644 (file)
@@ -55,19 +55,24 @@ STCDLL_OBJECTS =  \
        $(OBJS)\stcdll_LexAsn1.obj \
        $(OBJS)\stcdll_LexBaan.obj \
        $(OBJS)\stcdll_LexBash.obj \
+       $(OBJS)\stcdll_LexBasic.obj \
        $(OBJS)\stcdll_LexBullant.obj \
        $(OBJS)\stcdll_LexCLW.obj \
        $(OBJS)\stcdll_LexCPP.obj \
        $(OBJS)\stcdll_LexCSS.obj \
+       $(OBJS)\stcdll_LexCaml.obj \
+       $(OBJS)\stcdll_LexCsound.obj \
        $(OBJS)\stcdll_LexConf.obj \
        $(OBJS)\stcdll_LexCrontab.obj \
        $(OBJS)\stcdll_LexEScript.obj \
        $(OBJS)\stcdll_LexEiffel.obj \
        $(OBJS)\stcdll_LexErlang.obj \
+       $(OBJS)\stcdll_LexFlagship.obj \
        $(OBJS)\stcdll_LexForth.obj \
        $(OBJS)\stcdll_LexFortran.obj \
        $(OBJS)\stcdll_LexGui4Cli.obj \
        $(OBJS)\stcdll_LexHTML.obj \
+       $(OBJS)\stcdll_LexHaskell.obj \
        $(OBJS)\stcdll_LexKix.obj \
        $(OBJS)\stcdll_LexLisp.obj \
        $(OBJS)\stcdll_LexLout.obj \
@@ -85,8 +90,11 @@ STCDLL_OBJECTS =  \
        $(OBJS)\stcdll_LexPascal.obj \
        $(OBJS)\stcdll_LexPerl.obj \
        $(OBJS)\stcdll_LexPython.obj \
+       $(OBJS)\stcdll_LexRebol.obj \
        $(OBJS)\stcdll_LexRuby.obj \
        $(OBJS)\stcdll_LexSQL.obj \
+       $(OBJS)\stcdll_LexSmalltalk.obj \
+       $(OBJS)\stcdll_LexTADS3.obj \
        $(OBJS)\stcdll_LexScriptol.obj \
        $(OBJS)\stcdll_LexSpecman.obj \
        $(OBJS)\stcdll_LexTeX.obj \
@@ -137,19 +145,24 @@ STCLIB_OBJECTS =  \
        $(OBJS)\stclib_LexAsn1.obj \
        $(OBJS)\stclib_LexBaan.obj \
        $(OBJS)\stclib_LexBash.obj \
+       $(OBJS)\stclib_LexBasic.obj \
        $(OBJS)\stclib_LexBullant.obj \
        $(OBJS)\stclib_LexCLW.obj \
        $(OBJS)\stclib_LexCPP.obj \
        $(OBJS)\stclib_LexCSS.obj \
+       $(OBJS)\stclib_LexCaml.obj \
+       $(OBJS)\stclib_LexCsound.obj \
        $(OBJS)\stclib_LexConf.obj \
        $(OBJS)\stclib_LexCrontab.obj \
        $(OBJS)\stclib_LexEScript.obj \
        $(OBJS)\stclib_LexEiffel.obj \
        $(OBJS)\stclib_LexErlang.obj \
+       $(OBJS)\stclib_LexFlagship.obj \
        $(OBJS)\stclib_LexForth.obj \
        $(OBJS)\stclib_LexFortran.obj \
        $(OBJS)\stclib_LexGui4Cli.obj \
        $(OBJS)\stclib_LexHTML.obj \
+       $(OBJS)\stclib_LexHaskell.obj \
        $(OBJS)\stclib_LexKix.obj \
        $(OBJS)\stclib_LexLisp.obj \
        $(OBJS)\stclib_LexLout.obj \
@@ -167,8 +180,11 @@ STCLIB_OBJECTS =  \
        $(OBJS)\stclib_LexPascal.obj \
        $(OBJS)\stclib_LexPerl.obj \
        $(OBJS)\stclib_LexPython.obj \
+       $(OBJS)\stclib_LexRebol.obj \
        $(OBJS)\stclib_LexRuby.obj \
        $(OBJS)\stclib_LexSQL.obj \
+       $(OBJS)\stclib_LexSmalltalk.obj \
+       $(OBJS)\stclib_LexTADS3.obj \
        $(OBJS)\stclib_LexScriptol.obj \
        $(OBJS)\stclib_LexSpecman.obj \
        $(OBJS)\stclib_LexTeX.obj \
@@ -544,6 +560,9 @@ $(OBJS)\stcdll_LexBaan.obj: ../../src/stc\scintilla\src\LexBaan.cxx
 $(OBJS)\stcdll_LexBash.obj: ../../src/stc\scintilla\src\LexBash.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexBasic.obj: ../../src/stc\scintilla\src\LexBasic.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexBullant.obj: ../../src/stc\scintilla\src\LexBullant.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
@@ -556,6 +575,12 @@ $(OBJS)\stcdll_LexCPP.obj: ../../src/stc\scintilla\src\LexCPP.cxx
 $(OBJS)\stcdll_LexCSS.obj: ../../src/stc\scintilla\src\LexCSS.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexCaml.obj: ../../src/stc\scintilla\src\LexCaml.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
+
+$(OBJS)\stcdll_LexCsound.obj: ../../src/stc\scintilla\src\LexCsound.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexConf.obj: ../../src/stc\scintilla\src\LexConf.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
@@ -571,6 +596,9 @@ $(OBJS)\stcdll_LexEiffel.obj: ../../src/stc\scintilla\src\LexEiffel.cxx
 $(OBJS)\stcdll_LexErlang.obj: ../../src/stc\scintilla\src\LexErlang.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexFlagship.obj: ../../src/stc\scintilla\src\LexFlagship.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexForth.obj: ../../src/stc\scintilla\src\LexForth.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
@@ -583,6 +611,9 @@ $(OBJS)\stcdll_LexGui4Cli.obj: ../../src/stc\scintilla\src\LexGui4Cli.cxx
 $(OBJS)\stcdll_LexHTML.obj: ../../src/stc\scintilla\src\LexHTML.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexHaskell.obj: ../../src/stc\scintilla\src\LexHaskell.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexKix.obj: ../../src/stc\scintilla\src\LexKix.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
@@ -634,12 +665,21 @@ $(OBJS)\stcdll_LexPerl.obj: ../../src/stc\scintilla\src\LexPerl.cxx
 $(OBJS)\stcdll_LexPython.obj: ../../src/stc\scintilla\src\LexPython.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexRebol.obj: ../../src/stc\scintilla\src\LexRebol.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexRuby.obj: ../../src/stc\scintilla\src\LexRuby.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
 $(OBJS)\stcdll_LexSQL.obj: ../../src/stc\scintilla\src\LexSQL.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
+$(OBJS)\stcdll_LexSmalltalk.obj: ../../src/stc\scintilla\src\LexSmalltalk.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
+
+$(OBJS)\stcdll_LexTADS3.obj: ../../src/stc\scintilla\src\LexTADS3.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
+
 $(OBJS)\stcdll_LexScriptol.obj: ../../src/stc\scintilla\src\LexScriptol.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCDLL_CXXFLAGS) $**
 
@@ -757,6 +797,9 @@ $(OBJS)\stclib_LexBaan.obj: ../../src/stc\scintilla\src\LexBaan.cxx
 $(OBJS)\stclib_LexBash.obj: ../../src/stc\scintilla\src\LexBash.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexBasic.obj: ../../src/stc\scintilla\src\LexBasic.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexBullant.obj: ../../src/stc\scintilla\src\LexBullant.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
@@ -769,6 +812,12 @@ $(OBJS)\stclib_LexCPP.obj: ../../src/stc\scintilla\src\LexCPP.cxx
 $(OBJS)\stclib_LexCSS.obj: ../../src/stc\scintilla\src\LexCSS.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexCaml.obj: ../../src/stc\scintilla\src\LexCaml.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
+
+$(OBJS)\stclib_LexCsound.obj: ../../src/stc\scintilla\src\LexCsound.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexConf.obj: ../../src/stc\scintilla\src\LexConf.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
@@ -784,6 +833,9 @@ $(OBJS)\stclib_LexEiffel.obj: ../../src/stc\scintilla\src\LexEiffel.cxx
 $(OBJS)\stclib_LexErlang.obj: ../../src/stc\scintilla\src\LexErlang.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexFlagship.obj: ../../src/stc\scintilla\src\LexFlagship.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexForth.obj: ../../src/stc\scintilla\src\LexForth.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
@@ -796,6 +848,9 @@ $(OBJS)\stclib_LexGui4Cli.obj: ../../src/stc\scintilla\src\LexGui4Cli.cxx
 $(OBJS)\stclib_LexHTML.obj: ../../src/stc\scintilla\src\LexHTML.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexHaskell.obj: ../../src/stc\scintilla\src\LexHaskell.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexKix.obj: ../../src/stc\scintilla\src\LexKix.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
@@ -847,12 +902,21 @@ $(OBJS)\stclib_LexPerl.obj: ../../src/stc\scintilla\src\LexPerl.cxx
 $(OBJS)\stclib_LexPython.obj: ../../src/stc\scintilla\src\LexPython.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexRebol.obj: ../../src/stc\scintilla\src\LexRebol.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexRuby.obj: ../../src/stc\scintilla\src\LexRuby.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
 $(OBJS)\stclib_LexSQL.obj: ../../src/stc\scintilla\src\LexSQL.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
+$(OBJS)\stclib_LexSmalltalk.obj: ../../src/stc\scintilla\src\LexSmalltalk.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
+
+$(OBJS)\stclib_LexTADS3.obj: ../../src/stc\scintilla\src\LexTADS3.cxx
+       $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
+
 $(OBJS)\stclib_LexScriptol.obj: ../../src/stc\scintilla\src\LexScriptol.cxx
        $(CXX) /c /nologo /TP /Fo$@ $(STCLIB_CXXFLAGS) $**
 
index 99c5014529075ddbd93b551a5cfa4d614d599e8b..3d1554b72981c0197a3f9def3e0632713b88ff35 100644 (file)
@@ -252,19 +252,24 @@ STCDLL_OBJECTS =  &
        $(OBJS)\stcdll_LexAsn1.obj &
        $(OBJS)\stcdll_LexBaan.obj &
        $(OBJS)\stcdll_LexBash.obj &
+       $(OBJS)\stcdll_LexBasic.obj &
        $(OBJS)\stcdll_LexBullant.obj &
        $(OBJS)\stcdll_LexCLW.obj &
        $(OBJS)\stcdll_LexCPP.obj &
        $(OBJS)\stcdll_LexCSS.obj &
+       $(OBJS)\stcdll_LexCaml.obj &
+       $(OBJS)\stcdll_LexCsound.obj &
        $(OBJS)\stcdll_LexConf.obj &
        $(OBJS)\stcdll_LexCrontab.obj &
        $(OBJS)\stcdll_LexEScript.obj &
        $(OBJS)\stcdll_LexEiffel.obj &
        $(OBJS)\stcdll_LexErlang.obj &
+       $(OBJS)\stcdll_LexFlagship.obj &
        $(OBJS)\stcdll_LexForth.obj &
        $(OBJS)\stcdll_LexFortran.obj &
        $(OBJS)\stcdll_LexGui4Cli.obj &
        $(OBJS)\stcdll_LexHTML.obj &
+       $(OBJS)\stcdll_LexHaskell.obj &
        $(OBJS)\stcdll_LexKix.obj &
        $(OBJS)\stcdll_LexLisp.obj &
        $(OBJS)\stcdll_LexLout.obj &
@@ -282,8 +287,11 @@ STCDLL_OBJECTS =  &
        $(OBJS)\stcdll_LexPascal.obj &
        $(OBJS)\stcdll_LexPerl.obj &
        $(OBJS)\stcdll_LexPython.obj &
+       $(OBJS)\stcdll_LexRebol.obj &
        $(OBJS)\stcdll_LexRuby.obj &
        $(OBJS)\stcdll_LexSQL.obj &
+       $(OBJS)\stcdll_LexSmalltalk.obj &
+       $(OBJS)\stcdll_LexTADS3.obj &
        $(OBJS)\stcdll_LexScriptol.obj &
        $(OBJS)\stcdll_LexSpecman.obj &
        $(OBJS)\stcdll_LexTeX.obj &
@@ -332,19 +340,24 @@ STCLIB_OBJECTS =  &
        $(OBJS)\stclib_LexAsn1.obj &
        $(OBJS)\stclib_LexBaan.obj &
        $(OBJS)\stclib_LexBash.obj &
+       $(OBJS)\stclib_LexBasic.obj &
        $(OBJS)\stclib_LexBullant.obj &
        $(OBJS)\stclib_LexCLW.obj &
        $(OBJS)\stclib_LexCPP.obj &
        $(OBJS)\stclib_LexCSS.obj &
+       $(OBJS)\stclib_LexCaml.obj &
+       $(OBJS)\stclib_LexCsound.obj &
        $(OBJS)\stclib_LexConf.obj &
        $(OBJS)\stclib_LexCrontab.obj &
        $(OBJS)\stclib_LexEScript.obj &
        $(OBJS)\stclib_LexEiffel.obj &
        $(OBJS)\stclib_LexErlang.obj &
+       $(OBJS)\stclib_LexFlagship.obj &
        $(OBJS)\stclib_LexForth.obj &
        $(OBJS)\stclib_LexFortran.obj &
        $(OBJS)\stclib_LexGui4Cli.obj &
        $(OBJS)\stclib_LexHTML.obj &
+       $(OBJS)\stclib_LexHaskell.obj &
        $(OBJS)\stclib_LexKix.obj &
        $(OBJS)\stclib_LexLisp.obj &
        $(OBJS)\stclib_LexLout.obj &
@@ -362,8 +375,11 @@ STCLIB_OBJECTS =  &
        $(OBJS)\stclib_LexPascal.obj &
        $(OBJS)\stclib_LexPerl.obj &
        $(OBJS)\stclib_LexPython.obj &
+       $(OBJS)\stclib_LexRebol.obj &
        $(OBJS)\stclib_LexRuby.obj &
        $(OBJS)\stclib_LexSQL.obj &
+       $(OBJS)\stclib_LexSmalltalk.obj &
+       $(OBJS)\stclib_LexTADS3.obj &
        $(OBJS)\stclib_LexScriptol.obj &
        $(OBJS)\stclib_LexSpecman.obj &
        $(OBJS)\stclib_LexTeX.obj &
@@ -492,6 +508,9 @@ $(OBJS)\stcdll_LexBaan.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexBaan.cx
 $(OBJS)\stcdll_LexBash.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexBash.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
+$(OBJS)\stcdll_LexBasic.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexBasic.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
+
 $(OBJS)\stcdll_LexBullant.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexBullant.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
@@ -504,6 +523,12 @@ $(OBJS)\stcdll_LexCPP.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexCPP.cxx
 $(OBJS)\stcdll_LexCSS.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexCSS.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
+$(OBJS)\stcdll_LexCaml.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexCaml.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
+
+$(OBJS)\stcdll_LexCsound.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexCsound.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
+
 $(OBJS)\stcdll_LexConf.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexConf.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
@@ -519,6 +544,9 @@ $(OBJS)\stcdll_LexEiffel.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexEiffe
 $(OBJS)\stcdll_LexErlang.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexErlang.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
+$(OBJS)\stcdll_LexFlagship.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexFlagship.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
+
 $(OBJS)\stcdll_LexForth.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexForth.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
@@ -531,6 +559,9 @@ $(OBJS)\stcdll_LexGui4Cli.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexGui4
 $(OBJS)\stcdll_LexHTML.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexHTML.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
+$(OBJS)\stcdll_LexHaskell.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexHaskell.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
+
 $(OBJS)\stcdll_LexKix.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexKix.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
@@ -582,12 +613,21 @@ $(OBJS)\stcdll_LexPerl.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexPerl.cx
 $(OBJS)\stcdll_LexPython.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexPython.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
+$(OBJS)\stcdll_LexRebol.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexRebol.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
+
 $(OBJS)\stcdll_LexRuby.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexRuby.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
 $(OBJS)\stcdll_LexSQL.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexSQL.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
+$(OBJS)\stcdll_LexSmalltalk.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexSmalltalk.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
+
+$(OBJS)\stcdll_LexTADS3.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexTADS3.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
+
 $(OBJS)\stcdll_LexScriptol.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexScriptol.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCDLL_CXXFLAGS) $<
 
@@ -705,6 +745,9 @@ $(OBJS)\stclib_LexBaan.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexBaan.cx
 $(OBJS)\stclib_LexBash.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexBash.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
+$(OBJS)\stclib_LexBasic.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexBasic.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
+
 $(OBJS)\stclib_LexBullant.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexBullant.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
@@ -717,6 +760,12 @@ $(OBJS)\stclib_LexCPP.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexCPP.cxx
 $(OBJS)\stclib_LexCSS.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexCSS.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
+$(OBJS)\stclib_LexCaml.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexCaml.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
+
+$(OBJS)\stclib_LexCsound.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexCsound.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
+
 $(OBJS)\stclib_LexConf.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexConf.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
@@ -732,6 +781,9 @@ $(OBJS)\stclib_LexEiffel.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexEiffe
 $(OBJS)\stclib_LexErlang.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexErlang.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
+$(OBJS)\stclib_LexFlagship.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexFlagship.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
+
 $(OBJS)\stclib_LexForth.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexForth.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
@@ -744,6 +796,9 @@ $(OBJS)\stclib_LexGui4Cli.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexGui4
 $(OBJS)\stclib_LexHTML.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexHTML.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
+$(OBJS)\stclib_LexHaskell.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexHaskell.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
+
 $(OBJS)\stclib_LexKix.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexKix.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
@@ -795,12 +850,21 @@ $(OBJS)\stclib_LexPerl.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexPerl.cx
 $(OBJS)\stclib_LexPython.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexPython.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
+$(OBJS)\stclib_LexRebol.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexRebol.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
+
 $(OBJS)\stclib_LexRuby.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexRuby.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
 $(OBJS)\stclib_LexSQL.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexSQL.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
+$(OBJS)\stclib_LexSmalltalk.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexSmalltalk.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
+
+$(OBJS)\stclib_LexTADS3.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexTADS3.cxx
+       $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
+
 $(OBJS)\stclib_LexScriptol.obj :  .AUTODEPEND ../../src/stc\scintilla\src\LexScriptol.cxx
        $(CXX) -bt=nt -zq -fo=$^@ $(STCLIB_CXXFLAGS) $<
 
index 0e1fe5abbed56d276780d608530a88f93448205e..2e98036e0e23ca7f91d15c1693d95327ad0902ae 100644 (file)
         scintilla/src/LexAsn1.cxx
         scintilla/src/LexBaan.cxx
         scintilla/src/LexBash.cxx
+        scintilla/src/LexBasic.cxx
         scintilla/src/LexBullant.cxx
         scintilla/src/LexCLW.cxx
         scintilla/src/LexCPP.cxx
         scintilla/src/LexCSS.cxx
+        scintilla/src/LexCaml.cxx
+        scintilla/src/LexCsound.cxx
         scintilla/src/LexConf.cxx
         scintilla/src/LexCrontab.cxx
         scintilla/src/LexEScript.cxx
         scintilla/src/LexEiffel.cxx
         scintilla/src/LexErlang.cxx
+        scintilla/src/LexFlagship.cxx
         scintilla/src/LexForth.cxx
         scintilla/src/LexFortran.cxx
         scintilla/src/LexGui4Cli.cxx
         scintilla/src/LexHTML.cxx
+        scintilla/src/LexHaskell.cxx
         scintilla/src/LexKix.cxx
         scintilla/src/LexLisp.cxx
         scintilla/src/LexLout.cxx
         scintilla/src/LexPascal.cxx
         scintilla/src/LexPerl.cxx
         scintilla/src/LexPython.cxx
+        scintilla/src/LexRebol.cxx
         scintilla/src/LexRuby.cxx
         scintilla/src/LexSQL.cxx
+        scintilla/src/LexSmalltalk.cxx
+        scintilla/src/LexTADS3.cxx
         scintilla/src/LexScriptol.cxx
         scintilla/src/LexSpecman.cxx
         scintilla/src/LexTeX.cxx
index cc4c3f51794d95327c3dc1413f5f9f760e9291d6..dc3e0a8e3f20dafdf7ff8caa479d091f061cdf49 100644 (file)
@@ -528,6 +528,10 @@ SOURCE=../../src/stc\scintilla\src\LexBash.cxx
 # End Source File
 # Begin Source File
 
+SOURCE=../../src/stc\scintilla\src\LexBasic.cxx
+# End Source File
+# Begin Source File
+
 SOURCE=../../src/stc\scintilla\src\LexBullant.cxx
 # End Source File
 # Begin Source File
@@ -544,6 +548,10 @@ SOURCE=../../src/stc\scintilla\src\LexCSS.cxx
 # End Source File
 # Begin Source File
 
+SOURCE=../../src/stc\scintilla\src\LexCaml.cxx
+# End Source File
+# Begin Source File
+
 SOURCE=../../src/stc\scintilla\src\LexConf.cxx
 # End Source File
 # Begin Source File
@@ -552,6 +560,10 @@ SOURCE=../../src/stc\scintilla\src\LexCrontab.cxx
 # End Source File
 # Begin Source File
 
+SOURCE=../../src/stc\scintilla\src\LexCsound.cxx
+# End Source File
+# Begin Source File
+
 SOURCE=../../src/stc\scintilla\src\LexEScript.cxx
 # End Source File
 # Begin Source File
@@ -564,6 +576,10 @@ SOURCE=../../src/stc\scintilla\src\LexErlang.cxx
 # End Source File
 # Begin Source File
 
+SOURCE=../../src/stc\scintilla\src\LexFlagship.cxx
+# End Source File
+# Begin Source File
+
 SOURCE=../../src/stc\scintilla\src\LexForth.cxx
 # End Source File
 # Begin Source File
@@ -580,6 +596,10 @@ SOURCE=../../src/stc\scintilla\src\LexHTML.cxx
 # End Source File
 # Begin Source File
 
+SOURCE=../../src/stc\scintilla\src\LexHaskell.cxx
+# End Source File
+# Begin Source File
+
 SOURCE=../../src/stc\scintilla\src\LexKix.cxx
 # End Source File
 # Begin Source File
@@ -648,6 +668,10 @@ SOURCE=../../src/stc\scintilla\src\LexPython.cxx
 # End Source File
 # Begin Source File
 
+SOURCE=../../src/stc\scintilla\src\LexRebol.cxx
+# End Source File
+# Begin Source File
+
 SOURCE=../../src/stc\scintilla\src\LexRuby.cxx
 # End Source File
 # Begin Source File
@@ -660,10 +684,18 @@ SOURCE=../../src/stc\scintilla\src\LexScriptol.cxx
 # End Source File
 # Begin Source File
 
+SOURCE=../../src/stc\scintilla\src\LexSmalltalk.cxx
+# End Source File
+# Begin Source File
+
 SOURCE=../../src/stc\scintilla\src\LexSpecman.cxx
 # End Source File
 # Begin Source File
 
+SOURCE=../../src/stc\scintilla\src\LexTADS3.cxx
+# End Source File
+# Begin Source File
+
 SOURCE=../../src/stc\scintilla\src\LexTeX.cxx
 # End Source File
 # Begin Source File
index 5bf0cc31de2f3f5edb8ce0e294240c3cec928e5f..3a1132d020e6e493c72d55ff8cfecf7c7284d385 100644 (file)
 #define wxSTC_MARK_DOTDOTDOT 23
 #define wxSTC_MARK_ARROWS 24
 #define wxSTC_MARK_PIXMAP 25
+#define wxSTC_MARK_FULLRECT 26
 #define wxSTC_MARK_CHARACTER 10000
 
 // Markers used for outlining column.
 #define wxSTC_CHARSET_MAC 77
 #define wxSTC_CHARSET_OEM 255
 #define wxSTC_CHARSET_RUSSIAN 204
+#define wxSTC_CHARSET_CYRILLIC 1251
 #define wxSTC_CHARSET_SHIFTJIS 128
 #define wxSTC_CHARSET_SYMBOL 2
 #define wxSTC_CHARSET_TURKISH 162
 #define wxSTC_CHARSET_ARABIC 178
 #define wxSTC_CHARSET_VIETNAMESE 163
 #define wxSTC_CHARSET_THAI 222
+#define wxSTC_CHARSET_8859_15 1000
 #define wxSTC_CASE_MIXED 0
 #define wxSTC_CASE_UPPER 1
 #define wxSTC_CASE_LOWER 2
 #define wxSTC_TIME_FOREVER 10000000
 #define wxSTC_WRAP_NONE 0
 #define wxSTC_WRAP_WORD 1
+#define wxSTC_WRAP_CHAR 2
 #define wxSTC_WRAPVISUALFLAG_NONE 0x0000
 #define wxSTC_WRAPVISUALFLAG_END 0x0001
 #define wxSTC_WRAPVISUALFLAG_START 0x0002
 #define wxSTC_PERFORMED_USER 0x10
 #define wxSTC_PERFORMED_UNDO 0x20
 #define wxSTC_PERFORMED_REDO 0x40
+#define wxSTC_MULTISTEPUNDOREDO 0x80
 #define wxSTC_LASTSTEPINUNDOREDO 0x100
 #define wxSTC_MOD_CHANGEMARKER 0x200
 #define wxSTC_MOD_BEFOREINSERT 0x400
 #define wxSTC_MOD_BEFOREDELETE 0x800
-#define wxSTC_MODEVENTMASKALL 0xF77
+#define wxSTC_MULTILINEUNDOREDO 0x1000
+#define wxSTC_MODEVENTMASKALL 0x1FFF
 
 // Symbolic key codes and modifier flags.
 // ASCII and other printable characters below 256.
 #define wxSTC_KEY_ADD 310
 #define wxSTC_KEY_SUBTRACT 311
 #define wxSTC_KEY_DIVIDE 312
+#define wxSTC_SCMOD_NORM 0
 #define wxSTC_SCMOD_SHIFT 1
 #define wxSTC_SCMOD_CTRL 2
 #define wxSTC_SCMOD_ALT 4
 #define wxSTC_LEX_NNCRONTAB 26
 #define wxSTC_LEX_BULLANT 27
 #define wxSTC_LEX_VBSCRIPT 28
-#define wxSTC_LEX_ASP 29
-#define wxSTC_LEX_PHP 30
 #define wxSTC_LEX_BAAN 31
 #define wxSTC_LEX_MATLAB 32
 #define wxSTC_LEX_SCRIPTOL 33
 #define wxSTC_LEX_BASH 62
 #define wxSTC_LEX_ASN1 63
 #define wxSTC_LEX_VHDL 64
+#define wxSTC_LEX_CAML 65
+#define wxSTC_LEX_BLITZBASIC 66
+#define wxSTC_LEX_PUREBASIC 67
+#define wxSTC_LEX_HASKELL 68
+#define wxSTC_LEX_PHPSCRIPT 69
+#define wxSTC_LEX_TADS3 70
+#define wxSTC_LEX_REBOL 71
+#define wxSTC_LEX_SMALLTALK 72
+#define wxSTC_LEX_FLAGSHIP 73
+#define wxSTC_LEX_CSOUND 74
+#define wxSTC_LEX_FREEBASIC 75
 
 // When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
 // value assigned in sequence from SCLEX_AUTOMATIC+1.
 #define wxSTC_P_IDENTIFIER 11
 #define wxSTC_P_COMMENTBLOCK 12
 #define wxSTC_P_STRINGEOL 13
+#define wxSTC_P_WORD2 14
+#define wxSTC_P_DECORATOR 15
 
 // Lexical states for SCLEX_CPP
 #define wxSTC_C_DEFAULT 0
 #define wxSTC_PL_ARRAY 13
 #define wxSTC_PL_HASH 14
 #define wxSTC_PL_SYMBOLTABLE 15
+#define wxSTC_PL_VARIABLE_INDEXER 16
 #define wxSTC_PL_REGEX 17
 #define wxSTC_PL_REGSUBST 18
 #define wxSTC_PL_LONGQUOTE 19
 #define wxSTC_PL_STRING_QX 28
 #define wxSTC_PL_STRING_QR 29
 #define wxSTC_PL_STRING_QW 30
+#define wxSTC_PL_POD_VERB 31
+
+// Lexical states for SCLEX_RUBY
+#define wxSTC_RB_DEFAULT 0
+#define wxSTC_RB_ERROR 1
+#define wxSTC_RB_COMMENTLINE 2
+#define wxSTC_RB_POD 3
+#define wxSTC_RB_NUMBER 4
+#define wxSTC_RB_WORD 5
+#define wxSTC_RB_STRING 6
+#define wxSTC_RB_CHARACTER 7
+#define wxSTC_RB_CLASSNAME 8
+#define wxSTC_RB_DEFNAME 9
+#define wxSTC_RB_OPERATOR 10
+#define wxSTC_RB_IDENTIFIER 11
+#define wxSTC_RB_REGEX 12
+#define wxSTC_RB_GLOBAL 13
+#define wxSTC_RB_SYMBOL 14
+#define wxSTC_RB_MODULE_NAME 15
+#define wxSTC_RB_INSTANCE_VAR 16
+#define wxSTC_RB_CLASS_VAR 17
+#define wxSTC_RB_BACKTICKS 18
+#define wxSTC_RB_DATASECTION 19
+#define wxSTC_RB_HERE_DELIM 20
+#define wxSTC_RB_HERE_Q 21
+#define wxSTC_RB_HERE_QQ 22
+#define wxSTC_RB_HERE_QX 23
+#define wxSTC_RB_STRING_Q 24
+#define wxSTC_RB_STRING_QQ 25
+#define wxSTC_RB_STRING_QX 26
+#define wxSTC_RB_STRING_QR 27
+#define wxSTC_RB_STRING_QW 28
+#define wxSTC_RB_WORD_DEMOTED 29
+#define wxSTC_RB_STDIN 30
+#define wxSTC_RB_STDOUT 31
+#define wxSTC_RB_STDERR 40
+#define wxSTC_RB_UPPER_BOUND 41
 
 // Lexical states for SCLEX_VB, SCLEX_VBSCRIPT, SCLEX_POWERBASIC
 #define wxSTC_B_DEFAULT 0
 #define wxSTC_B_KEYWORD4 12
 #define wxSTC_B_CONSTANT 13
 #define wxSTC_B_ASM 14
+#define wxSTC_B_LABEL 15
+#define wxSTC_B_ERROR 16
+#define wxSTC_B_HEXNUMBER 17
+#define wxSTC_B_BINNUMBER 18
 
 // Lexical states for SCLEX_PROPERTIES
 #define wxSTC_PROPS_DEFAULT 0
 #define wxSTC_LISP_COMMENT 1
 #define wxSTC_LISP_NUMBER 2
 #define wxSTC_LISP_KEYWORD 3
+#define wxSTC_LISP_KEYWORD_KW 4
+#define wxSTC_LISP_SYMBOL 5
 #define wxSTC_LISP_STRING 6
 #define wxSTC_LISP_STRINGEOL 8
 #define wxSTC_LISP_IDENTIFIER 9
 #define wxSTC_LISP_OPERATOR 10
+#define wxSTC_LISP_SPECIAL 11
+#define wxSTC_LISP_MULTI_COMMENT 12
 
 // Lexical states for SCLEX_EIFFEL and SCLEX_EIFFELKW
 #define wxSTC_EIFFEL_DEFAULT 0
 #define wxSTC_CSS_DOUBLESTRING 13
 #define wxSTC_CSS_SINGLESTRING 14
 #define wxSTC_CSS_IDENTIFIER2 15
+#define wxSTC_CSS_ATTRIBUTE 16
 
 // Lexical states for SCLEX_POV
 #define wxSTC_POV_DEFAULT 0
 #define wxSTC_NSIS_MACRODEF 12
 #define wxSTC_NSIS_STRINGVAR 13
 #define wxSTC_NSIS_NUMBER 14
+#define wxSTC_NSIS_SECTIONGROUP 15
+#define wxSTC_NSIS_PAGEEX 16
+#define wxSTC_NSIS_FUNCTIONDEF 17
+#define wxSTC_NSIS_COMMENTBOX 18
 
 // Lexical states for SCLEX_MMIXAL
 #define wxSTC_MMIXAL_LEADWS 0
 #define wxSTC_CLW_PICTURE_STRING 7
 #define wxSTC_CLW_KEYWORD 8
 #define wxSTC_CLW_COMPILER_DIRECTIVE 9
-#define wxSTC_CLW_BUILTIN_PROCEDURES_FUNCTION 10
-#define wxSTC_CLW_STRUCTURE_DATA_TYPE 11
-#define wxSTC_CLW_ATTRIBUTE 12
-#define wxSTC_CLW_STANDARD_EQUATE 13
-#define wxSTC_CLW_ERROR 14
+#define wxSTC_CLW_RUNTIME_EXPRESSIONS 10
+#define wxSTC_CLW_BUILTIN_PROCEDURES_FUNCTION 11
+#define wxSTC_CLW_STRUCTURE_DATA_TYPE 12
+#define wxSTC_CLW_ATTRIBUTE 13
+#define wxSTC_CLW_STANDARD_EQUATE 14
+#define wxSTC_CLW_ERROR 15
+#define wxSTC_CLW_DEPRECATED 16
 
 // Lexical states for SCLEX_LOT
 #define wxSTC_LOT_DEFAULT 0
 #define wxSTC_AU3_SENT 10
 #define wxSTC_AU3_PREPROCESSOR 11
 #define wxSTC_AU3_SPECIAL 12
+#define wxSTC_AU3_EXPAND 13
+#define wxSTC_AU3_COMOBJ 14
 
 // Lexical states for SCLEX_APDL
 #define wxSTC_APDL_DEFAULT 0
 #define wxSTC_VHDL_STDTYPE 13
 #define wxSTC_VHDL_USERWORD 14
 
+// Lexical states for SCLEX_CAML
+#define wxSTC_CAML_DEFAULT 0
+#define wxSTC_CAML_IDENTIFIER 1
+#define wxSTC_CAML_TAGNAME 2
+#define wxSTC_CAML_KEYWORD 3
+#define wxSTC_CAML_KEYWORD2 4
+#define wxSTC_CAML_KEYWORD3 5
+#define wxSTC_CAML_LINENUM 6
+#define wxSTC_CAML_OPERATOR 7
+#define wxSTC_CAML_NUMBER 8
+#define wxSTC_CAML_CHAR 9
+#define wxSTC_CAML_STRING 11
+#define wxSTC_CAML_COMMENT 12
+#define wxSTC_CAML_COMMENT1 13
+#define wxSTC_CAML_COMMENT2 14
+#define wxSTC_CAML_COMMENT3 15
+
+// Lexical states for SCLEX_HASKELL
+#define wxSTC_HA_DEFAULT 0
+#define wxSTC_HA_IDENTIFIER 1
+#define wxSTC_HA_KEYWORD 2
+#define wxSTC_HA_NUMBER 3
+#define wxSTC_HA_STRING 4
+#define wxSTC_HA_CHARACTER 5
+#define wxSTC_HA_CLASS 6
+#define wxSTC_HA_MODULE 7
+#define wxSTC_HA_CAPITAL 8
+#define wxSTC_HA_DATA 9
+#define wxSTC_HA_IMPORT 10
+#define wxSTC_HA_OPERATOR 11
+#define wxSTC_HA_INSTANCE 12
+#define wxSTC_HA_COMMENTLINE 13
+#define wxSTC_HA_COMMENTBLOCK 14
+#define wxSTC_HA_COMMENTBLOCK2 15
+#define wxSTC_HA_COMMENTBLOCK3 16
+
+// Lexical states of SCLEX_TADS3
+#define wxSTC_T3_DEFAULT 0
+#define wxSTC_T3_X_DEFAULT 1
+#define wxSTC_T3_PREPROCESSOR 2
+#define wxSTC_T3_BLOCK_COMMENT 3
+#define wxSTC_T3_LINE_COMMENT 4
+#define wxSTC_T3_OPERATOR 5
+#define wxSTC_T3_KEYWORD 6
+#define wxSTC_T3_NUMBER 7
+#define wxSTC_T3_IDENTIFIER 8
+#define wxSTC_T3_S_STRING 9
+#define wxSTC_T3_D_STRING 10
+#define wxSTC_T3_X_STRING 11
+#define wxSTC_T3_LIB_DIRECTIVE 12
+#define wxSTC_T3_MSG_PARAM 13
+#define wxSTC_T3_HTML_TAG 14
+#define wxSTC_T3_HTML_DEFAULT 15
+#define wxSTC_T3_HTML_STRING 16
+#define wxSTC_T3_USER1 17
+#define wxSTC_T3_USER2 18
+#define wxSTC_T3_USER3 19
+
+// Lexical states for SCLEX_REBOL
+#define wxSTC_REBOL_DEFAULT 0
+#define wxSTC_REBOL_COMMENTLINE 1
+#define wxSTC_REBOL_COMMENTBLOCK 2
+#define wxSTC_REBOL_PREFACE 3
+#define wxSTC_REBOL_OPERATOR 4
+#define wxSTC_REBOL_CHARACTER 5
+#define wxSTC_REBOL_QUOTEDSTRING 6
+#define wxSTC_REBOL_BRACEDSTRING 7
+#define wxSTC_REBOL_NUMBER 8
+#define wxSTC_REBOL_PAIR 9
+#define wxSTC_REBOL_TUPLE 10
+#define wxSTC_REBOL_BINARY 11
+#define wxSTC_REBOL_MONEY 12
+#define wxSTC_REBOL_ISSUE 13
+#define wxSTC_REBOL_TAG 14
+#define wxSTC_REBOL_FILE 15
+#define wxSTC_REBOL_EMAIL 16
+#define wxSTC_REBOL_URL 17
+#define wxSTC_REBOL_DATE 18
+#define wxSTC_REBOL_TIME 19
+#define wxSTC_REBOL_IDENTIFIER 20
+#define wxSTC_REBOL_WORD 21
+#define wxSTC_REBOL_WORD2 22
+#define wxSTC_REBOL_WORD3 23
+#define wxSTC_REBOL_WORD4 24
+#define wxSTC_REBOL_WORD5 25
+#define wxSTC_REBOL_WORD6 26
+#define wxSTC_REBOL_WORD7 27
+#define wxSTC_REBOL_WORD8 28
+
+// Lexical states for SCLEX_SQL
+#define wxSTC_SQL_DEFAULT 0
+#define wxSTC_SQL_COMMENT 1
+#define wxSTC_SQL_COMMENTLINE 2
+#define wxSTC_SQL_COMMENTDOC 3
+#define wxSTC_SQL_NUMBER 4
+#define wxSTC_SQL_WORD 5
+#define wxSTC_SQL_STRING 6
+#define wxSTC_SQL_CHARACTER 7
+#define wxSTC_SQL_SQLPLUS 8
+#define wxSTC_SQL_SQLPLUS_PROMPT 9
+#define wxSTC_SQL_OPERATOR 10
+#define wxSTC_SQL_IDENTIFIER 11
+#define wxSTC_SQL_SQLPLUS_COMMENT 13
+#define wxSTC_SQL_COMMENTLINEDOC 15
+#define wxSTC_SQL_WORD2 16
+#define wxSTC_SQL_COMMENTDOCKEYWORD 17
+#define wxSTC_SQL_COMMENTDOCKEYWORDERROR 18
+#define wxSTC_SQL_USER1 19
+#define wxSTC_SQL_USER2 20
+#define wxSTC_SQL_USER3 21
+#define wxSTC_SQL_USER4 22
+#define wxSTC_SQL_QUOTEDIDENTIFIER 23
+
+// Lexical states for SCLEX_SMALLTALK
+#define wxSTC_ST_DEFAULT 0
+#define wxSTC_ST_STRING 1
+#define wxSTC_ST_NUMBER 2
+#define wxSTC_ST_COMMENT 3
+#define wxSTC_ST_SYMBOL 4
+#define wxSTC_ST_BINARY 5
+#define wxSTC_ST_BOOL 6
+#define wxSTC_ST_SELF 7
+#define wxSTC_ST_SUPER 8
+#define wxSTC_ST_NIL 9
+#define wxSTC_ST_GLOBAL 10
+#define wxSTC_ST_RETURN 11
+#define wxSTC_ST_SPECIAL 12
+#define wxSTC_ST_KWSEND 13
+#define wxSTC_ST_ASSIGN 14
+#define wxSTC_ST_CHARACTER 15
+#define wxSTC_ST_SPEC_SEL 16
+
+// Lexical states for SCLEX_FLAGSHIP (clipper)
+#define wxSTC_FS_DEFAULT 0
+#define wxSTC_FS_COMMENT 1
+#define wxSTC_FS_COMMENTLINE 2
+#define wxSTC_FS_COMMENTDOC 3
+#define wxSTC_FS_COMMENTLINEDOC 4
+#define wxSTC_FS_COMMENTDOCKEYWORD 5
+#define wxSTC_FS_COMMENTDOCKEYWORDERROR 6
+#define wxSTC_FS_KEYWORD 7
+#define wxSTC_FS_KEYWORD2 8
+#define wxSTC_FS_KEYWORD3 9
+#define wxSTC_FS_KEYWORD4 10
+#define wxSTC_FS_NUMBER 11
+#define wxSTC_FS_STRING 12
+#define wxSTC_FS_PREPROCESSOR 13
+#define wxSTC_FS_OPERATOR 14
+#define wxSTC_FS_IDENTIFIER 15
+#define wxSTC_FS_DATE 16
+#define wxSTC_FS_STRINGEOL 17
+#define wxSTC_FS_CONSTANT 18
+#define wxSTC_FS_ASM 19
+#define wxSTC_FS_LABEL 20
+#define wxSTC_FS_ERROR 21
+#define wxSTC_FS_HEXNUMBER 22
+#define wxSTC_FS_BINNUMBER 23
+
+// Lexical states for SCLEX_CSOUND
+#define wxSTC_CSOUND_DEFAULT 0
+#define wxSTC_CSOUND_COMMENT 1
+#define wxSTC_CSOUND_NUMBER 2
+#define wxSTC_CSOUND_OPERATOR 3
+#define wxSTC_CSOUND_INSTR 4
+#define wxSTC_CSOUND_IDENTIFIER 5
+#define wxSTC_CSOUND_OPCODE 6
+#define wxSTC_CSOUND_HEADERSTMT 7
+#define wxSTC_CSOUND_USERKEYWORD 8
+#define wxSTC_CSOUND_COMMENTBLOCK 9
+#define wxSTC_CSOUND_PARAM 10
+#define wxSTC_CSOUND_ARATE_VAR 11
+#define wxSTC_CSOUND_KRATE_VAR 12
+#define wxSTC_CSOUND_IRATE_VAR 13
+#define wxSTC_CSOUND_GLOBAL_VAR 14
+#define wxSTC_CSOUND_STRINGEOL 15
+
 
 //-----------------------------------------
 // Commands that can be bound to keystrokes
@@ -1679,6 +1928,9 @@ public:
     // Define a marker from a bitmap
     void MarkerDefineBitmap(int markerNumber, const wxBitmap& bmp);
 
+    // Add a set of markers to a line.
+    void MarkerAddSet(int line, int set);
+
     // Set a margin to be either numeric or symbolic.
     void SetMarginType(int margin, int marginType);
 
@@ -1914,6 +2166,20 @@ public:
     // Default is '?' but can be changed if items contain '?'.
     void AutoCompSetTypeSeparator(int separatorCharacter);
 
+    // Set the maximum width, in characters, of auto-completion and user lists.
+    // Set to 0 to autosize to fit longest item, which is the default.
+    void AutoCompSetMaxWidth(int characterCount);
+
+    // Get the maximum width, in characters, of auto-completion and user lists.
+    int AutoCompGetMaxWidth();
+
+    // Set the maximum height, in rows, of auto-completion and user lists.
+    // The default is 5 rows.
+    void AutoCompSetMaxHeight(int rowCount);
+
+    // Set the maximum height, in rows, of auto-completion and user lists.
+    int AutoCompGetMaxHeight();
+
     // Set the number of spaces used for one level of indentation.
     void SetIndent(int indentSize);
 
@@ -2176,6 +2442,9 @@ public:
     // Find the document line of a display line taking hidden lines into account.
     int DocLineFromVisible(int lineDisplay);
 
+    // The number of display lines needed to wrap a document line
+    int WrapCount(int line);
+
     // Set the fold level of a line.
     // This encodes an integer level along with flags indicating whether the
     // line is a header and whether it is effectively white space.
@@ -2290,7 +2559,7 @@ public:
 
     // Retrieve whether the maximum scroll position has the last
     // line at the bottom of the view.
-    int GetEndAtLastLine();
+    bool GetEndAtLastLine();
 
     // Retrieve the height of a particular line of text in pixels.
     int TextHeight(int line);
@@ -2773,10 +3042,28 @@ public:
     // Enlarge the document to a particular size of text bytes.
     void Allocate(int bytes);
 
-    // Find the position of a column on a line taking into account tabs and 
+    // Find the position of a column on a line taking into account tabs and
     // multi-byte characters. If beyond end of line, return line end position.
     int FindColumn(int line, int column);
 
+    // Can the caret preferred x position only be changed by explicit movement commands?
+    bool GetCaretSticky();
+
+    // Stop the caret preferred x position changing when the user types.
+    void SetCaretSticky(bool useCaretStickyBehaviour);
+
+    // Switch between sticky and non-sticky: meant to be bound to a key.
+    void ToggleCaretSticky();
+
+    // Enable/Disable convert-on-paste for line endings
+    void SetPasteConvertEndings(bool convert);
+
+    // Get convert-on-paste setting
+    bool GetPasteConvertEndings();
+
+    // Duplicate the selection. If selection empty duplicate the line containing the caret.
+    void SelectionDuplicate();
+
     // Start notifying the container of all key presses and commands.
     void StartRecord();
 
@@ -2801,6 +3088,20 @@ public:
     // Set the lexing language of the document based on string name.
     void SetLexerLanguage(const wxString& language);
 
+    // Retrieve a 'property' value previously set with SetProperty.
+    wxString GetProperty(const wxString& key);
+
+    // Retrieve a 'property' value previously set with SetProperty,
+    // with '$()' variable replacement on returned buffer.
+    wxString GetPropertyExpanded(const wxString& key);
+
+    // Retrieve a 'property' value previously set with SetProperty,
+    // interpreted as an int AFTER any '$()' variable replacement.
+    int GetPropertyInt(const wxString& key);
+
+    // Retrieve the number of bits the current lexer needs for styling.
+    int GetStyleBitsNeeded();
+
 // END of generated section
 //----------------------------------------------------------------------
 // Others...
@@ -3131,6 +3432,7 @@ BEGIN_DECLARE_EVENT_TYPES()
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_HOTSPOT_CLICK,      1673)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_HOTSPOT_DCLICK,     1674)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_CALLTIP_CLICK,      1675)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_AUTOCOMP_SELECTION, 1676)
 END_DECLARE_EVENT_TYPES()
 #else
     enum {
@@ -3158,7 +3460,8 @@ END_DECLARE_EVENT_TYPES()
         wxEVT_STC_ZOOM,
         wxEVT_STC_HOTSPOT_CLICK,
         wxEVT_STC_HOTSPOT_DCLICK,
-        wxEVT_STC_CALLTIP_CLICK
+        wxEVT_STC_CALLTIP_CLICK,
+        wxEVT_STC_AUTOCOMP_SELECTION
     };
 #endif
 
@@ -3192,7 +3495,7 @@ typedef void (wxEvtHandler::*wxStyledTextEventFunction)(wxStyledTextEvent&);
 #define EVT_STC_HOTSPOT_CLICK(id, fn)      DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_HOTSPOT_CLICK,         id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #define EVT_STC_HOTSPOT_DCLICK(id, fn)     DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_HOTSPOT_DCLICK,        id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #define EVT_STC_CALLTIP_CLICK(id, fn))     DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_CALLTIP_CLICK          id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
-
+#define EVT_STC_AUTOCOMP_SELECTION(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_AUTOCOMP_SELECTION     id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #endif
 
 //----------------------------------------------------------------------
index 9662358d41076051c01c6c6a170675f3dee89ab1..ef6471fac45ca24ed8bdf9e02acc2f4827db6602 100644 (file)
@@ -82,19 +82,24 @@ STCDLL_OBJECTS =  \
        stcdll_LexAsn1.o \
        stcdll_LexBaan.o \
        stcdll_LexBash.o \
+       stcdll_LexBasic.o \
        stcdll_LexBullant.o \
        stcdll_LexCLW.o \
        stcdll_LexCPP.o \
        stcdll_LexCSS.o \
+       stcdll_LexCaml.o \
+       stcdll_LexCsound.o \
        stcdll_LexConf.o \
        stcdll_LexCrontab.o \
        stcdll_LexEScript.o \
        stcdll_LexEiffel.o \
        stcdll_LexErlang.o \
+       stcdll_LexFlagship.o \
        stcdll_LexForth.o \
        stcdll_LexFortran.o \
        stcdll_LexGui4Cli.o \
        stcdll_LexHTML.o \
+       stcdll_LexHaskell.o \
        stcdll_LexKix.o \
        stcdll_LexLisp.o \
        stcdll_LexLout.o \
@@ -112,8 +117,11 @@ STCDLL_OBJECTS =  \
        stcdll_LexPascal.o \
        stcdll_LexPerl.o \
        stcdll_LexPython.o \
+       stcdll_LexRebol.o \
        stcdll_LexRuby.o \
        stcdll_LexSQL.o \
+       stcdll_LexSmalltalk.o \
+       stcdll_LexTADS3.o \
        stcdll_LexScriptol.o \
        stcdll_LexSpecman.o \
        stcdll_LexTeX.o \
@@ -159,19 +167,24 @@ STCLIB_OBJECTS =  \
        stclib_LexAsn1.o \
        stclib_LexBaan.o \
        stclib_LexBash.o \
+       stclib_LexBasic.o \
        stclib_LexBullant.o \
        stclib_LexCLW.o \
        stclib_LexCPP.o \
        stclib_LexCSS.o \
+       stclib_LexCaml.o \
+       stclib_LexCsound.o \
        stclib_LexConf.o \
        stclib_LexCrontab.o \
        stclib_LexEScript.o \
        stclib_LexEiffel.o \
        stclib_LexErlang.o \
+       stclib_LexFlagship.o \
        stclib_LexForth.o \
        stclib_LexFortran.o \
        stclib_LexGui4Cli.o \
        stclib_LexHTML.o \
+       stclib_LexHaskell.o \
        stclib_LexKix.o \
        stclib_LexLisp.o \
        stclib_LexLout.o \
@@ -189,8 +202,11 @@ STCLIB_OBJECTS =  \
        stclib_LexPascal.o \
        stclib_LexPerl.o \
        stclib_LexPython.o \
+       stclib_LexRebol.o \
        stclib_LexRuby.o \
        stclib_LexSQL.o \
+       stclib_LexSmalltalk.o \
+       stclib_LexTADS3.o \
        stclib_LexScriptol.o \
        stclib_LexSpecman.o \
        stclib_LexTeX.o \
@@ -447,6 +463,9 @@ stcdll_LexBaan.o: $(srcdir)/scintilla/src/LexBaan.cxx
 stcdll_LexBash.o: $(srcdir)/scintilla/src/LexBash.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexBash.cxx
 
+stcdll_LexBasic.o: $(srcdir)/scintilla/src/LexBasic.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexBasic.cxx
+
 stcdll_LexBullant.o: $(srcdir)/scintilla/src/LexBullant.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexBullant.cxx
 
@@ -459,6 +478,12 @@ stcdll_LexCPP.o: $(srcdir)/scintilla/src/LexCPP.cxx
 stcdll_LexCSS.o: $(srcdir)/scintilla/src/LexCSS.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexCSS.cxx
 
+stcdll_LexCaml.o: $(srcdir)/scintilla/src/LexCaml.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexCaml.cxx
+
+stcdll_LexCsound.o: $(srcdir)/scintilla/src/LexCsound.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexCsound.cxx
+
 stcdll_LexConf.o: $(srcdir)/scintilla/src/LexConf.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexConf.cxx
 
@@ -474,6 +499,9 @@ stcdll_LexEiffel.o: $(srcdir)/scintilla/src/LexEiffel.cxx
 stcdll_LexErlang.o: $(srcdir)/scintilla/src/LexErlang.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexErlang.cxx
 
+stcdll_LexFlagship.o: $(srcdir)/scintilla/src/LexFlagship.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexFlagship.cxx
+
 stcdll_LexForth.o: $(srcdir)/scintilla/src/LexForth.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexForth.cxx
 
@@ -486,6 +514,9 @@ stcdll_LexGui4Cli.o: $(srcdir)/scintilla/src/LexGui4Cli.cxx
 stcdll_LexHTML.o: $(srcdir)/scintilla/src/LexHTML.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexHTML.cxx
 
+stcdll_LexHaskell.o: $(srcdir)/scintilla/src/LexHaskell.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexHaskell.cxx
+
 stcdll_LexKix.o: $(srcdir)/scintilla/src/LexKix.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexKix.cxx
 
@@ -537,12 +568,21 @@ stcdll_LexPerl.o: $(srcdir)/scintilla/src/LexPerl.cxx
 stcdll_LexPython.o: $(srcdir)/scintilla/src/LexPython.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexPython.cxx
 
+stcdll_LexRebol.o: $(srcdir)/scintilla/src/LexRebol.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexRebol.cxx
+
 stcdll_LexRuby.o: $(srcdir)/scintilla/src/LexRuby.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexRuby.cxx
 
 stcdll_LexSQL.o: $(srcdir)/scintilla/src/LexSQL.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexSQL.cxx
 
+stcdll_LexSmalltalk.o: $(srcdir)/scintilla/src/LexSmalltalk.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexSmalltalk.cxx
+
+stcdll_LexTADS3.o: $(srcdir)/scintilla/src/LexTADS3.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexTADS3.cxx
+
 stcdll_LexScriptol.o: $(srcdir)/scintilla/src/LexScriptol.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexScriptol.cxx
 
@@ -660,6 +700,9 @@ stclib_LexBaan.o: $(srcdir)/scintilla/src/LexBaan.cxx
 stclib_LexBash.o: $(srcdir)/scintilla/src/LexBash.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexBash.cxx
 
+stclib_LexBasic.o: $(srcdir)/scintilla/src/LexBasic.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexBasic.cxx
+
 stclib_LexBullant.o: $(srcdir)/scintilla/src/LexBullant.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexBullant.cxx
 
@@ -672,6 +715,12 @@ stclib_LexCPP.o: $(srcdir)/scintilla/src/LexCPP.cxx
 stclib_LexCSS.o: $(srcdir)/scintilla/src/LexCSS.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexCSS.cxx
 
+stclib_LexCaml.o: $(srcdir)/scintilla/src/LexCaml.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexCaml.cxx
+
+stclib_LexCsound.o: $(srcdir)/scintilla/src/LexCsound.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexCsound.cxx
+
 stclib_LexConf.o: $(srcdir)/scintilla/src/LexConf.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexConf.cxx
 
@@ -687,6 +736,9 @@ stclib_LexEiffel.o: $(srcdir)/scintilla/src/LexEiffel.cxx
 stclib_LexErlang.o: $(srcdir)/scintilla/src/LexErlang.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexErlang.cxx
 
+stclib_LexFlagship.o: $(srcdir)/scintilla/src/LexFlagship.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexFlagship.cxx
+
 stclib_LexForth.o: $(srcdir)/scintilla/src/LexForth.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexForth.cxx
 
@@ -699,6 +751,9 @@ stclib_LexGui4Cli.o: $(srcdir)/scintilla/src/LexGui4Cli.cxx
 stclib_LexHTML.o: $(srcdir)/scintilla/src/LexHTML.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexHTML.cxx
 
+stclib_LexHaskell.o: $(srcdir)/scintilla/src/LexHaskell.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexHaskell.cxx
+
 stclib_LexKix.o: $(srcdir)/scintilla/src/LexKix.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexKix.cxx
 
@@ -750,12 +805,21 @@ stclib_LexPerl.o: $(srcdir)/scintilla/src/LexPerl.cxx
 stclib_LexPython.o: $(srcdir)/scintilla/src/LexPython.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexPython.cxx
 
+stclib_LexRebol.o: $(srcdir)/scintilla/src/LexRebol.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexRebol.cxx
+
 stclib_LexRuby.o: $(srcdir)/scintilla/src/LexRuby.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexRuby.cxx
 
 stclib_LexSQL.o: $(srcdir)/scintilla/src/LexSQL.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexSQL.cxx
 
+stclib_LexSmalltalk.o: $(srcdir)/scintilla/src/LexSmalltalk.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexSmalltalk.cxx
+
+stclib_LexTADS3.o: $(srcdir)/scintilla/src/LexTADS3.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexTADS3.cxx
+
 stclib_LexScriptol.o: $(srcdir)/scintilla/src/LexScriptol.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexScriptol.cxx
 
index 81f172cd71c0c449f534dd379258fc7b0b51aa5b..5d7948423b3685ef92d4551c003ad19a278a87d5 100644 (file)
@@ -12,6 +12,7 @@
 #include "wx/mstream.h"
 #include "wx/image.h"
 #include "wx/imaglist.h"
+#include "wx/tokenzr.h"
 
 #include "Platform.h"
 #include "PlatWX.h"
@@ -686,7 +687,7 @@ private:
     CallBackAction      doubleClickAction;
     void*               doubleClickActionData;
 public:
-    wxSTCListBoxWin(wxWindow* parent, wxWindowID id) :
+    wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point location) :
         wxPopupWindow(parent, wxBORDER_NONE)
     {
         SetBackgroundColour(*wxBLACK);  // for our simple border
@@ -804,8 +805,8 @@ private:
     CallBackAction      doubleClickAction;
     void*               doubleClickActionData;
 public:
-    wxSTCListBoxWin(wxWindow* parent, wxWindowID id) :
-        wxWindow(parent, id, wxDefaultPosition, wxSize(0,0), wxSIMPLE_BORDER )
+    wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point location) :
+        wxWindow(parent, id, wxPoint(location.x, location.y), wxSize(0,0), wxSIMPLE_BORDER )
     {
 
         lv = new wxSTCListBox(this, id, wxDefaultPosition, wxDefaultSize,
@@ -919,6 +920,7 @@ private:
     int                 desiredVisibleRows;
     int                 aveCharWidth;
     int                 maxStrWidth;
+    Point               location;       // Caret location at which the list is opened
     wxImageList*        imgList;
     wxArrayInt*         imgTypeMap;
 
@@ -927,13 +929,15 @@ public:
     ~ListBoxImpl();
 
     virtual void SetFont(Font &font);
-    virtual void Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_);
+    virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_);
     virtual void SetAverageCharWidth(int width);
     virtual void SetVisibleRows(int rows);
+    virtual int GetVisibleRows() const;
     virtual PRectangle GetDesiredRect();
     virtual int CaretFromEdge();
     virtual void Clear();
     virtual void Append(char *s, int type = -1);
+            void Append(const wxString& text, int type);
     virtual int Length();
     virtual void Select(int n);
     virtual int GetSelection();
@@ -942,7 +946,7 @@ public:
     virtual void RegisterImage(int type, const char *xpm_data);
     virtual void ClearRegisteredImages();
     virtual void SetDoubleClickAction(CallBackAction, void *);
-
+    virtual void SetList(const char* list, char separator, char typesep);
 };
 
 
@@ -970,11 +974,12 @@ void ListBoxImpl::SetFont(Font &font) {
 }
 
 
-void ListBoxImpl::Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_) {
+void ListBoxImpl::Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_) {
+    location = location_;
     lineHeight =  lineHeight_;
     unicodeMode = unicodeMode_;
     maxStrWidth = 0;
-    id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID);
+    id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID, location);
     if (imgList != NULL)
         GETLB(id)->SetImageList(imgList, wxIMAGE_LIST_SMALL);
 }
@@ -990,10 +995,14 @@ void ListBoxImpl::SetVisibleRows(int rows) {
 }
 
 
+int ListBoxImpl::GetVisibleRows() const {
+    return desiredVisibleRows;
+}
+
 PRectangle ListBoxImpl::GetDesiredRect() {
     // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
     // the max size in Append and calculate it here...
-    int maxw = maxStrWidth;
+    int maxw = maxStrWidth * aveCharWidth;
     int maxh ;
 
     // give it a default if there are no lines, and/or add a bit more
@@ -1039,13 +1048,14 @@ void ListBoxImpl::Clear() {
 
 
 void ListBoxImpl::Append(char *s, int type) {
-    wxString text = stc2wx(s);
+    Append(stc2wx(s), type);
+}
+
+void ListBoxImpl::Append(const wxString& text, int type) {
     long count  = GETLB(id)->GetItemCount();
     long itemID  = GETLB(id)->InsertItem(count, wxEmptyString);
     GETLB(id)->SetItem(itemID, 1, text);
-    int itemWidth = 0;
-    GETLB(id)->GetTextExtent(text, &itemWidth, NULL);
-    maxStrWidth = wxMax(maxStrWidth, itemWidth);
+    maxStrWidth = wxMax(maxStrWidth, text.Length());
     if (type != -1) {
         wxCHECK_RET(imgTypeMap, wxT("Unexpected NULL imgTypeMap"));
         long idx = imgTypeMap->Item(type);
@@ -1053,6 +1063,23 @@ void ListBoxImpl::Append(char *s, int type) {
     }
 }
 
+void ListBoxImpl::SetList(const char* list, char separator, char typesep) {
+    GETLB(id)->Freeze();
+    Clear();    
+    wxStringTokenizer tkzr(stc2wx(list), (wxChar)separator);
+    while ( tkzr.HasMoreTokens() ) {
+        wxString token = tkzr.GetNextToken();
+        long type = -1;
+        int pos = token.Find(typesep);
+        if (pos != -1) {
+            token.Mid(pos+1).ToLong(&type);
+            token.Truncate(pos);
+        }
+        Append(token, (int)type);
+    }
+    GETLB(id)->Thaw();
+}
+
 
 int ListBoxImpl::Length() {
     return GETLB(id)->GetItemCount();
@@ -1133,7 +1160,6 @@ void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data) {
 }
 
 
-
 ListBox::ListBox() {
 }
 
index 4e0afbb12919223ce91886da00d085fc8315d8bc..62d7a455184e809c0e68b5bbabeae03f90d4db64 100644 (file)
@@ -293,7 +293,12 @@ methodOverrideMap = {
     'AutoCGetTypeSeparator' : ('AutoCompGetTypeSeparator', 0, 0, 0),
     'AutoCSetTypeSeparator' : ('AutoCompSetTypeSeparator', 0, 0, 0),
     'AutoCGetCurrent'       : ('AutoCompGetCurrent', 0, 0, 0),
-
+    'AutoCSetMaxWidth'      : ('AutoCompSetMaxWidth', 0, 0, 0),
+    'AutoCGetMaxWidth'      : ('AutoCompGetMaxWidth', 0, 0, 0),
+    'AutoCSetMaxHeight'     : ('AutoCompSetMaxHeight', 0, 0, 0),
+    'AutoCGetMaxHeight'     : ('AutoCompGetMaxHeight', 0, 0, 0),
+    'AutoCGetMaxHeight'     : ('AutoCompGetMaxHeight', 0, 0, 0),
+    
     'RegisterImage' :
     (0,
      '''void %s(int type, const wxBitmap& bmp);''',
@@ -519,7 +524,45 @@ methodOverrideMap = {
     'TargetAsUTF8' :       ( None, 0, 0, 0),
     'SetLengthForEncode' : ( None, 0, 0, 0),
     'EncodedFromUTF8' :    ( None, 0, 0, 0),
-    
+
+
+    'GetProperty' :
+    (0,
+     'wxString %s(const wxString& key);',
+
+     '''wxString %s(const wxString& key) {
+         int len = SendMsg(SCI_GETPROPERTY, (long)(const char*)wx2stc(key), NULL);
+         if (!len) return wxEmptyString;
+
+         wxMemoryBuffer mbuf(len+1);
+         char* buf = (char*)mbuf.GetWriteBuf(len+1);
+         SendMsg(%s, (long)(const char*)wx2stc(key), (long)buf);
+         mbuf.UngetWriteBuf(len);
+         mbuf.AppendByte(0);
+         return stc2wx(buf);''',
+     ("Retrieve a 'property' value previously set with SetProperty.",)),
+
+    'GetPropertyExpanded' :
+    (0,
+     'wxString %s(const wxString& key);',
+
+     '''wxString %s(const wxString& key) {
+         int len = SendMsg(SCI_GETPROPERTYEXPANDED, (long)(const char*)wx2stc(key), NULL);
+         if (!len) return wxEmptyString;
+
+         wxMemoryBuffer mbuf(len+1);
+         char* buf = (char*)mbuf.GetWriteBuf(len+1);
+         SendMsg(%s, (long)(const char*)wx2stc(key), (long)buf);
+         mbuf.UngetWriteBuf(len);
+         mbuf.AppendByte(0);
+         return stc2wx(buf);''',
+     ("Retrieve a 'property' value previously set with SetProperty,",
+      "with '$()' variable replacement on returned buffer.")),
+
+    'GetPropertyInt'   : (0, 0, 0,
+       ("Retrieve a 'property' value previously set with SetProperty,",
+        "interpreted as an int AFTER any '$()' variable replacement.")),
+
 
     'GetDocPointer' :
     (0,
index fce427d5d11dfc75b6bf312ea3f3198f8b021914..3dfc8698517e4711d3bec7152853bc8f88ad1f39 100644 (file)
@@ -3,5 +3,5 @@ scintilla/include directories from the Scintilla/SCiTE source
 distribution.  All other code needed to implement Scintilla on top of
 wxWindows is located in the directory above this one.
 
-The current version of the Scintilla code is 1.62
+The current version of the Scintilla code is 1.67
 
index df4e870c580f507203f57f61f2cc58a7af04a2fe..059ac0da0fd881dbe31aebe03c584cb368837f39 100644 (file)
@@ -20,21 +20,29 @@ protected:
        LexerFunction fnLexer;
        LexerFunction fnFolder;
        const char * const * wordListDescriptions;
+       int styleBits;
 
        static const LexerModule *base;
        static int nextLanguage;
 
 public:
        const char *languageName;
-       LexerModule(int language_, LexerFunction fnLexer_, 
-               const char *languageName_=0, LexerFunction fnFolder_=0,
-               const char * const wordListDescriptions_[] = NULL);
+       LexerModule(int language_, 
+               LexerFunction fnLexer_, 
+               const char *languageName_=0, 
+               LexerFunction fnFolder_=0,
+               const char * const wordListDescriptions_[] = NULL,
+               int styleBits_=5);
+       virtual ~LexerModule() {
+       }
        int GetLanguage() const { return language; }
 
        // -1 is returned if no WordList information is available
        int GetNumWordLists() const;
        const char *GetWordListDescription(int index) const;
 
+       int GetStyleBitsNeeded() const;
+
        virtual void Lex(unsigned int startPos, int lengthDoc, int initStyle,
                   WordList *keywordlists[], Accessor &styler) const;
        virtual void Fold(unsigned int startPos, int lengthDoc, int initStyle,
index 1e3bd69d752e263134a739f8cda9eb722a11505c..88a05272fdc66b0d577e5668c1b5bef4392e8096 100644 (file)
@@ -393,9 +393,10 @@ public:
        static ListBox *Allocate();
 
        virtual void SetFont(Font &font)=0;
-       virtual void Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_)=0;
+       virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_)=0;
        virtual void SetAverageCharWidth(int width)=0;
        virtual void SetVisibleRows(int rows)=0;
+       virtual int GetVisibleRows() const=0;
        virtual PRectangle GetDesiredRect()=0;
        virtual int CaretFromEdge()=0;
        virtual void Clear()=0;
@@ -408,6 +409,7 @@ public:
        virtual void RegisterImage(int type, const char *xpm_data)=0;
        virtual void ClearRegisteredImages()=0;
        virtual void SetDoubleClickAction(CallBackAction, void *)=0;
+       virtual void SetList(const char* list, char separator, char typesep)=0;
 };
 
 /**
index 32aea8a0c7f59ce6b7f7873d3d47593e44c9e060..e38de7dc408f106970257fff1feafcf300655b12 100644 (file)
@@ -29,6 +29,7 @@ protected:
        Property *props[hashRoots];
        Property *enumnext;
        int enumhash;
+       static bool caseSensitiveFilenames;
        static unsigned int HashString(const char *s, size_t len) {
                unsigned int ret = 0;
                while (len--) {
@@ -58,9 +59,12 @@ public:
        char *ToString();       // Caller must delete[] the return value
        bool GetFirst(char **key, char **val);
        bool GetNext(char **key, char **val);
+       static void SetCaseSensitiveFilenames(bool caseSensitiveFilenames_) {
+               caseSensitiveFilenames = caseSensitiveFilenames_;
+       }
 
 private:
-       // copy-value semantics not implemented 
+       // copy-value semantics not implemented
        PropSet(const PropSet &copy);
        void operator=(const PropSet &assign);
 };
@@ -76,9 +80,11 @@ public:
        int len;
        bool onlyLineEnds;      ///< Delimited by any white space or only line ends
        bool sorted;
+       bool sortedNoCase;
        int starts[256];
        WordList(bool onlyLineEnds_ = false) :
-               words(0), wordsNoCase(0), list(0), len(0), onlyLineEnds(onlyLineEnds_), sorted(false) {}
+               words(0), wordsNoCase(0), list(0), len(0), onlyLineEnds(onlyLineEnds_),
+               sorted(false), sortedNoCase(false) {}
        ~WordList() { Clear(); }
        operator bool() { return len ? true : false; }
        char *operator[](int ind) { return words[ind]; }
@@ -87,6 +93,7 @@ public:
        char *Allocate(int size);
        void SetFromAllocated();
        bool InList(const char *s);
+       bool InListAbbreviated(const char *s, const char marker);
        const char *GetNearestWord(const char *wordStart, int searchLen,
                bool ignoreCase = false, SString wordCharacters="", int wordIndex = -1);
        char *GetNearestWords(const char *wordStart, int searchLen,
index 5c2a93d33b7737cb1a28c3b3bbe8680f5bf35409..38a206ccf2240224ce1dbdd3236c727ab54babc9 100644 (file)
@@ -197,7 +197,7 @@ public:
        bool operator!=(const char *sOther) const {
                return !operator==(sOther);
        }
-       bool contains(char ch) {
+       bool contains(char ch) const {
                return (s && *s) ? strchr(s, ch) != 0 : false;
        }
        void setsizegrowth(lenpos_t sizeGrowth_) {
@@ -253,7 +253,7 @@ public:
        bool startswith(const char *prefix);
        bool endswith(const char *suffix);
        int search(const char *sFind, lenpos_t start=0) const;
-       bool contains(const char *sFind) {
+       bool contains(const char *sFind) const {
                return search(sFind) >= 0;
        }
        int substitute(char chFind, char chReplace);
index ce50a7fab5fed63a4140a473e85a4ee23f01af68..9c7fc8a7ddae27b2abe9c0cb09fab060ec36ab07 100644 (file)
@@ -43,8 +43,6 @@
 #define SCLEX_NNCRONTAB 26
 #define SCLEX_BULLANT 27
 #define SCLEX_VBSCRIPT 28
-#define SCLEX_ASP 29
-#define SCLEX_PHP 30
 #define SCLEX_BAAN 31
 #define SCLEX_MATLAB 32
 #define SCLEX_SCRIPTOL 33
 #define SCLEX_BASH 62
 #define SCLEX_ASN1 63
 #define SCLEX_VHDL 64
+#define SCLEX_CAML 65
+#define SCLEX_BLITZBASIC 66
+#define SCLEX_PUREBASIC 67
+#define SCLEX_HASKELL 68
+#define SCLEX_PHPSCRIPT 69
+#define SCLEX_TADS3 70
+#define SCLEX_REBOL 71
+#define SCLEX_SMALLTALK 72
+#define SCLEX_FLAGSHIP 73
+#define SCLEX_CSOUND 74
+#define SCLEX_FREEBASIC 75
 #define SCLEX_AUTOMATIC 1000
 #define SCE_P_DEFAULT 0
 #define SCE_P_COMMENTLINE 1
 #define SCE_P_IDENTIFIER 11
 #define SCE_P_COMMENTBLOCK 12
 #define SCE_P_STRINGEOL 13
+#define SCE_P_WORD2 14
+#define SCE_P_DECORATOR 15
 #define SCE_C_DEFAULT 0
 #define SCE_C_COMMENT 1
 #define SCE_C_COMMENTLINE 2
 #define SCE_PL_ARRAY 13
 #define SCE_PL_HASH 14
 #define SCE_PL_SYMBOLTABLE 15
+#define SCE_PL_VARIABLE_INDEXER 16
 #define SCE_PL_REGEX 17
 #define SCE_PL_REGSUBST 18
 #define SCE_PL_LONGQUOTE 19
 #define SCE_PL_STRING_QX 28
 #define SCE_PL_STRING_QR 29
 #define SCE_PL_STRING_QW 30
+#define SCE_PL_POD_VERB 31
+#define SCE_RB_DEFAULT 0
+#define SCE_RB_ERROR 1
+#define SCE_RB_COMMENTLINE 2
+#define SCE_RB_POD 3
+#define SCE_RB_NUMBER 4
+#define SCE_RB_WORD 5
+#define SCE_RB_STRING 6
+#define SCE_RB_CHARACTER 7
+#define SCE_RB_CLASSNAME 8
+#define SCE_RB_DEFNAME 9
+#define SCE_RB_OPERATOR 10
+#define SCE_RB_IDENTIFIER 11
+#define SCE_RB_REGEX 12
+#define SCE_RB_GLOBAL 13
+#define SCE_RB_SYMBOL 14
+#define SCE_RB_MODULE_NAME 15
+#define SCE_RB_INSTANCE_VAR 16
+#define SCE_RB_CLASS_VAR 17
+#define SCE_RB_BACKTICKS 18
+#define SCE_RB_DATASECTION 19
+#define SCE_RB_HERE_DELIM 20
+#define SCE_RB_HERE_Q 21
+#define SCE_RB_HERE_QQ 22
+#define SCE_RB_HERE_QX 23
+#define SCE_RB_STRING_Q 24
+#define SCE_RB_STRING_QQ 25
+#define SCE_RB_STRING_QX 26
+#define SCE_RB_STRING_QR 27
+#define SCE_RB_STRING_QW 28
+#define SCE_RB_WORD_DEMOTED 29
+#define SCE_RB_STDIN 30
+#define SCE_RB_STDOUT 31
+#define SCE_RB_STDERR 40
+#define SCE_RB_UPPER_BOUND 41
 #define SCE_B_DEFAULT 0
 #define SCE_B_COMMENT 1
 #define SCE_B_NUMBER 2
 #define SCE_B_KEYWORD4 12
 #define SCE_B_CONSTANT 13
 #define SCE_B_ASM 14
+#define SCE_B_LABEL 15
+#define SCE_B_ERROR 16
+#define SCE_B_HEXNUMBER 17
+#define SCE_B_BINNUMBER 18
 #define SCE_PROPS_DEFAULT 0
 #define SCE_PROPS_COMMENT 1
 #define SCE_PROPS_SECTION 2
 #define SCE_LISP_COMMENT 1
 #define SCE_LISP_NUMBER 2
 #define SCE_LISP_KEYWORD 3
+#define SCE_LISP_KEYWORD_KW 4
+#define SCE_LISP_SYMBOL 5
 #define SCE_LISP_STRING 6
 #define SCE_LISP_STRINGEOL 8
 #define SCE_LISP_IDENTIFIER 9
 #define SCE_LISP_OPERATOR 10
+#define SCE_LISP_SPECIAL 11
+#define SCE_LISP_MULTI_COMMENT 12
 #define SCE_EIFFEL_DEFAULT 0
 #define SCE_EIFFEL_COMMENTLINE 1
 #define SCE_EIFFEL_NUMBER 2
 #define SCE_CSS_DOUBLESTRING 13
 #define SCE_CSS_SINGLESTRING 14
 #define SCE_CSS_IDENTIFIER2 15
+#define SCE_CSS_ATTRIBUTE 16
 #define SCE_POV_DEFAULT 0
 #define SCE_POV_COMMENT 1
 #define SCE_POV_COMMENTLINE 2
 #define SCE_NSIS_MACRODEF 12
 #define SCE_NSIS_STRINGVAR 13
 #define SCE_NSIS_NUMBER 14
+#define SCE_NSIS_SECTIONGROUP 15
+#define SCE_NSIS_PAGEEX 16
+#define SCE_NSIS_FUNCTIONDEF 17
+#define SCE_NSIS_COMMENTBOX 18
 #define SCE_MMIXAL_LEADWS 0
 #define SCE_MMIXAL_COMMENT 1
 #define SCE_MMIXAL_LABEL 2
 #define SCE_CLW_PICTURE_STRING 7
 #define SCE_CLW_KEYWORD 8
 #define SCE_CLW_COMPILER_DIRECTIVE 9
-#define SCE_CLW_BUILTIN_PROCEDURES_FUNCTION 10
-#define SCE_CLW_STRUCTURE_DATA_TYPE 11
-#define SCE_CLW_ATTRIBUTE 12
-#define SCE_CLW_STANDARD_EQUATE 13
-#define SCE_CLW_ERROR 14
+#define SCE_CLW_RUNTIME_EXPRESSIONS 10
+#define SCE_CLW_BUILTIN_PROCEDURES_FUNCTION 11
+#define SCE_CLW_STRUCTURE_DATA_TYPE 12
+#define SCE_CLW_ATTRIBUTE 13
+#define SCE_CLW_STANDARD_EQUATE 14
+#define SCE_CLW_ERROR 15
+#define SCE_CLW_DEPRECATED 16
 #define SCE_LOT_DEFAULT 0
 #define SCE_LOT_HEADER 1
 #define SCE_LOT_BREAK 2
 #define SCE_AU3_SENT 10
 #define SCE_AU3_PREPROCESSOR 11
 #define SCE_AU3_SPECIAL 12
+#define SCE_AU3_EXPAND 13
+#define SCE_AU3_COMOBJ 14
 #define SCE_APDL_DEFAULT 0
 #define SCE_APDL_COMMENT 1
 #define SCE_APDL_COMMENTBLOCK 2
 #define SCE_VHDL_STDPACKAGE 12
 #define SCE_VHDL_STDTYPE 13
 #define SCE_VHDL_USERWORD 14
+#define SCE_CAML_DEFAULT 0
+#define SCE_CAML_IDENTIFIER 1
+#define SCE_CAML_TAGNAME 2
+#define SCE_CAML_KEYWORD 3
+#define SCE_CAML_KEYWORD2 4
+#define SCE_CAML_KEYWORD3 5
+#define SCE_CAML_LINENUM 6
+#define SCE_CAML_OPERATOR 7
+#define SCE_CAML_NUMBER 8
+#define SCE_CAML_CHAR 9
+#define SCE_CAML_STRING 11
+#define SCE_CAML_COMMENT 12
+#define SCE_CAML_COMMENT1 13
+#define SCE_CAML_COMMENT2 14
+#define SCE_CAML_COMMENT3 15
+#define SCE_HA_DEFAULT 0
+#define SCE_HA_IDENTIFIER 1
+#define SCE_HA_KEYWORD 2
+#define SCE_HA_NUMBER 3
+#define SCE_HA_STRING 4
+#define SCE_HA_CHARACTER 5
+#define SCE_HA_CLASS 6
+#define SCE_HA_MODULE 7
+#define SCE_HA_CAPITAL 8
+#define SCE_HA_DATA 9
+#define SCE_HA_IMPORT 10
+#define SCE_HA_OPERATOR 11
+#define SCE_HA_INSTANCE 12
+#define SCE_HA_COMMENTLINE 13
+#define SCE_HA_COMMENTBLOCK 14
+#define SCE_HA_COMMENTBLOCK2 15
+#define SCE_HA_COMMENTBLOCK3 16
+#define SCE_T3_DEFAULT 0
+#define SCE_T3_X_DEFAULT 1
+#define SCE_T3_PREPROCESSOR 2
+#define SCE_T3_BLOCK_COMMENT 3
+#define SCE_T3_LINE_COMMENT 4
+#define SCE_T3_OPERATOR 5
+#define SCE_T3_KEYWORD 6
+#define SCE_T3_NUMBER 7
+#define SCE_T3_IDENTIFIER 8
+#define SCE_T3_S_STRING 9
+#define SCE_T3_D_STRING 10
+#define SCE_T3_X_STRING 11
+#define SCE_T3_LIB_DIRECTIVE 12
+#define SCE_T3_MSG_PARAM 13
+#define SCE_T3_HTML_TAG 14
+#define SCE_T3_HTML_DEFAULT 15
+#define SCE_T3_HTML_STRING 16
+#define SCE_T3_USER1 17
+#define SCE_T3_USER2 18
+#define SCE_T3_USER3 19
+#define SCE_REBOL_DEFAULT 0
+#define SCE_REBOL_COMMENTLINE 1
+#define SCE_REBOL_COMMENTBLOCK 2
+#define SCE_REBOL_PREFACE 3
+#define SCE_REBOL_OPERATOR 4
+#define SCE_REBOL_CHARACTER 5
+#define SCE_REBOL_QUOTEDSTRING 6
+#define SCE_REBOL_BRACEDSTRING 7
+#define SCE_REBOL_NUMBER 8
+#define SCE_REBOL_PAIR 9
+#define SCE_REBOL_TUPLE 10
+#define SCE_REBOL_BINARY 11
+#define SCE_REBOL_MONEY 12
+#define SCE_REBOL_ISSUE 13
+#define SCE_REBOL_TAG 14
+#define SCE_REBOL_FILE 15
+#define SCE_REBOL_EMAIL 16
+#define SCE_REBOL_URL 17
+#define SCE_REBOL_DATE 18
+#define SCE_REBOL_TIME 19
+#define SCE_REBOL_IDENTIFIER 20
+#define SCE_REBOL_WORD 21
+#define SCE_REBOL_WORD2 22
+#define SCE_REBOL_WORD3 23
+#define SCE_REBOL_WORD4 24
+#define SCE_REBOL_WORD5 25
+#define SCE_REBOL_WORD6 26
+#define SCE_REBOL_WORD7 27
+#define SCE_REBOL_WORD8 28
+#define SCE_SQL_DEFAULT 0
+#define SCE_SQL_COMMENT 1
+#define SCE_SQL_COMMENTLINE 2
+#define SCE_SQL_COMMENTDOC 3
+#define SCE_SQL_NUMBER 4
+#define SCE_SQL_WORD 5
+#define SCE_SQL_STRING 6
+#define SCE_SQL_CHARACTER 7
+#define SCE_SQL_SQLPLUS 8
+#define SCE_SQL_SQLPLUS_PROMPT 9
+#define SCE_SQL_OPERATOR 10
+#define SCE_SQL_IDENTIFIER 11
+#define SCE_SQL_SQLPLUS_COMMENT 13
+#define SCE_SQL_COMMENTLINEDOC 15
+#define SCE_SQL_WORD2 16
+#define SCE_SQL_COMMENTDOCKEYWORD 17
+#define SCE_SQL_COMMENTDOCKEYWORDERROR 18
+#define SCE_SQL_USER1 19
+#define SCE_SQL_USER2 20
+#define SCE_SQL_USER3 21
+#define SCE_SQL_USER4 22
+#define SCE_SQL_QUOTEDIDENTIFIER 23
+#define SCE_ST_DEFAULT 0
+#define SCE_ST_STRING 1
+#define SCE_ST_NUMBER 2
+#define SCE_ST_COMMENT 3
+#define SCE_ST_SYMBOL 4
+#define SCE_ST_BINARY 5
+#define SCE_ST_BOOL 6
+#define SCE_ST_SELF 7
+#define SCE_ST_SUPER 8
+#define SCE_ST_NIL 9
+#define SCE_ST_GLOBAL 10
+#define SCE_ST_RETURN 11
+#define SCE_ST_SPECIAL 12
+#define SCE_ST_KWSEND 13
+#define SCE_ST_ASSIGN 14
+#define SCE_ST_CHARACTER 15
+#define SCE_ST_SPEC_SEL 16
+#define SCE_FS_DEFAULT 0
+#define SCE_FS_COMMENT 1
+#define SCE_FS_COMMENTLINE 2
+#define SCE_FS_COMMENTDOC 3
+#define SCE_FS_COMMENTLINEDOC 4
+#define SCE_FS_COMMENTDOCKEYWORD 5
+#define SCE_FS_COMMENTDOCKEYWORDERROR 6
+#define SCE_FS_KEYWORD 7
+#define SCE_FS_KEYWORD2 8
+#define SCE_FS_KEYWORD3 9
+#define SCE_FS_KEYWORD4 10
+#define SCE_FS_NUMBER 11
+#define SCE_FS_STRING 12
+#define SCE_FS_PREPROCESSOR 13
+#define SCE_FS_OPERATOR 14
+#define SCE_FS_IDENTIFIER 15
+#define SCE_FS_DATE 16
+#define SCE_FS_STRINGEOL 17
+#define SCE_FS_CONSTANT 18
+#define SCE_FS_ASM 19
+#define SCE_FS_LABEL 20
+#define SCE_FS_ERROR 21
+#define SCE_FS_HEXNUMBER 22
+#define SCE_FS_BINNUMBER 23
+#define SCE_CSOUND_DEFAULT 0
+#define SCE_CSOUND_COMMENT 1
+#define SCE_CSOUND_NUMBER 2
+#define SCE_CSOUND_OPERATOR 3
+#define SCE_CSOUND_INSTR 4
+#define SCE_CSOUND_IDENTIFIER 5
+#define SCE_CSOUND_OPCODE 6
+#define SCE_CSOUND_HEADERSTMT 7
+#define SCE_CSOUND_USERKEYWORD 8
+#define SCE_CSOUND_COMMENTBLOCK 9
+#define SCE_CSOUND_PARAM 10
+#define SCE_CSOUND_ARATE_VAR 11
+#define SCE_CSOUND_KRATE_VAR 12
+#define SCE_CSOUND_IRATE_VAR 13
+#define SCE_CSOUND_GLOBAL_VAR 14
+#define SCE_CSOUND_STRINGEOL 15
+#define SCLEX_ASP 29
+#define SCLEX_PHP 30
 //--Autogenerated -- end of section automatically generated from Scintilla.iface
 
 #endif
index fb6c674a7ad84bf29d41e68ea350a830004a0585..b4ed329f726618133d7604223b6660399d207c18 100644 (file)
 #ifndef SCINTILLA_H
 #define SCINTILLA_H
 
-#ifdef PLAT_WIN
+#if LCCWIN
+typedef BOOL bool;
+#endif
+
 #if PLAT_WIN
 // Return false on failure:
 bool Scintilla_RegisterClasses(void *hInstance);
 bool Scintilla_ReleaseResources();
 #endif
-#endif
 int Scintilla_LinkLexers();
 
 // Here should be placed typedefs for uptr_t, an unsigned integer type large enough to
 // hold a pointer and sptr_t, a signed integer large enough to hold a pointer.
 // May need to be changed for 64 bit platforms.
-#ifdef _MSC_VER
 #if _MSC_VER >= 1300
 #include <BaseTsd.h>
 #endif
-#endif
 #ifdef MAXULONG_PTR
 typedef ULONG_PTR uptr_t;
 typedef LONG_PTR sptr_t;
@@ -117,6 +117,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SC_MARK_DOTDOTDOT 23
 #define SC_MARK_ARROWS 24
 #define SC_MARK_PIXMAP 25
+#define SC_MARK_FULLRECT 26
 #define SC_MARK_CHARACTER 10000
 #define SC_MARKNUM_FOLDEREND 25
 #define SC_MARKNUM_FOLDEROPENMID 26
@@ -136,6 +137,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_MARKERNEXT 2047
 #define SCI_MARKERPREVIOUS 2048
 #define SCI_MARKERDEFINEPIXMAP 2049
+#define SCI_MARKERADDSET 2466
 #define SC_MARGIN_SYMBOL 0
 #define SC_MARGIN_NUMBER 1
 #define SCI_SETMARGINTYPEN 2240
@@ -165,6 +167,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SC_CHARSET_MAC 77
 #define SC_CHARSET_OEM 255
 #define SC_CHARSET_RUSSIAN 204
+#define SC_CHARSET_CYRILLIC 1251
 #define SC_CHARSET_SHIFTJIS 128
 #define SC_CHARSET_SYMBOL 2
 #define SC_CHARSET_TURKISH 162
@@ -173,6 +176,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SC_CHARSET_ARABIC 178
 #define SC_CHARSET_VIETNAMESE 163
 #define SC_CHARSET_THAI 222
+#define SC_CHARSET_8859_15 1000
 #define SCI_STYLECLEARALL 2050
 #define SCI_STYLESETFORE 2051
 #define SCI_STYLESETBACK 2052
@@ -255,6 +259,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_CLEARREGISTEREDIMAGES 2408
 #define SCI_AUTOCGETTYPESEPARATOR 2285
 #define SCI_AUTOCSETTYPESEPARATOR 2286
+#define SCI_AUTOCSETMAXWIDTH 2208
+#define SCI_AUTOCGETMAXWIDTH 2209
+#define SCI_AUTOCSETMAXHEIGHT 2210
+#define SCI_AUTOCGETMAXHEIGHT 2211
 #define SCI_SETINDENT 2122
 #define SCI_GETINDENT 2123
 #define SCI_SETUSETABS 2124
@@ -352,6 +360,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_CALLTIPSETFOREHLT 2207
 #define SCI_VISIBLEFROMDOCLINE 2220
 #define SCI_DOCLINEFROMVISIBLE 2221
+#define SCI_WRAPCOUNT 2235
 #define SC_FOLDLEVELBASE 0x400
 #define SC_FOLDLEVELWHITEFLAG 0x1000
 #define SC_FOLDLEVELHEADERFLAG 0x2000
@@ -390,6 +399,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_WORDENDPOSITION 2267
 #define SC_WRAP_NONE 0
 #define SC_WRAP_WORD 1
+#define SC_WRAP_CHAR 2
 #define SCI_SETWRAPMODE 2268
 #define SCI_GETWRAPMODE 2269
 #define SC_WRAPVISUALFLAG_NONE 0x0000
@@ -591,6 +601,12 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_SETLENGTHFORENCODE 2448
 #define SCI_ENCODEDFROMUTF8 2449
 #define SCI_FINDCOLUMN 2456
+#define SCI_GETCARETSTICKY 2457
+#define SCI_SETCARETSTICKY 2458
+#define SCI_TOGGLECARETSTICKY 2459
+#define SCI_SETPASTECONVERTENDINGS 2467
+#define SCI_GETPASTECONVERTENDINGS 2468
+#define SCI_SELECTIONDUPLICATE 2469
 #define SCI_STARTRECORD 3001
 #define SCI_STOPRECORD 3002
 #define SCI_SETLEXER 4001
@@ -601,6 +617,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_SETKEYWORDS 4005
 #define SCI_SETLEXERLANGUAGE 4006
 #define SCI_LOADLEXERLIBRARY 4007
+#define SCI_GETPROPERTY 4008
+#define SCI_GETPROPERTYEXPANDED 4009
+#define SCI_GETPROPERTYINT 4010
+#define SCI_GETSTYLEBITSNEEDED 4011
 #define SC_MOD_INSERTTEXT 0x1
 #define SC_MOD_DELETETEXT 0x2
 #define SC_MOD_CHANGESTYLE 0x4
@@ -608,11 +628,13 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SC_PERFORMED_USER 0x10
 #define SC_PERFORMED_UNDO 0x20
 #define SC_PERFORMED_REDO 0x40
+#define SC_MULTISTEPUNDOREDO 0x80
 #define SC_LASTSTEPINUNDOREDO 0x100
 #define SC_MOD_CHANGEMARKER 0x200
 #define SC_MOD_BEFOREINSERT 0x400
 #define SC_MOD_BEFOREDELETE 0x800
-#define SC_MODEVENTMASKALL 0xF77
+#define SC_MULTILINEUNDOREDO 0x1000
+#define SC_MODEVENTMASKALL 0x1FFF
 #define SCEN_CHANGE 768
 #define SCEN_SETFOCUS 512
 #define SCEN_KILLFOCUS 256
@@ -633,6 +655,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCK_ADD 310
 #define SCK_SUBTRACT 311
 #define SCK_DIVIDE 312
+#define SCMOD_NORM 0
 #define SCMOD_SHIFT 1
 #define SCMOD_CTRL 2
 #define SCMOD_ALT 4
@@ -657,6 +680,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCN_HOTSPOTCLICK 2019
 #define SCN_HOTSPOTDOUBLECLICK 2020
 #define SCN_CALLTIPCLICK 2021
+#define SCN_AUTOCSELECTION 2022
 //--Autogenerated -- end of section automatically generated from Scintilla.iface
 
 // These structures are defined to be exactly the same shape as the Win32
@@ -695,11 +719,11 @@ struct RangeToFormat {
 #endif
 
 struct NotifyHeader {
-       // hwndFrom is really an environment specifc window handle or pointer
+       // Compatible with Windows NMHDR.
+       // hwndFrom is really an environment specific window handle or pointer
        // but most clients of Scintilla.h do not have this type visible.
-       //WindowID hwndFrom;
        void *hwndFrom;
-       unsigned int idFrom;
+       uptr_t idFrom;
        unsigned int code;
 };
 
@@ -709,7 +733,7 @@ struct SCNotification {
        int ch;         // SCN_CHARADDED, SCN_KEY
        int modifiers;  // SCN_KEY
        int modificationType;   // SCN_MODIFIED
-       const char *text;       // SCN_MODIFIED
+       const char *text;       // SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION
        int length;             // SCN_MODIFIED
        int linesAdded; // SCN_MODIFIED
        int message;    // SCN_MACRORECORD
index 5be763f258d78f748efb24c8dc1469a6ac43e3be..a35f352e923382b56dc5e87085c405c1597221d8 100644 (file)
@@ -267,6 +267,7 @@ val SC_MARK_BACKGROUND=22
 val SC_MARK_DOTDOTDOT=23
 val SC_MARK_ARROWS=24
 val SC_MARK_PIXMAP=25
+val SC_MARK_FULLRECT=26
 
 val SC_MARK_CHARACTER=10000
 
@@ -312,6 +313,9 @@ fun int MarkerPrevious=2048(int lineStart, int markerMask)
 # Define a marker from a pixmap.
 fun void MarkerDefinePixmap=2049(int markerNumber, string pixmap)
 
+# Add a set of markers to a line.
+fun void MarkerAddSet=2466(int line, int set)
+
 enu MarginType=SC_MARGIN_
 val SC_MARGIN_SYMBOL=0
 val SC_MARGIN_NUMBER=1
@@ -366,6 +370,7 @@ val SC_CHARSET_HANGUL=129
 val SC_CHARSET_MAC=77
 val SC_CHARSET_OEM=255
 val SC_CHARSET_RUSSIAN=204
+val SC_CHARSET_CYRILLIC=1251
 val SC_CHARSET_SHIFTJIS=128
 val SC_CHARSET_SYMBOL=2
 val SC_CHARSET_TURKISH=162
@@ -374,6 +379,7 @@ val SC_CHARSET_HEBREW=177
 val SC_CHARSET_ARABIC=178
 val SC_CHARSET_VIETNAMESE=163
 val SC_CHARSET_THAI=222
+val SC_CHARSET_8859_15=1000
 
 # Clear all the styles and make equivalent to the global default style.
 set void StyleClearAll=2050(,)
@@ -607,6 +613,20 @@ get int AutoCGetTypeSeparator=2285(,)
 # Default is '?' but can be changed if items contain '?'.
 set void AutoCSetTypeSeparator=2286(int separatorCharacter,)
 
+# Set the maximum width, in characters, of auto-completion and user lists.
+# Set to 0 to autosize to fit longest item, which is the default.
+set void AutoCSetMaxWidth=2208(int characterCount,)
+
+# Get the maximum width, in characters, of auto-completion and user lists.
+get int AutoCGetMaxWidth=2209(,)
+
+# Set the maximum height, in rows, of auto-completion and user lists.
+# The default is 5 rows.
+set void AutoCSetMaxHeight=2210(int rowCount,)
+
+# Set the maximum height, in rows, of auto-completion and user lists.
+get int AutoCGetMaxHeight=2211(,)
+
 # Set the number of spaces used for one level of indentation.
 set void SetIndent=2122(int indentSize,)
 
@@ -905,6 +925,9 @@ fun int VisibleFromDocLine=2220(int line,)
 # Find the document line of a display line taking hidden lines into account.
 fun int DocLineFromVisible=2221(int lineDisplay,)
 
+# The number of display lines needed to wrap a document line
+fun int WrapCount=2235(int line,)
+
 enu FoldLevel=SC_FOLDLEVEL
 val SC_FOLDLEVELBASE=0x400
 val SC_FOLDLEVELWHITEFLAG=0x1000
@@ -994,6 +1017,7 @@ fun int WordEndPosition=2267(position pos, bool onlyWordCharacters)
 enu Wrap=SC_WRAP_
 val SC_WRAP_NONE=0
 val SC_WRAP_WORD=1
+val SC_WRAP_CHAR=2
 
 # Sets whether text is word wrapped.
 set void SetWrapMode=2268(int mode,)
@@ -1059,7 +1083,7 @@ set void SetEndAtLastLine=2277(bool endAtLastLine,)
 
 # Retrieve whether the maximum scroll position has the last
 # line at the bottom of the view.
-get int GetEndAtLastLine=2278(,)
+get bool GetEndAtLastLine=2278(,)
 
 # Retrieve the height of a particular line of text in pixels.
 fun int TextHeight=2279(int line,)
@@ -1588,7 +1612,7 @@ fun void Allocate=2446(int bytes,)
 fun int TargetAsUTF8=2447(, stringresult s)
 
 # Set the length of the utf8 argument for calling EncodedFromUTF8.
-# Set to 0 and the string will be measured to the first nul.
+# Set to -1 and the string will be measured to the first nul.
 fun void SetLengthForEncode=2448(int bytes,)
 
 # Translates a UTF8 string into the document encoding.
@@ -1596,10 +1620,28 @@ fun void SetLengthForEncode=2448(int bytes,)
 # On error return 0.
 fun int EncodedFromUTF8=2449(string utf8, stringresult encoded)
 
-# Find the position of a column on a line taking into account tabs and 
+# Find the position of a column on a line taking into account tabs and
 # multi-byte characters. If beyond end of line, return line end position.
 fun int FindColumn=2456(int line, int column)
 
+# Can the caret preferred x position only be changed by explicit movement commands?
+get bool GetCaretSticky=2457(,)
+
+# Stop the caret preferred x position changing when the user types.
+set void SetCaretSticky=2458(bool useCaretStickyBehaviour,)
+
+# Switch between sticky and non-sticky: meant to be bound to a key.
+fun void ToggleCaretSticky=2459(,)
+
+# Enable/Disable convert-on-paste for line endings
+set void SetPasteConvertEndings=2467(bool convert,)
+
+# Get convert-on-paste setting
+get bool GetPasteConvertEndings=2468(,)
+
+# Duplicate the selection. If selection empty duplicate the line containing the caret.
+fun void SelectionDuplicate=2469(,)
+
 # Start notifying the container of all key presses and commands.
 fun void StartRecord=3001(,)
 
@@ -1630,6 +1672,20 @@ set void SetLexerLanguage=4006(, string language)
 # Load a lexer library (dll / so).
 fun void LoadLexerLibrary=4007(, string path)
 
+# Retrieve a "property" value previously set with SetProperty.
+fun int GetProperty=4008(string key, stringresult buf)
+
+# Retrieve a "property" value previously set with SetProperty,
+# with "$()" variable replacement on returned buffer.
+fun int GetPropertyExpanded=4009(string key, stringresult buf)
+
+# Retrieve a "property" value previously set with SetProperty,
+# interpreted as an int AFTER any "$()" variable replacement.
+get int GetPropertyInt=4010(string key,)
+
+# Retrieve the number of bits the current lexer needs for styling.
+get int GetStyleBitsNeeded=4011(,)
+
 # Notifications
 # Type of modification and the action which caused the modification.
 # These are defined as a bit mask to make it easy to specify which notifications are wanted.
@@ -1642,11 +1698,13 @@ val SC_MOD_CHANGEFOLD=0x8
 val SC_PERFORMED_USER=0x10
 val SC_PERFORMED_UNDO=0x20
 val SC_PERFORMED_REDO=0x40
+val SC_MULTISTEPUNDOREDO=0x80
 val SC_LASTSTEPINUNDOREDO=0x100
 val SC_MOD_CHANGEMARKER=0x200
 val SC_MOD_BEFOREINSERT=0x400
 val SC_MOD_BEFOREDELETE=0x800
-val SC_MODEVENTMASKALL=0xF77
+val SC_MULTILINEUNDOREDO=0x1000
+val SC_MODEVENTMASKALL=0x1FFF
 
 # For compatibility, these go through the COMMAND notification rather than NOTIFY
 # and should have had exactly the same values as the EN_* constants.
@@ -1680,6 +1738,7 @@ val SCK_SUBTRACT=311
 val SCK_DIVIDE=312
 
 enu KeyMod=SCMOD_
+val SCMOD_NORM=0
 val SCMOD_SHIFT=1
 val SCMOD_CTRL=2
 val SCMOD_ALT=4
@@ -1716,8 +1775,6 @@ val SCLEX_TCL=25
 val SCLEX_NNCRONTAB=26
 val SCLEX_BULLANT=27
 val SCLEX_VBSCRIPT=28
-val SCLEX_ASP=29
-val SCLEX_PHP=30
 val SCLEX_BAAN=31
 val SCLEX_MATLAB=32
 val SCLEX_SCRIPTOL=33
@@ -1752,13 +1809,23 @@ val SCLEX_APDL=61
 val SCLEX_BASH=62
 val SCLEX_ASN1=63
 val SCLEX_VHDL=64
+val SCLEX_CAML=65
+val SCLEX_BLITZBASIC=66
+val SCLEX_PUREBASIC=67
+val SCLEX_HASKELL=68
+val SCLEX_PHPSCRIPT=69
+val SCLEX_TADS3=70
+val SCLEX_REBOL=71
+val SCLEX_SMALLTALK=72
+val SCLEX_FLAGSHIP=73
+val SCLEX_CSOUND=74
+val SCLEX_FREEBASIC=75
 
 # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
 # value assigned in sequence from SCLEX_AUTOMATIC+1.
 val SCLEX_AUTOMATIC=1000
 # Lexical states for SCLEX_PYTHON
 lex Python=SCLEX_PYTHON SCE_P_
-lex Ruby=SCLEX_RUBY SCE_P_
 val SCE_P_DEFAULT=0
 val SCE_P_COMMENTLINE=1
 val SCE_P_NUMBER=2
@@ -1773,9 +1840,10 @@ val SCE_P_OPERATOR=10
 val SCE_P_IDENTIFIER=11
 val SCE_P_COMMENTBLOCK=12
 val SCE_P_STRINGEOL=13
+val SCE_P_WORD2=14
+val SCE_P_DECORATOR=15
 # Lexical states for SCLEX_CPP
 lex Cpp=SCLEX_CPP SCE_C_
-lex SQL=SCLEX_SQL SCE_C_
 lex Pascal=SCLEX_PASCAL SCE_C_
 lex TCL=SCLEX_TCL SCE_C_
 lex BullAnt=SCLEX_BULLANT SCE_C_
@@ -1945,6 +2013,7 @@ val SCE_PL_SCALAR=12
 val SCE_PL_ARRAY=13
 val SCE_PL_HASH=14
 val SCE_PL_SYMBOLTABLE=15
+val SCE_PL_VARIABLE_INDEXER=16
 val SCE_PL_REGEX=17
 val SCE_PL_REGSUBST=18
 val SCE_PL_LONGQUOTE=19
@@ -1959,6 +2028,43 @@ val SCE_PL_STRING_QQ=27
 val SCE_PL_STRING_QX=28
 val SCE_PL_STRING_QR=29
 val SCE_PL_STRING_QW=30
+val SCE_PL_POD_VERB=31
+# Lexical states for SCLEX_RUBY
+lex Ruby=SCLEX_RUBY SCE_RB_
+val SCE_RB_DEFAULT=0
+val SCE_RB_ERROR=1
+val SCE_RB_COMMENTLINE=2
+val SCE_RB_POD=3
+val SCE_RB_NUMBER=4
+val SCE_RB_WORD=5
+val SCE_RB_STRING=6
+val SCE_RB_CHARACTER=7
+val SCE_RB_CLASSNAME=8
+val SCE_RB_DEFNAME=9
+val SCE_RB_OPERATOR=10
+val SCE_RB_IDENTIFIER=11
+val SCE_RB_REGEX=12
+val SCE_RB_GLOBAL=13
+val SCE_RB_SYMBOL=14
+val SCE_RB_MODULE_NAME=15
+val SCE_RB_INSTANCE_VAR=16
+val SCE_RB_CLASS_VAR=17
+val SCE_RB_BACKTICKS=18
+val SCE_RB_DATASECTION=19
+val SCE_RB_HERE_DELIM=20
+val SCE_RB_HERE_Q=21
+val SCE_RB_HERE_QQ=22
+val SCE_RB_HERE_QX=23
+val SCE_RB_STRING_Q=24
+val SCE_RB_STRING_QQ=25
+val SCE_RB_STRING_QX=26
+val SCE_RB_STRING_QR=27
+val SCE_RB_STRING_QW=28
+val SCE_RB_WORD_DEMOTED=29
+val SCE_RB_STDIN=30
+val SCE_RB_STDOUT=31
+val SCE_RB_STDERR=40
+val SCE_RB_UPPER_BOUND=41
 # Lexical states for SCLEX_VB, SCLEX_VBSCRIPT, SCLEX_POWERBASIC
 lex VB=SCLEX_VB SCE_B_
 lex VBScript=SCLEX_VBSCRIPT SCE_B_
@@ -1978,6 +2084,10 @@ val SCE_B_KEYWORD3=11
 val SCE_B_KEYWORD4=12
 val SCE_B_CONSTANT=13
 val SCE_B_ASM=14
+val SCE_B_LABEL=15
+val SCE_B_ERROR=16
+val SCE_B_HEXNUMBER=17
+val SCE_B_BINNUMBER=18
 # Lexical states for SCLEX_PROPERTIES
 lex Properties=SCLEX_PROPERTIES SCE_PROPS_
 val SCE_PROPS_DEFAULT=0
@@ -2127,10 +2237,14 @@ val SCE_LISP_DEFAULT=0
 val SCE_LISP_COMMENT=1
 val SCE_LISP_NUMBER=2
 val SCE_LISP_KEYWORD=3
+val SCE_LISP_KEYWORD_KW=4
+val SCE_LISP_SYMBOL=5
 val SCE_LISP_STRING=6
 val SCE_LISP_STRINGEOL=8
 val SCE_LISP_IDENTIFIER=9
 val SCE_LISP_OPERATOR=10
+val SCE_LISP_SPECIAL=11
+val SCE_LISP_MULTI_COMMENT=12
 # Lexical states for SCLEX_EIFFEL and SCLEX_EIFFELKW
 lex Eiffel=SCLEX_EIFFEL SCE_EIFFEL_
 lex EiffelKW=SCLEX_EIFFELKW SCE_EIFFEL_
@@ -2253,6 +2367,7 @@ val SCE_CSS_DIRECTIVE=12
 val SCE_CSS_DOUBLESTRING=13
 val SCE_CSS_SINGLESTRING=14
 val SCE_CSS_IDENTIFIER2=15
+val SCE_CSS_ATTRIBUTE=16
 # Lexical states for SCLEX_POV
 lex POV=SCLEX_POV SCE_POV_
 val SCE_POV_DEFAULT=0
@@ -2334,6 +2449,10 @@ val SCE_NSIS_IFDEFINEDEF=11
 val SCE_NSIS_MACRODEF=12
 val SCE_NSIS_STRINGVAR=13
 val SCE_NSIS_NUMBER=14
+val SCE_NSIS_SECTIONGROUP=15
+val SCE_NSIS_PAGEEX=16
+val SCE_NSIS_FUNCTIONDEF=17
+val SCE_NSIS_COMMENTBOX=18
 # Lexical states for SCLEX_MMIXAL
 lex MMIXAL=SCLEX_MMIXAL SCE_MMIXAL_
 val SCE_MMIXAL_LEADWS=0
@@ -2366,11 +2485,13 @@ val SCE_CLW_REAL_CONSTANT=6
 val SCE_CLW_PICTURE_STRING=7
 val SCE_CLW_KEYWORD=8
 val SCE_CLW_COMPILER_DIRECTIVE=9
-val SCE_CLW_BUILTIN_PROCEDURES_FUNCTION=10
-val SCE_CLW_STRUCTURE_DATA_TYPE=11
-val SCE_CLW_ATTRIBUTE=12
-val SCE_CLW_STANDARD_EQUATE=13
-val SCE_CLW_ERROR=14
+val SCE_CLW_RUNTIME_EXPRESSIONS=10
+val SCE_CLW_BUILTIN_PROCEDURES_FUNCTION=11
+val SCE_CLW_STRUCTURE_DATA_TYPE=12
+val SCE_CLW_ATTRIBUTE=13
+val SCE_CLW_STANDARD_EQUATE=14
+val SCE_CLW_ERROR=15
+val SCE_CLW_DEPRECATED=16
 # Lexical states for SCLEX_LOT
 lex LOT=SCLEX_LOT SCE_LOT_
 val SCE_LOT_DEFAULT=0
@@ -2518,6 +2639,8 @@ val SCE_AU3_VARIABLE=9
 val SCE_AU3_SENT=10
 val SCE_AU3_PREPROCESSOR=11
 val SCE_AU3_SPECIAL=12
+val SCE_AU3_EXPAND=13
+val SCE_AU3_COMOBJ=14
 # Lexical states for SCLEX_APDL
 lex APDL=SCLEX_APDL SCE_APDL_
 val SCE_APDL_DEFAULT=0
@@ -2579,6 +2702,182 @@ val SCE_VHDL_STDFUNCTION=11
 val SCE_VHDL_STDPACKAGE=12
 val SCE_VHDL_STDTYPE=13
 val SCE_VHDL_USERWORD=14
+# Lexical states for SCLEX_CAML
+lex Caml=SCLEX_CAML SCE_CAML_
+val SCE_CAML_DEFAULT=0
+val SCE_CAML_IDENTIFIER=1
+val SCE_CAML_TAGNAME=2
+val SCE_CAML_KEYWORD=3
+val SCE_CAML_KEYWORD2=4
+val SCE_CAML_KEYWORD3=5
+val SCE_CAML_LINENUM=6
+val SCE_CAML_OPERATOR=7
+val SCE_CAML_NUMBER=8
+val SCE_CAML_CHAR=9
+val SCE_CAML_STRING=11
+val SCE_CAML_COMMENT=12
+val SCE_CAML_COMMENT1=13
+val SCE_CAML_COMMENT2=14
+val SCE_CAML_COMMENT3=15
+# Lexical states for SCLEX_HASKELL
+lex Haskell=SCLEX_HASKELL SCE_HA_
+val SCE_HA_DEFAULT=0
+val SCE_HA_IDENTIFIER=1
+val SCE_HA_KEYWORD=2
+val SCE_HA_NUMBER=3
+val SCE_HA_STRING=4
+val SCE_HA_CHARACTER=5
+val SCE_HA_CLASS=6
+val SCE_HA_MODULE=7
+val SCE_HA_CAPITAL=8
+val SCE_HA_DATA=9
+val SCE_HA_IMPORT=10
+val SCE_HA_OPERATOR=11
+val SCE_HA_INSTANCE=12
+val SCE_HA_COMMENTLINE=13
+val SCE_HA_COMMENTBLOCK=14
+val SCE_HA_COMMENTBLOCK2=15
+val SCE_HA_COMMENTBLOCK3=16
+# Lexical states of SCLEX_TADS3
+lex TADS3=SCLEX_TADS3 SCE_T3_
+val SCE_T3_DEFAULT=0
+val SCE_T3_X_DEFAULT=1
+val SCE_T3_PREPROCESSOR=2
+val SCE_T3_BLOCK_COMMENT=3
+val SCE_T3_LINE_COMMENT=4
+val SCE_T3_OPERATOR=5
+val SCE_T3_KEYWORD=6
+val SCE_T3_NUMBER=7
+val SCE_T3_IDENTIFIER=8
+val SCE_T3_S_STRING=9
+val SCE_T3_D_STRING=10
+val SCE_T3_X_STRING=11
+val SCE_T3_LIB_DIRECTIVE=12
+val SCE_T3_MSG_PARAM=13
+val SCE_T3_HTML_TAG=14
+val SCE_T3_HTML_DEFAULT=15
+val SCE_T3_HTML_STRING=16
+val SCE_T3_USER1=17
+val SCE_T3_USER2=18
+val SCE_T3_USER3=19
+# Lexical states for SCLEX_REBOL
+lex Rebol=SCLEX_REBOL SCE_REBOL_
+val SCE_REBOL_DEFAULT=0
+val SCE_REBOL_COMMENTLINE=1
+val SCE_REBOL_COMMENTBLOCK=2
+val SCE_REBOL_PREFACE=3
+val SCE_REBOL_OPERATOR=4
+val SCE_REBOL_CHARACTER=5
+val SCE_REBOL_QUOTEDSTRING=6
+val SCE_REBOL_BRACEDSTRING=7
+val SCE_REBOL_NUMBER=8
+val SCE_REBOL_PAIR=9
+val SCE_REBOL_TUPLE=10
+val SCE_REBOL_BINARY=11
+val SCE_REBOL_MONEY=12
+val SCE_REBOL_ISSUE=13
+val SCE_REBOL_TAG=14
+val SCE_REBOL_FILE=15
+val SCE_REBOL_EMAIL=16
+val SCE_REBOL_URL=17
+val SCE_REBOL_DATE=18
+val SCE_REBOL_TIME=19
+val SCE_REBOL_IDENTIFIER=20
+val SCE_REBOL_WORD=21
+val SCE_REBOL_WORD2=22
+val SCE_REBOL_WORD3=23
+val SCE_REBOL_WORD4=24
+val SCE_REBOL_WORD5=25
+val SCE_REBOL_WORD6=26
+val SCE_REBOL_WORD7=27
+val SCE_REBOL_WORD8=28
+# Lexical states for SCLEX_SQL
+lex SQL=SCLEX_SQL SCE_SQL_
+val SCE_SQL_DEFAULT=0
+val SCE_SQL_COMMENT=1
+val SCE_SQL_COMMENTLINE=2
+val SCE_SQL_COMMENTDOC=3
+val SCE_SQL_NUMBER=4
+val SCE_SQL_WORD=5
+val SCE_SQL_STRING=6
+val SCE_SQL_CHARACTER=7
+val SCE_SQL_SQLPLUS=8
+val SCE_SQL_SQLPLUS_PROMPT=9
+val SCE_SQL_OPERATOR=10
+val SCE_SQL_IDENTIFIER=11
+val SCE_SQL_SQLPLUS_COMMENT=13
+val SCE_SQL_COMMENTLINEDOC=15
+val SCE_SQL_WORD2=16
+val SCE_SQL_COMMENTDOCKEYWORD=17
+val SCE_SQL_COMMENTDOCKEYWORDERROR=18
+val SCE_SQL_USER1=19
+val SCE_SQL_USER2=20
+val SCE_SQL_USER3=21
+val SCE_SQL_USER4=22
+val SCE_SQL_QUOTEDIDENTIFIER=23
+# Lexical states for SCLEX_SMALLTALK
+lex Smalltalk=SCLEX_SMALLTALK SCE_ST_
+val SCE_ST_DEFAULT=0
+val SCE_ST_STRING=1
+val SCE_ST_NUMBER=2
+val SCE_ST_COMMENT=3
+val SCE_ST_SYMBOL=4
+val SCE_ST_BINARY=5
+val SCE_ST_BOOL=6
+val SCE_ST_SELF=7
+val SCE_ST_SUPER=8
+val SCE_ST_NIL=9
+val SCE_ST_GLOBAL=10
+val SCE_ST_RETURN=11
+val SCE_ST_SPECIAL=12
+val SCE_ST_KWSEND=13
+val SCE_ST_ASSIGN=14
+val SCE_ST_CHARACTER=15
+val SCE_ST_SPEC_SEL=16
+# Lexical states for SCLEX_FLAGSHIP (clipper)
+lex FlagShip=SCLEX_FLAGSHIP SCE_B_
+val SCE_FS_DEFAULT=0
+val SCE_FS_COMMENT=1
+val SCE_FS_COMMENTLINE=2
+val SCE_FS_COMMENTDOC=3
+val SCE_FS_COMMENTLINEDOC=4
+val SCE_FS_COMMENTDOCKEYWORD=5
+val SCE_FS_COMMENTDOCKEYWORDERROR=6
+val SCE_FS_KEYWORD=7
+val SCE_FS_KEYWORD2=8
+val SCE_FS_KEYWORD3=9
+val SCE_FS_KEYWORD4=10
+val SCE_FS_NUMBER=11
+val SCE_FS_STRING=12
+val SCE_FS_PREPROCESSOR=13
+val SCE_FS_OPERATOR=14
+val SCE_FS_IDENTIFIER=15
+val SCE_FS_DATE=16
+val SCE_FS_STRINGEOL=17
+val SCE_FS_CONSTANT=18
+val SCE_FS_ASM=19
+val SCE_FS_LABEL=20
+val SCE_FS_ERROR=21
+val SCE_FS_HEXNUMBER=22
+val SCE_FS_BINNUMBER=23
+# Lexical states for SCLEX_CSOUND
+lex Csound=SCLEX_CSOUND SCE_CSOUND_
+val SCE_CSOUND_DEFAULT=0
+val SCE_CSOUND_COMMENT=1
+val SCE_CSOUND_NUMBER=2
+val SCE_CSOUND_OPERATOR=3
+val SCE_CSOUND_INSTR=4
+val SCE_CSOUND_IDENTIFIER=5
+val SCE_CSOUND_OPCODE=6
+val SCE_CSOUND_HEADERSTMT=7
+val SCE_CSOUND_USERKEYWORD=8
+val SCE_CSOUND_COMMENTBLOCK=9
+val SCE_CSOUND_PARAM=10
+val SCE_CSOUND_ARATE_VAR=11
+val SCE_CSOUND_KRATE_VAR=12
+val SCE_CSOUND_IRATE_VAR=13
+val SCE_CSOUND_GLOBAL_VAR=14
+val SCE_CSOUND_STRINGEOL=15
 
 # Events
 
@@ -2604,6 +2903,7 @@ evt void Zoom=2018(void)
 evt void HotSpotClick=2019(int modifiers, int position)
 evt void HotSpotDoubleClick=2020(int modifiers, int position)
 evt void CallTipClick=2021(int position)
+evt void AutoCSelection=2022(string text)
 
 cat Deprecated
 
@@ -2617,3 +2917,6 @@ val CARET_XJUMPS=0x10
 val SCN_CHECKBRACE=2007
 evt void PosChanged=2012(int position)
 
+# SCLEX_HTML should be used in preference to these.
+val SCLEX_ASP=29
+val SCLEX_PHP=30
index 765fd8594d159e6420d32fdcc3cc420711400b00..7f47de7e13c33fd31b7aec0bb10a8ad12a703d50 100644 (file)
@@ -34,9 +34,9 @@ struct _ScintillaClass {
        void (* notify) (ScintillaObject *ttt);
 };
 
-guint          scintilla_get_type      (void);
+GtkType                scintilla_get_type      (void);
 GtkWidget*     scintilla_new           (void);
-void           scintilla_set_id        (ScintillaObject *sci,int id);
+void           scintilla_set_id        (ScintillaObject *sci, uptr_t id);
 sptr_t         scintilla_send_message  (ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam);
 void           scintilla_release_resources(void);
 
index adbd24d038fa5cdc6def23578b7c1ced63ad868e..753adca77978e624daf6c3ba9b0518001c231470 100644 (file)
@@ -43,12 +43,13 @@ bool AutoComplete::Active() {
        return active;
 }
 
-void AutoComplete::Start(Window &parent, int ctrlID, int position,
-       int startLen_, int lineHeight, bool unicodeMode) {
+void AutoComplete::Start(Window &parent, int ctrlID, 
+       int position, Point location, int startLen_, 
+       int lineHeight, bool unicodeMode) {
        if (active) {
                Cancel();
        }
-       lb->Create(parent, ctrlID, lineHeight, unicodeMode);
+       lb->Create(parent, ctrlID, location, lineHeight, unicodeMode);
        lb->Clear();
        active = true;
        startLen = startLen_;
@@ -90,41 +91,18 @@ char AutoComplete::GetTypesep() {
 }
 
 void AutoComplete::SetList(const char *list) {
-       lb->Clear();
-       char *words = new char[strlen(list) + 1];
-       if (words) {
-               strcpy(words, list);
-               char *startword = words;
-               char *numword = NULL;
-               int i = 0;
-               for (; words && words[i]; i++) {
-                       if (words[i] == separator) {
-                               words[i] = '\0';
-                               if (numword)
-                                       *numword = '\0';
-                               lb->Append(startword, numword?atoi(numword + 1):-1);
-                               startword = words + i + 1;
-                               numword = NULL;
-                       } else if (words[i] == typesep) {
-                               numword = words + i;
-                       }
-               }
-               if (startword) {
-                       if (numword)
-                               *numword = '\0';
-                       lb->Append(startword, numword?atoi(numword + 1):-1);
-               }
-               delete []words;
-       }
+       lb->SetList(list, separator, typesep);
 }
 
-void AutoComplete::Show() {
-       lb->Show();
-       lb->Select(0);
+void AutoComplete::Show(bool show) {
+       lb->Show(show);
+       if (show)
+               lb->Select(0);
 }
 
 void AutoComplete::Cancel() {
        if (lb->Created()) {
+               lb->Clear();
                lb->Destroy();
                active = false;
        }
@@ -170,6 +148,18 @@ void AutoComplete::Select(const char *word) {
                                --pivot;
                        }
                        location = pivot;
+                       if (ignoreCase) {
+                               // Check for exact-case match
+                               for (; pivot <= end; pivot++) {
+                                       lb->GetValue(pivot, item, maxItemLen);
+                                       if (!strncmp(word, item, lenWord)) {
+                                               location = pivot;
+                                               break;
+                                       }
+                                       if (CompareNCaseInsensitive(word, item, lenWord))
+                                               break;
+                               }
+                       }
                } else if (cond < 0) {
                        end = pivot - 1;
                } else if (cond > 0) {
index eedab5625e834af99c981e1594701ca641356198..10577ca38057c0f10d369eb2d2175e75781dbcf3 100644 (file)
@@ -15,7 +15,7 @@ class AutoComplete {
        char stopChars[256];
        char fillUpChars[256];
        char separator;
-       char typesep; // Type separator
+       char typesep; // Type seperator
 
 public:
        bool ignoreCase;
@@ -35,7 +35,7 @@ public:
        bool Active();
 
        /// Display the auto completion list positioned to be near a character position
-       void Start(Window &parent, int ctrlID, int position,
+       void Start(Window &parent, int ctrlID, int position, Point location,
                int startLen_, int lineHeight, bool unicodeMode);
 
        /// The stop chars are characters which, when typed, cause the auto completion list to disappear
@@ -50,14 +50,14 @@ public:
        void SetSeparator(char separator_);
        char GetSeparator();
 
-       /// The typesep character is used for separating the word from the type
+       /// The typesep character is used for seperating the word from the type
        void SetTypesep(char separator_);
        char GetTypesep();
 
        /// The list string contains a sequence of words separated by the separator character
        void SetList(const char *list);
 
-       void Show();
+       void Show(bool show);
        void Cancel();
 
        /// Move the current list element by delta, scrolling appropriately
index 003284c12df5f14e8ef85a4669f8d50c2f7b71f7..80fd55d7b85dc9cdd178cf42fb4203fe065116b2 100644 (file)
@@ -18,8 +18,8 @@ CallTip::CallTip() {
        inCallTipMode = false;
        posStartCallTip = 0;
        val = 0;
-       xUp = -100;
-       xDown = -100;
+       rectUp = PRectangle(0,0,0,0);
+       rectDown = PRectangle(0,0,0,0);
        lineHeight = 1;
        startHighlight = 0;
        endHighlight = 0;
@@ -75,12 +75,12 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
                        if (IsArrowCharacter(s[startSeg])) {
                                xEnd = x + widthArrow;
                                offsetMain = xEnd;
+                               rcClient.left = x;
+                               rcClient.right = xEnd;
                                if (draw) {
                                        const int halfWidth = widthArrow / 2 - 3;
                                        const int centreX = x + widthArrow / 2 - 1;
                                        const int centreY = (rcClient.top + rcClient.bottom) / 2;
-                                       rcClient.left = x;
-                                       rcClient.right = xEnd;
                                        surface->FillRectangle(rcClient, colourBG.allocated);
                                        PRectangle rcClientInner(rcClient.left+1, rcClient.top+1, rcClient.right-2, rcClient.bottom-1);
                                        surface->FillRectangle(rcClientInner, colourUnSel.allocated);
@@ -104,12 +104,11 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
                                                surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                                                                colourBG.allocated, colourBG.allocated);
                                        }
-                               } else {
-                                       if (s[startSeg] == '\001') {
-                                               xUp = x+1;
-                                       } else {
-                                               xDown = x+1;
-                                       }
+                               }
+                               if (s[startSeg] == '\001') {
+                                       rectUp = rcClient;
+                               } else if (s[startSeg] == '\002') {
+                                       rectDown = rcClient;
                                }
                        } else {
                                xEnd = x + surface->WidthText(font, s+startSeg, endSeg - startSeg);
@@ -203,13 +202,10 @@ void CallTip::PaintCT(Surface *surfaceWindow) {
 
 void CallTip::MouseClick(Point pt) {
        clickPlace = 0;
-       if (pt.y < lineHeight) {
-               if ((pt.x > xUp) && (pt.x < xUp + widthArrow - 2)) {
-                       clickPlace = 1;
-               } else if ((pt.x > xDown) && (pt.x < xDown + widthArrow - 2)) {
-                       clickPlace = 2;
-               }
-       }
+       if (rectUp.Contains(pt))
+               clickPlace = 1;
+       if (rectDown.Contains(pt))
+               clickPlace = 2;
 }
 
 PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
@@ -240,8 +236,8 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
        int numLines = 1;
        const char *newline;
        const char *look = val;
-       xUp = -100;
-       xDown = -100;
+       rectUp = PRectangle(0,0,0,0);
+       rectDown = PRectangle(0,0,0,0);
        offsetMain = 5;
        int width = PaintContents(surfaceMeasure, false) + 5;
        while ((newline = strchr(look, '\n')) != NULL) {
index feff7ea0b1ef4355e9a65efdd6f62e538a85dfd4..53eec832a25e3a48128f8ffeebd650aff97b17e1 100644 (file)
@@ -15,8 +15,8 @@ class CallTip {
        int endHighlight;
        char *val;
        Font font;
-       int xUp;
-       int xDown;
+       PRectangle rectUp;
+       PRectangle rectDown;
        int lineHeight;
        int offsetMain;
        // Private so CallTip objects can not be copied
index 8183e4d8d3ca9fffc41ddbc983c85cb1b8557146..1109a17fbe54293c865c78d86cb17f0a5ae29bca 100644 (file)
@@ -254,13 +254,14 @@ void LineVector::Remove(int pos) {
                linesData[i] = linesData[i + 1];
        }
        if (levels) {
-               // Level information merges back onto previous line
-               int posAbove = pos - 1;
-               if (posAbove < 0)
-                       posAbove = 0;
-               for (int j = posAbove; j < lines; j++) {
+               // Move up following lines but merge header flag from this line
+               // to line before to avoid a temporary disappearence causing expansion.
+               int firstHeader = levels[pos] & SC_FOLDLEVELHEADERFLAG;
+               for (int j = pos; j < lines; j++) {
                        levels[j] = levels[j + 1];
                }
+               if (pos > 0)
+                       levels[pos-1] |= firstHeader;
        }
        lines--;
 }
@@ -464,7 +465,7 @@ void UndoHistory::AppendAction(actionType at, int position, char *data, int leng
                        } else if (currentAction == savePoint) {
                                currentAction++;
                        } else if ((at == insertAction) &&
-                                  (position != (actPrevious.position + actPrevious.lenData*2))) {
+                                  (position != (actPrevious.position + actPrevious.lenData))) {
                                // Insertions must be immediately after to coalesce
                                currentAction++;
                        } else if (!actions[currentAction].mayCoalesce) {
@@ -472,7 +473,7 @@ void UndoHistory::AppendAction(actionType at, int position, char *data, int leng
                                currentAction++;
                        } else if (at == removeAction) {
                                if ((lengthData == 1) || (lengthData == 2)){
-                                       if ((position + lengthData * 2) == actPrevious.position) {
+                                       if ((position + lengthData) == actPrevious.position) {
                                                ; // Backspace -> OK
                                        } else if (position == actPrevious.position) {
                                                ; // Delete -> OK
@@ -724,7 +725,7 @@ const char *CellBuffer::InsertString(int position, char *s, int insertLength) {
                        for (int i = 0; i < insertLength / 2; i++) {
                                data[i] = s[i * 2];
                        }
-                       uh.AppendAction(insertAction, position, data, insertLength / 2);
+                       uh.AppendAction(insertAction, position / 2, data, insertLength / 2);
                }
 
                BasicInsertString(position, s, insertLength);
@@ -732,13 +733,6 @@ const char *CellBuffer::InsertString(int position, char *s, int insertLength) {
        return data;
 }
 
-void CellBuffer::InsertCharStyle(int position, char ch, char style) {
-       char s[2];
-       s[0] = ch;
-       s[1] = style;
-       InsertString(position*2, s, 2);
-}
-
 bool CellBuffer::SetStyleAt(int position, char style, char mask) {
        style &= mask;
        char curVal = ByteAt(position * 2 + 1);
@@ -768,6 +762,7 @@ bool CellBuffer::SetStyleFor(int position, int lengthStyle, char style, char mas
 
 const char *CellBuffer::DeleteChars(int position, int deleteLength) {
        // InsertString and DeleteChars are the bottleneck though which all changes occur
+       PLATFORM_ASSERT(deleteLength > 0);
        char *data = 0;
        if (!readOnly) {
                if (collectingUndo) {
@@ -776,7 +771,7 @@ const char *CellBuffer::DeleteChars(int position, int deleteLength) {
                        for (int i = 0; i < deleteLength / 2; i++) {
                                data[i] = ByteAt(position + i * 2);
                        }
-                       uh.AppendAction(removeAction, position, data, deleteLength / 2);
+                       uh.AppendAction(removeAction, position / 2, data, deleteLength / 2);
                }
 
                BasicDeleteChars(position, deleteLength);
@@ -874,6 +869,7 @@ void CellBuffer::BasicInsertString(int position, char *s, int insertLength) {
        //Platform::DebugPrintf("Inserting at %d for %d\n", position, insertLength);
        if (insertLength == 0)
                return ;
+       PLATFORM_ASSERT(insertLength > 0);
        RoomFor(insertLength);
        GapTo(position);
 
@@ -1028,7 +1024,7 @@ void CellBuffer::DeleteUndoHistory() {
 }
 
 bool CellBuffer::CanUndo() {
-       return (!readOnly) && (uh.CanUndo());
+       return uh.CanUndo();
 }
 
 int CellBuffer::StartUndo() {
@@ -1042,21 +1038,21 @@ const Action &CellBuffer::GetUndoStep() const {
 void CellBuffer::PerformUndoStep() {
        const Action &actionStep = uh.GetUndoStep();
        if (actionStep.at == insertAction) {
-               BasicDeleteChars(actionStep.position, actionStep.lenData*2);
+               BasicDeleteChars(actionStep.position*2, actionStep.lenData*2);
        } else if (actionStep.at == removeAction) {
                char *styledData = new char[actionStep.lenData * 2];
                for (int i = 0; i < actionStep.lenData; i++) {
                        styledData[i*2] = actionStep.data[i];
                        styledData[i*2 + 1] = 0;
                }
-               BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
+               BasicInsertString(actionStep.position*2, styledData, actionStep.lenData*2);
                delete []styledData;
        }
        uh.CompletedUndoStep();
 }
 
 bool CellBuffer::CanRedo() {
-       return (!readOnly) && (uh.CanRedo());
+       return uh.CanRedo();
 }
 
 int CellBuffer::StartRedo() {
@@ -1075,10 +1071,10 @@ void CellBuffer::PerformRedoStep() {
                        styledData[i*2] = actionStep.data[i];
                        styledData[i*2 + 1] = 0;
                }
-               BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
+               BasicInsertString(actionStep.position*2, styledData, actionStep.lenData*2);
                delete []styledData;
        } else if (actionStep.at == removeAction) {
-               BasicDeleteChars(actionStep.position, actionStep.lenData*2);
+               BasicDeleteChars(actionStep.position*2, actionStep.lenData*2);
        }
        uh.CompletedRedoStep();
 }
index b16eef5e51a745f92ed3ae10d5098fd9b0c2818c..bb81fd5722d3784d697a1705140183bbaf1505a7 100644 (file)
@@ -191,7 +191,6 @@ public:
        int LineStart(int line);
        int LineFromPosition(int pos) { return lv.LineFromPosition(pos); }
        const char *InsertString(int position, char *s, int insertLength);
-       void InsertCharStyle(int position, char ch, char style);
 
        /// Setting styles for positions outside the range of the buffer is safe and has no effect.
        /// @return true if the style of a character is changed.
index 76fa456ccb613e44366b2205081e91d4bac74150..a88468cb1a8b26431c99864764564e68a43a1bcf 100644 (file)
@@ -103,26 +103,40 @@ void Document::SetSavePoint() {
 
 int Document::AddMark(int line, int markerNum) {
        int prev = cb.AddMark(line, markerNum);
-       DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0);
+       DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+       mh.line = line;
        NotifyModified(mh);
        return prev;
 }
 
+void Document::AddMarkSet(int line, int valueSet) {
+       unsigned int m = valueSet;
+       for (int i = 0; m; i++, m >>= 1)
+               if (m & 1)
+                       cb.AddMark(line, i);
+       DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+       mh.line = line;
+       NotifyModified(mh);
+}
+
 void Document::DeleteMark(int line, int markerNum) {
        cb.DeleteMark(line, markerNum);
-       DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0);
+       DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+       mh.line = line;
        NotifyModified(mh);
 }
 
 void Document::DeleteMarkFromHandle(int markerHandle) {
        cb.DeleteMarkFromHandle(markerHandle);
        DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
+       mh.line = -1;
        NotifyModified(mh);
 }
 
 void Document::DeleteAllMarks(int markerNum) {
        cb.DeleteAllMarks(markerNum);
        DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
+       mh.line = -1;
        NotifyModified(mh);
 }
 
@@ -266,7 +280,7 @@ int Document::LenChar(int pos) {
                return 1;
        }
 }
-#include <assert.h>
+
 // Normalise a position so that it is not halfway through a two byte character.
 // This can occur in two situations -
 // When lines are terminated with \r\n pairs which should be treated as one character.
@@ -280,7 +294,7 @@ int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) {
        if (pos >= Length())
                return Length();
 
-       // assert pos > 0 && pos < Length()
+       // PLATFORM_ASSERT(pos > 0 && pos < Length());
        if (checkLineEnd && IsCrLf(pos - 1)) {
                if (moveDir > 0)
                        return pos + 1;
@@ -336,6 +350,14 @@ void Document::ModifiedAt(int pos) {
                endStyled = pos;
 }
 
+void Document::CheckReadOnly() {
+       if (cb.IsReadOnly() && enteredReadOnlyCount == 0) {
+               enteredReadOnlyCount++;
+               NotifyModifyAttempt();
+               enteredReadOnlyCount--;
+       }
+}
+
 // Document only modified by gateways DeleteChars, InsertStyledString, Undo, Redo, and SetStyleAt.
 // SetStyleAt does not change the persistent state of a document
 
@@ -345,11 +367,7 @@ bool Document::DeleteChars(int pos, int len) {
                return false;
        if ((pos + len) > Length())
                return false;
-       if (cb.IsReadOnly() && enteredReadOnlyCount == 0) {
-               enteredReadOnlyCount++;
-               NotifyModifyAttempt();
-               enteredReadOnlyCount--;
-       }
+       CheckReadOnly();
        if (enteredCount != 0) {
                return false;
        } else {
@@ -384,11 +402,7 @@ bool Document::DeleteChars(int pos, int len) {
  * Insert a styled string (char/style pairs) with a length.
  */
 bool Document::InsertStyledString(int position, char *s, int insertLength) {
-       if (cb.IsReadOnly() && enteredReadOnlyCount == 0) {
-               enteredReadOnlyCount++;
-               NotifyModifyAttempt();
-               enteredReadOnlyCount--;
-       }
+       CheckReadOnly();
        if (enteredCount != 0) {
                return false;
        } else {
@@ -417,86 +431,110 @@ bool Document::InsertStyledString(int position, char *s, int insertLength) {
 }
 
 int Document::Undo() {
-       int newPos = 0;
+       int newPos = -1;
+       CheckReadOnly();
        if (enteredCount == 0) {
                enteredCount++;
-               bool startSavePoint = cb.IsSavePoint();
-               int steps = cb.StartUndo();
-               //Platform::DebugPrintf("Steps=%d\n", steps);
-               for (int step = 0; step < steps; step++) {
-                       int prevLinesTotal = LinesTotal();
-                       const Action &action = cb.GetUndoStep();
-                       if (action.at == removeAction) {
-                               NotifyModified(DocModification(
-                                                  SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action));
-                       } else {
-                               NotifyModified(DocModification(
-                                                  SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action));
-                       }
-                       cb.PerformUndoStep();
-                       int cellPosition = action.position / 2;
-                       ModifiedAt(cellPosition);
-                       newPos = cellPosition;
-
-                       int modFlags = SC_PERFORMED_UNDO;
-                       // With undo, an insertion action becomes a deletion notification
-                       if (action.at == removeAction) {
-                               newPos += action.lenData;
-                               modFlags |= SC_MOD_INSERTTEXT;
-                       } else {
-                               modFlags |= SC_MOD_DELETETEXT;
+               if (!cb.IsReadOnly()) {
+                       bool startSavePoint = cb.IsSavePoint();
+                       bool multiLine = false;
+                       int steps = cb.StartUndo();
+                       //Platform::DebugPrintf("Steps=%d\n", steps);
+                       for (int step = 0; step < steps; step++) {
+                               const int prevLinesTotal = LinesTotal();
+                               const Action &action = cb.GetUndoStep();
+                               if (action.at == removeAction) {
+                                       NotifyModified(DocModification(
+                                                                       SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action));
+                               } else {
+                                       NotifyModified(DocModification(
+                                                                       SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action));
+                               }
+                               cb.PerformUndoStep();
+                               int cellPosition = action.position;
+                               ModifiedAt(cellPosition);
+                               newPos = cellPosition;
+
+                               int modFlags = SC_PERFORMED_UNDO;
+                               // With undo, an insertion action becomes a deletion notification
+                               if (action.at == removeAction) {
+                                       newPos += action.lenData;
+                                       modFlags |= SC_MOD_INSERTTEXT;
+                               } else {
+                                       modFlags |= SC_MOD_DELETETEXT;
+                               }
+                               if (steps > 1)
+                                       modFlags |= SC_MULTISTEPUNDOREDO;
+                               const int linesAdded = LinesTotal() - prevLinesTotal;
+                               if (linesAdded != 0)
+                                       multiLine = true;
+                               if (step == steps - 1) {
+                                       modFlags |= SC_LASTSTEPINUNDOREDO;
+                                       if (multiLine)
+                                               modFlags |= SC_MULTILINEUNDOREDO;
+                               }
+                               NotifyModified(DocModification(modFlags, cellPosition, action.lenData,
+                                                                                          linesAdded, action.data));
                        }
-                       if (step == steps - 1)
-                               modFlags |= SC_LASTSTEPINUNDOREDO;
-                       NotifyModified(DocModification(modFlags, cellPosition, action.lenData,
-                                                      LinesTotal() - prevLinesTotal, action.data));
-               }
 
-               bool endSavePoint = cb.IsSavePoint();
-               if (startSavePoint != endSavePoint)
-                       NotifySavePoint(endSavePoint);
+                       bool endSavePoint = cb.IsSavePoint();
+                       if (startSavePoint != endSavePoint)
+                               NotifySavePoint(endSavePoint);
+               }
                enteredCount--;
        }
        return newPos;
 }
 
 int Document::Redo() {
-       int newPos = 0;
+       int newPos = -1;
+       CheckReadOnly();
        if (enteredCount == 0) {
                enteredCount++;
-               bool startSavePoint = cb.IsSavePoint();
-               int steps = cb.StartRedo();
-               for (int step = 0; step < steps; step++) {
-                       int prevLinesTotal = LinesTotal();
-                       const Action &action = cb.GetRedoStep();
-                       if (action.at == insertAction) {
-                               NotifyModified(DocModification(
-                                                  SC_MOD_BEFOREINSERT | SC_PERFORMED_REDO, action));
-                       } else {
-                               NotifyModified(DocModification(
-                                                  SC_MOD_BEFOREDELETE | SC_PERFORMED_REDO, action));
-                       }
-                       cb.PerformRedoStep();
-                       ModifiedAt(action.position / 2);
-                       newPos = action.position / 2;
-
-                       int modFlags = SC_PERFORMED_REDO;
-                       if (action.at == insertAction) {
-                               newPos += action.lenData;
-                               modFlags |= SC_MOD_INSERTTEXT;
-                       } else {
-                               modFlags |= SC_MOD_DELETETEXT;
+               if (!cb.IsReadOnly()) {
+                       bool startSavePoint = cb.IsSavePoint();
+                       bool multiLine = false;
+                       int steps = cb.StartRedo();
+                       for (int step = 0; step < steps; step++) {
+                               const int prevLinesTotal = LinesTotal();
+                               const Action &action = cb.GetRedoStep();
+                               if (action.at == insertAction) {
+                                       NotifyModified(DocModification(
+                                                                       SC_MOD_BEFOREINSERT | SC_PERFORMED_REDO, action));
+                               } else {
+                                       NotifyModified(DocModification(
+                                                                       SC_MOD_BEFOREDELETE | SC_PERFORMED_REDO, action));
+                               }
+                               cb.PerformRedoStep();
+                               ModifiedAt(action.position);
+                               newPos = action.position;
+
+                               int modFlags = SC_PERFORMED_REDO;
+                               if (action.at == insertAction) {
+                                       newPos += action.lenData;
+                                       modFlags |= SC_MOD_INSERTTEXT;
+                               } else {
+                                       modFlags |= SC_MOD_DELETETEXT;
+                               }
+                               if (steps > 1)
+                                       modFlags |= SC_MULTISTEPUNDOREDO;
+                               const int linesAdded = LinesTotal() - prevLinesTotal;
+                               if (linesAdded != 0)
+                                       multiLine = true;
+                               if (step == steps - 1) {
+                                       modFlags |= SC_LASTSTEPINUNDOREDO;
+                                       if (multiLine)
+                                               modFlags |= SC_MULTILINEUNDOREDO;
+                               }
+                               NotifyModified(
+                                       DocModification(modFlags, action.position, action.lenData,
+                                                                       linesAdded, action.data));
                        }
-                       if (step == steps - 1)
-                               modFlags |= SC_LASTSTEPINUNDOREDO;
-                       NotifyModified(
-                           DocModification(modFlags, action.position / 2, action.lenData,
-                                           LinesTotal() - prevLinesTotal, action.data));
-               }
 
-               bool endSavePoint = cb.IsSavePoint();
-               if (startSavePoint != endSavePoint)
-                       NotifySavePoint(endSavePoint);
+                       bool endSavePoint = cb.IsSavePoint();
+                       if (startSavePoint != endSavePoint)
+                               NotifySavePoint(endSavePoint);
+               }
                enteredCount--;
        }
        return newPos;
@@ -524,15 +562,17 @@ bool Document::InsertString(int position, const char *s) {
  */
 bool Document::InsertString(int position, const char *s, size_t insertLength) {
        bool changed = false;
-       char *sWithStyle = new char[insertLength * 2];
-       if (sWithStyle) {
-               for (size_t i = 0; i < insertLength; i++) {
-                       sWithStyle[i*2] = s[i];
-                       sWithStyle[i*2 + 1] = 0;
+       if (insertLength > 0) {
+               char *sWithStyle = new char[insertLength * 2];
+               if (sWithStyle) {
+                       for (size_t i = 0; i < insertLength; i++) {
+                               sWithStyle[i*2] = s[i];
+                               sWithStyle[i*2 + 1] = 0;
+                       }
+                       changed = InsertStyledString(position*2, sWithStyle,
+                               static_cast<int>(insertLength*2));
+                       delete []sWithStyle;
                }
-               changed = InsertStyledString(position*2, sWithStyle,
-                       static_cast<int>(insertLength*2));
-               delete []sWithStyle;
        }
        return changed;
 }
@@ -611,8 +651,10 @@ void Document::SetLineIndentation(int line, int indent) {
                CreateIndentation(linebuf, sizeof(linebuf), indent, tabInChars, !useTabs);
                int thisLineStart = LineStart(line);
                int indentPos = GetLineIndentPosition(line);
+               BeginUndoAction();
                DeleteChars(thisLineStart, indentPos - thisLineStart);
                InsertString(thisLineStart, linebuf);
+               EndUndoAction();
        }
 }
 
@@ -675,10 +717,13 @@ void Document::Indent(bool forwards, int lineBottom, int lineTop) {
        // Dedent - suck white space off the front of the line to dedent by equivalent of a tab
        for (int line = lineBottom; line >= lineTop; line--) {
                int indentOfLine = GetLineIndentation(line);
-               if (forwards)
-                       SetLineIndentation(line, indentOfLine + IndentSize());
-               else
+               if (forwards) {
+                       if (LineStart(line) < LineEnd(line)) {
+                               SetLineIndentation(line, indentOfLine + IndentSize());
+                       }
+               } else {
                        SetLineIndentation(line, indentOfLine - IndentSize());
+               }
        }
 }
 
@@ -718,7 +763,7 @@ void Document::ConvertLineEnds(int eolModeSet) {
 
        for (int pos = 0; pos < Length(); pos++) {
                if (cb.CharAt(pos) == '\r') {
-                       if (cb.CharAt(pos + 1) == '\n') { 
+                       if (cb.CharAt(pos + 1) == '\n') {
                                // CRLF
                                if (eolModeSet == SC_EOL_CR) {
                                        DeleteChars(pos + 1, 1); // Delete the LF
@@ -727,7 +772,7 @@ void Document::ConvertLineEnds(int eolModeSet) {
                                } else {
                                        pos++;
                                }
-                       } else { 
+                       } else {
                                // CR
                                if (eolModeSet == SC_EOL_CRLF) {
                                        InsertString(pos + 1, "\n", 1); // Insert LF
@@ -752,33 +797,45 @@ void Document::ConvertLineEnds(int eolModeSet) {
        EndUndoAction();
 }
 
-int Document::ParaDown(int pos) {
-       int line = LineFromPosition(pos);
-       while (line < LinesTotal() && LineStart(line) != LineEnd(line)) { // skip non-empty lines
-               line++;
-       }
-       while (line < LinesTotal() && LineStart(line) == LineEnd(line)) { // skip empty lines
-               line++;
+bool Document::IsWhiteLine(int line) {
+       int currentChar = LineStart(line);
+       int endLine = LineEnd(line);
+       while (currentChar < endLine) {
+               if (cb.CharAt(currentChar) != ' ' && cb.CharAt(currentChar) != '\t') {
+                       return false;
+               }
+               ++currentChar;
        }
-       if (line < LinesTotal())
-               return LineStart(line);
-       else // end of a document
-               return LineEnd(line-1);
+       return true;
 }
 
 int Document::ParaUp(int pos) {
        int line = LineFromPosition(pos);
        line--;
-       while (line >= 0 && LineStart(line) == LineEnd(line)) { // skip empty lines
+       while (line >= 0 && IsWhiteLine(line)) { // skip empty lines
                line--;
        }
-       while (line >= 0 && LineStart(line) != LineEnd(line)) { // skip non-empty lines
+       while (line >= 0 && !IsWhiteLine(line)) { // skip non-empty lines
                line--;
        }
        line++;
        return LineStart(line);
 }
 
+int Document::ParaDown(int pos) {
+       int line = LineFromPosition(pos);
+       while (line < LinesTotal() && !IsWhiteLine(line)) { // skip non-empty lines
+               line++;
+       }
+       while (line < LinesTotal() && IsWhiteLine(line)) { // skip empty lines
+               line++;
+       }
+       if (line < LinesTotal())
+               return LineStart(line);
+       else // end of a document
+               return LineEnd(line-1);
+}
+
 Document::charClassification Document::WordCharClass(unsigned char ch) {
        if ((SC_CP_UTF8 == dbcsCodePage) && (ch >= 0x80))
                return ccWord;
@@ -926,6 +983,9 @@ public:
                pdoc(pdoc_), end(end_) {
        }
 
+       virtual ~DocumentIndexer() {
+       }
+
        virtual char CharAt(int index) {
                if (index < 0 || index >= end)
                        return 0;
@@ -1001,7 +1061,7 @@ long Document::FindText(int minPos, int maxPos, const char *s,
                                if (line == lineRangeStart) {
                                        if ((startPos != endOfLine) && (searchEnd == '$'))
                                                continue;       // Can't match end of line if start position before end of line
-                                       endOfLine = startPos+1;
+                                       endOfLine = startPos;
                                }
                        }
 
@@ -1013,10 +1073,10 @@ long Document::FindText(int minPos, int maxPos, const char *s,
                                if (increment == -1) {
                                        // Check for the last match on this line.
                                        int repetitions = 1000; // Break out of infinite loop
-                                       while (success && (pre->eopat[0] <= (endOfLine+1)) && (repetitions--)) {
-                                               success = pre->Execute(di, pos+1, endOfLine+1);
+                                       while (success && (pre->eopat[0] <= endOfLine) && (repetitions--)) {
+                                               success = pre->Execute(di, pos+1, endOfLine);
                                                if (success) {
-                                                       if (pre->eopat[0] <= (minPos+1)) {
+                                                       if (pre->eopat[0] <= minPos) {
                                                                pos = pre->bopat[0];
                                                                lenRet = pre->eopat[0] - pre->bopat[0];
                                                        } else {
@@ -1052,12 +1112,13 @@ long Document::FindText(int minPos, int maxPos, const char *s,
                char firstChar = s[0];
                if (!caseSensitive)
                        firstChar = static_cast<char>(MakeUpperCase(firstChar));
-               int pos = startPos;
+               int pos = forward ? startPos : (startPos - 1);
                while (forward ? (pos < endSearch) : (pos >= endSearch)) {
                        char ch = CharAt(pos);
                        if (caseSensitive) {
                                if (ch == firstChar) {
                                        bool found = true;
+                                       if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false;
                                        for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
                                                ch = CharAt(pos + posMatch);
                                                if (ch != s[posMatch])
@@ -1073,6 +1134,7 @@ long Document::FindText(int minPos, int maxPos, const char *s,
                        } else {
                                if (MakeUpperCase(ch) == firstChar) {
                                        bool found = true;
+                                       if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false;
                                        for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
                                                ch = CharAt(pos + posMatch);
                                                if (MakeUpperCase(ch) != MakeUpperCase(s[posMatch]))
@@ -1185,11 +1247,9 @@ int Document::LinesTotal() {
 }
 
 void Document::ChangeCase(Range r, bool makeUpperCase) {
-       for (int pos = r.start; pos < r.end; pos++) {
+       for (int pos = r.start; pos < r.end;) {
                int len = LenChar(pos);
-               if (dbcsCodePage && (len > 1)) {
-                       pos += len;
-               } else {
+               if (len == 1) {
                        char ch = CharAt(pos);
                        if (makeUpperCase) {
                                if (IsLowerCase(ch)) {
@@ -1201,6 +1261,7 @@ void Document::ChangeCase(Range r, bool makeUpperCase) {
                                }
                        }
                }
+               pos += len;
        }
 }
 
@@ -1265,19 +1326,22 @@ bool Document::SetStyles(int length, char *styles) {
                return false;
        } else {
                enteredCount++;
-               int prevEndStyled = endStyled;
                bool didChange = false;
-               int lastChange = 0;
+               int startMod = 0;
+               int endMod = 0;
                for (int iPos = 0; iPos < length; iPos++, endStyled++) {
                        PLATFORM_ASSERT(endStyled < Length());
                        if (cb.SetStyleAt(endStyled, styles[iPos], stylingMask)) {
+                               if (!didChange) {
+                                       startMod = endStyled;
+                               }
                                didChange = true;
-                               lastChange = iPos;
+                               endMod = endStyled;
                        }
                }
                if (didChange) {
                        DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER,
-                                          prevEndStyled, lastChange);
+                                          startMod, endMod - startMod + 1);
                        NotifyModified(mh);
                }
                enteredCount--;
@@ -1475,3 +1539,55 @@ int Document::ExtendStyleRange(int pos, int delta, bool singleLine) {
        }
        return pos;
 }
+
+static char BraceOpposite(char ch) {
+       switch (ch) {
+       case '(':
+               return ')';
+       case ')':
+               return '(';
+       case '[':
+               return ']';
+       case ']':
+               return '[';
+       case '{':
+               return '}';
+       case '}':
+               return '{';
+       case '<':
+               return '>';
+       case '>':
+               return '<';
+       default:
+               return '\0';
+       }
+}
+
+// TODO: should be able to extend styled region to find matching brace
+int Document::BraceMatch(int position, int /*maxReStyle*/) {
+       char chBrace = CharAt(position);
+       char chSeek = BraceOpposite(chBrace);
+       if (chSeek == '\0')
+               return - 1;
+       char styBrace = static_cast<char>(StyleAt(position) & stylingBitsMask);
+       int direction = -1;
+       if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<')
+               direction = 1;
+       int depth = 1;
+       position = position + direction;
+       while ((position >= 0) && (position < Length())) {
+               position = MovePositionOutsideChar(position, direction);
+               char chAtPos = CharAt(position);
+               char styAtPos = static_cast<char>(StyleAt(position) & stylingBitsMask);
+               if ((position > GetEndStyled()) || (styAtPos == styBrace)) {
+                       if (chAtPos == chBrace)
+                               depth++;
+                       if (chAtPos == chSeek)
+                               depth--;
+                       if (depth == 0)
+                               return position;
+               }
+               position = position + direction;
+       }
+       return - 1;
+}
index ce27ffc47611e638e8365ef78285abd5e0d05df8..6ff858b9238b517fb90b438e3e3425f016685c2c 100644 (file)
@@ -134,6 +134,7 @@ public:
        int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
 
        // Gateways to modifying document
+       void ModifiedAt(int pos);
        bool DeleteChars(int pos, int len);
        bool InsertStyledString(int position, char *s, int insertLength);
        int Undo();
@@ -175,6 +176,7 @@ public:
        char StyleAt(int position) { return cb.StyleAt(position); }
        int GetMark(int line) { return cb.GetMark(line); }
        int AddMark(int line, int markerNum);
+       void AddMarkSet(int line, int valueSet);
        void DeleteMark(int line, int markerNum);
        void DeleteMarkFromHandle(int markerHandle);
        void DeleteAllMarks(int markerNum);
@@ -228,16 +230,19 @@ public:
        int WordPartLeft(int pos);
        int WordPartRight(int pos);
        int ExtendStyleRange(int pos, int delta, bool singleLine = false);
+       bool IsWhiteLine(int line);
        int ParaUp(int pos);
        int ParaDown(int pos);
        int IndentSize() { return actualIndentInChars; }
+       int BraceMatch(int position, int maxReStyle);
 
 private:
+       void CheckReadOnly();
+
        charClassification WordCharClass(unsigned char ch);
        bool IsWordStartAt(int pos);
        bool IsWordEndAt(int pos);
        bool IsWordAt(int start, int end);
-       void ModifiedAt(int pos);
 
        void NotifyModifyAttempt();
        void NotifySavePoint(bool atSavePoint);
@@ -261,19 +266,19 @@ public:
        int foldLevelPrev;
 
        DocModification(int modificationType_, int position_=0, int length_=0,
-               int linesAdded_=0, const char *text_=0) :
+               int linesAdded_=0, const char *text_=0, int line_=0) :
                modificationType(modificationType_),
                position(position_),
                length(length_),
                linesAdded(linesAdded_),
                text(text_),
-               line(0),
+               line(line_),
                foldLevelNow(0),
                foldLevelPrev(0) {}
 
-    DocModification(int modificationType_, const Action &act, int linesAdded_=0) :
+       DocModification(int modificationType_, const Action &act, int linesAdded_=0) :
                modificationType(modificationType_),
-               position(act.position / 2),
+               position(act.position),
                length(act.lenData),
                linesAdded(linesAdded_),
                text(act.data),
index 738eca7a07695a3f6be0e9ecb1dbd4fe189f7f94..f479ce0259258fe9d668a32c6efb3558c628721b 100644 (file)
@@ -58,7 +58,8 @@ bool DocumentAccessor::Match(int pos, const char *s) {
 }
 
 char DocumentAccessor::StyleAt(int position) {
-       return pdoc->StyleAt(position);
+       // Mask off all bits which aren't in the 'mask'.
+       return static_cast<char>(pdoc->StyleAt(position) & mask);
 }
 
 int DocumentAccessor::GetLine(int position) {
@@ -88,6 +89,8 @@ int DocumentAccessor::SetLineState(int line, int state) {
 }
 
 void DocumentAccessor::StartAt(unsigned int start, char chMask) {
+       // Store the mask specified for use with StyleAt.
+       mask = chMask;
        pdoc->StartStyling(start, chMask);
        startPosStyling = start;
 }
index dc591d13ec3142c08216f5451b18e752db0fb6e1..7406520452313cb6ed8106037b2952b3eab689e0 100644 (file)
@@ -27,6 +27,7 @@ protected:
        char chWhile;
        unsigned int startSeg;
        int startPosStyling;
+       int mask;
 
        bool InternalIsLeadByte(char ch);
        void Fill(int position);
@@ -35,7 +36,8 @@ public:
        DocumentAccessor(Document *pdoc_, PropSet &props_, WindowID id_=0) : 
                Accessor(), pdoc(pdoc_), props(props_), id(id_),
                lenDoc(-1), validLen(0), chFlags(0), chWhile(0), 
-               startSeg(0), startPosStyling(0) {
+               startSeg(0), startPosStyling(0),
+               mask(127) { // Initialize the mask to be big enough for any lexer.
        }
        ~DocumentAccessor();
        bool Match(int pos, const char *s);
index d32022ff118bfdc60ca6760c284dcf3dd0547469..0aa2a651c63278332608969654a6653dddf64fbf 100644 (file)
 #include "Document.h"
 #include "Editor.h"
 
+/*
+       return whether this modification represents an operation that
+       may reasonably be deferred (not done now OR [possibly] at all)
+*/
+static bool CanDeferToLastStep(const DocModification& mh) {
+       if (mh.modificationType & (SC_MOD_BEFOREINSERT|SC_MOD_BEFOREDELETE))
+               return true;    // CAN skip
+       if (!(mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO)))
+               return false;   // MUST do
+       if (mh.modificationType & SC_MULTISTEPUNDOREDO)
+               return true;    // CAN skip
+       return false;           // PRESUMABLY must do
+}
+
+static bool CanEliminate(const DocModification& mh) {
+       return
+               (mh.modificationType & (SC_MOD_BEFOREINSERT|SC_MOD_BEFOREDELETE)) != 0;
+}
+
+/*
+       return whether this modification represents the FINAL step
+       in a [possibly lengthy] multi-step Undo/Redo sequence
+*/
+static bool IsLastStep(const DocModification& mh) {
+       return
+               (mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO)) != 0
+               && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
+               && (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
+               && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
+}
+
 Caret::Caret() :
 active(false), on(false), period(500) {}
 
@@ -54,6 +85,7 @@ LineLayout::LineLayout(int maxLineLength_) :
        edgeColumn(0),
        chars(0),
        styles(0),
+       styleBitsSet(0),
        indicators(0),
        positions(0),
        hsStart(0),
@@ -157,7 +189,7 @@ void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[]) {
 
 LineLayoutCache::LineLayoutCache() :
        level(0), length(0), size(0), cache(0),
-       allInvalidated(false), styleClock(-1) {
+       allInvalidated(false), styleClock(-1), useCount(0) {
        Allocate(0);
 }
 
@@ -166,6 +198,7 @@ LineLayoutCache::~LineLayoutCache() {
 }
 
 void LineLayoutCache::Allocate(int length_) {
+       PLATFORM_ASSERT(cache == NULL);
        allInvalidated = false;
        length = length_;
        size = length;
@@ -180,6 +213,7 @@ void LineLayoutCache::Allocate(int length_) {
 }
 
 void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) {
+       PLATFORM_ASSERT(useCount == 0);
        int lengthForLevel = 0;
        if (level == llcCaret) {
                lengthForLevel = 1;
@@ -190,23 +224,28 @@ void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) {
        }
        if (lengthForLevel > size) {
                Deallocate();
-       } else if (lengthForLevel < length) {
-               for (int i = lengthForLevel; i < length; i++) {
-                       delete cache[i];
-                       cache[i] = 0;
-               }
-       }
-       if (!cache) {
                Allocate(lengthForLevel);
+       } else {
+               if (lengthForLevel < length) {
+                       for (int i = lengthForLevel; i < length; i++) {
+                               delete cache[i];
+                               cache[i] = 0;
+                       }
+               }
+               length = lengthForLevel;
        }
+       PLATFORM_ASSERT(length == lengthForLevel);
+       PLATFORM_ASSERT(cache != NULL || length == 0);
 }
 
 void LineLayoutCache::Deallocate() {
+       PLATFORM_ASSERT(useCount == 0);
        for (int i = 0; i < length; i++)
                delete cache[i];
        delete []cache;
        cache = 0;
        length = 0;
+       size = 0;
 }
 
 void LineLayoutCache::Invalidate(LineLayout::validLevel validity_) {
@@ -244,14 +283,15 @@ LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChar
                pos = 0;
        } else if (level == llcPage) {
                if (lineNumber == lineCaret) {
-                       pos = length;
+                       pos = 0;
                } else {
-                       pos = lineNumber % length;
+                       pos = 1 + (lineNumber % (length - 1));
                }
        } else if (level == llcDocument) {
                pos = lineNumber;
        }
        if (pos >= 0) {
+               PLATFORM_ASSERT(useCount == 0);
                if (cache && (pos < length)) {
                        if (cache[pos]) {
                                if ((cache[pos]->lineNumber != lineNumber) ||
@@ -267,6 +307,7 @@ LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChar
                                cache[pos]->lineNumber = lineNumber;
                                cache[pos]->inCache = true;
                                ret = cache[pos];
+                               useCount++;
                        }
                }
        }
@@ -284,7 +325,9 @@ void LineLayoutCache::Dispose(LineLayout *ll) {
        if (ll) {
                if (!ll->inCache) {
                        delete ll;
-               }
+               } else {
+                       useCount--;
+               }
        }
 }
 
@@ -344,6 +387,7 @@ Editor::Editor() {
        scrollWidth = 2000;
        verticalScrollBarVisible = true;
        endAtLastLine = true;
+       caretSticky = false;
 
        pixmapLine = Surface::Allocate();
        pixmapSelMargin = Surface::Allocate();
@@ -361,7 +405,7 @@ Editor::Editor() {
        topLine = 0;
        posTopLine = 0;
 
-       lengthForEncode = 0;
+       lengthForEncode = -1;
 
        needUpdateUI = true;
        braces[0] = invalidPosition;
@@ -392,6 +436,8 @@ Editor::Editor() {
        wrapVisualStartIndent = 0;
        actualWrapVisualStartIndent = 0;
 
+       convertPastes = true;
+
        hsStart = -1;
        hsEnd = -1;
 
@@ -420,6 +466,7 @@ void Editor::DropGraphics() {
        pixmapSelMargin->Release();
        pixmapSelPattern->Release();
        pixmapIndentGuide->Release();
+       pixmapIndentGuideHighlight->Release();
 }
 
 void Editor::InvalidateStyleData() {
@@ -842,13 +889,19 @@ void Editor::Redraw() {
        //wMain.InvalidateAll();
 }
 
-void Editor::RedrawSelMargin() {
+void Editor::RedrawSelMargin(int line) {
        if (!AbandonPaint()) {
                if (vs.maskInLine) {
                        Redraw();
                } else {
                        PRectangle rcSelMargin = GetClientRectangle();
                        rcSelMargin.right = vs.fixedColumnWidth;
+                       if (line != -1) {
+                               int position = pdoc->LineStart(line);
+                               PRectangle rcLine = RectangleFromRange(position, position);
+                               rcSelMargin.top = rcLine.top;
+                               rcSelMargin.bottom = rcLine.bottom;
+                       }
                        wMain.InvalidateRectangle(rcSelMargin);
                }
        }
@@ -899,6 +952,13 @@ int Editor::SelectionEnd() {
        return Platform::Maximum(currentPos, anchor);
 }
 
+void Editor::SetRectangularRange() {
+       if (selType == selRectangle) {
+               xStartSelect = XFromPosition(anchor);
+               xEndSelect = XFromPosition(currentPos);
+       }
+}
+
 void Editor::InvalidateSelection(int currentPos_, int anchor_) {
        int firstAffected = anchor;
        if (firstAffected > currentPos)
@@ -926,10 +986,7 @@ void Editor::SetSelection(int currentPos_, int anchor_) {
                currentPos = currentPos_;
                anchor = anchor_;
        }
-       if (selType == selRectangle) {
-               xStartSelect = XFromPosition(anchor);
-               xEndSelect = XFromPosition(currentPos);
-       }
+       SetRectangularRange();
        ClaimSelection();
 }
 
@@ -939,10 +996,7 @@ void Editor::SetSelection(int currentPos_) {
                InvalidateSelection(currentPos_, currentPos_);
                currentPos = currentPos_;
        }
-       if (selType == selRectangle) {
-               xStartSelect = XFromPosition(anchor);
-               xEndSelect = XFromPosition(currentPos);
-       }
+       SetRectangularRange();
        ClaimSelection();
 }
 
@@ -1065,11 +1119,15 @@ void Editor::ScrollTo(int line, bool moveThumb) {
                SetTopLine(topLineNew);
                ShowCaretAtCurrentPosition();
                // Perform redraw rather than scroll if many lines would be redrawn anyway.
+#ifndef UNDER_CE
                if (abs(linesToMove) <= 10) {
                        ScrollText(linesToMove);
                } else {
                        Redraw();
                }
+#else
+               Redraw();
+#endif
                if (moveThumb) {
                        SetVerticalScrollPos();
                }
@@ -1872,39 +1930,41 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
                posLineEnd = posLineStart + ll->maxLineLength;
        }
        if (ll->validity == LineLayout::llCheckTextAndStyle) {
-               int lineLength = 0;
-               for (int cid = posLineStart; cid < posLineEnd; cid++) {
-                       char chDoc = pdoc->CharAt(cid);
-                       if (vstyle.viewEOL || (!IsEOLChar(chDoc))) {
-                               lineLength++;
+               int lineLength = posLineEnd - posLineStart;
+               if (!vstyle.viewEOL) {
+                       int cid = posLineEnd - 1;
+                       while ((cid > posLineStart) && IsEOLChar(pdoc->CharAt(cid))) {
+                               cid--;
+                               lineLength--;
                        }
                }
                if (lineLength == ll->numCharsInLine) {
-                       int numCharsInLine = 0;
                        // See if chars, styles, indicators, are all the same
                        bool allSame = true;
                        const int styleMask = pdoc->stylingBitsMask;
                        // Check base line layout
-                       for (int charInDoc = posLineStart; allSame && (charInDoc < posLineEnd); charInDoc++) {
+                       char styleByte = 0;
+                       int numCharsInLine = 0;
+                       while (numCharsInLine < lineLength) {
+                               int charInDoc = numCharsInLine + posLineStart;
                                char chDoc = pdoc->CharAt(charInDoc);
-                               if (vstyle.viewEOL || (!IsEOLChar(chDoc))) {
-                                       char styleByte = pdoc->StyleAt(charInDoc);
+                               styleByte = pdoc->StyleAt(charInDoc);
+                               allSame = allSame &&
+                                               (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte & styleMask));
+                               allSame = allSame &&
+                                               (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask));
+                               if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed)
                                        allSame = allSame &&
-                                                 (ll->styles[numCharsInLine] == static_cast<char>(styleByte & styleMask));
+                                                       (ll->chars[numCharsInLine] == chDoc);
+                               else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
                                        allSame = allSame &&
-                                                 (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask));
-                                       if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseUpper)
-                                               allSame = allSame &&
-                                                         (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
-                                       else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
-                                               allSame = allSame &&
-                                                         (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
-                                       else
-                                               allSame = allSame &&
-                                                         (ll->chars[numCharsInLine] == chDoc);
-                                       numCharsInLine++;
-                               }
+                                                       (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
+                               else    // Style::caseUpper
+                                       allSame = allSame &&
+                                                       (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
+                               numCharsInLine++;
                        }
+                       allSame = allSame && (ll->styles[numCharsInLine] == styleByte); // For eolFilled
                        if (allSame) {
                                ll->validity = LineLayout::llPositions;
                        } else {
@@ -1929,10 +1989,12 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
 
                char styleByte = 0;
                int styleMask = pdoc->stylingBitsMask;
+               ll->styleBitsSet = 0;
                // Fill base line layout
                for (int charInDoc = posLineStart; charInDoc < posLineEnd; charInDoc++) {
                        char chDoc = pdoc->CharAt(charInDoc);
                        styleByte = pdoc->StyleAt(charInDoc);
+                       ll->styleBitsSet |= styleByte;
                        if (vstyle.viewEOL || (!IsEOLChar(chDoc))) {
                                ll->chars[numCharsInLine] = chDoc;
                                ll->styles[numCharsInLine] = static_cast<char>(styleByte & styleMask);
@@ -1959,6 +2021,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
                bool lastSegItalics = false;
                Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font;
 
+               int ctrlCharWidth[32] = {0};
                bool isControlNext = IsControlCharacter(ll->chars[0]);
                for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) {
                        bool isControl = isControlNext;
@@ -1972,9 +2035,13 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
                                                        ll->positions[charInLine + 1] = ((((startsegx + 2) /
                                                                                           tabWidth) + 1) * tabWidth) - startsegx;
                                                } else if (controlCharSymbol < 32) {
-                                                       const char *ctrlChar = ControlCharacterString(ll->chars[charInLine]);
-                                                       // +3 For a blank on front and rounded edge each side:
-                                                       ll->positions[charInLine + 1] = surface->WidthText(ctrlCharsFont, ctrlChar, istrlen(ctrlChar)) + 3;
+                                                       if (ctrlCharWidth[ll->chars[charInLine]] == 0) {
+                                                               const char *ctrlChar = ControlCharacterString(ll->chars[charInLine]);
+                                                               // +3 For a blank on front and rounded edge each side:
+                                                               ctrlCharWidth[ll->chars[charInLine]] =
+                                                                       surface->WidthText(ctrlCharsFont, ctrlChar, istrlen(ctrlChar)) + 3;
+                                                       }
+                                                       ll->positions[charInLine + 1] = ctrlCharWidth[ll->chars[charInLine]];
                                                } else {
                                                        char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
                                                        surface->MeasureWidths(ctrlCharsFont, cc, 1,
@@ -2059,7 +2126,12 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
                                        continue;
                                }
                                if (p > 0) {
-                                       if (ll->styles[p] != ll->styles[p - 1]) {
+                                       if (wrapState == eWrapChar){
+                                               lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
+                                                                                               - posLineStart;
+                                               p = pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
+                                               continue;
+                                       } else if (ll->styles[p] != ll->styles[p - 1]) {
                                                lastGoodBreak = p;
                                        } else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) {
                                                lastGoodBreak = p;
@@ -2358,6 +2430,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
                                                }
                                        }
                                }
+                       } else if (rcSegment.left > rcLine.right) {
+                               break;
                        }
                        startseg = i + 1;
                }
@@ -2520,41 +2594,46 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
                                        rcUL.bottom = rcUL.top + 1;
                                        surface->FillRectangle(rcUL, textFore);
                                }
+                       } else if (rcSegment.left > rcLine.right) {
+                               break;
                        }
                        startseg = i + 1;
                }
        }
 
        // Draw indicators
-       int indStart[INDIC_MAX + 1] = {0};
-       for (int indica = 0; indica <= INDIC_MAX; indica++)
-               indStart[indica] = 0;
-
-       for (int indicPos = lineStart; indicPos <= lineEnd; indicPos++) {
-               if ((indicPos == lineStart) || (indicPos == lineEnd) ||
-                       (ll->indicators[indicPos] != ll->indicators[indicPos + 1])) {
-                       int mask = 1 << pdoc->stylingBits;
-                       for (int indicnum = 0; mask < 0x100; indicnum++) {
-                               if ((indicPos == lineStart) || (indicPos == lineEnd)) {
-                                       indStart[indicnum] = ll->positions[indicPos];
-                               } else if ((ll->indicators[indicPos + 1] & mask) && !(ll->indicators[indicPos] & mask)) {
-                                       indStart[indicnum] = ll->positions[indicPos + 1];
-                               }
-                               if ((ll->indicators[indicPos] & mask) &&
-                                       ((indicPos == lineEnd) || !(ll->indicators[indicPos + 1] & mask))) {
-                                       int endIndicator = indicPos;
-                                       if (endIndicator >= lineEnd)
-                                               endIndicator = lineEnd-1;
+       // foreach indicator...
+       for (int indicnum = 0, mask = 1 << pdoc->stylingBits; mask < 0x100; indicnum++) {
+               if (!(mask & ll->styleBitsSet)) {
+                       mask <<= 1;
+                       continue;
+               }
+               int startPos = -1;
+               // foreach style pos in line...
+               for (int indicPos = lineStart; indicPos <= lineEnd; indicPos++) {
+                       // look for starts...
+                       if (startPos < 0) {
+                               // NOT in indicator run, looking for START
+                               if (indicPos < lineEnd && (ll->indicators[indicPos] & mask))
+                                       startPos = indicPos;
+                       }
+                       // ... or ends
+                       if (startPos >= 0) {
+                               // IN indicator run, looking for END
+                               if (indicPos >= lineEnd || !(ll->indicators[indicPos] & mask)) {
+                                       // AT end of indicator run, DRAW it!
                                        PRectangle rcIndic(
-                                               indStart[indicnum] + xStart - subLineStart,
+                                               ll->positions[startPos] + xStart - subLineStart,
                                                rcLine.top + vsDraw.maxAscent,
-                                               ll->positions[endIndicator + 1] + xStart - subLineStart,
+                                               ll->positions[indicPos] + xStart - subLineStart,
                                                rcLine.top + vsDraw.maxAscent + 3);
                                        vsDraw.indicators[indicnum].Draw(surface, rcIndic, rcLine);
+                                       // RESET control var
+                                       startPos = -1;
                                }
-                               mask = mask << 1;
                        }
                }
+               mask <<= 1;
        }
        // End of the drawing of the current line
        if (!twoPhaseDraw) {
@@ -2629,7 +2708,7 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) {
        if (bufferedDraw) {
                if (!pixmapLine->Initialised()) {
                        PRectangle rcClient = GetClientRectangle();
-                       pixmapLine->InitPixMap(rcClient.Width(), rcClient.Height(),
+                       pixmapLine->InitPixMap(rcClient.Width(), vs.lineHeight,
                                               surfaceWindow, wMain.GetID());
                        pixmapSelMargin->InitPixMap(vs.fixedColumnWidth,
                                                    rcClient.Height(), surfaceWindow, wMain.GetID());
@@ -2760,6 +2839,8 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
                        //ElapsedTime et;
                        if (lineDoc != lineDocPrevious) {
                                ll.Set(0);
+                               // For rectangular selection this accesses the layout cache so should be after layout returned.
+                               lineIterator.SetAt(lineDoc);
                                ll.Set(RetrieveLineLayout(lineDoc));
                                LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
                                lineDocPrevious = lineDoc;
@@ -2771,7 +2852,6 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
                                        ll->selStart = SelectionStart();
                                        ll->selEnd = SelectionEnd();
                                } else {
-                                       lineIterator.SetAt(lineDoc);
                                        ll->selStart = lineIterator.startPos;
                                        ll->selEnd = lineIterator.endPos;
                                }
@@ -2920,6 +3000,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
                        visibleLine++;
                        //gdk_flush();
                }
+               ll.Set(0);
                //if (durPaint < 0.00000001)
                //      durPaint = 0.00000001;
 
@@ -3160,6 +3241,9 @@ void Editor::SetScrollBars() {
        int nMax = MaxScrollPos();
        int nPage = LinesOnScreen();
        bool modified = ModifyScrollBars(nMax + nPage - 1, nPage);
+       if (modified) {
+               DwellEnd(true);
+       }
 
        // TODO: ensure always showing as many lines as possible
        // May not be, if, for example, window made larger
@@ -3199,9 +3283,12 @@ void Editor::AddChar(char ch) {
 void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
        bool wasSelection = currentPos != anchor;
        ClearSelection();
+       bool charReplaceAction = false;
        if (inOverstrike && !wasSelection && !RangeContainsProtected(currentPos, currentPos + 1)) {
                if (currentPos < (pdoc->Length())) {
                        if (!IsEOLChar(pdoc->CharAt(currentPos))) {
+                               charReplaceAction = true;
+                               pdoc->BeginUndoAction();
                                pdoc->DelChar(currentPos);
                        }
                }
@@ -3209,10 +3296,15 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
        if (pdoc->InsertString(currentPos, s, len)) {
                SetEmptySelection(currentPos + len);
        }
+       if (charReplaceAction) {
+               pdoc->EndUndoAction();
+       }
        EnsureCaretVisible();
        // Avoid blinking during rapid typing:
        ShowCaretAtCurrentPosition();
-       SetLastXChosen();
+       if (!caretSticky) {
+               SetLastXChosen();
+       }
 
        if (treatAsDBCS) {
                NotifyChar((static_cast<unsigned char>(s[0]) << 8) |
@@ -3292,7 +3384,7 @@ void Editor::ClearAll() {
        currentPos = 0;
        SetTopLine(0);
        SetVerticalScrollPos();
-        InvalidateStyleRedraw();        // RPD: patch #1106564
+       InvalidateStyleRedraw();
 }
 
 void Editor::ClearDocumentStyle() {
@@ -3371,7 +3463,8 @@ void Editor::Undo() {
        if (pdoc->CanUndo()) {
                InvalidateCaret();
                int newPos = pdoc->Undo();
-               SetEmptySelection(newPos);
+               if (newPos >= 0)
+                       SetEmptySelection(newPos);
                EnsureCaretVisible();
        }
 }
@@ -3379,7 +3472,8 @@ void Editor::Undo() {
 void Editor::Redo() {
        if (pdoc->CanRedo()) {
                int newPos = pdoc->Redo();
-               SetEmptySelection(newPos);
+               if (newPos >= 0)
+                       SetEmptySelection(newPos);
                EnsureCaretVisible();
        }
 }
@@ -3425,7 +3519,7 @@ void Editor::DelCharBack(bool allowLineStartDeletion) {
 void Editor::NotifyFocus(bool) {}
 
 void Editor::NotifyStyleToNeeded(int endStyleNeeded) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_STYLENEEDED;
        scn.position = endStyleNeeded;
        NotifyParent(scn);
@@ -3436,7 +3530,7 @@ void Editor::NotifyStyleNeeded(Document*, void *, int endStyleNeeded) {
 }
 
 void Editor::NotifyChar(int ch) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_CHARADDED;
        scn.ch = ch;
        NotifyParent(scn);
@@ -3449,7 +3543,7 @@ void Editor::NotifyChar(int ch) {
 }
 
 void Editor::NotifySavePoint(bool isSavePoint) {
-       SCNotification scn;
+       SCNotification scn = {0};
        if (isSavePoint) {
                scn.nmhdr.code = SCN_SAVEPOINTREACHED;
        } else {
@@ -3459,19 +3553,19 @@ void Editor::NotifySavePoint(bool isSavePoint) {
 }
 
 void Editor::NotifyModifyAttempt() {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_MODIFYATTEMPTRO;
        NotifyParent(scn);
 }
 
 void Editor::NotifyDoubleClick(Point, bool) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_DOUBLECLICK;
        NotifyParent(scn);
 }
 
 void Editor::NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_HOTSPOTDOUBLECLICK;
        scn.position = position;
        scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
@@ -3480,7 +3574,7 @@ void Editor::NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, boo
 }
 
 void Editor::NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_HOTSPOTCLICK;
        scn.position = position;
        scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
@@ -3489,13 +3583,13 @@ void Editor::NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt)
 }
 
 void Editor::NotifyUpdateUI() {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_UPDATEUI;
        NotifyParent(scn);
 }
 
 void Editor::NotifyPainted() {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_PAINTED;
        NotifyParent(scn);
 }
@@ -3509,7 +3603,7 @@ bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
                x += vs.ms[margin].width;
        }
        if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
-               SCNotification scn;
+               SCNotification scn = {0};
                scn.nmhdr.code = SCN_MARGINCLICK;
                scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
                                (alt ? SCI_ALT : 0);
@@ -3523,7 +3617,7 @@ bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
 }
 
 void Editor::NotifyNeedShown(int pos, int len) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_NEEDSHOWN;
        scn.position = pos;
        scn.length = len;
@@ -3531,7 +3625,7 @@ void Editor::NotifyNeedShown(int pos, int len) {
 }
 
 void Editor::NotifyDwelling(Point pt, bool state) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = state ? SCN_DWELLSTART : SCN_DWELLEND;
        scn.position = PositionFromLocationClose(pt);
        scn.x = pt.x;
@@ -3540,7 +3634,7 @@ void Editor::NotifyDwelling(Point pt, bool state) {
 }
 
 void Editor::NotifyZoom() {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_ZOOM;
        NotifyParent(scn);
 }
@@ -3552,7 +3646,7 @@ void Editor::NotifyModifyAttempt(Document*, void *) {
 }
 
 void Editor::NotifyMove(int position) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_POSCHANGED;
        scn.position = position;
        NotifyParent(scn);
@@ -3564,8 +3658,7 @@ void Editor::NotifySavePoint(Document*, void *, bool atSavePoint) {
 }
 
 void Editor::CheckModificationForWrap(DocModification mh) {
-       if ((mh.modificationType & SC_MOD_INSERTTEXT) ||
-               (mh.modificationType & SC_MOD_DELETETEXT)) {
+       if (mh.modificationType & (SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT)) {
                llc.Invalidate(LineLayout::llCheckTextAndStyle);
                if (wrapState != eWrapNone) {
                        int lineDoc = pdoc->LineFromPosition(mh.position);
@@ -3641,7 +3734,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
                        // Some lines are hidden so may need shown.
                        // TODO: check if the modified area is hidden.
                        if (mh.modificationType & SC_MOD_BEFOREINSERT) {
-                               NotifyNeedShown(mh.position, mh.length);
+                               NotifyNeedShown(mh.position, 0);
                        } else if (mh.modificationType & SC_MOD_BEFOREDELETE) {
                                NotifyNeedShown(mh.position, mh.length);
                        }
@@ -3659,7 +3752,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
                CheckModificationForWrap(mh);
                if (mh.linesAdded != 0) {
                        // Avoid scrolling of display if change before current display
-                       if (mh.position < posTopLine) {
+                       if (mh.position < posTopLine && !CanDeferToLastStep(mh)) {
                                int newTop = Platform::Clamp(topLine + mh.linesAdded, 0, MaxScrollPos());
                                if (newTop != topLine) {
                                        SetTopLine(newTop);
@@ -3670,28 +3763,39 @@ 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) {
+                       if (paintState == notPainting && !CanDeferToLastStep(mh)) {
                                Redraw();
                        }
                } else {
                        //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this,
                        //      mh.position, mh.position + mh.length);
-                       if (paintState == notPainting) {
+                       if (paintState == notPainting && mh.length && !CanEliminate(mh)) {
                                InvalidateRange(mh.position, mh.position + mh.length);
                        }
                }
        }
 
-       if (mh.linesAdded != 0) {
+       if (mh.linesAdded != 0 && !CanDeferToLastStep(mh)) {
                SetScrollBars();
        }
 
        if (mh.modificationType & SC_MOD_CHANGEMARKER) {
-               if (paintState == notPainting) {
-                       RedrawSelMargin();
+               if ((paintState == notPainting) || !PaintContainsMargin()) {
+                       if (mh.modificationType & SC_MOD_CHANGEFOLD) {
+                               // Fold changes can affect the drawing of following lines so redraw whole margin
+                               RedrawSelMargin();
+                       } else {
+                               RedrawSelMargin(mh.line);
+                       }
                }
        }
 
+       // NOW pay the piper WRT "deferred" visual updates
+       if (IsLastStep(mh)) {
+               SetScrollBars();
+               Redraw();
+       }
+
        // If client wants to see this modification
        if (mh.modificationType & modEventMask) {
                if ((mh.modificationType & SC_MOD_CHANGESTYLE) == 0) {
@@ -3699,7 +3803,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
                        NotifyChange(); // Send EN_CHANGE
                }
 
-               SCNotification scn;
+               SCNotification scn = {0};
                scn.nmhdr.code = SCN_MODIFIED;
                scn.position = mh.position;
                scn.modificationType = mh.modificationType;
@@ -3717,7 +3821,7 @@ void Editor::NotifyDeleted(Document *, void *) {
        /* Do nothing */
 }
 
-void Editor::NotifyMacroRecord(unsigned int iMessage, unsigned long wParam, long lParam) {
+void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
 
        // Enumerates all macroable messages
        switch (iMessage) {
@@ -3818,6 +3922,7 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, unsigned long wParam, long
        case SCI_LINEENDRECTEXTEND:
        case SCI_PAGEUPRECTEXTEND:
        case SCI_PAGEDOWNRECTEXTEND:
+       case SCI_SELECTIONDUPLICATE:
                break;
 
        // Filter out all others like display changes. Also, newlines are redundant
@@ -3829,7 +3934,7 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, unsigned long wParam, long
        }
 
        // Send notification
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_MACRORECORD;
        scn.message = iMessage;
        scn.wParam = wParam;
@@ -3931,15 +4036,26 @@ void Editor::LineTranspose() {
        }
 }
 
-void Editor::LineDuplicate() {
-       int line = pdoc->LineFromPosition(currentPos);
-       int start = pdoc->LineStart(line);
-       int end = pdoc->LineEnd(line);
-       char *thisLine = CopyRange(start, end);
-       const char *eol = StringFromEOLMode(pdoc->eolMode);
-       pdoc->InsertString(end, eol);
-       pdoc->InsertString(end + istrlen(eol), thisLine, end - start);
-       delete []thisLine;
+void Editor::Duplicate(bool forLine) {
+       int start = SelectionStart();
+       int end = SelectionEnd();
+       if (start == end) {
+               forLine = true;
+       }
+       if (forLine) {
+               int line = pdoc->LineFromPosition(currentPos);
+               start = pdoc->LineStart(line);
+               end = pdoc->LineEnd(line);
+       }
+       char *text = CopyRange(start, end);
+       if (forLine) {
+               const char *eol = StringFromEOLMode(pdoc->eolMode);
+               pdoc->InsertString(end, eol);
+               pdoc->InsertString(end + istrlen(eol), text, end - start);
+       } else {
+               pdoc->InsertString(end, text, end - start);
+       }
+       delete []text;
 }
 
 void Editor::CancelModes() {
@@ -3963,6 +4079,8 @@ void Editor::NewLine() {
        }
        SetLastXChosen();
        EnsureCaretVisible();
+       // Avoid blinking during rapid typing:
+       ShowCaretAtCurrentPosition();
 }
 
 void Editor::CursorUpOrDown(int direction, selTypes sel) {
@@ -3983,6 +4101,22 @@ void Editor::CursorUpOrDown(int direction, selTypes sel) {
        MovePositionTo(posNew, sel);
 }
 
+void Editor::ParaUpOrDown(int direction, selTypes sel) {
+       int lineDoc, savedPos = currentPos;
+       do {
+               MovePositionTo(direction > 0 ? pdoc->ParaDown(currentPos) : pdoc->ParaUp(currentPos), sel);
+               lineDoc = pdoc->LineFromPosition(currentPos);
+               if (direction > 0) {
+                       if (currentPos >= pdoc->Length() && !cs.GetVisible(lineDoc)) {
+                               if (sel == noSel) {
+                                       MovePositionTo(pdoc->LineEndPosition(savedPos));
+                               }
+                               break;
+                       }
+               }
+       } while (!cs.GetVisible(lineDoc));
+}
+
 int Editor::StartEndDisplayLine(int pos, bool start) {
        RefreshStyleData();
        int line = pdoc->LineFromPosition(pos);
@@ -4027,10 +4161,10 @@ int Editor::KeyCommand(unsigned int iMessage) {
                CursorUpOrDown(1, selRectangle);
                break;
        case SCI_PARADOWN:
-               MovePositionTo(pdoc->ParaDown(currentPos));
+               ParaUpOrDown(1);
                break;
        case SCI_PARADOWNEXTEND:
-               MovePositionTo(pdoc->ParaDown(currentPos), selStream);
+               ParaUpOrDown(1, selStream);
                break;
        case SCI_LINESCROLLDOWN:
                ScrollTo(topLine + 1);
@@ -4046,10 +4180,10 @@ int Editor::KeyCommand(unsigned int iMessage) {
                CursorUpOrDown(-1, selRectangle);
                break;
        case SCI_PARAUP:
-               MovePositionTo(pdoc->ParaUp(currentPos));
+               ParaUpOrDown(-1);
                break;
        case SCI_PARAUPEXTEND:
-               MovePositionTo(pdoc->ParaUp(currentPos), selStream);
+               ParaUpOrDown(-1, selStream);
                break;
        case SCI_LINESCROLLUP:
                ScrollTo(topLine - 1);
@@ -4239,22 +4373,30 @@ int Editor::KeyCommand(unsigned int iMessage) {
                break;
        case SCI_DELETEBACK:
                DelCharBack(true);
-               SetLastXChosen();
+               if (!caretSticky) {
+                       SetLastXChosen();
+               }
                EnsureCaretVisible();
                break;
        case SCI_DELETEBACKNOTLINE:
                DelCharBack(false);
-               SetLastXChosen();
+               if (!caretSticky) {
+                       SetLastXChosen();
+               }
                EnsureCaretVisible();
                break;
        case SCI_TAB:
                Indent(true);
-               SetLastXChosen();
+               if (!caretSticky) {
+                       SetLastXChosen();
+               }
                EnsureCaretVisible();
                break;
        case SCI_BACKTAB:
                Indent(false);
-               SetLastXChosen();
+               if (!caretSticky) {
+                       SetLastXChosen();
+               }
                EnsureCaretVisible();
                break;
        case SCI_NEWLINE:
@@ -4361,7 +4503,10 @@ int Editor::KeyCommand(unsigned int iMessage) {
                LineTranspose();
                break;
        case SCI_LINEDUPLICATE:
-               LineDuplicate();
+               Duplicate(true);
+               break;
+       case SCI_SELECTIONDUPLICATE:
+               Duplicate(false);
                break;
        case SCI_LOWERCASE:
                ChangeCaseOfSelection(false);
@@ -4978,7 +5123,7 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b
                                NotifyHotSpotClicked(newPos, shift, ctrl, alt);
                        }
                        if (!shift) {
-                               inDragDrop = PointInSelection(pt);
+                               inDragDrop = PointInSelection(pt) && !SelectionEmpty();
                        }
                        if (inDragDrop) {
                                SetMouseCapture(false);
@@ -4992,9 +5137,9 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b
                                        SetEmptySelection(newPos);
                                }
                                selType = alt ? selRectangle : selStream;
-                               xStartSelect = xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
                                selectionType = selChar;
                                originalAnchorPos = currentPos;
+                               SetRectangularRange();
                        }
                }
        }
@@ -5131,7 +5276,7 @@ void Editor::ButtonMove(Point pt) {
                        }
                }
                // Display regular (drag) cursor over selection
-               if (PointInSelection(pt)) {
+               if (PointInSelection(pt) && !SelectionEmpty()) {
                        DisplayCursor(Window::cursorArrow);
                } else if (PointIsHotspot(pt)) {
                        DisplayCursor(Window::cursorHand);
@@ -5144,7 +5289,7 @@ void Editor::ButtonMove(Point pt) {
 }
 
 void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
-       //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture());
+        //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture());
        if (HaveMouseCapture()) {
                if (PointInSelMargin(pt)) {
                        DisplayCursor(Window::cursorReverseArrow);
@@ -5188,9 +5333,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
                                SetSelection(newPos);
                        }
                }
-               // Now we rely on the current pos to compute rectangular selection
-               xStartSelect = XFromPosition(anchor);
-               xEndSelect = XFromPosition(currentPos);
+               SetRectangularRange();
                lastClickTime = curTime;
                lastClick = pt;
                lastXChosen = pt.x;
@@ -5214,7 +5357,9 @@ void Editor::Tick() {
                if (timer.ticksToWait <= 0) {
                        caret.on = !caret.on;
                        timer.ticksToWait = caret.period;
-                       InvalidateCaret();
+                       if (caret.active) {
+                               InvalidateCaret();
+                       }
                }
        }
        if ((dwellDelay < SC_TIME_FOREVER) &&
@@ -5263,16 +5408,14 @@ void Editor::SetFocusState(bool focusState) {
        }
 }
 
-static bool IsIn(int a, int minimum, int maximum) {
-       return (a >= minimum) && (a <= maximum);
+bool Editor::PaintContains(PRectangle rc) {
+       return rcPaint.Contains(rc);
 }
 
-static bool IsOverlap(int mina, int maxa, int minb, int maxb) {
-       return
-           IsIn(mina, minb, maxb) ||
-           IsIn(maxa, minb, maxb) ||
-           IsIn(minb, mina, maxa) ||
-           IsIn(maxb, mina, maxa);
+bool Editor::PaintContainsMargin() {
+       PRectangle rcSelMargin = GetClientRectangle();
+       rcSelMargin.right = vs.fixedColumnWidth;
+       return PaintContains(rcSelMargin);
 }
 
 void Editor::CheckForChangeOutsidePaint(Range r) {
@@ -5281,99 +5424,21 @@ void Editor::CheckForChangeOutsidePaint(Range r) {
                if (!r.Valid())
                        return;
 
+               PRectangle rcRange = RectangleFromRange(r.start, r.end);
                PRectangle rcText = GetTextRectangle();
-               // Determine number of lines displayed including a possible partially displayed last line
-               int linesDisplayed = (rcText.bottom - rcText.top - 1) / vs.lineHeight + 1;
-               int bottomLine = topLine + linesDisplayed - 1;
-
-               int lineRangeStart = cs.DisplayFromDoc(pdoc->LineFromPosition(r.start));
-               int lineRangeEnd = cs.DisplayFromDoc(pdoc->LineFromPosition(r.end));
-               if (!IsOverlap(topLine, bottomLine, lineRangeStart, lineRangeEnd)) {
-                       //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n",
-                       //              lineRangeStart, lineRangeEnd, topLine, bottomLine);
-                       return;
+               if (rcRange.top < rcText.top) {
+                       rcRange.top = rcText.top;
                }
-
-               // Assert rcPaint contained within or equal to rcText
-               if (rcPaint.top > rcText.top) {
-                       // does range intersect rcText.top .. rcPaint.top
-                       int paintTopLine = ((rcPaint.top - rcText.top - 1) / vs.lineHeight) + topLine;
-                       // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle
-                       if (IsOverlap(topLine, paintTopLine, lineRangeStart, lineRangeEnd)) {
-                               //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n",
-                               //      lineRangeStart, lineRangeEnd, topLine, paintTopLine);
-                               AbandonPaint();
-                               return;
-                       }
+               if (rcRange.bottom > rcText.bottom) {
+                       rcRange.bottom = rcText.bottom;
                }
-               if (rcPaint.bottom < rcText.bottom) {
-                       // does range intersect rcPaint.bottom .. rcText.bottom
-                       int paintBottomLine = ((rcPaint.bottom - rcText.top - 1) / vs.lineHeight + 1) + topLine;
-                       // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle
-                       if (IsOverlap(paintBottomLine, bottomLine, lineRangeStart, lineRangeEnd)) {
-                               //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n",
-                               //      lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine);
-                               AbandonPaint();
-                               return;
-                       }
+
+               if (!PaintContains(rcRange)) {
+                       AbandonPaint();
                }
        }
 }
 
-char BraceOpposite(char ch) {
-       switch (ch) {
-       case '(':
-               return ')';
-       case ')':
-               return '(';
-       case '[':
-               return ']';
-       case ']':
-               return '[';
-       case '{':
-               return '}';
-       case '}':
-               return '{';
-       case '<':
-               return '>';
-       case '>':
-               return '<';
-       default:
-               return '\0';
-       }
-}
-
-// TODO: should be able to extend styled region to find matching brace
-// TODO: may need to make DBCS safe
-// so should be moved into Document
-int Editor::BraceMatch(int position, int /*maxReStyle*/) {
-       char chBrace = pdoc->CharAt(position);
-       char chSeek = BraceOpposite(chBrace);
-       if (chSeek == '\0')
-               return - 1;
-       char styBrace = static_cast<char>(
-                           pdoc->StyleAt(position) & pdoc->stylingBitsMask);
-       int direction = -1;
-       if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<')
-               direction = 1;
-       int depth = 1;
-       position = position + direction;
-       while ((position >= 0) && (position < pdoc->Length())) {
-               char chAtPos = pdoc->CharAt(position);
-               char styAtPos = static_cast<char>(pdoc->StyleAt(position) & pdoc->stylingBitsMask);
-               if ((position > pdoc->GetEndStyled()) || (styAtPos == styBrace)) {
-                       if (chAtPos == chBrace)
-                               depth++;
-                       if (chAtPos == chSeek)
-                               depth--;
-                       if (depth == 0)
-                               return position;
-               }
-               position = position + direction;
-       }
-       return - 1;
-}
-
 void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {
        if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) {
                if ((braces[0] != pos0) || (matchStyle != bracesMatchStyle)) {
@@ -5421,8 +5486,8 @@ void Editor::SetDocPointer(Document *document) {
        NeedWrapping();
 
        pdoc->AddWatcher(this, 0);
-       Redraw();
        SetScrollBars();
+       Redraw();
 }
 
 /**
@@ -5558,6 +5623,18 @@ int Editor::CodePage() const {
                return 0;
 }
 
+int Editor::WrapCount(int line) {
+       AutoSurface surface(this);
+       AutoLineLayout ll(llc, RetrieveLineLayout(line));
+
+       if (surface && ll) {
+               LayoutLine(line, surface, vs, ll, wrapWidth);
+               return ll->lines;
+       } else {
+               return 1;
+       }
+}
+
 static bool ValidMargin(unsigned long wParam) {
        return wParam < ViewStyle::margins;
 }
@@ -5621,7 +5698,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
 
        case SCI_PASTE:
                Paste();
-               SetLastXChosen();
+               if (!caretSticky) {
+                       SetLastXChosen();
+               }
                EnsureCaretVisible();
                break;
 
@@ -5637,7 +5716,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                break;
 
        case SCI_CANUNDO:
-               return pdoc->CanUndo() ? 1 : 0;
+               return (pdoc->CanUndo() && !pdoc->IsReadOnly()) ? 1 : 0;
 
        case SCI_EMPTYUNDOBUFFER:
                pdoc->DeleteUndoHistory();
@@ -6066,7 +6145,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                }
 
        case SCI_CANREDO:
-               return pdoc->CanRedo() ? 1 : 0;
+               return (pdoc->CanRedo() && !pdoc->IsReadOnly()) ? 1 : 0;
 
        case SCI_MARKERLINEFROMHANDLE:
                return pdoc->LineFromHandle(wParam);
@@ -6106,6 +6185,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                        if (lParam == 0) {
                                return 1 + lineEnd - lineStart;
                        }
+                       PLATFORM_ASSERT(wParam > 0);
                        char *ptr = CharPtrFromSPtr(lParam);
                        unsigned int iPlace = 0;
                        for (unsigned int iChar = lineStart; iChar < lineEnd && iPlace < wParam - 1; iChar++) {
@@ -6225,7 +6305,17 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                return pdoc->ExtendWordSelect(wParam, 1, lParam != 0);
 
        case SCI_SETWRAPMODE:
-               wrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone;
+               switch(wParam){
+                       case SC_WRAP_WORD:
+                               wrapState = eWrapWord;
+                               break;
+                       case SC_WRAP_CHAR:
+                               wrapState = eWrapChar;
+                               break;
+                       default:
+                               wrapState = eWrapNone;
+                               break;
+               }
                xOffset = 0;
                InvalidateStyleRedraw();
                ReconfigureScrollBars();
@@ -6311,6 +6401,20 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
        case SCI_GETENDATLASTLINE:
                return endAtLastLine;
 
+       case SCI_SETCARETSTICKY:
+               PLATFORM_ASSERT((wParam == 0) || (wParam == 1));
+               if (caretSticky != (wParam != 0)) {
+                       caretSticky = wParam != 0;
+               }
+               break;
+
+       case SCI_GETCARETSTICKY:
+               return caretSticky;
+
+       case SCI_TOGGLECARETSTICKY:
+               caretSticky = !caretSticky;
+               break;
+
        case SCI_GETCOLUMN:
                return pdoc->GetColumn(wParam);
 
@@ -6399,6 +6503,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                        int markerID = pdoc->AddMark(wParam, lParam);
                        return markerID;
                }
+       case SCI_MARKERADDSET:
+               if (lParam != 0)
+                       pdoc->AddMarkSet(wParam, lParam);
+               break;
 
        case SCI_MARKERDELETE:
                pdoc->DeleteMark(wParam, lParam);
@@ -6618,6 +6726,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
        case SCI_DOCLINEFROMVISIBLE:
                return cs.DocFromDisplay(wParam);
 
+       case SCI_WRAPCOUNT:
+               return WrapCount(wParam);
+
        case SCI_SETFOLDLEVEL: {
                        int prev = pdoc->SetLevel(wParam, lParam);
                        if (prev != lParam)
@@ -6873,6 +6984,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
        case SCI_LINEENDRECTEXTEND:
        case SCI_PAGEUPRECTEXTEND:
        case SCI_PAGEDOWNRECTEXTEND:
+       case SCI_SELECTIONDUPLICATE:
                return KeyCommand(iMessage);
 
        case SCI_BRACEHIGHLIGHT:
@@ -6886,7 +6998,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
        case SCI_BRACEMATCH:
                // wParam is position of char to find brace for,
                // lParam is maximum amount of text to restyle to find it
-               return BraceMatch(wParam, lParam);
+               return pdoc->BraceMatch(wParam, lParam);
 
        case SCI_GETVIEWEOL:
                return vs.viewEOL;
@@ -7103,6 +7215,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                InvalidateStyleRedraw();
                break;
 
+       case SCI_SETPASTECONVERTENDINGS:
+               convertPastes = wParam != 0;
+               break;
+
+       case SCI_GETPASTECONVERTENDINGS:
+               return convertPastes ? 1 : 0;
+
        default:
                return DefWndProc(iMessage, wParam, lParam);
        }
index e14cb5ed95c125891c6a4f16cea35c3365ebaa47..9243d3a2f42cf433ade40a24c2b170208b0c975d 100644 (file)
@@ -64,6 +64,7 @@ public:
        int edgeColumn;
        char *chars;
        unsigned char *styles;
+       int styleBitsSet;
        char *indicators;
        int *positions;
        char bracePreviousStyles[2];
@@ -105,6 +106,7 @@ class LineLayoutCache {
        LineLayout **cache;
        bool allInvalidated;
        int styleClock;
+       int useCount;
        void Allocate(int length_);
        void AllocateForLevel(int linesOnScreen, int linesInDoc);
 public:
@@ -218,6 +220,7 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        int scrollWidth;
        bool verticalScrollBarVisible;
        bool endAtLastLine;
+       bool caretSticky;
 
        Surface *pixmapLine;
        Surface *pixmapSelMargin;
@@ -301,7 +304,7 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        int hsEnd;
 
        // Wrapping support
-       enum { eWrapNone, eWrapWord } wrapState;
+       enum { eWrapNone, eWrapWord, eWrapChar } wrapState;
        bool backgroundWrapEnabled;
        int wrapWidth;
        int docLineLastWrapped;
@@ -311,6 +314,8 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        int wrapVisualStartIndent;
        int actualWrapVisualStartIndent;
 
+       bool convertPastes;
+
        Document *pdoc;
 
        Editor();
@@ -341,7 +346,7 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        bool AbandonPaint();
        void RedrawRect(PRectangle rc);
        void Redraw();
-       void RedrawSelMargin();
+       void RedrawSelMargin(int line=-1);
        PRectangle RectangleFromRange(int start, int end);
        void InvalidateRange(int start, int end);
 
@@ -349,6 +354,7 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        bool SelectionEmpty();
        int SelectionStart();
        int SelectionEnd();
+       void SetRectangularRange();
        void InvalidateSelection(int currentPos_, int anchor_);
        void SetSelection(int currentPos_, int anchor_);
        void SetSelection(int currentPos_);
@@ -450,10 +456,11 @@ protected:        // ScintillaBase subclass needs access to much of Editor
        void PageMove(int direction, selTypes sel=noSel, bool stuttered = false);
        void ChangeCaseOfSelection(bool makeUpperCase);
        void LineTranspose();
-       void LineDuplicate();
+       void Duplicate(bool forLine);
        virtual void CancelModes();
        void NewLine();
        void CursorUpOrDown(int direction, selTypes sel=noSel);
+       void ParaUpOrDown(int direction, selTypes sel=noSel);
        int StartEndDisplayLine(int pos, bool start);
        virtual int KeyCommand(unsigned int iMessage);
        virtual int KeyDefault(int /* key */, int /*modifiers*/);
@@ -499,8 +506,9 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        virtual bool HaveMouseCapture() = 0;
        void SetFocusState(bool focusState);
 
+       virtual bool PaintContains(PRectangle rc);
+       bool PaintContainsMargin();
        void CheckForChangeOutsidePaint(Range r);
-       int BraceMatch(int position, int maxReStyle);
        void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);
 
        void SetDocPointer(Document *document);
@@ -516,6 +524,7 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        void GetHotSpotRange(int& hsStart, int& hsEnd);
 
        int CodePage() const;
+       int WrapCount(int line);
 
        virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0;
 
index 950916bd08dc14764a96de579e8983bdfcd03939..bfa6e2d7899294cbec83e45ed1f8963bcd1427d5 100644 (file)
@@ -140,7 +140,7 @@ const KeyToCommand KeyMap::MapDefault[] = {
     {'L',                      SCI_CSHIFT,     SCI_LINEDELETE},
     {'T',                      SCI_CSHIFT,     SCI_LINECOPY},
     {'T',                      SCI_CTRL,       SCI_LINETRANSPOSE},
-    {'D',                      SCI_CTRL,       SCI_LINEDUPLICATE},
+    {'D',                      SCI_CTRL,       SCI_SELECTIONDUPLICATE},
     {'U',                      SCI_CTRL,       SCI_LOWERCASE},
     {'U',                      SCI_CSHIFT,     SCI_UPPERCASE},
     {0,0,0},
index 67e52ec11ad312874d7947bec42730176016b43d..1ffc4fb5f89e73cb59b1c917c840481d46f48b12 100644 (file)
 const LexerModule *LexerModule::base = 0;
 int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1;
 
-LexerModule::LexerModule(int language_, LexerFunction fnLexer_,
-       const char *languageName_, LexerFunction fnFolder_,
-       const char * const wordListDescriptions_[]) :
+LexerModule::LexerModule(int language_,
+       LexerFunction fnLexer_,
+       const char *languageName_,
+       LexerFunction fnFolder_,
+       const char * const wordListDescriptions_[],
+       int styleBits_) :
        language(language_),
        fnLexer(fnLexer_),
        fnFolder(fnFolder_),
        wordListDescriptions(wordListDescriptions_),
+       styleBits(styleBits_),
        languageName(languageName_) {
        next = base;
        base = this;
@@ -52,7 +56,7 @@ int LexerModule::GetNumWordLists() const {
        }
 }
 
-const char * LexerModule::GetWordListDescription(int index) const {
+const char *LexerModule::GetWordListDescription(int index) const {
        static const char *emptyStr = "";
 
        PLATFORM_ASSERT(index < GetNumWordLists());
@@ -63,6 +67,10 @@ const char * LexerModule::GetWordListDescription(int index) const {
        }
 }
 
+int LexerModule::GetStyleBitsNeeded() const {
+       return styleBits;
+}
+
 const LexerModule *LexerModule::Find(int language) {
        const LexerModule *lm = base;
        while (lm) {
@@ -130,67 +138,78 @@ int Scintilla_LinkLexers() {
 //++Autogenerated -- run src/LexGen.py to regenerate
 //**\(\tLINK_LEXER(\*);\n\)
        LINK_LEXER(lmAda);
+       LINK_LEXER(lmAns1);
        LINK_LEXER(lmAPDL);
        LINK_LEXER(lmAsm);
-       LINK_LEXER(lmAsn1);
+       LINK_LEXER(lmASP);
        LINK_LEXER(lmAU3);
        LINK_LEXER(lmAVE);
        LINK_LEXER(lmBaan);
        LINK_LEXER(lmBash);
+       LINK_LEXER(lmBatch);
+       LINK_LEXER(lmBlitzBasic);
        LINK_LEXER(lmBullant);
+       LINK_LEXER(lmCaml);
        LINK_LEXER(lmClw);
        LINK_LEXER(lmClwNoCase);
        LINK_LEXER(lmConf);
        LINK_LEXER(lmCPP);
        LINK_LEXER(lmCPPNoCase);
-       LINK_LEXER(lmTCL);
-       LINK_LEXER(lmNncrontab);
+       LINK_LEXER(lmCsound);
        LINK_LEXER(lmCss);
+       LINK_LEXER(lmDiff);
        LINK_LEXER(lmEiffel);
        LINK_LEXER(lmEiffelkw);
        LINK_LEXER(lmErlang);
+       LINK_LEXER(lmErrorList);
        LINK_LEXER(lmESCRIPT);
+       LINK_LEXER(lmF77);
+       LINK_LEXER(lmFlagShip);
        LINK_LEXER(lmForth);
        LINK_LEXER(lmFortran);
-       LINK_LEXER(lmF77);
+       LINK_LEXER(lmFreeBasic);
        LINK_LEXER(lmGui4Cli);
+       LINK_LEXER(lmHaskell);
        LINK_LEXER(lmHTML);
-       LINK_LEXER(lmXML);
-       LINK_LEXER(lmASP);
-       LINK_LEXER(lmPHP);
        LINK_LEXER(lmKix);
+       LINK_LEXER(lmLatex);
        LINK_LEXER(lmLISP);
+       LINK_LEXER(lmLot);
        LINK_LEXER(lmLout);
        LINK_LEXER(lmLua);
+       LINK_LEXER(lmMake);
        LINK_LEXER(lmMatlab);
-       LINK_LEXER(lmOctave);
        LINK_LEXER(lmMETAPOST);
        LINK_LEXER(lmMMIXAL);
-       LINK_LEXER(lmLot);
        LINK_LEXER(lmMSSQL);
+       LINK_LEXER(lmNncrontab);
        LINK_LEXER(lmNsis);
-       LINK_LEXER(lmBatch);
-       LINK_LEXER(lmDiff);
-       LINK_LEXER(lmProps);
-       LINK_LEXER(lmMake);
-       LINK_LEXER(lmErrorList);
-       LINK_LEXER(lmLatex);
        LINK_LEXER(lmNull);
+       LINK_LEXER(lmOctave);
        LINK_LEXER(lmPascal);
        LINK_LEXER(lmPB);
        LINK_LEXER(lmPerl);
+       LINK_LEXER(lmPHP);
+       LINK_LEXER(lmPHPSCRIPT);
        LINK_LEXER(lmPOV);
+       LINK_LEXER(lmProps);
        LINK_LEXER(lmPS);
+       LINK_LEXER(lmPureBasic);
        LINK_LEXER(lmPython);
+       LINK_LEXER(lmREBOL);
        LINK_LEXER(lmRuby);
        LINK_LEXER(lmScriptol);
+       LINK_LEXER(lmSmalltalk);
        LINK_LEXER(lmSpecman);
        LINK_LEXER(lmSQL);
+       LINK_LEXER(lmTADS3);
+       LINK_LEXER(lmTCL);
        LINK_LEXER(lmTeX);
        LINK_LEXER(lmVB);
        LINK_LEXER(lmVBScript);
        LINK_LEXER(lmVerilog);
        LINK_LEXER(lmVHDL);
+       LINK_LEXER(lmXML);
        LINK_LEXER(lmYAML);
 
 //--Autogenerated -- end of automatically generated section
index 31e4ee52d2d78be5a5ce611d5e1cd1702eca52ed..ee547f497fb0665a0fa1bf1ce1b746356b8b0899 100644 (file)
 //                  Added fold.compact support set with fold.compact=1
 //                  Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1
 //                        it will now only happen when fold.comment=2.
-// 
+// Sep 5, 2004    - Added logic to handle colourizing words on the last line. 
+//                        Typed Characters now show as "default" till they match any table.
+// Oct 10, 2004   - Added logic to show Comments in "Special" directives. 
+// Nov  1, 2004   - Added better testing for Numbers supporting x and e notation.
+// Nov 28, 2004   - Added logic to handle continuation lines for syntax highlighting.
+// Jan 10, 2005   - Added Abbreviations Keyword used for expansion
+// Mar 24, 2005   - Updated Abbreviations Keywords to fix when followed by Operator.
+// Apr 18, 2005   - Updated #CE/#Comment-End logic to take a linecomment ";" into account
+//                - Added folding support for With...EndWith
+//                - Added support for a DOT in variable names
+//                - Fixed Underscore in CommentBlock
+// May 23, 2005   - Fixed the SentKey lexing in case of a missing }
+// Aug 11, 2005   - Fixed possible bug with s_save length > 100.
+// Aug 23, 2005   - Added Switch/endswitch support to the folding logic.
+//
 // Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 // Scintilla source code edit control
@@ -56,7 +70,7 @@ static inline bool IsAWordChar(const int ch)
 
 static inline bool IsAWordStart(const int ch)
 {
-    return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$');
+    return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.');
 }
 
 static inline bool IsAOperator(char ch) {
@@ -88,7 +102,11 @@ static int GetSendKey(const char *szLine, char *szKey)
        // split the portion of the sendkey in the part before and after the spaces
        while ( ( (cTemp = szLine[nPos]) != '\0'))
        {
-               if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space
+               // skip leading Ctrl/Shift/ALt state
+               if ((cTemp == '#' || cTemp == '!' || cTemp == '^') && (szLine[nPos+1] == '{') ) 
+               {
+               }       
+               else if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space
                {
                        nFlag = 1;
                        // Add } to the end of the first bit for table lookup later.
@@ -132,6 +150,34 @@ static int GetSendKey(const char *szLine, char *szKey)
 
 } // GetSendKey() 
 
+//
+// Routine to check the last "none comment" character on a line to see if its a continuation
+// 
+static bool IsContinuationLine(unsigned int szLine, Accessor &styler)
+{
+       int nsPos = styler.LineStart(szLine);
+       int nePos = styler.LineStart(szLine+1) - 2;
+       //int stylech = styler.StyleAt(nsPos);
+       while (nsPos < nePos)
+       {
+               //stylech = styler.StyleAt(nePos);
+               int stylech = styler.StyleAt(nsPos);
+               if (!(stylech == SCE_AU3_COMMENT)) {
+                       char ch = styler.SafeGetCharAt(nePos);
+                       if (!isspacechar(ch)) {
+                               if (ch == '_')
+                                       return true;
+                               else
+                                       return false;
+                       }
+               }
+               nePos--; // skip to next char
+       } // End While
+       return false;
+} // IsContinuationLine()
+
+//
+// syntax highlighting logic
 static void ColouriseAU3Doc(unsigned int startPos, 
                                                        int length, int initStyle,
                                                        WordList *keywordlists[],
@@ -143,25 +189,78 @@ static void ColouriseAU3Doc(unsigned int startPos,
     WordList &keywords4 = *keywordlists[3];
     WordList &keywords5 = *keywordlists[4];
     WordList &keywords6 = *keywordlists[5];
+    WordList &keywords7 = *keywordlists[6];
+       // find the first previous line without continuation character at the end
+       int lineCurrent = styler.GetLine(startPos);
+       int s_startPos = startPos;
+       // When not inside a Block comment: find First line without _
+       if (!(initStyle==SCE_AU3_COMMENTBLOCK)) {
+               while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) ||
+                          (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) {
+                       lineCurrent--;
+                       startPos = styler.LineStart(lineCurrent); // get start position
+                       initStyle =  0;                           // reset the start style to 0 
+               }
+       }
+       // Set the new length to include it from the start and set the start position
+       length = length + s_startPos - startPos;      // correct the total length to process
     styler.StartAt(startPos);
-
+       
     StyleContext sc(startPos, length, initStyle, styler);
        char si;     // string indicator "=1 '=2
-       si=0;
+       char ni;     // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3
+       char ci;     // comment indicator 0=not linecomment(;) 
+       char s_save[100];
+       si=0;  
+       ni=0;
+       ci=0;
        //$$$
     for (; sc.More(); sc.Forward()) {
                char s[100];
                sc.GetCurrentLowered(s, sizeof(s));
+               // **********************************************
+               // save the total current word for eof processing 
+               if (IsAWordChar(sc.ch) || sc.ch == '}') 
+               {
+                       strcpy(s_save,s);
+                       int tp = strlen(s_save);
+                       if (tp < 99) {
+                               s_save[tp] = static_cast<char>(tolower(sc.ch));
+                               s_save[tp+1] = '\0';
+                       }
+               }
+               // **********************************************
+               //
                switch (sc.state)
         {
             case SCE_AU3_COMMENTBLOCK:
             {
-                               if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0)))
-                               {
+                               //Reset at line end
+                               if (sc.atLineEnd) {
+                                       ci=0;
+                                       sc.SetState(SCE_AU3_COMMENTBLOCK);
+                               }
+                               //skip rest of line when a ; is encountered
+                               if (sc.chPrev == ';') {
+                                       ci=2;
+                                       sc.SetState(SCE_AU3_COMMENTBLOCK);
+                               }
+                               // skip rest of the line
+                               if (ci==2) 
+                                       break;
+                               // check when first character is detected on the line 
+                               if (ci==0) {
+                                       if (IsAWordStart(static_cast<char>(sc.ch)) || IsAOperator(static_cast<char>(sc.ch))) {
+                                               ci=1;
+                                               sc.SetState(SCE_AU3_COMMENTBLOCK);
+                                       }
+                                       break;
+                               }
+                               if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) {
                                        if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0)) 
-                                       {sc.SetState(SCE_AU3_COMMENT);}  // set to comment line for the rest of the line
+                                               sc.SetState(SCE_AU3_COMMENT);  // set to comment line for the rest of the line
                                        else
-                                       {sc.SetState(SCE_AU3_COMMENTBLOCK);}
+                                               ci=2;  // line doesn't begin with #CE so skip the rest of the line
                                }
                 break;
                        }
@@ -172,12 +271,19 @@ static void ColouriseAU3Doc(unsigned int startPos,
             }
             case SCE_AU3_OPERATOR:
             {
-                sc.SetState(SCE_AU3_DEFAULT);
+                // check if its a COMobject 
+                               if (sc.chPrev == '.' && IsAWordChar(sc.ch)) {
+                                       sc.SetState(SCE_AU3_COMOBJ);
+                               }       
+                               else {
+                                       sc.SetState(SCE_AU3_DEFAULT);
+                               }
                 break;
             }
             case SCE_AU3_SPECIAL:
             {
-                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
+                if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
+                               if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
                 break;
             }
             case SCE_AU3_KEYWORD:
@@ -215,6 +321,10 @@ static void ColouriseAU3Doc(unsigned int startPos,
                                                        sc.ChangeState(SCE_AU3_SPECIAL);
                                                        sc.SetState(SCE_AU3_SPECIAL);
                                                }
+                                               else if ((keywords7.InList(s)) && (!IsAOperator(static_cast<char>(sc.ch)))) {
+                                                       sc.ChangeState(SCE_AU3_EXPAND);
+                                                       sc.SetState(SCE_AU3_DEFAULT);
+                                               }
                                                else if (strcmp(s, "_") == 0) {
                                                        sc.ChangeState(SCE_AU3_OPERATOR);
                                                        sc.SetState(SCE_AU3_DEFAULT);
@@ -225,18 +335,74 @@ static void ColouriseAU3Doc(unsigned int startPos,
                                                }
                                        }
                                }       
-                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
+                if (sc.atLineEnd) {
+                                       sc.SetState(SCE_AU3_DEFAULT);}
                 break;
             }
-            case SCE_AU3_NUMBER:
+                       case SCE_AU3_NUMBER:
             {
-                if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_AU3_DEFAULT);}
-                break;
+                               // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3
+                               //
+                               // test for Hex notation
+                               if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0)
+                               {
+                                       ni = 2;
+                                       break;
+                               }
+                               // test for E notation
+                               if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1)
+                               {
+                                       ni = 3;
+                                       break;
+                               }
+                               //  Allow Hex characters inside hex numeric strings
+                               if ((ni == 2) &&
+                                       (sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' ||
+                                        sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' ))
+                               {
+                                       break;
+                               }
+                               // test for 1 dec point only
+                               if (sc.ch == '.')
+                               {
+                                       if (ni==0)
+                                       {
+                                               ni=1;
+                                       }
+                                       else
+                                       {
+                                               ni=9;
+                                       }
+                                       break;
+                               }
+                               // end of numeric string ?
+                               if (!(IsADigit(sc.ch)))
+                               {
+                                       if (ni==9)
+                                       {
+                                               sc.ChangeState(SCE_AU3_DEFAULT);
+                                       }
+                                       sc.SetState(SCE_AU3_DEFAULT);
+                               }
+                               break;
+                       }
+                       case SCE_AU3_VARIABLE:
+                       {
+                               // Check if its a COMObject
+                               if (sc.ch == '.' && !IsADigit(sc.chNext)) {
+                                       sc.SetState(SCE_AU3_OPERATOR);
+                               }
+                               else if (!IsAWordChar(sc.ch)) {
+                                       sc.SetState(SCE_AU3_DEFAULT);
+                               }
+                               break;
             }
-            case SCE_AU3_VARIABLE:
-            {
-                if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_AU3_DEFAULT);}
-                break;
+                       case SCE_AU3_COMOBJ:
+                       {
+                               if (!(IsAWordChar(sc.ch))) {
+                                       sc.SetState(SCE_AU3_DEFAULT);
+                               }
+                               break;
             }
             case SCE_AU3_STRING:
             {
@@ -246,7 +412,15 @@ static void ColouriseAU3Doc(unsigned int startPos,
                                {
                                        sc.ForwardSetState(SCE_AU3_DEFAULT);
                                }
-                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
+                if (sc.atLineEnd)
+                               {
+                                       // at line end and not found a continuation char then reset to default
+                                       int lineCurrent = styler.GetLine(sc.currentPos);
+                                       if (!IsContinuationLine(lineCurrent,styler)) 
+                                       {
+                                               sc.SetState(SCE_AU3_DEFAULT);
+                                       }
+                               }
                                // find Sendkeys in a STRING
                                if (sc.ch == '{') {sc.SetState(SCE_AU3_SENT);}
                                if (sc.ch == '+' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
@@ -288,10 +462,11 @@ static void ColouriseAU3Doc(unsigned int startPos,
                                // check if next portion is again a sendkey
                                if (sc.atLineEnd) 
                                {
+                                       sc.ChangeState(SCE_AU3_STRING);
                                        sc.SetState(SCE_AU3_DEFAULT);
                                        si = 0;  // reset string indicator
                                }
-                               if (sc.ch == '{' && sc.chPrev != '{') {sc.SetState(SCE_AU3_SENT);}
+                               //if (sc.ch == '{' && sc.chPrev != '{') {sc.SetState(SCE_AU3_SENT);}
                                if (sc.ch == '+' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
                                if (sc.ch == '!' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
                                if (sc.ch == '^' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
@@ -314,6 +489,7 @@ static void ColouriseAU3Doc(unsigned int startPos,
             if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
             else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);}
             else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);}
+            else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);}
             else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);}
             else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);}  // string after #include 
             else if (sc.ch == '\"') {
@@ -322,13 +498,94 @@ static void ColouriseAU3Doc(unsigned int startPos,
             else if (sc.ch == '\'') {
                                sc.SetState(SCE_AU3_STRING);
                                si = 2; }
-            else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {sc.SetState(SCE_AU3_NUMBER);}
+            else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) 
+                       {
+                               sc.SetState(SCE_AU3_NUMBER);
+                               ni = 0;
+                       }
             else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);}
             else if (IsAOperator(static_cast<char>(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);}
                        else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
         }
     }      //for (; sc.More(); sc.Forward())
-    sc.Complete();
+
+       //*************************************
+       // Colourize the last word correctly 
+       //*************************************
+       if (sc.state == SCE_AU3_KEYWORD)
+               {
+               if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 )
+               {
+                       sc.ChangeState(SCE_AU3_COMMENTBLOCK);
+                       sc.SetState(SCE_AU3_COMMENTBLOCK);
+               }
+               else if (keywords.InList(s_save)) {
+                       sc.ChangeState(SCE_AU3_KEYWORD);
+                       sc.SetState(SCE_AU3_KEYWORD);
+               }
+               else if (keywords2.InList(s_save)) {
+                       sc.ChangeState(SCE_AU3_FUNCTION);
+                       sc.SetState(SCE_AU3_FUNCTION);
+               }
+               else if (keywords3.InList(s_save)) {
+                       sc.ChangeState(SCE_AU3_MACRO);
+                       sc.SetState(SCE_AU3_MACRO);
+               }
+               else if (keywords5.InList(s_save)) {
+                       sc.ChangeState(SCE_AU3_PREPROCESSOR);
+                       sc.SetState(SCE_AU3_PREPROCESSOR);
+               }
+               else if (keywords6.InList(s_save)) {
+                       sc.ChangeState(SCE_AU3_SPECIAL);
+                       sc.SetState(SCE_AU3_SPECIAL);
+               }
+               else if (keywords7.InList(s_save) && sc.atLineEnd) {
+                       sc.ChangeState(SCE_AU3_EXPAND);
+                       sc.SetState(SCE_AU3_EXPAND);
+               }
+               else {
+                       sc.ChangeState(SCE_AU3_DEFAULT);
+                       sc.SetState(SCE_AU3_DEFAULT);
+               }
+       }
+       if (sc.state == SCE_AU3_SENT)
+    {
+               // Send key string ended 
+               if (sc.chPrev == '}' && sc.ch != '}') 
+               {
+                       // set color to SENDKEY when valid sendkey .. else set back to regular string
+                       char sk[100];
+                       // split {111 222} and return {111} and check if 222 is valid.
+                       // if return code = 1 then invalid 222 so must be string
+                       if (GetSendKey(s_save,sk))   
+                       {
+                               sc.ChangeState(SCE_AU3_STRING);
+                       }
+                       // if single char between {?} then its ok as sendkey for a single character
+                       else if (strlen(sk) == 3)  
+                       {
+                               sc.ChangeState(SCE_AU3_SENT);
+                       }
+                       // if sendkey {111} is in table then ok as sendkey
+                       else if (keywords4.InList(sk)) 
+                       {
+                               sc.ChangeState(SCE_AU3_SENT);
+                       }
+                       else
+                       {
+                               sc.ChangeState(SCE_AU3_STRING);
+                       }
+                       sc.SetState(SCE_AU3_STRING);
+               }
+               // check if next portion is again a sendkey
+               if (sc.atLineEnd) 
+               {
+                       sc.ChangeState(SCE_AU3_STRING);
+                       sc.SetState(SCE_AU3_DEFAULT);
+               }
+    }
+       //*************************************
+       sc.Complete();
 }
 
 //
@@ -352,32 +609,6 @@ static int GetStyleFirstWord(unsigned int szLine, Accessor &styler)
 
 } // GetStyleFirstWord()
 
-//
-// Routine to check the last "none comment" character on a line to see if its a continuation
-// 
-static bool IsContinuationLine(unsigned int szLine, Accessor &styler)
-{
-       int nsPos = styler.LineStart(szLine);
-       int nePos = styler.LineStart(szLine+1) - 2;
-       //int stylech = styler.StyleAt(nsPos);
-       while (nsPos < nePos)
-       {
-               //stylech = styler.StyleAt(nePos);
-               int stylech = styler.StyleAt(nsPos);
-               if (!(stylech == SCE_AU3_COMMENT)) {
-                       char ch = styler.SafeGetCharAt(nePos);
-                       if (!isspacechar(ch)) {
-                               if (ch == '_')
-                                       return true;
-                               else
-                                       return false;
-                       }
-               }
-               nePos--; // skip to next char
-       } // End While
-       return false;
-} // IsContinuationLine()
-
 
 //
 static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
@@ -496,18 +727,18 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc
                                // create new fold for these words 
                                if (strcmp(szKeyword,"do") == 0   || strcmp(szKeyword,"for") == 0 ||
                                        strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0||
-                                       strcmp(szKeyword,"#region") == 0 ) {
+                                       strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) {
                                                levelNext++;
                                }
-                               // create double Fold for select because Case will subtract one of the current level
-                               if (strcmp(szKeyword,"select") == 0) {
+                               // create double Fold for select&switch because Case will subtract one of the current level
+                               if (strcmp(szKeyword,"select") == 0 || strcmp(szKeyword,"switch") == 0) {
                                                levelNext++;
                                                levelNext++;
                                }
                                // end the fold for these words before the current line
                                if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 ||
                                        strcmp(szKeyword,"next") == 0    || strcmp(szKeyword,"until") == 0 || 
-                                       strcmp(szKeyword,"wend") == 0){
+                                       strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){
                                                levelNext--;
                                                levelCurrent--;
                                }
@@ -517,7 +748,7 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc
                                                levelCurrent--;
                                }
                                // end the double fold for this word before the current line
-                               if (strcmp(szKeyword,"endselect") == 0 ) {
+                               if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) {
                                                levelNext--;
                                                levelNext--;
                                                levelCurrent--;
@@ -609,6 +840,7 @@ static const char * const AU3WordLists[] = {
     "#autoit Sent keys",
     "#autoit Pre-processors",
     "#autoit Special",
+    "#autoit Expand",
     0
 };
 LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists);
index 900aea317cfedb83d63b87269714b81326185bd0..e30ee7dc9e9c05b8b8ba1b6116862179a6d4c27f 100644 (file)
@@ -12,7 +12,6 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <fcntl.h>
 
 #include "Platform.h"
 
@@ -183,7 +182,9 @@ static void FoldAveDoc(unsigned int startPos, int length, int /* initStyle */, W
                                if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) {
                                        levelCurrent++;
                                }
-                               if ((strcmp(s, "end") == 0)) {
+                               if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) {
+                                       // Normally "elseif" and "then" will be on the same line and will cancel
+                                       // each other out.  // As implemented, this does not support fold.at.else.
                                        levelCurrent--;
                                }
                        }
index be6c3f2aeacc89b9c5a75c4e8b34bb775ae5a52f..1600e6329d461bf3cf8253fa329f2785332b5f56 100644 (file)
@@ -178,4 +178,4 @@ static const char * const asn1WordLists[] = {
        0, };
 
 
-LexerModule lmAsn1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists);
+LexerModule lmAns1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists);
index abd02c46b386e9510b16dc059403a6367e8c3858..903d793bb0b7b5551cbbcabe39eda665ffb083f1 100644 (file)
@@ -2,7 +2,7 @@
 /** @file LexBash.cxx
  ** Lexer for Bash.
  **/
-// Copyright 2004 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 2004-2005 by Neil Hodgson <neilh@scintilla.org>
 // Adapted from LexPerl by Kein-Hong Man <mkh@pl.jaring.my> 2004
 // The License.txt file describes the conditions under which this software may be distributed.
 
@@ -144,6 +144,9 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
                char *Delimiter;        // the Delimiter, 256: sizeof PL_tokenbuf
                HereDocCls() {
                        State = 0;
+            Quote = 0;
+            Quoted = false;
+            Indent = 0;
                        DelimiterLength = 0;
                        Delimiter = new char[HERE_DELIM_MAX];
                        Delimiter[0] = '\0';
@@ -442,7 +445,7 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
                                        HereDoc.Quoted = false;
                                        HereDoc.DelimiterLength = 0;
                                        HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
-                                       if (chNext == '\'') {   // a quoted here-doc delimiter (' only)
+                                       if (chNext == '\'' || chNext == '\"') { // a quoted here-doc delimiter (' or ")
                                                i++;
                                                ch = chNext;
                                                chNext = chNext2;
@@ -451,8 +454,9 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
                                                HereDoc.Indent = true;
                                                HereDoc.State = 0;
                                        } else if (isalpha(chNext) || chNext == '_' || chNext == '\\'
-                                               || chNext == '-' || chNext == '+') {
+                                               || chNext == '-' || chNext == '+' || chNext == '!') {
                                                // an unquoted here-doc delimiter, no special handling
+                        // TODO check what exactly bash considers part of the delim
                                        } else if (chNext == '<') {     // HERE string <<<
                                                i++;
                                                ch = chNext;
@@ -486,7 +490,7 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
                                                        HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
                                                }
                                        } else { // an unquoted here-doc delimiter
-                                               if (isalnum(ch) || ch == '_' || ch == '-' || ch == '+') {
+                                               if (isalnum(ch) || ch == '_' || ch == '-' || ch == '+' || ch == '!') {
                                                        HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
                                                        HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
                                                } else if (ch == '\\') {
@@ -582,6 +586,19 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
        styler.ColourTo(lengthDoc - 1, state);
 }
 
+static bool IsCommentLine(int line, Accessor &styler) {
+       int pos = styler.LineStart(line);
+       int eol_pos = styler.LineStart(line + 1) - 1;
+       for (int i = pos; i < eol_pos; i++) {
+               char ch = styler[i];
+               if (ch == '#')
+                       return true;
+               else if (ch != ' ' && ch != '\t')
+                       return false;
+       }
+       return false;
+}
+
 static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[],
                             Accessor &styler) {
        bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
@@ -599,16 +616,16 @@ static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[],
                int style = styleNext;
                styleNext = styler.StyleAt(i + 1);
                bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
-               if (foldComment && (style == SCE_SH_COMMENTLINE)) {
-                       if ((ch == '/') && (chNext == '/')) {
-                               char chNext2 = styler.SafeGetCharAt(i + 2);
-                               if (chNext2 == '{') {
-                                       levelCurrent++;
-                               } else if (chNext2 == '}') {
-                                       levelCurrent--;
-                               }
-                       }
-               }
+        // Comment folding
+               if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
+        {
+            if (!IsCommentLine(lineCurrent - 1, styler)
+                && IsCommentLine(lineCurrent + 1, styler))
+                levelCurrent++;
+            else if (IsCommentLine(lineCurrent - 1, styler)
+                     && !IsCommentLine(lineCurrent+1, styler))
+                levelCurrent--;
+        }
                if (style == SCE_C_OPERATOR) {
                        if (ch == '{') {
                                levelCurrent++;
diff --git a/contrib/src/stc/scintilla/src/LexBasic.cxx b/contrib/src/stc/scintilla/src/LexBasic.cxx
new file mode 100644 (file)
index 0000000..4a1843a
--- /dev/null
@@ -0,0 +1,364 @@
+// Scintilla source code edit control
+/** @file LexBasic.cxx
+ ** Lexer for BlitzBasic and PureBasic.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+// This tries to be a unified Lexer/Folder for all the BlitzBasic/BlitzMax/PurBasic basics
+// and derivatives. Once they diverge enough, might want to split it into multiple
+// lexers for more code clearity.
+//
+// Mail me (elias <at> users <dot> sf <dot> net) for any bugs.
+
+// Folding only works for simple things like functions or types.
+
+// You may want to have a look at my ctags lexer as well, if you additionally to coloring
+// and folding need to extract things like label tags in your editor.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+/* Bits:
+ * 1  - whitespace
+ * 2  - operator
+ * 4  - identifier
+ * 8  - decimal digit
+ * 16 - hex digit
+ * 32 - bin digit
+ */
+static int character_classification[128] =
+{
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    1,  2,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  10, 2,
+    60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2,  2,  2,  2,  2,  2,
+    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  4,
+    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  0
+};
+
+static bool IsSpace(int c) {
+       return c < 128 && (character_classification[c] & 1);
+}
+
+static bool IsOperator(int c) {
+       return c < 128 && (character_classification[c] & 2);
+}
+
+static bool IsIdentifier(int c) {
+       return c < 128 && (character_classification[c] & 4);
+}
+
+static bool IsDigit(int c) {
+       return c < 128 && (character_classification[c] & 8);
+}
+
+static bool IsHexDigit(int c) {
+       return c < 128 && (character_classification[c] & 16);
+}
+
+static bool IsBinDigit(int c) {
+       return c < 128 && (character_classification[c] & 32);
+}
+
+static int LowerCase(int c)
+{
+       if (c >= 'A' && c <= 'Z')
+               return 'a' + c - 'A';
+       return c;
+}
+
+static void ColouriseBasicDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler, char comment_char) {
+       bool wasfirst = true, isfirst = true; // true if first token in a line
+       styler.StartAt(startPos);
+
+       StyleContext sc(startPos, length, initStyle, styler);
+
+       // Can't use sc.More() here else we miss the last character
+       for (; ; sc.Forward()) {
+               if (sc.state == SCE_B_IDENTIFIER) {
+                       if (!IsIdentifier(sc.ch)) {
+                               // Labels
+                               if (wasfirst && sc.Match(':')) {
+                                       sc.ChangeState(SCE_B_LABEL);
+                                       sc.ForwardSetState(SCE_B_DEFAULT);
+                               } else {
+                                       char s[100];
+                                       int kstates[4] = {
+                                               SCE_B_KEYWORD,
+                                               SCE_B_KEYWORD2,
+                                               SCE_B_KEYWORD3,
+                                               SCE_B_KEYWORD4,
+                                       };
+                                       sc.GetCurrentLowered(s, sizeof(s));
+                                       for (int i = 0; i < 4; i++) {
+                                               if (keywordlists[i]->InList(s)) {
+                                                       sc.ChangeState(kstates[i]);
+                                               }
+                                       }
+                                       // Types, must set them as operator else they will be
+                                       // matched as number/constant
+                                       if (sc.Match('.') || sc.Match('$') || sc.Match('%') ||
+                                               sc.Match('#')) {
+                                               sc.SetState(SCE_B_OPERATOR);
+                                       } else {
+                                               sc.SetState(SCE_B_DEFAULT);
+                                       }
+                               }
+                       }
+               } else if (sc.state == SCE_B_OPERATOR) {
+                       if (!IsOperator(sc.ch) || sc.Match('#'))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_LABEL) {
+                       if (!IsIdentifier(sc.ch))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_CONSTANT) {
+                       if (!IsIdentifier(sc.ch))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_NUMBER) {
+                       if (!IsDigit(sc.ch))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_HEXNUMBER) {
+                       if (!IsHexDigit(sc.ch))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_BINNUMBER) {
+                       if (!IsBinDigit(sc.ch))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_STRING) {
+                       if (sc.ch == '"') {
+                               sc.ForwardSetState(SCE_B_DEFAULT);
+                       }
+                       if (sc.atLineEnd) {
+                               sc.ChangeState(SCE_B_ERROR);
+                               sc.SetState(SCE_B_DEFAULT);
+                       }
+               } else if (sc.state == SCE_B_COMMENT) {
+                       if (sc.atLineEnd) {
+                               sc.SetState(SCE_B_DEFAULT);
+                       }
+               }
+
+               if (sc.atLineStart)
+                       isfirst = true;
+
+               if (sc.state == SCE_B_DEFAULT || sc.state == SCE_B_ERROR) {
+                       if (isfirst && sc.Match('.')) {
+                               sc.SetState(SCE_B_LABEL);
+                       } else if (isfirst && sc.Match('#')) {
+                               wasfirst = isfirst;
+                               sc.SetState(SCE_B_IDENTIFIER);
+                       } else if (sc.Match(comment_char)) {
+                               sc.SetState(SCE_B_COMMENT);
+                       } else if (sc.Match('"')) {
+                               sc.SetState(SCE_B_STRING);
+                       } else if (IsDigit(sc.ch)) {
+                               sc.SetState(SCE_B_NUMBER);
+                       } else if (sc.Match('$')) {
+                               sc.SetState(SCE_B_HEXNUMBER);
+                       } else if (sc.Match('%')) {
+                               sc.SetState(SCE_B_BINNUMBER);
+                       } else if (sc.Match('#')) {
+                               sc.SetState(SCE_B_CONSTANT);
+                       } else if (IsOperator(sc.ch)) {
+                               sc.SetState(SCE_B_OPERATOR);
+                       } else if (IsIdentifier(sc.ch)) {
+                               wasfirst = isfirst;
+                               sc.SetState(SCE_B_IDENTIFIER);
+                       } else if (!IsSpace(sc.ch)) {
+                               sc.SetState(SCE_B_ERROR);
+                       }
+               }
+
+               if (!IsSpace(sc.ch))
+                       isfirst = false;
+
+               if (!sc.More())
+                       break;
+       }
+       sc.Complete();
+}
+
+static int CheckBlitzFoldPoint(char const *token, int &level) {
+       if (!strcmp(token, "function") ||
+               !strcmp(token, "type")) {
+               level |= SC_FOLDLEVELHEADERFLAG;
+               return 1;
+       }
+       if (!strcmp(token, "end function") ||
+               !strcmp(token, "end type")) {
+               return -1;
+       }
+       return 0;
+}
+
+static int CheckPureFoldPoint(char const *token, int &level) {
+       if (!strcmp(token, "procedure") ||
+               !strcmp(token, "enumeration") ||
+               !strcmp(token, "interface") ||
+               !strcmp(token, "structure")) {
+               level |= SC_FOLDLEVELHEADERFLAG;
+               return 1;
+       }
+       if (!strcmp(token, "endprocedure") ||
+               !strcmp(token, "endenumeration") ||
+               !strcmp(token, "endinterface") ||
+               !strcmp(token, "endstructure")) {
+               return -1;
+       }
+       return 0;
+}
+
+static int CheckFreeFoldPoint(char const *token, int &level) {
+       if (!strcmp(token, "function") ||
+               !strcmp(token, "sub") ||
+               !strcmp(token, "type")) {
+               level |= SC_FOLDLEVELHEADERFLAG;
+               return 1;
+       }
+       if (!strcmp(token, "end function") ||
+               !strcmp(token, "end sub") ||
+               !strcmp(token, "end type")) {
+               return -1;
+       }
+       return 0;
+}
+
+static void FoldBasicDoc(unsigned int startPos, int length,
+       Accessor &styler, int (*CheckFoldPoint)(char const *, int &)) {
+       int line = styler.GetLine(startPos);
+       int level = styler.LevelAt(line);
+       int go = 0, done = 0;
+       int endPos = startPos + length;
+       char word[256];
+       int wordlen = 0;
+       int i;
+        bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+       // Scan for tokens at the start of the line (they may include
+       // whitespace, for tokens like "End Function"
+       for (i = startPos; i < endPos; i++) {
+               int c = styler.SafeGetCharAt(i);
+               if (!done && !go) {
+                       if (wordlen) { // are we scanning a token already?
+                               word[wordlen] = static_cast<char>(LowerCase(c));
+                               if (!IsIdentifier(c)) { // done with token
+                                       word[wordlen] = '\0';
+                                       go = CheckFoldPoint(word, level);
+                                       if (!go) {
+                                               // Treat any whitespace as single blank, for
+                                               // things like "End   Function".
+                                               if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) {
+                                                       word[wordlen] = ' ';
+                                                       if (wordlen < 255)
+                                                               wordlen++;
+                                               }
+                                               else // done with this line
+                                                       done = 1;
+                                       }
+                               } else if (wordlen < 255) {
+                                       wordlen++;
+                               }
+                       } else { // start scanning at first non-whitespace character
+                               if (!IsSpace(c)) {
+                                       if (IsIdentifier(c)) {
+                                               word[0] = static_cast<char>(LowerCase(c));
+                                               wordlen = 1;
+                                       } else // done with this line
+                                               done = 1;
+                               }
+                       }
+               }
+               if (c == '\n') { // line end
+                       if (!done && wordlen == 0 && foldCompact) // line was only space
+                               level |= SC_FOLDLEVELWHITEFLAG;
+                       if (level != styler.LevelAt(line))
+                               styler.SetLevel(line, level);
+                       level += go;
+                       line++;
+                       // reset state
+                       wordlen = 0;
+                       level &= ~SC_FOLDLEVELHEADERFLAG;
+                       level &= ~SC_FOLDLEVELWHITEFLAG;
+                       go = 0;
+                       done = 0;
+               }
+       }
+}
+
+static void ColouriseBlitzBasicDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler) {
+       ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';');
+}
+
+static void ColourisePureBasicDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler) {
+       ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';');
+}
+
+static void ColouriseFreeBasicDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler) {
+       ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, '\'');
+}
+
+static void FoldBlitzBasicDoc(unsigned int startPos, int length, int,
+       WordList *[], Accessor &styler) {
+       FoldBasicDoc(startPos, length, styler, CheckBlitzFoldPoint);
+}
+
+static void FoldPureBasicDoc(unsigned int startPos, int length, int,
+       WordList *[], Accessor &styler) {
+       FoldBasicDoc(startPos, length, styler, CheckPureFoldPoint);
+}
+
+static void FoldFreeBasicDoc(unsigned int startPos, int length, int,
+       WordList *[], Accessor &styler) {
+       FoldBasicDoc(startPos, length, styler, CheckFreeFoldPoint);
+}
+
+static const char * const blitzbasicWordListDesc[] = {
+       "BlitzBasic Keywords",
+       "user1",
+       "user2",
+       "user3",
+       0
+};
+
+static const char * const purebasicWordListDesc[] = {
+       "PureBasic Keywords",
+       "PureBasic PreProcessor Keywords",
+       "user defined 1",
+       "user defined 2",
+       0
+};
+
+static const char * const freebasicWordListDesc[] = {
+       "FreeBasic Keywords",
+       "FreeBasic PreProcessor Keywords",
+       "user defined 1",
+       "user defined 2",
+       0
+};
+
+LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, ColouriseBlitzBasicDoc, "blitzbasic",
+       FoldBlitzBasicDoc, blitzbasicWordListDesc);
+
+LexerModule lmPureBasic(SCLEX_PUREBASIC, ColourisePureBasicDoc, "purebasic",
+       FoldPureBasicDoc, purebasicWordListDesc);
+
+LexerModule lmFreeBasic(SCLEX_FREEBASIC, ColouriseFreeBasicDoc, "freebasic",
+       FoldFreeBasicDoc, freebasicWordListDesc);
+
index e5240776cc0d59656dad979d599333ff8998efa7..e28e4b13b48a259978240410066f416850a25a47 100644 (file)
@@ -1,15 +1,16 @@
 // Scintilla source code edit control
 /** @file LexClw.cxx
  ** Lexer for Clarion.
+ ** 2004/12/17 Updated Lexer
  **/
-// Copyright 2003 by Ron Schofield <ron@schofieldcomputer.com>
+// Copyright 2003-2004 by Ron Schofield <ron@schofieldcomputer.com>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <ctype.h>
 
 #include "Platform.h"
 
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-static char MakeUpperCase(char ch) {
-       if (ch < 'a' || ch > 'z')
-               return ch;
-       else
-               return static_cast<char>(ch - 'a' + 'A');
+// Is an end of line character
+inline bool IsEOL(const int ch) {
+
+       return(ch == '\n');
+}
+
+// Convert character to uppercase
+static char CharacterUpper(char chChar) {
+
+       if (chChar < 'a' || chChar > 'z') {
+               return(chChar);
+       }
+       else {
+               return(static_cast<char>(chChar - 'a' + 'A'));
+       }
 }
 
-static void MakeUpperCaseString(char *s) {
-       while (*s) {
-               *s = MakeUpperCase(*s);
-               s++;
+// Convert string to uppercase
+static void StringUpper(char *szString) {
+
+       while (*szString) {
+               *szString = CharacterUpper(*szString);
+               szString++;
        }
 }
 
 // Is a label start character
 inline bool IsALabelStart(const int iChar) {
+
        return(isalpha(iChar) || iChar == '_');
 }
 
 // Is a label character
 inline bool IsALabelCharacter(const int iChar) {
-       return(isalnum(iChar) || iChar == '_' || iChar == ':');
+
+       return(isalnum(iChar) || iChar == '_' || iChar == ':'); 
 }
 
-// Is the character is a ! and the the next character is not a !
-inline bool IsACommentStart(StyleContext &scDoc) {
-       return(scDoc.ch == '!' && scDoc.chNext != '!');
+// Is the character is a ! and the the next character is not a ! 
+inline bool IsACommentStart(const int iChar) {
+
+       return(iChar == '!');
 }
 
 // Is the character a Clarion hex character (ABCDEF)
 inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
+
        // Case insensitive.
        if (!bCaseSensitive) {
                if (strchr("ABCDEFabcdef", iChar) != NULL) {
@@ -68,6 +85,7 @@ inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
 
 // Is the character a Clarion base character (B=Binary, O=Octal, H=Hex)
 inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {
+
        // Case insensitive.
        if (!bCaseSensitive) {
                // If character is a numeric base character
@@ -87,8 +105,9 @@ inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {
 
 // Set the correct numeric constant state
 inline bool SetNumericConstantState(StyleContext &scDoc) {
+
        int iPoints = 0;                        // Point counter
-       char cNumericString[100];       // Numeric string buffer
+       char cNumericString[512];       // Numeric string buffer
 
        // Buffer the current numberic string
        scDoc.GetCurrent(cNumericString, sizeof(cNumericString));
@@ -103,7 +122,7 @@ inline bool SetNumericConstantState(StyleContext &scDoc) {
                                break;
                        default :
                                break;
-               }
+               }       
        }
        // If points found (can be more than one for improper formatted number
        if (iPoints > 0) {
@@ -115,18 +134,68 @@ inline bool SetNumericConstantState(StyleContext &scDoc) {
        }
 }
 
+// Get the next word in uppercase from the current position (keyword lookahead)
+inline bool GetNextWordUpper(Accessor &styler, unsigned int uiStartPos, int iLength, char *cWord) {
+
+       unsigned int iIndex = 0;                // Buffer Index
+
+       // Loop through the remaining string from the current position
+       for (int iOffset = uiStartPos; iOffset < iLength; iOffset++) {
+               // Get the character from the buffer using the offset
+               char cCharacter = styler[iOffset];
+               if (IsEOL(cCharacter)) {
+                       break;
+               }
+               // If the character is alphabet character
+               if (isalpha(cCharacter)) {
+                       // Add UPPERCASE character to the word buffer
+                       cWord[iIndex++] = CharacterUpper(cCharacter);
+               }
+       }
+       // Add null termination
+       cWord[iIndex] = '\0';
+       // If no word was found
+       if (iIndex == 0) {
+               // Return failure
+               return(false);
+       }
+       // Else word was found
+       else {
+               // Return success
+               return(true);
+       }
+}
+
 // Clarion Language Colouring Procedure
-static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {
+static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {
+
+       int iParenthesesLevel = 0;              // Parenthese Level
+       int iColumn1Label = false;              // Label starts in Column 1
+
+       WordList &wlClarionKeywords = *wlKeywords[0];                   // Clarion Keywords
+       WordList &wlCompilerDirectives = *wlKeywords[1];                // Compiler Directives
+       WordList &wlRuntimeExpressions = *wlKeywords[2];                // Runtime Expressions
+       WordList &wlBuiltInProcsFuncs = *wlKeywords[3];                 // Builtin Procedures and Functions
+       WordList &wlStructsDataTypes = *wlKeywords[4];                  // Structures and Data Types
+       WordList &wlAttributes = *wlKeywords[5];                                // Procedure Attributes
+       WordList &wlStandardEquates = *wlKeywords[6];                   // Standard Equates
+       WordList &wlLabelReservedWords = *wlKeywords[7];                // Clarion Reserved Keywords (Labels)
+       WordList &wlProcLabelReservedWords = *wlKeywords[8];    // Clarion Reserved Keywords (Procedure Labels)
 
-       int iParenthesesLevel=0;                // Parenthese Level
+       const char wlProcReservedKeywordList[] = 
+       "PROCEDURE FUNCTION";
+       WordList wlProcReservedKeywords;
+       wlProcReservedKeywords.Set(wlProcReservedKeywordList);
 
-       WordList &wlClarionKeywords = *wlKeywords[0];           // Clarion Keywords
-       WordList &wlCompilerDirectives = *wlKeywords[1];        // Compiler Directives
-       WordList &wlBuiltInProcsFuncs = *wlKeywords[2];         // Builtin Procedures and Functions
-       WordList &wlStructsDataTypes = *wlKeywords[3];          // Structures and Data Types
-       WordList &wlAttributes = *wlKeywords[4];                        // Procedure Attributes
-       WordList &wlStandardEquates = *wlKeywords[5];           // Standard Equates
-       WordList &wlReservedWords = *wlKeywords[6];                     // Clarion Reserved Keywords
+       const char wlCompilerKeywordList[] = 
+       "COMPILE OMIT";
+       WordList wlCompilerKeywords;
+       wlCompilerKeywords.Set(wlCompilerKeywordList);
+
+       const char wlLegacyStatementsList[] =
+       "BOF EOF FUNCTION POINTER SHARE";
+       WordList wlLegacyStatements;
+       wlLegacyStatements.Set(wlLegacyStatementsList);
 
        StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler);
 
@@ -143,26 +212,45 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                        if (!IsALabelCharacter(scDoc.ch)) {
                                // If the character is a . (dot syntax)
                                if (scDoc.ch == '.') {
+                                       // Turn off column 1 label flag as label now cannot be reserved work
+                                       iColumn1Label = false;
                                        // Uncolour the . (dot) to default state, move forward one character,
                                        // and change back to the label state.
                                        scDoc.SetState(SCE_CLW_DEFAULT);
                                        scDoc.Forward();
                                        scDoc.SetState(SCE_CLW_LABEL);
                                }
-                               // Else terminate the label state
+                               // Else check label
                                else {
-                                       char cLabel[100];               // Label buffer
+                                       char cLabel[512];               // Label buffer
                                        // Buffer the current label string
                                        scDoc.GetCurrent(cLabel,sizeof(cLabel));
                                        // If case insensitive, convert string to UPPERCASE to match passed keywords.
                                        if (!bCaseSensitive) {
-                                               MakeUpperCaseString(cLabel);
+                                               StringUpper(cLabel);
                                        }
-                                       // If label string is in the Clarion reserved keyword list
-                                       if (wlReservedWords.InList(cLabel)){
-                                               // change to error state
+                                       // Else if UPPERCASE label string is in the Clarion compiler keyword list
+                                       if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){
+                                               // change the label to error state
+                                               scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
+                                       }
+                                       // Else if UPPERCASE label string is in the Clarion reserved keyword list
+                                       else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){
+                                               // change the label to error state
                                                scDoc.ChangeState(SCE_CLW_ERROR);
                                        }
+                                       // Else if UPPERCASE label string is 
+                                       else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) {
+                                               char cWord[512];        // Word buffer
+                                               // Get the next word from the current position
+                                               if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) {
+                                                       // If the next word is a procedure reserved word
+                                                       if (wlProcReservedKeywords.InList(cWord)) {
+                                                               // Change the label to error state
+                                                               scDoc.ChangeState(SCE_CLW_ERROR);
+                                                       }
+                                               }
+                                       }
                                        // Else if label string is in the compiler directive keyword list
                                        else if (wlCompilerDirectives.InList(cLabel)) {
                                                // change the state to compiler directive state
@@ -177,14 +265,14 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                else if (scDoc.state == SCE_CLW_KEYWORD) {
                        // If character is : (colon)
                        if (scDoc.ch == ':') {
-                               char cEquate[100];              // Equate buffer
+                               char cEquate[512];              // Equate buffer
                                // Move forward to include : (colon) in buffer
                                scDoc.Forward();
                                // Buffer the equate string
                                scDoc.GetCurrent(cEquate,sizeof(cEquate));
                                // If case insensitive, convert string to UPPERCASE to match passed keywords.
                                if (!bCaseSensitive) {
-                                       MakeUpperCaseString(cEquate);
+                                       StringUpper(cEquate);
                                }
                                // If statement string is in the equate list
                                if (wlStandardEquates.InList(cEquate)) {
@@ -194,43 +282,58 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                        }
                        // If the character is not a valid label character
                        else if (!IsALabelCharacter(scDoc.ch)) {
-                               char cStatement[100];           // Statement buffer
+                               char cStatement[512];           // Statement buffer
                                // Buffer the statement string
                                scDoc.GetCurrent(cStatement,sizeof(cStatement));
                                // If case insensitive, convert string to UPPERCASE to match passed keywords.
                                if (!bCaseSensitive) {
-                                       MakeUpperCaseString(cStatement);
+                                       StringUpper(cStatement);
                                }
                                // If statement string is in the Clarion keyword list
                                if (wlClarionKeywords.InList(cStatement)) {
-                                       // Set to the Clarion keyword state
+                                       // Change the statement string to the Clarion keyword state
                                        scDoc.ChangeState(SCE_CLW_KEYWORD);
                                }
                                // Else if statement string is in the compiler directive keyword list
                                else if (wlCompilerDirectives.InList(cStatement)) {
-                                       // Set to the compiler directive state
+                                       // Change the statement string to the compiler directive state
                                        scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
                                }
+                               // Else if statement string is in the runtime expressions keyword list
+                               else if (wlRuntimeExpressions.InList(cStatement)) {
+                                       // Change the statement string to the runtime expressions state
+                                       scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS);
+                               }
                                // Else if statement string is in the builtin procedures and functions keyword list
                                else if (wlBuiltInProcsFuncs.InList(cStatement)) {
-                                       // Set to the builtin procedures and functions state
+                                       // Change the statement string to the builtin procedures and functions state
                                        scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION);
                                }
                                // Else if statement string is in the tructures and data types keyword list
                                else if (wlStructsDataTypes.InList(cStatement)) {
-                                       // Set to the structures and data types state
+                                       // Change the statement string to the structures and data types state
                                        scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE);
                                }
                                // Else if statement string is in the procedure attribute keyword list
                                else if (wlAttributes.InList(cStatement)) {
-                                       // Set to the procedure attribute state
+                                       // Change the statement string to the procedure attribute state
                                        scDoc.ChangeState(SCE_CLW_ATTRIBUTE);
                                }
                                // Else if statement string is in the standard equate keyword list
                                else if (wlStandardEquates.InList(cStatement)) {
-                                       // Set to the standard equate state
+                                       // Change the statement string to the standard equate state
                                        scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
                                }
+                               // Else if statement string is in the deprecated or legacy keyword list
+                               else if (wlLegacyStatements.InList(cStatement)) {
+                                       // Change the statement string to the standard equate state
+                                       scDoc.ChangeState(SCE_CLW_DEPRECATED);
+                               }
+                               // Else the statement string doesn't match any work list
+                               else {
+                                       // Change the statement string to the default state
+                                       scDoc.ChangeState(SCE_CLW_DEFAULT);
+                               }
                                // Terminate the keyword state and set to default state
                                scDoc.SetState(SCE_CLW_DEFAULT);
                        }
@@ -261,13 +364,13 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                                // Increment the parenthese level
                                iParenthesesLevel++;
                        }
-                       // Else if the character is a ) (close parenthese)
+                       // Else if the character is a ) (close parenthese) 
                        else if (scDoc.ch == ')') {
                                // If the parenthese level is set to zero
                                // parentheses matched
                                if (!iParenthesesLevel) {
                                        scDoc.SetState(SCE_CLW_DEFAULT);
-                               }
+                               } 
                                // Else parenthese level is greater than zero
                                // still looking for matching parentheses
                                else {
@@ -292,7 +395,7 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                        || IsAHexCharacter(scDoc.ch, bCaseSensitive)
                        || scDoc.ch == '.'
                        || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) {
-                               // If the number was a real
+                               // If the number was a real 
                                if (SetNumericConstantState(scDoc)) {
                                        // Colour the matched string to the real constant state
                                        scDoc.ChangeState(SCE_CLW_REAL_CONSTANT);
@@ -313,8 +416,13 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
 
                // Beginning of Line Handling
                if (scDoc.atLineStart) {
+                       // Reset the column 1 label flag
+                       iColumn1Label = false;
                        // If column 1 character is a label start character
                        if (IsALabelStart(scDoc.ch)) {
+                               // Label character is found in column 1
+                               // so set column 1 label flag and clear last column 1 label
+                               iColumn1Label = true;
                                // Set the state to label
                                scDoc.SetState(SCE_CLW_LABEL);
                        }
@@ -323,8 +431,8 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                                // Set to default state
                                scDoc.SetState(SCE_CLW_DEFAULT);
                        }
-                       // else if the start of a comment or is an * (asterisk)
-                       else if (IsACommentStart(scDoc) || scDoc.ch == '*' ) {
+                       // else if comment start (!) or is an * (asterisk)
+                       else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) {
                                // then set the state to comment.
                                scDoc.SetState(SCE_CLW_COMMENT);
                        }
@@ -349,7 +457,7 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                }
                // Default Handling
                else {
-                       // If in default state
+                       // If in default state 
                        if (scDoc.state == SCE_CLW_DEFAULT) {
                                // If is a letter could be a possible statement
                                if (isalpha(scDoc.ch)) {
@@ -362,13 +470,13 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                                        scDoc.SetState(SCE_CLW_INTEGER_CONSTANT);
                                }
                                // else if the start of a comment or a | (line continuation)
-                               else if (IsACommentStart(scDoc) || scDoc.ch == '|') {
+                               else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') {
                                        // then set the state to comment.
                                        scDoc.SetState(SCE_CLW_COMMENT);
-                               }
+                               }               
                                // else if the character is a ' (single quote)
                                else if (scDoc.ch == '\'') {
-                                       // If the character is also a ' (single quote)
+                                       // If the character is also a ' (single quote) 
                                        // Embedded Apostrophe
                                        if (scDoc.chNext == '\'') {
                                                // Move forward colouring it as default state
@@ -378,8 +486,8 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                                                // move to the next character and then set the state to comment.
                                                scDoc.ForwardSetState(SCE_CLW_STRING);
                                        }
-                               }
-                               // else the character is an @ (apersand)
+                               }               
+                               // else the character is an @ (ampersand)
                                else if (scDoc.ch == '@') {
                                        // Case insensitive.
                                        if (!bCaseSensitive) {
@@ -397,7 +505,7 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                                                        scDoc.SetState(SCE_CLW_PICTURE_STRING);
                                                }
                                        }
-                               }
+                               }               
                        }
                }
        }
@@ -406,36 +514,162 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
 }
 
 // Clarion Language Case Sensitive Colouring Procedure
-static void ColouriseClwDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
-       ColouriseClwDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
+static void ColouriseClarionDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
+
+       ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
 }
 
 // Clarion Language Case Insensitive Colouring Procedure
-static void ColouriseClwDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
-       ColouriseClwDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
+static void ColouriseClarionDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
+
+       ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
+}
+
+// Fill Buffer
+
+static void FillBuffer(unsigned int uiStart, unsigned int uiEnd, Accessor &accStyler, char *szBuffer, unsigned int uiLength) {
+
+       unsigned int uiPos = 0;
+
+       while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) {
+               szBuffer[uiPos] = static_cast<char>(toupper(accStyler[uiStart + uiPos]));
+               uiPos++;
+       }
+       szBuffer[uiPos] = '\0';
+}
+
+// Classify Clarion Fold Point
+
+static int ClassifyClarionFoldPoint(int iLevel, const char* szString) {
+
+       if (!(isdigit(szString[0]) || (szString[0] == '.'))) {
+               if (strcmp(szString, "PROCEDURE") == 0) {
+       //              iLevel = SC_FOLDLEVELBASE + 1;
+               }
+               else if (strcmp(szString, "MAP") == 0 ||
+                       strcmp(szString,"ACCEPT") == 0 ||
+                       strcmp(szString,"BEGIN") == 0 ||
+                       strcmp(szString,"CASE") == 0 ||
+                       strcmp(szString,"EXECUTE") == 0 ||
+                       strcmp(szString,"IF") == 0 ||
+                       strcmp(szString,"ITEMIZE") == 0 ||
+                       strcmp(szString,"INTERFACE") == 0 ||
+                       strcmp(szString,"JOIN") == 0 ||
+                       strcmp(szString,"LOOP") == 0 ||
+                       strcmp(szString,"MODULE") == 0 ||
+                       strcmp(szString,"RECORD") == 0) {
+                       iLevel++;
+               }
+               else if (strcmp(szString, "APPLICATION") == 0 ||
+                       strcmp(szString, "CLASS") == 0 ||
+                       strcmp(szString, "DETAIL") == 0 ||
+                       strcmp(szString, "FILE") == 0 ||
+                       strcmp(szString, "FOOTER") == 0 ||
+                       strcmp(szString, "FORM") == 0 ||
+                       strcmp(szString, "GROUP") == 0 ||
+                       strcmp(szString, "HEADER") == 0 ||
+                       strcmp(szString, "INTERFACE") == 0 ||
+                       strcmp(szString, "MENU") == 0 ||
+                       strcmp(szString, "MENUBAR") == 0 ||
+                       strcmp(szString, "OLE") == 0 ||
+                       strcmp(szString, "OPTION") == 0 ||
+                       strcmp(szString, "QUEUE") == 0 ||
+                       strcmp(szString, "REPORT") == 0 ||
+                       strcmp(szString, "SHEET") == 0 ||
+                       strcmp(szString, "TAB") == 0 ||
+                       strcmp(szString, "TOOLBAR") == 0 ||
+                       strcmp(szString, "VIEW") == 0 ||
+                       strcmp(szString, "WINDOW") == 0) {
+                       iLevel++;
+               }
+               else if (strcmp(szString, "END") == 0 ||
+                       strcmp(szString, "UNTIL") == 0 ||
+                       strcmp(szString, "WHILE") == 0) {
+                       iLevel--;
+               }
+       }
+       return(iLevel);
 }
 
 // Clarion Language Folding Procedure
-#ifdef FOLDING_IMPLEMENTED
-static void FoldClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
+static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *[], Accessor &accStyler) {
+
+       unsigned int uiEndPos = uiStartPos + iLength;
+       int iLineCurrent = accStyler.GetLine(uiStartPos);
+       int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int iLevelCurrent = iLevelPrev;
+       char chNext = accStyler[uiStartPos];
+       int iStyle = iInitStyle;
+       int iStyleNext = accStyler.StyleAt(uiStartPos);
+       int iVisibleChars = 0;
+       int iLastStart = 0;
+
+       for (unsigned int uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) {
+
+               char chChar = chNext;
+               chNext = accStyler.SafeGetCharAt(uiPos + 1);
+               int iStylePrev = iStyle;
+               iStyle = iStyleNext;
+               iStyleNext = accStyler.StyleAt(uiPos + 1);
+               bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n');
+       
+               if (iStylePrev == SCE_CLW_DEFAULT) {
+                       if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) {
+                               // Store last word start point.
+                               iLastStart = uiPos;
+                       }
+               }
+
+               if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) {
+                       if(iswordchar(chChar) && !iswordchar(chNext)) {
+                               char chBuffer[100];
+                               FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer));
+                               iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer);
+                       //      if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) {
+                       //              accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE);
+                       //              iLevelPrev = SC_FOLDLEVELBASE;
+                       //      }
+                       }
+               }
+
+               if (bEOL) {
+                       int iLevel = iLevelPrev;
+                       if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0))
+                               iLevel |= SC_FOLDLEVELHEADERFLAG;
+                       if (iLevel != accStyler.LevelAt(iLineCurrent)) {
+                               accStyler.SetLevel(iLineCurrent,iLevel);
+                       }
+                       iLineCurrent++;
+                       iLevelPrev = iLevelCurrent;
+                       iVisibleChars = 0;
+               }
+               
+               if (!isspacechar(chChar))
+                       iVisibleChars++;
+       }
 
+       // Fill in the real level of the next line, keeping the current flags
+       // as they will be filled in later.
+       int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+       accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext);
 }
-#endif
 
 // Word List Descriptions
 static const char * const rgWordListDescriptions[] = {
        "Clarion Keywords",
        "Compiler Directives",
        "Built-in Procedures and Functions",
+       "Runtime Expressions",
        "Structure and Data Types",
        "Attributes",
        "Standard Equates",
-       "Reserved Words",
+       "Reserved Words (Labels)",
+       "Reserved Words (Procedure Labels)",
        0,
 };
 
 // Case Sensitive Clarion Language Lexer
-LexerModule lmClw(SCLEX_CLW, ColouriseClwDocSensitive, "clw", NULL, rgWordListDescriptions);
+LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions);
 
 // Case Insensitive Clarion Language Lexer
-LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClwDocInsensitive, "clwnocase", NULL, rgWordListDescriptions);
+LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions);
index c6ca0650585470cf431a24f9579f0f02c794b01a..40f3a60bd37a4f3451cd3211d8acff13dd8e2f3c 100644 (file)
@@ -1,8 +1,8 @@
 // Scintilla source code edit control
 /** @file LexCPP.cxx
- ** Lexer for C++, C, Java, and Javascript.
+ ** Lexer for C++, C, Java, and JavaScript.
  **/
-// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
 #define KEYWORD_BOXHEADER 1
 #define KEYWORD_FOLDCONTRACTED 2
 
-static bool IsOKBeforeRE(const int ch) {
+static bool IsOKBeforeRE(int ch) {
        return (ch == '(') || (ch == '=') || (ch == ',');
 }
 
-static inline bool IsAWordChar(const int ch) {
+static inline bool IsAWordChar(int ch) {
        return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
 }
 
-static inline bool IsAWordStart(const int ch) {
-       return (ch < 0x80) && (isalnum(ch) || ch == '_');
+static inline bool IsAWordStart(int ch) {
+       return (ch < 0x80) && (isalpha(ch) || ch == '_');
 }
 
-static inline bool IsADoxygenChar(const int ch) {
-       return (islower(ch) || ch == '$' || ch == '@' ||
-               ch == '\\' || ch == '&' || ch == '<' ||
-               ch == '>' || ch == '#' || ch == '{' ||
-               ch == '}' || ch == '[' || ch == ']');
+static inline bool IsADoxygenChar(int ch) {
+       return (ch < 0x80 && islower(ch)) || ch == '$' || ch == '@' ||
+               ch == '\\' || ch == '&' || ch == '<' ||
+               ch == '>' || ch == '#' || ch == '{' ||
+               ch == '}' || ch == '[' || ch == ']';
 }
 
-static inline bool IsStateComment(const int state) {
-       return ((state == SCE_C_COMMENT) ||
-               (state == SCE_C_COMMENTLINE) ||
-               (state == SCE_C_COMMENTDOC) ||
-               (state == SCE_C_COMMENTDOCKEYWORD) ||
-               (state == SCE_C_COMMENTDOCKEYWORDERROR));
-}
-
-static inline bool IsStateString(const int state) {
-       return ((state == SCE_C_STRING) || (state == SCE_C_VERBATIM));
+static bool IsSpaceEquiv(int state) {
+       return (state <= SCE_C_COMMENTDOC) ||
+               // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE
+               (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) ||
+               (state == SCE_C_COMMENTDOCKEYWORDERROR);
 }
 
 static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
@@ -64,21 +59,52 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
 
        bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
 
-       // Do not leak onto next line
-       if (initStyle == SCE_C_STRINGEOL)
-               initStyle = SCE_C_DEFAULT;
-
        int chPrevNonWhite = ' ';
        int visibleChars = 0;
        bool lastWordWasUUID = false;
+       int styleBeforeDCKeyword = SCE_C_DEFAULT;
+       bool continuationLine = false;
+
+       if (initStyle == SCE_C_PREPROCESSOR) {
+               // Set continuationLine if last character of previous line is '\'
+               int lineCurrent = styler.GetLine(startPos);
+               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;
+                       }
+                       continuationLine = lineEndChar == '\\';
+               }
+       }
+
+       // look back to set chPrevNonWhite properly for better regex colouring
+       if (startPos > 0) {
+               int back = startPos;
+               while (--back && IsSpaceEquiv(styler.StyleAt(back)))
+                       ;
+               if (styler.StyleAt(back) == SCE_C_OPERATOR) {
+                       chPrevNonWhite = styler.SafeGetCharAt(back);
+               }
+       }
 
        StyleContext sc(startPos, length, initStyle, styler);
 
        for (; sc.More(); sc.Forward()) {
 
-               if (sc.atLineStart && (sc.state == SCE_C_STRING)) {
-                       // Prevent SCE_C_STRINGEOL from leaking back to previous line
-                       sc.SetState(SCE_C_STRING);
+               if (sc.atLineStart) {
+                       if (sc.state == SCE_C_STRING) {
+                               // Prevent SCE_C_STRINGEOL from leaking back to previous line which 
+                               // ends with a line continuation by locking in the state upto this position.
+                               sc.SetState(SCE_C_STRING);
+                       }
+                       // Reset states to begining of colourise so no surprises
+                       // if different sets of lines lexed.
+                       visibleChars = 0;
+                       lastWordWasUUID = false;
                }
 
                // Handle line continuation generically.
@@ -88,124 +114,161 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
                                if (sc.ch == '\r' && sc.chNext == '\n') {
                                        sc.Forward();
                                }
+                               continuationLine = true;
                                continue;
                        }
                }
 
                // Determine if the current state should terminate.
-               if (sc.state == SCE_C_OPERATOR) {
-                       sc.SetState(SCE_C_DEFAULT);
-               } else if (sc.state == SCE_C_NUMBER) {
-                       if (!IsAWordChar(sc.ch)) {
-                               sc.SetState(SCE_C_DEFAULT);
-                       }
-               } else if (sc.state == SCE_C_IDENTIFIER) {
-                       if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
-                               char s[100];
-                               if (caseSensitive) {
-                                       sc.GetCurrent(s, sizeof(s));
-                               } else {
-                                       sc.GetCurrentLowered(s, sizeof(s));
-                               }
-                               if (keywords.InList(s)) {
-                                       lastWordWasUUID = strcmp(s, "uuid") == 0;
-                                       sc.ChangeState(SCE_C_WORD);
-                               } else if (keywords2.InList(s)) {
-                                       sc.ChangeState(SCE_C_WORD2);
-                               } else if (keywords4.InList(s)) {
-                                       sc.ChangeState(SCE_C_GLOBALCLASS);
-                               }
+               switch (sc.state) {
+                       case SCE_C_OPERATOR:
                                sc.SetState(SCE_C_DEFAULT);
-                       }
-               } else if (sc.state == SCE_C_PREPROCESSOR) {
-                       if (stylingWithinPreprocessor) {
-                               if (IsASpace(sc.ch)) {
+                               break;
+                       case SCE_C_NUMBER:
+                               // We accept almost anything because of hex. and number suffixes
+                               if (!IsAWordChar(sc.ch)) {
                                        sc.SetState(SCE_C_DEFAULT);
                                }
-                       } else {
-                               if ((sc.ch == '\r') || (sc.ch == '\n') || (sc.Match('/', '*')) || (sc.Match('/', '/'))) {
+                               break;
+                       case SCE_C_IDENTIFIER:
+                               if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
+                                       char s[1000];
+                                       if (caseSensitive) {
+                                               sc.GetCurrent(s, sizeof(s));
+                                       } else {
+                                               sc.GetCurrentLowered(s, sizeof(s));
+                                       }
+                                       if (keywords.InList(s)) {
+                                               lastWordWasUUID = strcmp(s, "uuid") == 0;
+                                               sc.ChangeState(SCE_C_WORD);
+                                       } else if (keywords2.InList(s)) {
+                                               sc.ChangeState(SCE_C_WORD2);
+                                       } else if (keywords4.InList(s)) {
+                                               sc.ChangeState(SCE_C_GLOBALCLASS);
+                                       }
                                        sc.SetState(SCE_C_DEFAULT);
                                }
-                       }
-               } else if (sc.state == SCE_C_COMMENT) {
-                       if (sc.Match('*', '/')) {
-                               sc.Forward();
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       }
-               } else if (sc.state == SCE_C_COMMENTDOC) {
-                       if (sc.Match('*', '/')) {
-                               sc.Forward();
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       } else if (sc.ch == '@' || sc.ch == '\\') {
-                               sc.SetState(SCE_C_COMMENTDOCKEYWORD);
-                       }
-               } else if (sc.state == SCE_C_COMMENTLINE || sc.state == SCE_C_COMMENTLINEDOC) {
-                       if (sc.ch == '\r' || sc.ch == '\n') {
-                               sc.SetState(SCE_C_DEFAULT);
-                               visibleChars = 0;
-                       }
-               } else if (sc.state == SCE_C_COMMENTDOCKEYWORD) {
-                       if (sc.Match('*', '/')) {
-                               sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
-                               sc.Forward();
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       } else if (!IsADoxygenChar(sc.ch)) {
-                               char s[100];
-                               if (caseSensitive) {
-                                       sc.GetCurrent(s, sizeof(s));
+                               break;
+                       case SCE_C_PREPROCESSOR:
+                               if (sc.atLineStart && !continuationLine) {
+                                       sc.SetState(SCE_C_DEFAULT);
+                               } else if (stylingWithinPreprocessor) {
+                                       if (IsASpace(sc.ch)) {
+                                               sc.SetState(SCE_C_DEFAULT);
+                                       }
                                } else {
-                                       sc.GetCurrentLowered(s, sizeof(s));
-                               }
-                               if (!isspace(sc.ch) || !keywords3.InList(s + 1)) {
-                                       sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
+                                       if (sc.Match('/', '*') || sc.Match('/', '/')) {
+                                               sc.SetState(SCE_C_DEFAULT);
+                                       }
                                }
-                               sc.SetState(SCE_C_COMMENTDOC);
-                       }
-               } else if (sc.state == SCE_C_STRING) {
-                       if (sc.ch == '\\') {
-                               if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+                               break;
+                       case SCE_C_COMMENT:
+                               if (sc.Match('*', '/')) {
                                        sc.Forward();
+                                       sc.ForwardSetState(SCE_C_DEFAULT);
                                }
-                       } else if (sc.ch == '\"') {
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       } else if (sc.atLineEnd) {
-                               sc.ChangeState(SCE_C_STRINGEOL);
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                               visibleChars = 0;
-                       }
-               } else if (sc.state == SCE_C_CHARACTER) {
-                       if (sc.atLineEnd) {
-                               sc.ChangeState(SCE_C_STRINGEOL);
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                               visibleChars = 0;
-                       } else if (sc.ch == '\\') {
-                               if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+                               break;
+                       case SCE_C_COMMENTDOC:
+                               if (sc.Match('*', '/')) {
                                        sc.Forward();
+                                       sc.ForwardSetState(SCE_C_DEFAULT);
+                               } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
+                                       // Verify that we have the conditions to mark a comment-doc-keyword
+                                       if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
+                                               styleBeforeDCKeyword = SCE_C_COMMENTDOC;
+                                               sc.SetState(SCE_C_COMMENTDOCKEYWORD);
+                                       }
                                }
-                       } else if (sc.ch == '\'') {
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       }
-               } else if (sc.state == SCE_C_REGEX) {
-                       if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == '/') {
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       } else if (sc.ch == '\\') {
-                               // Gobble up the quoted character
-                               if (sc.chNext == '\\' || sc.chNext == '/') {
-                                       sc.Forward();
+                               break;
+                       case SCE_C_COMMENTLINE:
+                               if (sc.atLineStart) {
+                                       sc.SetState(SCE_C_DEFAULT);
                                }
-                       }
-               } else if (sc.state == SCE_C_VERBATIM) {
-                       if (sc.ch == '\"') {
-                               if (sc.chNext == '\"') {
+                               break;
+                       case SCE_C_COMMENTLINEDOC:
+                               if (sc.atLineStart) {
+                                       sc.SetState(SCE_C_DEFAULT);
+                               } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
+                                       // Verify that we have the conditions to mark a comment-doc-keyword
+                                       if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) {
+                                               styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC;
+                                               sc.SetState(SCE_C_COMMENTDOCKEYWORD);
+                                       }
+                               }
+                               break;
+                       case SCE_C_COMMENTDOCKEYWORD:
+                               if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) {
+                                       sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
                                        sc.Forward();
-                               } else {
                                        sc.ForwardSetState(SCE_C_DEFAULT);
+                               } else if (!IsADoxygenChar(sc.ch)) {
+                                       char s[100];
+                                       if (caseSensitive) {
+                                               sc.GetCurrent(s, sizeof(s));
+                                       } else {
+                                               sc.GetCurrentLowered(s, sizeof(s));
+                                       }
+                                       if (!isspace(sc.ch) || !keywords3.InList(s + 1)) {
+                                               sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
+                                       }
+                                       sc.SetState(styleBeforeDCKeyword);
+                               }
+                               break;
+                       case SCE_C_STRING:
+                               if (sc.atLineEnd) {
+                                       sc.ChangeState(SCE_C_STRINGEOL);
+                               } else if (sc.ch == '\\') {
+                                       if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+                                               sc.Forward();
+                                       }
+                               } else if (sc.ch == '\"') {
+                                       sc.ForwardSetState(SCE_C_DEFAULT);
+                               }
+                               break;
+                       case SCE_C_CHARACTER:
+                               if (sc.atLineEnd) {
+                                       sc.ChangeState(SCE_C_STRINGEOL);
+                               } else if (sc.ch == '\\') {
+                                       if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+                                               sc.Forward();
+                                       }
+                               } else if (sc.ch == '\'') {
+                                       sc.ForwardSetState(SCE_C_DEFAULT);
+                               }
+                               break;
+                       case SCE_C_REGEX:
+                               if (sc.atLineStart) {
+                                       sc.SetState(SCE_C_DEFAULT);
+                               } else if (sc.ch == '/') {
+                                       sc.Forward();
+                                       while ((sc.ch < 0x80) && islower(sc.ch))
+                                               sc.Forward();    // gobble regex flags
+                                       sc.SetState(SCE_C_DEFAULT);
+                               } else if (sc.ch == '\\') {
+                                       // Gobble up the quoted character
+                                       if (sc.chNext == '\\' || sc.chNext == '/') {
+                                               sc.Forward();
+                                       }
+                               }
+                               break;
+                       case SCE_C_STRINGEOL:
+                               if (sc.atLineStart) {
+                                       sc.SetState(SCE_C_DEFAULT);
+                               }
+                               break;
+                       case SCE_C_VERBATIM:
+                               if (sc.ch == '\"') {
+                                       if (sc.chNext == '\"') {
+                                               sc.Forward();
+                                       } else {
+                                               sc.ForwardSetState(SCE_C_DEFAULT);
+                                       }
+                               }
+                               break;
+                       case SCE_C_UUID:
+                               if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
+                                       sc.SetState(SCE_C_DEFAULT);
                                }
-                       }
-               } else if (sc.state == SCE_C_UUID) {
-                       if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
-                               sc.SetState(SCE_C_DEFAULT);
-                       }
                }
 
                // Determine if a new state should be entered.
@@ -241,7 +304,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
                                else
                                        sc.SetState(SCE_C_COMMENTLINE);
                        } else if (sc.ch == '/' && IsOKBeforeRE(chPrevNonWhite)) {
-                               sc.SetState(SCE_C_REGEX);
+                               sc.SetState(SCE_C_REGEX);       // JavaScript's RegEx
                        } else if (sc.ch == '\"') {
                                sc.SetState(SCE_C_STRING);
                        } else if (sc.ch == '\'') {
@@ -253,7 +316,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
                                do {
                                        sc.Forward();
                                } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
-                               if (sc.ch == '\r' || sc.ch == '\n') {
+                               if (sc.atLineEnd) {
                                        sc.SetState(SCE_C_DEFAULT);
                                }
                        } else if (isoperator(static_cast<char>(sc.ch))) {
@@ -261,26 +324,20 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
                        }
                }
 
-               if (sc.atLineEnd) {
-                       // Reset states to begining of colourise so no surprises
-                       // if different sets of lines lexed.
-                       chPrevNonWhite = ' ';
-                       visibleChars = 0;
-                       lastWordWasUUID = false;
-               }
-               if (!IsASpace(sc.ch)) {
+               if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) {
                        chPrevNonWhite = sc.ch;
                        visibleChars++;
                }
+               continuationLine = false;
        }
        sc.Complete();
 }
 
 static bool IsStreamCommentStyle(int style) {
        return style == SCE_C_COMMENT ||
-              style == SCE_C_COMMENTDOC ||
-              style == SCE_C_COMMENTDOCKEYWORD ||
-              style == SCE_C_COMMENTDOCKEYWORDERROR;
+               style == SCE_C_COMMENTDOC ||
+               style == SCE_C_COMMENTDOCKEYWORD ||
+               style == SCE_C_COMMENTDOCKEYWORDERROR;
 }
 
 // Store both the current line's fold level and the next lines in the
index f45ce1cda4c656fedf11860b19e74be7b851765c..963a7b3ef77f10ac8a5e29075b7d7ec3151afab9 100644 (file)
@@ -107,6 +107,25 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo
                                if (lastState == SCE_CSS_DEFAULT)
                                        sc.SetState(SCE_CSS_DIRECTIVE);
                                break;
+                       case '*':
+                               if (lastState == SCE_CSS_DEFAULT)
+                                       sc.SetState(SCE_CSS_TAG);
+                               break;
+                       case '>':
+                       case '+':
+                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_CLASS
+                                       || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
+                                       sc.SetState(SCE_CSS_DEFAULT);
+                               break;
+                       case '[':
+                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
+                                       lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
+                                       sc.SetState(SCE_CSS_ATTRIBUTE);
+                               break;
+                       case ']':
+                               if (lastState == SCE_CSS_ATTRIBUTE)
+                                       sc.SetState(SCE_CSS_TAG);
+                               break;
                        case '{':
                                if (lastState == SCE_CSS_DIRECTIVE)
                                        sc.SetState(SCE_CSS_DEFAULT);
@@ -126,11 +145,13 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo
                                        sc.SetState(SCE_CSS_VALUE);
                                break;
                        case '.':
-                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT)
+                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
+                                       lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
                                        sc.SetState(SCE_CSS_CLASS);
                                break;
                        case '#':
-                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT)
+                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
+                                       lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
                                        sc.SetState(SCE_CSS_ID);
                                break;
                        case ',':
@@ -208,6 +229,7 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo
                } else if (sc.state == SCE_CSS_VALUE && (sc.ch == '\"' || sc.ch == '\'')) {
                        sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING));
                } else if (IsCssOperator(static_cast<char>(sc.ch))
+                       && (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']')
                        && (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!')
                        && (sc.state != SCE_CSS_DIRECTIVE || sc.ch == ';' || sc.ch == '{')
                ) {
diff --git a/contrib/src/stc/scintilla/src/LexCaml.cxx b/contrib/src/stc/scintilla/src/LexCaml.cxx
new file mode 100644 (file)
index 0000000..5f4fad5
--- /dev/null
@@ -0,0 +1,399 @@
+// Scintilla source code edit control
+/** @file LexCaml.cxx
+ ** Lexer for Objective Caml.
+ **/
+// Copyright 2005 by Robert Roessler <robertr@rftp.com>
+// The License.txt file describes the conditions under which this software may be distributed.
+/*     Release History
+       20050204 Initial release.
+       20050205 Quick compiler standards/"cleanliness" adjustment.
+       20050206 Added cast for IsLeadByte().
+       20050209 Changes to "external" build support.
+       20050306 Fix for 1st-char-in-doc "corner" case.
+       20050502 Fix for [harmless] one-past-the-end coloring.
+       20050515 Refined numeric token recognition logic.
+       20051125 Added 2nd "optional" keywords class.
+       20051129 Support "magic" (read-only) comments for RCaml.
+       20051204 Swtich to using StyleContext infrastructure.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+//     Since the Microsoft __iscsym[f] funcs are not ANSI...
+inline int  iscaml(int c) {return isalnum(c) || c == '_';}
+inline int iscamlf(int c) {return isalpha(c) || c == '_';}
+inline int iscamld(int c) {return isdigit(c) || c == '_';}
+
+static const int baseT[24] = {
+       0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* A - L */
+       0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,16      /* M - X */
+};
+
+#ifdef BUILD_AS_EXTERNAL_LEXER
+/*
+       (actually seems to work!)
+*/
+#include "WindowAccessor.h"
+#include "ExternalLexer.h"
+
+#if PLAT_WIN
+#include <windows.h>
+#endif
+
+static void ColouriseCamlDoc(
+       unsigned int startPos, int length,
+       int initStyle,
+       WordList *keywordlists[],
+       Accessor &styler);
+
+static void FoldCamlDoc(
+       unsigned int startPos, int length,
+       int initStyle,
+       WordList *keywordlists[],
+       Accessor &styler);
+
+static void InternalLexOrFold(int lexOrFold, unsigned int startPos, int length,
+       int initStyle, char *words[], WindowID window, char *props);
+
+static const char* LexerName = "caml";
+
+#ifdef TRACE
+void Platform::DebugPrintf(const char *format, ...) {
+       char buffer[2000];
+       va_list pArguments;
+       va_start(pArguments, format);
+       vsprintf(buffer,format,pArguments);
+       va_end(pArguments);
+       Platform::DebugDisplay(buffer);
+}
+#else
+void Platform::DebugPrintf(const char *, ...) {
+}
+#endif
+
+bool Platform::IsDBCSLeadByte(int codePage, char ch) {
+       return ::IsDBCSLeadByteEx(codePage, ch) != 0;
+}
+
+long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) {
+       return ::SendMessage(reinterpret_cast<HWND>(w), msg, wParam, lParam);
+}
+
+long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam) {
+       return ::SendMessage(reinterpret_cast<HWND>(w), msg, wParam,
+               reinterpret_cast<LPARAM>(lParam));
+}
+
+void EXT_LEXER_DECL Fold(unsigned int lexer, unsigned int startPos, int length,
+       int initStyle, char *words[], WindowID window, char *props)
+{
+       // below useless evaluation(s) to supress "not used" warnings
+       lexer;
+       // build expected data structures and do the Fold
+       InternalLexOrFold(1, startPos, length, initStyle, words, window, props);
+
+}
+
+int EXT_LEXER_DECL GetLexerCount()
+{
+       return 1;       // just us [Objective] Caml lexers here!
+}
+
+void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)
+{
+       // below useless evaluation(s) to supress "not used" warnings
+       Index;
+       // return as much of our lexer name as will fit (what's up with Index?)
+       if (buflength > 0) {
+               buflength--;
+               int n = strlen(LexerName);
+               if (n > buflength)
+                       n = buflength;
+               memcpy(name, LexerName, n), name[n] = '\0';
+       }
+}
+
+void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length,
+       int initStyle, char *words[], WindowID window, char *props)
+{
+       // below useless evaluation(s) to supress "not used" warnings
+       lexer;
+       // build expected data structures and do the Lex
+       InternalLexOrFold(0, startPos, length, initStyle, words, window, props);
+}
+
+static void InternalLexOrFold(int foldOrLex, unsigned int startPos, int length,
+       int initStyle, char *words[], WindowID window, char *props)
+{
+       // create and initialize a WindowAccessor (including contained PropSet)
+       PropSet ps;
+       ps.SetMultiple(props);
+       WindowAccessor wa(window, ps);
+       // create and initialize WordList(s)
+       int nWL = 0;
+       for (; words[nWL]; nWL++) ;     // count # of WordList PTRs needed
+       WordList** wl = new WordList* [nWL + 1];// alloc WordList PTRs
+       int i = 0;
+       for (; i < nWL; i++) {
+               wl[i] = new WordList(); // (works or THROWS bad_alloc EXCEPTION)
+               wl[i]->Set(words[i]);
+       }
+       wl[i] = 0;
+       // call our "internal" folder/lexer (... then do Flush!)
+       if (foldOrLex)
+               FoldCamlDoc(startPos, length, initStyle, wl, wa);
+       else
+               ColouriseCamlDoc(startPos, length, initStyle, wl, wa);
+       wa.Flush();
+       // clean up before leaving
+       for (i = nWL - 1; i >= 0; i--)
+               delete wl[i];
+       delete [] wl;
+}
+
+static
+#endif /* BUILD_AS_EXTERNAL_LEXER */
+
+void ColouriseCamlDoc(
+       unsigned int startPos, int length,
+       int initStyle,
+       WordList *keywordlists[],
+       Accessor &styler)
+{
+       // initialize styler
+       StyleContext sc(startPos, length, initStyle, styler);
+       // set up [initial] state info (terminating states that shouldn't "bleed")
+       int nesting = 0;
+       if (sc.state < SCE_CAML_STRING)
+               sc.state = SCE_CAML_DEFAULT;
+       if (sc.state >= SCE_CAML_COMMENT)
+               nesting = (sc.state & 0x0f) - SCE_CAML_COMMENT;
+
+       int chBase = 0, chToken = 0, chLit = 0;
+       WordList& keywords  = *keywordlists[0];
+       WordList& keywords2 = *keywordlists[1];
+       WordList& keywords3 = *keywordlists[2];
+       const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0);
+
+       // foreach char in range...
+       while (sc.More()) {
+               // set up [per-char] state info
+               int state2 = -1;                // (ASSUME no state change)
+               int chColor = sc.currentPos - 1;// (ASSUME standard coloring range)
+               bool advance = true;    // (ASSUME scanner "eats" 1 char)
+
+               // step state machine
+               switch (sc.state & 0x0f) {
+               case SCE_CAML_DEFAULT:
+                       chToken = sc.currentPos;        // save [possible] token start (JIC)
+                       // it's wide open; what do we have?
+                       if (iscamlf(sc.ch))
+                               state2 = SCE_CAML_IDENTIFIER;
+                       else if (sc.Match('`') && iscamlf(sc.chNext))
+                               state2 = SCE_CAML_TAGNAME;
+                       else if (sc.Match('#') && isdigit(sc.chNext))
+                               state2 = SCE_CAML_LINENUM;
+                       else if (isdigit(sc.ch)) {
+                               state2 = SCE_CAML_NUMBER, chBase = 10;
+                               if (sc.Match('0') && strchr("bBoOxX", sc.chNext))
+                                       chBase = baseT[tolower(sc.chNext) - 'a'], sc.Forward();
+                       } else if (sc.Match('\''))      /* (char literal?) */
+                               state2 = SCE_CAML_CHAR, chLit = 0;
+                       else if (sc.Match('\"'))
+                               state2 = SCE_CAML_STRING;
+                       else if (sc.Match('(', '*'))
+                               state2 = SCE_CAML_COMMENT,
+                                       sc.ch = ' ',    // (make SURE "(*)" isn't seen as a closed comment)
+                                       sc.Forward();
+                       else if (strchr("!?~"           /* Caml "prefix-symbol" */
+                                       "=<>@^|&+-*/$%"         /* Caml "infix-symbol" */
+                                       "()[]{};,:.#", sc.ch))  /* Caml "bracket" or ;,:.# */
+                               state2 = SCE_CAML_OPERATOR;
+                       break;
+
+               case SCE_CAML_IDENTIFIER:
+                       // [try to] interpret as [additional] identifier char
+                       if (!(iscaml(sc.ch) || sc.Match('\''))) {
+                               const int n = sc.currentPos - chToken;
+                               if (n < 24) {
+                                       // length is believable as keyword, [re-]construct token
+                                       char t[24];
+                                       for (int i = -n; i < 0; i++)
+                                               t[n + i] = static_cast<char>(sc.GetRelative(i));
+                                       t[n] = '\0';
+                                       // special-case "_" token as KEYWORD
+                                       if ((n == 1 && sc.chPrev == '_') || keywords.InList(t))
+                                               sc.ChangeState(SCE_CAML_KEYWORD);
+                                       else if (keywords2.InList(t))
+                                               sc.ChangeState(SCE_CAML_KEYWORD2);
+                                       else if (keywords3.InList(t))
+                                               sc.ChangeState(SCE_CAML_KEYWORD3);
+                               }
+                               state2 = SCE_CAML_DEFAULT, advance = false;
+                       }
+                       break;
+
+               case SCE_CAML_TAGNAME:
+                       // [try to] interpret as [additional] tagname char
+                       if (!(iscaml(sc.ch) || sc.Match('\'')))
+                               state2 = SCE_CAML_DEFAULT, advance = false;
+                       break;
+
+               /*case SCE_CAML_KEYWORD:
+               case SCE_CAML_KEYWORD2:
+               case SCE_CAML_KEYWORD3:
+                       // [try to] interpret as [additional] keyword char
+                       if (!iscaml(ch))
+                               state2 = SCE_CAML_DEFAULT, advance = false;
+                       break;*/
+
+               case SCE_CAML_LINENUM:
+                       // [try to] interpret as [additional] linenum directive char
+                       if (!isdigit(sc.ch))
+                               state2 = SCE_CAML_DEFAULT, advance = false;
+                       break;
+
+               case SCE_CAML_OPERATOR: {
+                       // [try to] interpret as [additional] operator char
+                       const char* o = 0;
+                       if (iscaml(sc.ch) || isspace(sc.ch)                /* ident or whitespace */
+                               || (o = strchr(")]};,\'\"`#", sc.ch),o)/* "termination" chars */
+                               || !strchr("!$%&*+-./:<=>?@^|~", sc.ch)/* "operator" chars */) {
+                               // check for INCLUSIVE termination
+                               if (o && strchr(")]};,", sc.ch)) {
+                                       if ((sc.Match(')') && sc.chPrev == '(')
+                                               || (sc.Match(']') && sc.chPrev == '['))
+                                               // special-case "()" and "[]" tokens as KEYWORDS
+                                               sc.ChangeState(SCE_CAML_KEYWORD);
+                                       chColor++;
+                               } else
+                                       advance = false;
+                               state2 = SCE_CAML_DEFAULT;
+                       }
+                       break;
+               }
+
+               case SCE_CAML_NUMBER:
+                       // [try to] interpret as [additional] numeric literal char
+                       // N.B. - improperly accepts "extra" digits in base 2 or 8 literals
+                       if (iscamld(sc.ch) || IsADigit(sc.ch, chBase))
+                               break;
+                       // how about an integer suffix?
+                       if ((sc.Match('l') || sc.Match('L') || sc.Match('n'))
+                               && (iscamld(sc.chPrev) || IsADigit(sc.chPrev, chBase)))
+                               break;
+                       // or a floating-point literal?
+                       if (chBase == 10) {
+                               // with a decimal point?
+                               if (sc.Match('.') && iscamld(sc.chPrev))
+                                       break;
+                               // with an exponent? (I)
+                               if ((sc.Match('e') || sc.Match('E'))
+                                       && (iscamld(sc.chPrev) || sc.chPrev == '.'))
+                                       break;
+                               // with an exponent? (II)
+                               if ((sc.Match('+') || sc.Match('-'))
+                                       && (sc.chPrev == 'e' || sc.chPrev == 'E'))
+                                       break;
+                       }
+                       // it looks like we have run out of number
+                       state2 = SCE_CAML_DEFAULT, advance = false;
+                       break;
+
+               case SCE_CAML_CHAR:
+                       // [try to] interpret as [additional] char literal char
+                       if (sc.Match('\\')) {
+                               chLit = 1;      // (definitely IS a char literal)
+                               if (sc.chPrev == '\\')
+                                       sc.ch = ' ';    // (so termination test isn't fooled)
+                       // should we be terminating - one way or another?
+                       } else if ((sc.Match('\'') && sc.chPrev != '\\') || sc.atLineEnd) {
+                               state2 = SCE_CAML_DEFAULT;
+                               if (sc.Match('\''))
+                                       chColor++;
+                               else
+                                       sc.ChangeState(SCE_CAML_IDENTIFIER);
+                       // ... maybe a char literal, maybe not
+                       } else if (chLit < 1 && sc.currentPos - chToken >= 2)
+                               sc.ChangeState(SCE_CAML_IDENTIFIER), advance = false;
+                       break;
+
+               case SCE_CAML_STRING:
+                       // [try to] interpret as [additional] string literal char
+                       if (sc.Match('\\') && sc.chPrev == '\\')
+                               sc.ch = ' ';    // (so '\\' doesn't cause us trouble)
+                       else if (sc.Match('\"') && sc.chPrev != '\\')
+                               state2 = SCE_CAML_DEFAULT, chColor++;
+                       break;
+
+               case SCE_CAML_COMMENT:
+               case SCE_CAML_COMMENT1:
+               case SCE_CAML_COMMENT2:
+               case SCE_CAML_COMMENT3:
+                       // we're IN a comment - does this start a NESTED comment?
+                       if (sc.Match('(', '*'))
+                               state2 = sc.state + 1, chToken = sc.currentPos,
+                                       sc.ch = ' ',    // (make SURE "(*)" isn't seen as a closed comment)
+                                       sc.Forward(), nesting++;
+                       // [try to] interpret as [additional] comment char
+                       else if (sc.Match(')') && sc.chPrev == '*') {
+                               if (nesting)
+                                       state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--;
+                               else
+                                       state2 = SCE_CAML_DEFAULT;
+                               chColor++;
+                       // enable "magic" (read-only) comment AS REQUIRED
+                       } else if (useMagic && sc.currentPos - chToken == 4
+                               && sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@')
+                               sc.state |= 0x10;       // (switch to read-only comment style)
+                       break;
+               }
+
+               // handle state change and char coloring as required
+               if (state2 >= 0)
+                       styler.ColourTo(chColor, sc.state), sc.ChangeState(state2);
+               // move to next char UNLESS re-scanning current char
+               if (advance)
+                       sc.Forward();
+       }
+
+       // do any required terminal char coloring (JIC)
+       sc.Complete();
+}
+
+#ifdef BUILD_AS_EXTERNAL_LEXER
+static
+#endif /* BUILD_AS_EXTERNAL_LEXER */
+void FoldCamlDoc(
+       unsigned int startPos, int length,
+       int initStyle,
+       WordList *keywordlists[],
+       Accessor &styler)
+{
+       // below useless evaluation(s) to supress "not used" warnings
+       startPos || length || initStyle || keywordlists[0] || styler.Length();
+}
+
+static const char * const camlWordListDesc[] = {
+       "Keywords",             // primary Objective Caml keywords
+       "Keywords2",    // "optional" keywords (typically from Pervasives)
+       "Keywords3",    // "optional" keywords (typically typenames)
+       0
+};
+
+#ifndef BUILD_AS_EXTERNAL_LEXER
+LexerModule lmCaml(SCLEX_CAML, ColouriseCamlDoc, "caml", FoldCamlDoc, camlWordListDesc);
+#endif /* BUILD_AS_EXTERNAL_LEXER */
diff --git a/contrib/src/stc/scintilla/src/LexCsound.cxx b/contrib/src/stc/scintilla/src/LexCsound.cxx
new file mode 100644 (file)
index 0000000..27f7b99
--- /dev/null
@@ -0,0 +1,207 @@
+// Scintilla source code edit control
+/** @file LexCsound.cxx
+ ** Lexer for Csound (Orchestra & Score)
+ ** Written by Georg Ritter - <ritterfuture A T gmail D O T com>
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+
+static inline bool IsAWordChar(const int ch) {
+       return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
+               ch == '_' || ch == '?');
+}
+
+static inline bool IsAWordStart(const int ch) {
+       return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' ||
+               ch == '%' || ch == '@' || ch == '$' || ch == '?');
+}
+
+static inline bool IsCsoundOperator(char ch) {
+       if (isalnum(ch))
+               return false;
+       // '.' left out as it is used to make up numbers
+       if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
+               ch == '(' || ch == ')' || ch == '=' || ch == '^' ||
+               ch == '[' || ch == ']' || ch == '<' || ch == '&' ||
+               ch == '>' || ch == ',' || ch == '|' || ch == '~' ||
+               ch == '%' || ch == ':')
+               return true;
+       return false;
+}
+
+static void ColouriseCsoundDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+                               Accessor &styler) {
+
+       WordList &opcode = *keywordlists[0];
+       WordList &headerStmt = *keywordlists[1];
+       WordList &otherKeyword = *keywordlists[2];
+
+       // Do not leak onto next line
+       if (initStyle == SCE_CSOUND_STRINGEOL)
+               initStyle = SCE_CSOUND_DEFAULT;
+
+       StyleContext sc(startPos, length, initStyle, styler);
+
+       for (; sc.More(); sc.Forward())
+       {
+               // Handle line continuation generically.
+               if (sc.ch == '\\') {
+                       if (sc.chNext == '\n' || sc.chNext == '\r') {
+                               sc.Forward();
+                               if (sc.ch == '\r' && sc.chNext == '\n') {
+                                       sc.Forward();
+                               }
+                               continue;
+                       }
+               }
+              
+               // Determine if the current state should terminate.
+               if (sc.state == SCE_CSOUND_OPERATOR) {
+                       if (!IsCsoundOperator(static_cast<char>(sc.ch))) {
+                           sc.SetState(SCE_CSOUND_DEFAULT);
+                       }
+               }else if (sc.state == SCE_CSOUND_NUMBER) {
+                       if (!IsAWordChar(sc.ch)) {
+                               sc.SetState(SCE_CSOUND_DEFAULT);
+                       }
+               } else if (sc.state == SCE_CSOUND_IDENTIFIER) {
+                       if (!IsAWordChar(sc.ch) ) {
+                               char s[100];
+                               sc.GetCurrent(s, sizeof(s));
+
+                               if (opcode.InList(s)) {
+                                       sc.ChangeState(SCE_CSOUND_OPCODE);
+                               } else if (headerStmt.InList(s)) {
+                                       sc.ChangeState(SCE_CSOUND_HEADERSTMT);
+                               } else if (otherKeyword.InList(s)) {
+                                       sc.ChangeState(SCE_CSOUND_USERKEYWORD);
+                               } else if (s[0] == 'p') {
+                                       sc.ChangeState(SCE_CSOUND_PARAM);
+                               } else if (s[0] == 'a') {
+                                       sc.ChangeState(SCE_CSOUND_ARATE_VAR);
+                               } else if (s[0] == 'k') {
+                                       sc.ChangeState(SCE_CSOUND_KRATE_VAR);
+                               } else if (s[0] == 'i') { // covers both i-rate variables and i-statements
+                                       sc.ChangeState(SCE_CSOUND_IRATE_VAR);
+                               } else if (s[0] == 'g') {
+                                       sc.ChangeState(SCE_CSOUND_GLOBAL_VAR);
+                               }
+                               sc.SetState(SCE_CSOUND_DEFAULT);
+                       }
+               }
+               else if (sc.state == SCE_CSOUND_COMMENT ) {
+                       if (sc.atLineEnd) {
+                               sc.SetState(SCE_CSOUND_DEFAULT);
+                       }
+               }
+               else if ((sc.state == SCE_CSOUND_ARATE_VAR) ||
+                       (sc.state == SCE_CSOUND_KRATE_VAR) ||
+               (sc.state == SCE_CSOUND_IRATE_VAR)) {
+                       if (!IsAWordChar(sc.ch)) {
+                               sc.SetState(SCE_CSOUND_DEFAULT);
+                       }
+               }
+               
+               // Determine if a new state should be entered.
+               if (sc.state == SCE_CSOUND_DEFAULT) {
+                       if (sc.ch == ';'){
+                               sc.SetState(SCE_CSOUND_COMMENT);
+                       } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) {
+                               sc.SetState(SCE_CSOUND_NUMBER);
+                       } else if (IsAWordStart(sc.ch)) {
+                               sc.SetState(SCE_CSOUND_IDENTIFIER);
+                       } else if (IsCsoundOperator(static_cast<char>(sc.ch))) {
+                               sc.SetState(SCE_CSOUND_OPERATOR);
+                       } else if (sc.ch == 'p') {
+                               sc.SetState(SCE_CSOUND_PARAM);
+                       } else if (sc.ch == 'a') {
+                               sc.SetState(SCE_CSOUND_ARATE_VAR);
+                       } else if (sc.ch == 'k') {
+                               sc.SetState(SCE_CSOUND_KRATE_VAR);
+                       } else if (sc.ch == 'i') { // covers both i-rate variables and i-statements
+                               sc.SetState(SCE_CSOUND_IRATE_VAR);
+                       } else if (sc.ch == 'g') {
+                               sc.SetState(SCE_CSOUND_GLOBAL_VAR);
+                       }
+               }
+       }
+       sc.Complete();
+}
+
+static void FoldCsoundInstruments(unsigned int startPos, int length, int /* initStyle */, WordList *[], 
+               Accessor &styler) {
+       unsigned int lengthDoc = startPos + length;
+       int visibleChars = 0;
+       int lineCurrent = styler.GetLine(startPos);
+       int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int levelCurrent = levelPrev;
+       char chNext = styler[startPos];
+       int stylePrev = 0;
+       int styleNext = styler.StyleAt(startPos);
+       for (unsigned int i = startPos; i < lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               int style = styleNext;
+               styleNext = styler.StyleAt(i + 1);
+               bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+               if ((stylePrev != SCE_CSOUND_OPCODE) && (style == SCE_CSOUND_OPCODE)) {
+                       char s[20];
+                       unsigned int j = 0;
+                       while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) {
+                               s[j] = styler[i + j];
+                               j++;
+                       }
+                       s[j] = '\0';
+
+                       if (strcmp(s, "instr") == 0)
+                               levelCurrent++;
+                       if (strcmp(s, "endin") == 0)
+                               levelCurrent--;
+               }
+
+               if (atEOL) {
+                       int lev = levelPrev;
+                       if (visibleChars == 0)
+                               lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visibleChars > 0))
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+                       if (lev != styler.LevelAt(lineCurrent)) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+                       lineCurrent++;
+                       levelPrev = levelCurrent;
+                       visibleChars = 0;
+               }
+               if (!isspacechar(ch))
+                       visibleChars++;
+               stylePrev = style;
+       }
+       // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+       int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+       styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+}
+
+
+static const char * const csoundWordListDesc[] = {
+       "Opcodes",
+       "Header Statements",
+       "User keywords",
+       0
+};
+
+LexerModule lmCsound(SCLEX_CSOUND, ColouriseCsoundDoc, "csound", FoldCsoundInstruments, csoundWordListDesc);
index 974efd9a72e1d9a3a5071fb4315b2c92e296ee68..e9e154cd5f64b8eb8051aa11c7ccbf8ad08a0cda 100644 (file)
@@ -10,7 +10,6 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <fcntl.h>
 
 #include "Platform.h"
 
diff --git a/contrib/src/stc/scintilla/src/LexFlagship.cxx b/contrib/src/stc/scintilla/src/LexFlagship.cxx
new file mode 100644 (file)
index 0000000..db0314e
--- /dev/null
@@ -0,0 +1,226 @@
+// Scintilla source code edit control
+/** @file LexFlagShip.cxx
+ ** Lexer for FlagShip 
+ ** (Syntactically compatible to other XBase dialects, like dBase, Clipper, Fox etc.)
+ **/
+// Copyright 2005 by Randy Butler
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+static bool IsFlagShipComment(Accessor &styler, int pos, int len) {
+       return len>0 && styler[pos]=='\'';
+}
+
+static inline bool IsTypeCharacter(int ch) {
+       return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$';
+}
+
+// Extended to accept accented characters
+static inline bool IsAWordChar(int ch) {
+       return ch >= 0x80 ||
+              (isalnum(ch) || ch == '.' || ch == '_');
+}
+
+static inline bool IsAWordStart(int ch) {
+       return ch >= 0x80 ||
+              (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsADateCharacter(const int ch) {
+       return (ch < 0x80) &&
+               (isalnum(ch) || ch == '|' || ch == '-' || ch == '/' || ch == ':' || ch == ' ' || ch == '\t');
+}
+
+
+static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler) {
+
+       //bool FSScriptSyntax = true;
+       WordList &keywords = *keywordlists[0];
+       WordList &keywords2 = *keywordlists[1];
+       WordList &keywords3 = *keywordlists[2];
+       WordList &keywords4 = *keywordlists[3];
+
+       styler.StartAt(startPos);
+
+       int visibleChars = 0;
+
+       StyleContext sc(startPos, length, initStyle, styler);
+
+       for (; sc.More(); sc.Forward()) {
+
+               if (sc.state == SCE_FS_OPERATOR) {
+                       sc.SetState(SCE_FS_DEFAULT);
+               } else if (sc.state == SCE_FS_IDENTIFIER) {
+                       if (!IsAWordChar(sc.ch)) {
+                               char s[100];
+                               sc.GetCurrentLowered(s, sizeof(s));
+                               if (keywords.InList(s)) {
+                                       sc.ChangeState(SCE_FS_KEYWORD);
+                               } else if (keywords2.InList(s)) {
+                                       sc.ChangeState(SCE_FS_KEYWORD2);
+                               } else if (keywords3.InList(s)) {
+                                       sc.ChangeState(SCE_FS_KEYWORD3);
+                               } else if (keywords4.InList(s)) {
+                                       sc.ChangeState(SCE_FS_KEYWORD4);
+                               }// Else, it is really an identifier...
+                               sc.SetState(SCE_FS_DEFAULT);
+                       }
+               } else if (sc.state == SCE_FS_NUMBER) {
+                       if (!IsAWordChar(sc.ch)) {
+                               sc.SetState(SCE_FS_DEFAULT);
+                       }
+               } else if (sc.state == SCE_FS_STRING) {
+                       // VB doubles quotes to preserve them, so just end this string
+                       // state now as a following quote will start again
+                       if (sc.ch == '\"') {
+                               if (tolower(sc.chNext) == 'c') {
+                                       sc.Forward();
+                               }
+                               sc.ForwardSetState(SCE_FS_DEFAULT);
+                       } else if (sc.atLineEnd) {
+                               sc.ChangeState(SCE_FS_STRINGEOL);
+                               sc.ForwardSetState(SCE_FS_DEFAULT);
+                       }
+               } else if (sc.state == SCE_FS_COMMENT) {
+                       if (sc.Match('*', '/')) {   // new code
+                               sc.Forward();
+                               sc.ForwardSetState(SCE_FS_DEFAULT);
+                       //if (sc.atLineEnd) {       // old code
+                       //      sc.SetState(SCE_FS_DEFAULT);
+                       }
+               } else if (sc.state == SCE_FS_COMMENTLINE) {  //new code
+                       if (sc.ch == '\r' || sc.ch == '\n') {
+                               sc.SetState(SCE_FS_DEFAULT);
+                               visibleChars = 0;
+                       }
+               } else if (sc.state == SCE_FS_PREPROCESSOR) {
+                       if (sc.atLineEnd) {
+                               sc.SetState(SCE_FS_DEFAULT);
+                       }
+               } else if (sc.state == SCE_FS_DATE) {
+                       if (sc.ch == '#' || !IsADateCharacter(sc.chNext)) {
+                               sc.ForwardSetState(SCE_FS_DEFAULT);
+                       }
+               }
+
+               // Determine if a new state should be entered.
+               if (sc.state == SCE_FS_DEFAULT) {
+                       if (sc.Match('/', '*')) {  // New code
+                               sc.SetState(SCE_FS_COMMENT);
+                               sc.Forward();   // Eat the * so it isn't used for the end of the comment
+                       //if (sc.ch == '\'') {  // Old code
+                       //      sc.SetState(SCE_FS_COMMENT); // old code
+                       } else if (sc.Match('/', '/')) { // New code
+                               sc.SetState(SCE_FS_COMMENTLINE);
+                       } else if (sc.ch == '\"') {
+                               sc.SetState(SCE_FS_STRING);
+                       } else if (sc.ch == '#' && visibleChars == 0) {
+                               // Preprocessor commands are alone on their line
+                               sc.SetState(SCE_FS_PREPROCESSOR);
+                       } else if (sc.ch == '#') {
+                               int n = 1;
+                               int chSeek = ' ';
+                               while ((n < 100) && (chSeek == ' ' || chSeek == '\t')) {
+                                       chSeek = sc.GetRelative(n);
+                                       n++;
+                               }
+                               if (IsADigit(chSeek)) {
+                                       sc.SetState(SCE_FS_DATE);
+                               } else {
+                                       sc.SetState(SCE_FS_OPERATOR);
+                               }
+                       } else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {
+                               sc.SetState(SCE_FS_NUMBER);
+                       } else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {
+                               sc.SetState(SCE_FS_NUMBER);
+                       } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+                               sc.SetState(SCE_FS_NUMBER);
+                       } else if (IsAWordStart(sc.ch) || (sc.ch == '[')) {
+                               sc.SetState(SCE_FS_IDENTIFIER);
+                       } else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {
+                               sc.SetState(SCE_FS_OPERATOR);
+                       }
+               }
+
+               if (sc.atLineEnd) {
+                       visibleChars = 0;
+               }
+               if (!IsASpace(sc.ch)) {
+                       visibleChars++;
+               }
+       }
+       sc.Complete();
+}
+
+static void FoldFlagShipDoc(unsigned int startPos, int length, int,
+                                                  WordList *[], Accessor &styler) {
+
+       int endPos = startPos + length;
+
+       // Backtrack to previous line in case need to fix its fold status
+       int lineCurrent = styler.GetLine(startPos);
+       if (startPos > 0) {
+               if (lineCurrent > 0) {
+                       lineCurrent--;
+                       startPos = styler.LineStart(lineCurrent);
+               }
+       }
+       int spaceFlags = 0;
+       int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsFlagShipComment);
+       char chNext = styler[startPos];
+       for (int i = startPos; i < endPos; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+
+               if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
+                       int lev = indentCurrent;
+                       int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsFlagShipComment);
+                       if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+                               // Only non whitespace lines can be headers
+                               if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
+                                       lev |= SC_FOLDLEVELHEADERFLAG;
+                               } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
+                                       // Line after is blank so check the next - maybe should continue further?
+                                       int spaceFlags2 = 0;
+                                       int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsFlagShipComment);
+                                       if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
+                                               lev |= SC_FOLDLEVELHEADERFLAG;
+                                       }
+                               }
+                       }
+                       indentCurrent = indentNext;
+                       styler.SetLevel(lineCurrent, lev);
+                       lineCurrent++;
+               }
+       }
+}
+
+
+static const char * const FSWordListDesc[] = {
+       "Keywords",
+       "functions",
+       "user2",
+       "user3",
+       0
+};
+
+LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc);
+
+
+
index 0cc7342e69134535e4d329e3e4cd5449d77de823..3ab1116ea6ed2a889830452e32615f27cfc5f9f7 100644 (file)
@@ -273,9 +273,11 @@ static void FoldFortranDoc(unsigned int startPos, int length, int initStyle,
        int style = initStyle;
        /***************************************/
        int lastStart = 0;
-       char prevWord[32] = "", Label[6] = "";
+       char prevWord[32] = "";
+       char Label[6] = "";
        // Variables for do label folding.
-       static int doLabels[100], posLabel=-1;
+       static int doLabels[100];
+       static int posLabel=-1;
        /***************************************/
        for (unsigned int i = startPos; i < endPos; i++) {
                char ch = chNext;
index 2e3c02c1c927cd461ca1a599751f5b38fa234880..f76fff6cc4b86e5d665a1b12445d065e27723612 100644 (file)
@@ -236,7 +236,7 @@ ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle,
                if (!noforward) sc.Forward();
 
        }
-       styler.ColourTo(sc.currentPos, sc.state);
+       sc.Complete();
 }
 
 // Main folding function called by Scintilla - (based on props (.ini) files function)
index e3546b436fdb6b1674a29fef85e44e92a3cedd71..d830a46439e822b5a0704ccbd29d27152a618b81 100644 (file)
@@ -2,7 +2,7 @@
 /** @file LexHTML.cxx
  ** Lexer for HTML.
  **/
-// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
@@ -35,13 +35,24 @@ static inline bool IsAWordStart(const int ch) {
        return (ch < 0x80) && (isalnum(ch) || ch == '_');
 }
 
-static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) {
-       char s[30 + 1];
-       unsigned int i = 0;
-       for (; i < end - start + 1 && i < 30; i++) {
-               s[i] = static_cast<char>(tolower(styler[start + i]));
+static inline int MakeLowerCase(int ch) {
+       if (ch < 'A' || ch > 'Z')
+               return ch;
+       else
+               return ch - 'A' + 'a';
+}
+
+static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) {
+       size_t i = 0;
+       for (; (i < end - start + 1) && (i < len-1); i++) {
+               s[i] = static_cast<char>(MakeLowerCase(styler[start + i]));
        }
        s[i] = '\0';
+}
+
+static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) {
+       char s[100];
+       GetTextSegment(styler, start, end, s, sizeof(s));
        //Platform::DebugPrintf("Scripting indicator [%s]\n", s);
        if (strstr(s, "src"))   // External script
                return eScriptNone;
@@ -63,12 +74,8 @@ static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start,
 
 static int PrintScriptingIndicatorOffset(Accessor &styler, unsigned int start, unsigned int end) {
        int iResult = 0;
-       char s[30 + 1];
-       unsigned int i = 0;
-       for (; i < end - start + 1 && i < 30; i++) {
-               s[i] = static_cast<char>(tolower(styler[start + i]));
-       }
-       s[i] = '\0';
+       char s[100];
+       GetTextSegment(styler, start, end, s, sizeof(s));
        if (0 == strncmp(s, "php", 3)) {
                iResult = 3;
        }
@@ -183,12 +190,8 @@ static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &k
        if (wordIsNumber) {
                chAttr = SCE_H_NUMBER;
        } else {
-               char s[30 + 1];
-               unsigned int i = 0;
-               for (; i < end - start + 1 && i < 30; i++) {
-                       s[i] = static_cast<char>(tolower(styler[start + i]));
-               }
-               s[i] = '\0';
+               char s[100];
+               GetTextSegment(styler, start, end, s, sizeof(s));
                if (keywords.InList(s))
                        chAttr = SCE_H_ATTRIBUTE;
        }
@@ -207,7 +210,7 @@ static int classifyTagHTML(unsigned int start, unsigned int end,
        for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) {
                char ch = styler[cPos];
                if ((ch != '<') && (ch != '/')) {
-                       s[i++] = caseSensitive ? ch : static_cast<char>(tolower(ch));
+                       s[i++] = caseSensitive ? ch : static_cast<char>(MakeLowerCase(ch));
                }
        }
 
@@ -270,12 +273,8 @@ static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keyw
        if (wordIsNumber)
                chAttr = SCE_HB_NUMBER;
        else {
-               char s[30 + 1];
-               unsigned int i = 0;
-               for (; i < end - start + 1 && i < 30; i++) {
-                       s[i] = static_cast<char>(tolower(styler[start + i]));
-               }
-               s[i] = '\0';
+               char s[100];
+               GetTextSegment(styler, start, end, s, sizeof(s));
                if (keywords.InList(s)) {
                        chAttr = SCE_HB_WORD;
                        if (strcmp(s, "rem") == 0)
@@ -318,12 +317,8 @@ static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &ke
        if (wordIsNumber)
                chAttr = SCE_HPHP_NUMBER;
        else {
-               char s[100 + 1];
-               unsigned int i = 0;
-               for (; i < end - start + 1 && i < 100; i++) {
-                       s[i] = static_cast<char>(tolower(styler[start + i]));
-               }
-               s[i] = '\0';
+               char s[100];
+               GetTextSegment(styler, start, end, s, sizeof(s));
                if (keywords.InList(s))
                        chAttr = SCE_HPHP_WORD;
        }
@@ -406,6 +401,11 @@ static bool IsCommentState(const int state) {
        return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT;
 }
 
+static bool IsScriptCommentState(const int state) {
+       return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT ||
+                  state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE;
+}
+
 static bool isLineEnd(char ch) {
        return ch == '\r' || ch == '\n';
 }
@@ -424,6 +424,8 @@ static bool isPHPStringState(int state) {
 
 static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler) {
        int j;
+       while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t'))
+               i++;
        phpStringDelimiter[0] = '\n';
        for (j = i; j < lengthDoc && styler[j] != '\n' && styler[j] != '\r'; j++) {
                if (j - i < phpStringDelimiterSize - 2)
@@ -501,12 +503,28 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
        char chPrev = ' ';
        char ch = ' ';
        char chPrevNonWhite = ' ';
+       // look back to set chPrevNonWhite properly for better regex colouring
+       if (scriptLanguage == eScriptJS && startPos > 0) {
+               int back = startPos;
+               int style = 0;
+               while (--back) {
+                       style = styler.StyleAt(back);
+                       if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC)
+                               // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE
+                               break;
+               }
+               if (style == SCE_HJ_SYMBOLS) {
+                       chPrevNonWhite = styler.SafeGetCharAt(back);
+               }
+       }
+
        styler.StartSegment(startPos);
        const int lengthDoc = startPos + length;
        for (int i = startPos; i < lengthDoc; i++) {
                const char chPrev2 = chPrev;
                chPrev = ch;
-               if (ch != ' ' && ch != '\t')
+               if (!isspacechar(ch) && state != SCE_HJ_COMMENT &&
+                       state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC)
                        chPrevNonWhite = ch;
                ch = styler[i];
                char chNext = styler.SafeGetCharAt(i + 1);
@@ -605,9 +623,8 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                        case SCE_H_SINGLESTRING:
                        case SCE_HJ_COMMENT:
                        case SCE_HJ_COMMENTDOC:
-                               // SCE_HJ_COMMENTLINE removed as this is a common thing done to hide
-                               // the end of script marker from some JS interpreters.
-                               //case SCE_HJ_COMMENTLINE:
+                       //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide
+                       // the end of script marker from some JS interpreters.
                        case SCE_HJ_DOUBLESTRING:
                        case SCE_HJ_SINGLESTRING:
                        case SCE_HJ_REGEX:
@@ -617,6 +634,19 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                        case SCE_HP_TRIPLEDOUBLE:
                                break;
                        default :
+                               // check if the closing tag is a script tag
+                               if (state == SCE_HJ_COMMENTLINE) {
+                                       char tag[7]; // room for the <script> tag
+                                       char chr;       // current char
+                                       int j=0;
+                                       chr = styler.SafeGetCharAt(i+2);
+                                       while (j < 6 && !isspacechar(chr)) {
+                                               tag[j++] = static_cast<char>(MakeLowerCase(chr));
+                                               chr = styler.SafeGetCharAt(i+2+j);
+                                       }
+                                       tag[j] = '\0';
+                                       if (strcmp(tag, "script") != 0) break;
+                               }
                                // closing tag of the script (it's a closing HTML tag anyway)
                                styler.ColourTo(i - 1, StateToPrint);
                                state = SCE_H_TAGUNKNOWN;
@@ -636,7 +666,8 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                         !isPHPStringState(state) &&
                         (state != SCE_HPHP_COMMENT) &&
                         (ch == '<') &&
-                        (chNext == '?')) {
+                        (chNext == '?') &&
+                                !IsScriptCommentState(state) ) {
                        scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment() + 2, i + 10, eScriptPHP);
                        if (scriptLanguage != eScriptPHP && isStringState(state)) continue;
                        styler.ColourTo(i - 1, StateToPrint);
@@ -653,11 +684,9 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                                inScriptType = eNonHtmlScriptPreProc;
                        else
                                inScriptType = eNonHtmlPreProc;
-                       // fold whole script
-                       if (foldHTMLPreprocessor){
+                       // Fold whole script, but not if the XML first tag (all XML-like tags in this case)
+                       if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
                                levelCurrent++;
-                               if (scriptLanguage == eScriptXML)
-                                       levelCurrent--; // no folding of the XML first tag (all XML-like tags in this case)
                        }
                        // should be better
                        ch = styler.SafeGetCharAt(i);
@@ -665,7 +694,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                }
 
                // handle the start of ASP pre-processor = Non-HTML
-               else if (!isCommentASPState(state) && (ch == '<') && (chNext == '%')) {
+               else if (!isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) {
                        styler.ColourTo(i - 1, StateToPrint);
                        beforePreProc = state;
                        if (inScriptType == eNonHtmlScript)
@@ -706,15 +735,18 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                /////////////////////////////////////
                // handle the start of SGML language (DTD)
                else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) &&
-                        (chPrev == '<') &&
-                        (ch == '!') &&
-                        (StateToPrint != SCE_H_CDATA) && (!IsCommentState(StateToPrint))) {
+                                (chPrev == '<') &&
+                                (ch == '!') &&
+                                (StateToPrint != SCE_H_CDATA) &&
+                                (!IsCommentState(StateToPrint)) &&
+                                (!IsScriptCommentState(StateToPrint)) ) {
                        beforePreProc = state;
                        styler.ColourTo(i - 2, StateToPrint);
                        if ((chNext == '-') && (chNext2 == '-')) {
                                state = SCE_H_COMMENT; // wait for a pending command
-                       }
-                       else if (isWordCdata(i + 1, i + 7, styler)) {
+                               styler.ColourTo(i + 2, SCE_H_COMMENT);
+                               i += 2; // follow styling after the --
+                       } else if (isWordCdata(i + 1, i + 7, styler)) {
                                state = SCE_H_CDATA;
                        } else {
                                styler.ColourTo(i, SCE_H_SGML_DEFAULT); // <! is default
@@ -733,7 +765,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                              || (inScriptType == eNonHtmlScriptPreProc)) && (
                                 ((scriptLanguage == eScriptPHP) && (ch == '?') && !isPHPStringState(state) && (state != SCE_HPHP_COMMENT)) ||
                                 ((scriptLanguage != eScriptNone) && !isStringState(state) &&
-                                 (ch == '%'))
+                                 ((ch == '%') || (ch == '?')))
                             ) && (chNext == '>')) ||
                         ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) {
                        if (state == SCE_H_ASPAT) {
@@ -778,10 +810,11 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                                inScriptType = eNonHtmlScript;
                        else
                                inScriptType = eHtml;
-                       scriptLanguage = eScriptNone;
-                       // unfold all scripting languages
-                       if (foldHTMLPreprocessor)
+                       // Unfold all scripting languages, except for XML tag
+                       if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
                                levelCurrent--;
+                       }
+                       scriptLanguage = eScriptNone;
                        continue;
                }
                /////////////////////////////////////
@@ -1219,12 +1252,14 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                        if (ch == '/' && chPrev == '*') {
                                styler.ColourTo(i, StateToPrint);
                                state = SCE_HJ_DEFAULT;
+                               ch = ' ';
                        }
                        break;
                case SCE_HJ_COMMENTLINE:
                        if (ch == '\r' || ch == '\n') {
                                styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType));
                                state = SCE_HJ_DEFAULT;
+                               ch = ' ';
                        }
                        break;
                case SCE_HJ_DOUBLESTRING:
@@ -1272,6 +1307,13 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                        break;
                case SCE_HJ_REGEX:
                        if (ch == '\r' || ch == '\n' || ch == '/') {
+                               if (ch == '/') {
+                                       while (isascii(chNext) && islower(chNext)) {   // gobble regex flags
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               }
                                styler.ColourTo(i, StateToPrint);
                                state = SCE_HJ_DEFAULT;
                        } else if (ch == '\\') {
@@ -1496,7 +1538,10 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                        }
                        break;
                case SCE_HPHP_NUMBER:
-                       if (!IsADigit(ch) && ch != '.' && ch != 'e' && ch != 'E' && (ch != '-' || (chPrev != 'e' && chPrev != 'E'))) {
+                       // recognize bases 8,10 or 16 integers OR floating-point numbers
+                       if (!IsADigit(ch)
+                               && strchr(".xXabcdefABCDEF", ch) == NULL
+                               && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) {
                                styler.ColourTo(i - 1, SCE_HPHP_NUMBER);
                                if (isoperator(ch))
                                        state = SCE_HPHP_OPERATOR;
@@ -1946,6 +1991,12 @@ static void ColourisePHPDoc(unsigned int startPos, int length, int initStyle, Wo
        sc.Complete();
 }
 
+static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+                                               Accessor &styler) {
+       if(startPos == 0) initStyle = SCE_HPHP_DEFAULT;
+               ColouriseHyperTextDoc(startPos,length,initStyle,keywordlists,styler);
+}
+
 static const char * const htmlWordListDesc[] = {
        "HTML elements and attributes",
        "JavaScript keywords",
@@ -1956,7 +2007,19 @@ static const char * const htmlWordListDesc[] = {
        0,
 };
 
-LexerModule lmHTML(SCLEX_HTML, ColouriseHyperTextDoc, "hypertext", 0, htmlWordListDesc);
-LexerModule lmXML(SCLEX_XML, ColouriseHyperTextDoc, "xml", 0, htmlWordListDesc);
-LexerModule lmASP(SCLEX_ASP, ColouriseASPDoc, "asp", 0, htmlWordListDesc);
-LexerModule lmPHP(SCLEX_PHP, ColourisePHPDoc, "php", 0, htmlWordListDesc);
+static const char * const phpscriptWordListDesc[] = {
+       "", //Unused
+       "", //Unused
+       "", //Unused
+       "", //Unused
+       "PHP keywords",
+       "", //Unused
+       0,
+};
+
+LexerModule lmHTML(SCLEX_HTML, ColouriseHyperTextDoc, "hypertext", 0, htmlWordListDesc, 7);
+LexerModule lmXML(SCLEX_XML, ColouriseHyperTextDoc, "xml", 0, htmlWordListDesc, 7);
+// SCLEX_ASP and SCLEX_PHP should not be used in new code: use SCLEX_HTML instead.
+LexerModule lmASP(SCLEX_ASP, ColouriseASPDoc, "asp", 0, htmlWordListDesc, 7);
+LexerModule lmPHP(SCLEX_PHP, ColourisePHPDoc, "php", 0, htmlWordListDesc, 7);
+LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 7);
diff --git a/contrib/src/stc/scintilla/src/LexHaskell.cxx b/contrib/src/stc/scintilla/src/LexHaskell.cxx
new file mode 100644 (file)
index 0000000..0e4be85
--- /dev/null
@@ -0,0 +1,263 @@
+/******************************************************************
+ *    LexHaskell.cxx
+ *
+ *    A haskell lexer for the scintilla code control.
+ *    Some stuff "lended" from LexPython.cxx and LexCPP.cxx.
+ *    External lexer stuff inspired from the caml external lexer.
+ *
+ *    Written by Tobias Engvall - tumm at dtek dot chalmers dot se
+ *
+ *
+ *    TODO:
+ *    * Implement a folder :)
+ *    * Nice Character-lexing (stuff inside '\''), LexPython has
+ *      this.
+ *
+ *
+ *****************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef BUILD_AS_EXTERNAL_LEXER
+
+#include "ExternalLexer.h"
+#include "WindowAccessor.h"
+
+#define BUILD_EXTERNAL_LEXER 0
+
+#endif
+
+// Max level of nested comments
+#define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3
+
+
+enum kwType { kwOther, kwClass, kwData, kwInstance, kwImport, kwModule, kwType};
+
+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 (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsAWordChar(const int ch) {
+   return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
+}
+
+static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
+                               WordList *keywordlists[], Accessor &styler) {
+
+   WordList &keywords = *keywordlists[0];
+
+   int kwLast = kwOther;
+
+   StyleContext sc(startPos, length, initStyle, styler);
+
+   for (; sc.More(); sc.Forward()) {
+
+      // Check for state end
+         // Operator
+      if (sc.state == SCE_HA_OPERATOR) {
+         kwLast = kwOther;
+         sc.SetState(SCE_HA_DEFAULT);
+      }
+         // String
+      else if (sc.state == SCE_HA_STRING) {
+         if (sc.ch == '\"') {
+            sc.ForwardSetState(SCE_HA_DEFAULT);
+         }
+      }
+         // Char
+      else if (sc.state == SCE_HA_CHARACTER) {
+         if (sc.ch == '\'') {
+            sc.ForwardSetState(SCE_HA_DEFAULT);
+         }
+      }
+         // Number
+      else if (sc.state == SCE_HA_NUMBER) {
+         if (!IsADigit(sc.ch)) {
+            sc.SetState(SCE_HA_DEFAULT);
+         }
+      }
+         // Types, constructors, etc.
+      else if (sc.state == SCE_HA_CAPITAL) {
+         if (!IsAWordChar(sc.ch) || sc.ch == '.') {
+            sc.SetState(SCE_HA_DEFAULT);
+         }
+      }
+         // Identifier
+      else if (sc.state == SCE_HA_IDENTIFIER) {
+         if (!IsAWordChar(sc.ch)) {
+            char s[100];
+            sc.GetCurrent(s, sizeof(s));
+            int style = SCE_HA_IDENTIFIER;
+            if ((kwLast == kwImport) || (strcmp(s,"qualified") == 0) || (strcmp(s,"as") == 0)) {
+               style = SCE_HA_IMPORT;
+            } else if (keywords.InList(s)) {
+               style = SCE_HA_KEYWORD;
+            } else if (kwLast == kwData) {
+               style = SCE_HA_DATA;
+            } else if (kwLast == kwClass) {
+               style = SCE_HA_CLASS;
+            } else if (kwLast == kwModule) {
+               style = SCE_HA_MODULE;
+            } else if (isupper(s[0])) {
+               style = SCE_HA_CAPITAL;
+            }
+            sc.ChangeState(style);
+            sc.SetState(SCE_HA_DEFAULT);
+            if (style == SCE_HA_KEYWORD) {
+               if (0 == strcmp(s, "class"))
+                  kwLast = kwClass;
+               else if (0 == strcmp(s, "data"))
+                  kwLast = kwData;
+               else if (0 == strcmp(s, "instance"))
+                  kwLast = kwInstance;
+               else if (0 == strcmp(s, "import"))
+                  kwLast = kwImport;
+               else if (0 == strcmp(s, "module"))
+                  kwLast = kwModule;
+               else
+                  kwLast = kwOther;
+            } else if (style == SCE_HA_CLASS || style == SCE_HA_IMPORT ||
+                       style == SCE_HA_MODULE || style == SCE_HA_CAPITAL ||
+                       style == SCE_HA_DATA || style == SCE_HA_INSTANCE) {
+               kwLast = kwOther;
+            }
+         }
+      }
+         // Comments
+            // Oneliner
+      else if (sc.state == SCE_HA_COMMENTLINE) {
+         if (IsNewline(sc.ch))
+            sc.SetState(SCE_HA_DEFAULT);
+      }
+            // Nested
+      else if (sc.state >= SCE_HA_COMMENTBLOCK) {
+         if (sc.Match("{-")) {
+            if (sc.state < SCE_HA_COMMENTMAX)
+               sc.SetState(sc.state + 1);
+         }
+         else if (sc.Match("-}")) {
+            sc.Forward();
+            if (sc.state == SCE_HA_COMMENTBLOCK)
+               sc.ForwardSetState(SCE_HA_DEFAULT);
+            else
+               sc.ForwardSetState(sc.state - 1);
+         }
+      }
+      // New state?
+      if (sc.state == SCE_HA_DEFAULT) {
+         // Digit
+         if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+            sc.SetState(SCE_HA_NUMBER);
+         }
+         // Comment line
+         else if (sc.Match("--")) {
+            sc.SetState(SCE_HA_COMMENTLINE);
+         // Comment block
+         }
+         else if (sc.Match("{-")) {
+            sc.SetState(SCE_HA_COMMENTBLOCK);
+         }
+         // String
+         else if (sc.Match('\"')) {
+            sc.SetState(SCE_HA_STRING);
+         }
+         // Character
+         else if (sc.Match('\'') && IsWhitespace(sc.GetRelative(-1)) ) {
+            sc.SetState(SCE_HA_CHARACTER);
+         }
+         // Stringstart
+         else if (sc.Match('\"')) {
+            sc.SetState(SCE_HA_STRING);
+         }
+         // Operator
+         else if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
+            sc.SetState(SCE_HA_OPERATOR);
+         }
+         // Keyword
+         else if (IsAWordStart(sc.ch)) {
+               sc.SetState(SCE_HA_IDENTIFIER);
+         }
+
+      }
+   }
+   sc.Complete();
+}
+
+// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet.
+// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com
+#ifdef BUILD_EXTERNAL_LEXER
+static const char* LexerName = "haskell";
+
+void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle,
+                        char *words[], WindowID window, char *props)
+{
+   PropSet ps;
+   ps.SetMultiple(props);
+   WindowAccessor wa(window, ps);
+
+   int nWL = 0;
+   for (; words[nWL]; nWL++) ;
+   WordList** wl = new WordList* [nWL + 1];
+   int i = 0;
+   for (; i<nWL; i++)
+   {
+      wl[i] = new WordList();
+      wl[i]->Set(words[i]);
+   }
+   wl[i] = 0;
+
+   ColorizeHaskellDoc(startPos, length, initStyle, wl, wa);
+   wa.Flush();
+   for (i=nWL-1;i>=0;i--)
+      delete wl[i];
+   delete [] wl;
+}
+
+void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle,
+                        char *words[], WindowID window, char *props)
+{
+
+}
+
+int EXT_LEXER_DECL GetLexerCount()
+{
+   return 1;
+}
+
+void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)
+{
+   if (buflength > 0) {
+      buflength--;
+      int n = strlen(LexerName);
+      if (n > buflength)
+         n = buflength;
+      memcpy(name, LexerName, n), name[n] = '\0';
+   }
+}
+#endif
+
+LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell");
+
index 549b573e2ed3275a31d97e9a5d1dfdbdadd7d01a..91385f0fd4914efc1347e9039f1d35f5dcd4d7f6 100644 (file)
 #include "KeyWords.h"
 #include "Scintilla.h"
 #include "SciLexer.h"
+#include "StyleContext.h"
 
+#define SCE_LISP_CHARACTER 29
+#define SCE_LISP_MACRO 30
+#define SCE_LISP_MACRO_DISPATCH 31
 
 static inline bool isLispoperator(char ch) {
        if (isascii(ch) && isalnum(ch))
                return false;
-       if (ch == '\'' || ch == '(' || ch == ')' )
+       if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' )
                return true;
        return false;
 }
@@ -35,7 +39,7 @@ static inline bool isLispwordstart(char ch) {
 }
 
 
-static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
+static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
        PLATFORM_ASSERT(end >= start);
        char s[100];
        unsigned int i;
@@ -51,6 +55,11 @@ static void classifyWordLisp(unsigned int start, unsigned int end, WordList &key
        else {
                if (keywords.InList(s)) {
                        chAttr = SCE_LISP_KEYWORD;
+               } else if (keywords_kw.InList(s)) {
+                       chAttr = SCE_LISP_KEYWORD_KW;
+               } else if ((s[0] == '*' && s[i-1] == '*') ||
+                          (s[0] == '+' && s[i-1] == '+')) {
+                       chAttr = SCE_LISP_SPECIAL;
                }
        }
        styler.ColourTo(end, chAttr);
@@ -62,10 +71,11 @@ static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, W
                             Accessor &styler) {
 
        WordList &keywords = *keywordlists[0];
+       WordList &keywords_kw = *keywordlists[1];
 
        styler.StartAt(startPos);
 
-       int state = initStyle;
+       int state = initStyle, radix = -1;
        char chNext = styler[startPos];
        unsigned int lengthDoc = startPos + length;
        styler.StartSegment(startPos);
@@ -82,7 +92,11 @@ static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, W
                }
 
                if (state == SCE_LISP_DEFAULT) {
-                       if (isLispwordstart(ch)) {
+                       if (ch == '#') {
+                               styler.ColourTo(i - 1, state);
+                               radix = -1;
+                               state = SCE_LISP_MACRO_DISPATCH;
+                       } else if (isLispwordstart(ch)) {
                                styler.ColourTo(i - 1, state);
                                state = SCE_LISP_IDENTIFIER;
                        }
@@ -93,27 +107,105 @@ static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, W
                        else if (isLispoperator(ch) || ch=='\'') {
                                styler.ColourTo(i - 1, state);
                                styler.ColourTo(i, SCE_LISP_OPERATOR);
+                               if (ch=='\'' && isLispwordstart(chNext)) {
+                                       state = SCE_LISP_SYMBOL;
+                               }
                        }
                        else if (ch == '\"') {
                                styler.ColourTo(i - 1, state);
                                state = SCE_LISP_STRING;
                        }
-               } else if (state == SCE_LISP_IDENTIFIER) {
+               } else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) {
                        if (!isLispwordstart(ch)) {
-                               classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, styler);
+                               if (state == SCE_LISP_IDENTIFIER) {
+                                       classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
+                               } else {
+                                       styler.ColourTo(i - 1, state);
+                               }
                                state = SCE_LISP_DEFAULT;
                        } /*else*/
                        if (isLispoperator(ch) || ch=='\'') {
                                styler.ColourTo(i - 1, state);
                                styler.ColourTo(i, SCE_LISP_OPERATOR);
+                               if (ch=='\'' && isLispwordstart(chNext)) {
+                                       state = SCE_LISP_SYMBOL;
+                               }
+                       }
+               } else if (state == SCE_LISP_MACRO_DISPATCH) {
+                       if (!isdigit(ch)) {
+                               if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
+                                       state = SCE_LISP_DEFAULT;
+                               } else {
+                                       switch (ch) {
+                                               case '|': state = SCE_LISP_MULTI_COMMENT; break;
+                                               case 'o':
+                                               case 'O': radix = 8; state = SCE_LISP_MACRO; break;
+                                               case 'x':
+                                               case 'X': radix = 16; state = SCE_LISP_MACRO; break;
+                                               case 'b':
+                                               case 'B': radix = 2; state = SCE_LISP_MACRO; break;
+                                               case '\\': state = SCE_LISP_CHARACTER; break;
+                                               case ':':
+                                               case '-':
+                                               case '+': state = SCE_LISP_MACRO; break;
+                                               case '\'': if (isLispwordstart(chNext)) {
+                                                                  state = SCE_LISP_SPECIAL;
+                                                          } else {
+                                                                  styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
+                                                                  styler.ColourTo(i, SCE_LISP_OPERATOR);
+                                                                  state = SCE_LISP_DEFAULT;
+                                                          }
+                                                          break;
+                                               default: if (isLispoperator(ch)) {
+                                                                styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
+                                                                styler.ColourTo(i, SCE_LISP_OPERATOR);
+                                                        }
+                                                        state = SCE_LISP_DEFAULT;
+                                                        break;
+                                       }
+                               }
+                       }
+               } else if (state == SCE_LISP_MACRO) {
+                       if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
+                               state = SCE_LISP_SPECIAL;
+                       } else {
+                               state = SCE_LISP_DEFAULT;
+                       }
+               } else if (state == SCE_LISP_CHARACTER) {
+                       if (isLispoperator(ch)) {
+                               styler.ColourTo(i, SCE_LISP_SPECIAL);
+                               state = SCE_LISP_DEFAULT;
+                       } else if (isLispwordstart(ch)) {
+                               styler.ColourTo(i, SCE_LISP_SPECIAL);
+                               state = SCE_LISP_SPECIAL;
+                       } else {
+                               state = SCE_LISP_DEFAULT;
+                       }
+               } else if (state == SCE_LISP_SPECIAL) {
+                       if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_LISP_DEFAULT;
+                       }
+                       if (isLispoperator(ch) || ch=='\'') {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_LISP_OPERATOR);
+                               if (ch=='\'' && isLispwordstart(chNext)) {
+                                       state = SCE_LISP_SYMBOL;
+                               }
                        }
-
                } else {
                        if (state == SCE_LISP_COMMENT) {
                                if (atEOL) {
                                        styler.ColourTo(i - 1, state);
                                        state = SCE_LISP_DEFAULT;
                                }
+                       } else if (state == SCE_LISP_MULTI_COMMENT) {
+                               if (ch == '|' && chNext == '#') {
+                                       i++;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       styler.ColourTo(i, state);
+                                       state = SCE_LISP_DEFAULT;
+                               }
                        } else if (state == SCE_LISP_STRING) {
                                if (ch == '\\') {
                                        if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
@@ -175,6 +267,7 @@ static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */,
 }
 
 static const char * const lispWordListDesc[] = {
+       "Functions and special operators",
        "Keywords",
        0
 };
index 3e4b25cb5e9acb3c600b0077ef09545673d0e900..7f6df070acb081cb97d95962d2df1d7f2defb54d 100644 (file)
@@ -12,7 +12,6 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <fcntl.h>
 
 #include "Platform.h"
 
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-static inline bool IsAWordChar(const int ch) {
-       return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
+// Extended to accept accented characters
+static inline bool IsAWordChar(int ch) {
+       return ch >= 0x80 ||
+              (isalnum(ch) || ch == '.' || ch == '_');
 }
 
-static inline bool IsAWordStart(const int ch) {
-       return (ch < 0x80) && (isalnum(ch) || ch == '_');
+static inline bool IsAWordStart(int ch) {
+       return ch >= 0x80 ||
+              (isalpha(ch) || ch == '_');
 }
 
-static inline bool IsANumberChar(const int ch) {
+static inline bool IsANumberChar(int ch) {
        // Not exactly following number definition (several dots are seen as OK, etc.)
        // but probably enough in most cases.
        return (ch < 0x80) &&
@@ -55,6 +57,18 @@ static inline bool IsLuaOperator(int ch) {
        return false;
 }
 
+// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
+// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
+// The maximum number of '=' characters allowed is 254.
+static int LongDelimCheck(StyleContext &sc) {
+       int sep = 1;
+       while (sc.GetRelative(sep) == '=' && sep < 0xFF)
+               sep++;
+       if (sc.GetRelative(sep) == sc.ch)
+               return sep;
+       return 0;
+}
+
 static void ColouriseLuaDoc(
        unsigned int startPos,
        int length,
@@ -72,19 +86,19 @@ static void ColouriseLuaDoc(
        WordList &keywords8 = *keywordlists[7];
 
        int currentLine = styler.GetLine(startPos);
-       // Initialize the literal string [[ ... ]] nesting level, if we are inside such a string.
-       int literalStringLevel = 0;
-       if (initStyle == SCE_LUA_LITERALSTRING) {
-               literalStringLevel = styler.GetLineState(currentLine - 1);
-       }
-       // Initialize the block comment --[[ ... ]] nesting level, if we are inside such a comment
-       int blockCommentLevel = 0;
-       if (initStyle == SCE_LUA_COMMENT) {
-               blockCommentLevel = styler.GetLineState(currentLine - 1);
+       // Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level,
+       // if we are inside such a string. Block comment was introduced in Lua 5.0,
+       // blocks with separators [=[ ... ]=] in Lua 5.1.
+       int nestLevel = 0;
+       int sepCount = 0;
+       if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) {
+               int lineState = styler.GetLineState(currentLine - 1);
+               nestLevel = lineState >> 8;
+               sepCount = lineState & 0xFF;
        }
 
        // Do not leak onto next line
-       if (initStyle == SCE_LUA_STRINGEOL) {
+       if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
                initStyle = SCE_LUA_DEFAULT;
        }
 
@@ -99,12 +113,9 @@ static void ColouriseLuaDoc(
                        currentLine = styler.GetLine(sc.currentPos);
                        switch (sc.state) {
                        case SCE_LUA_LITERALSTRING:
-                               // Inside a literal string, we set the line state
-                               styler.SetLineState(currentLine, literalStringLevel);
-                               break;
-                       case SCE_LUA_COMMENT:   // Block comment
-                               // Inside a block comment, we set the line state
-                               styler.SetLineState(currentLine, blockCommentLevel);
+                       case SCE_LUA_COMMENT:
+                               // Inside a literal string or block comment, we set the line state
+                               styler.SetLineState(currentLine, (nestLevel << 8) | sepCount);
                                break;
                        default:
                                // Reset the line state
@@ -162,13 +173,9 @@ static void ColouriseLuaDoc(
                                }
                                sc.SetState(SCE_LUA_DEFAULT);
                        }
-               } else if (sc.state == SCE_LUA_COMMENTLINE ) {
+               } else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
                        if (sc.atLineEnd) {
-                               sc.SetState(SCE_LUA_DEFAULT);
-                       }
-               } else if (sc.state == SCE_LUA_PREPROCESSOR ) {
-                       if (sc.atLineEnd) {
-                               sc.SetState(SCE_LUA_DEFAULT);
+                               sc.ForwardSetState(SCE_LUA_DEFAULT);
                        }
                } else if (sc.state == SCE_LUA_STRING) {
                        if (sc.ch == '\\') {
@@ -192,26 +199,23 @@ static void ColouriseLuaDoc(
                                sc.ChangeState(SCE_LUA_STRINGEOL);
                                sc.ForwardSetState(SCE_LUA_DEFAULT);
                        }
-               } else if (sc.state == SCE_LUA_LITERALSTRING) {
-                       if (sc.Match('[', '[')) {
-                               literalStringLevel++;
-                               sc.Forward();
-                               sc.SetState(SCE_LUA_LITERALSTRING);
-                       } else if (sc.Match(']', ']') && literalStringLevel > 0) {
-                               literalStringLevel--;
-                               sc.Forward();
-                               if (literalStringLevel == 0) {
-                                       sc.ForwardSetState(SCE_LUA_DEFAULT);
+               } else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
+                       if (sc.ch == '[') {
+                               int sep = LongDelimCheck(sc);
+                               if (sep == 1 && sepCount == 1) {    // [[-only allowed to nest
+                                       nestLevel++;
+                                       sc.Forward();
                                }
-                       }
-               } else if (sc.state == SCE_LUA_COMMENT) {       // Lua 5.0's block comment
-                       if (sc.Match('[', '[')) {
-                               blockCommentLevel++;
-                               sc.Forward();
-                       } else if (sc.Match(']', ']') && blockCommentLevel > 0) {
-                               blockCommentLevel--;
-                               sc.Forward();
-                               if (blockCommentLevel == 0) {
+                       } else if (sc.ch == ']') {
+                               int sep = LongDelimCheck(sc);
+                               if (sep == 1 && sepCount == 1) {    // un-nest with ]]-only
+                                       nestLevel--;
+                                       sc.Forward();
+                                       if (nestLevel == 0) {
+                                               sc.ForwardSetState(SCE_LUA_DEFAULT);
+                                       }
+                               } else if (sep > 1 && sep == sepCount) {   // ]=]-style delim
+                                       sc.Forward(sep);
                                        sc.ForwardSetState(SCE_LUA_DEFAULT);
                                }
                        }
@@ -223,21 +227,32 @@ static void ColouriseLuaDoc(
                                sc.SetState(SCE_LUA_NUMBER);
                        } else if (IsAWordStart(sc.ch)) {
                                sc.SetState(SCE_LUA_IDENTIFIER);
-                       } else if (sc.Match('\"')) {
+                       } else if (sc.ch == '\"') {
                                sc.SetState(SCE_LUA_STRING);
-                       } else if (sc.Match('\'')) {
+                       } else if (sc.ch == '\'') {
                                sc.SetState(SCE_LUA_CHARACTER);
-                       } else if (sc.Match('[', '[')) {
-                               literalStringLevel = 1;
-                               sc.SetState(SCE_LUA_LITERALSTRING);
-                               sc.Forward();
-                       } else if (sc.Match("--[[")) {  // Lua 5.0's block comment
-                               blockCommentLevel = 1;
-                               sc.SetState(SCE_LUA_COMMENT);
-                               sc.Forward(3);
+                       } else if (sc.ch == '[') {
+                               sepCount = LongDelimCheck(sc);
+                               if (sepCount == 0) {
+                                       sc.SetState(SCE_LUA_OPERATOR);
+                               } else {
+                                       nestLevel = 1;
+                                       sc.SetState(SCE_LUA_LITERALSTRING);
+                                       sc.Forward(sepCount);
+                               }
                        } else if (sc.Match('-', '-')) {
                                sc.SetState(SCE_LUA_COMMENTLINE);
-                               sc.Forward();
+                               if (sc.Match("--[")) {
+                                       sc.Forward(2);
+                                       sepCount = LongDelimCheck(sc);
+                                       if (sepCount > 0) {
+                                               nestLevel = 1;
+                                               sc.ChangeState(SCE_LUA_COMMENT);
+                                               sc.Forward(sepCount);
+                                       }
+                               } else {
+                                       sc.Forward();
+                               }
                        } else if (sc.atLineStart && sc.Match('$')) {
                                sc.SetState(SCE_LUA_PREPROCESSOR);      // Obsolete since Lua 4.0, but still in old code
                        } else if (IsLuaOperator(static_cast<char>(sc.ch))) {
@@ -267,7 +282,7 @@ static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, W
                styleNext = styler.StyleAt(i + 1);
                bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
                if (style == SCE_LUA_WORD) {
-                       if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e') {
+                       if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
                                for (unsigned int j = 0; j < 8; j++) {
                                        if (!iswordchar(styler[i + j])) {
                                                break;
@@ -276,10 +291,10 @@ static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, W
                                        s[j + 1] = '\0';
                                }
 
-                               if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0)) {
+                               if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
                                        levelCurrent++;
                                }
-                               if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) {
+                               if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) {
                                        levelCurrent--;
                                }
                        }
@@ -289,6 +304,12 @@ static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, W
                        } else if (ch == '}' || ch == ')') {
                                levelCurrent--;
                        }
+               } else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
+                       if (ch == '[') {
+                               levelCurrent++;
+                       } else if (ch == ']') {
+                               levelCurrent--;
+                       }
                }
 
                if (atEOL) {
@@ -321,8 +342,10 @@ static const char * const luaWordListDesc[] = {
        "Basic functions",
        "String, (table) & math functions",
        "(coroutines), I/O & system facilities",
-       "XXX",
-       "XXX",
+       "user1",
+       "user2",
+       "user3",
+       "user4",
        0
 };
 
index 6019f24d39450ffebb81fa553ac91faeddcdad54..0c54ce670153033c7a6d3138a35d88207173b221 100644 (file)
@@ -2,7 +2,7 @@
 /** @file LexMSSQL.cxx
  ** Lexer for MSSQL.
  **/
-// Copyright 1998-2002 by Filip Yaghob <fy@eg.cz>
+// By Filip Yaghob <fyaghob@gmail.com>
 
 
 #include <stdlib.h>
 #define KW_MSSQL_STORED_PROCEDURES  5
 #define KW_MSSQL_OPERATORS          6
 
-//~ val SCE_MSSQL_DEFAULT=0
-//~ val SCE_MSSQL_COMMENT=1
-//~ val SCE_MSSQL_LINE_COMMENT=2
-//~ val SCE_MSSQL_NUMBER=3
-//~ val SCE_MSSQL_STRING=4
-//~ val SCE_MSSQL_OPERATOR=5
-//~ val SCE_MSSQL_IDENTIFIER=6
-//~ val SCE_MSSQL_VARIABLE=7
-//~ val SCE_MSSQL_COLUMN_NAME=8
-//~ val SCE_MSSQL_STATEMENT=9
-//~ val SCE_MSSQL_DATATYPE=10
-//~ val SCE_MSSQL_SYSTABLE=11
-//~ val SCE_MSSQL_GLOBAL_VARIABLE=12
-//~ val SCE_MSSQL_FUNCTION=13
-//~ val SCE_MSSQL_STORED_PROCEDURE=14
-//~ val SCE_MSSQL_DEFAULT_PREF_DATATYPE 15
-//~ val SCE_MSSQL_COLUMN_NAME_2 16
-
 static bool isMSSQLOperator(char ch) {
        if (isascii(ch) && isalnum(ch))
                return false;
@@ -133,22 +115,7 @@ static void ColouriseMSSQLDoc(unsigned int startPos, int length,
        bool fold = styler.GetPropertyInt("fold") != 0;
        int lineCurrent = styler.GetLine(startPos);
        int spaceFlags = 0;
-/*
-       WordList &kwStatements          = *keywordlists[KW_MSSQL_STATEMENTS];
-    WordList &kwDataTypes           = *keywordlists[KW_MSSQL_DATA_TYPES];
-    WordList &kwSystemTables        = *keywordlists[KW_MSSQL_SYSTEM_TABLES];
-    WordList &kwGlobalVariables     = *keywordlists[KW_MSSQL_GLOBAL_VARIABLES];
-    WordList &kwFunctions           = *keywordlists[KW_MSSQL_FUNCTIONS];
 
-       char s[100];
-       int iixx = 0;
-       s[0] = 's';     s[1] = 'e'; s[2] = 'l'; s[3] = 'e'; s[4] = 'c'; s[5] = 't'; s[6] = 0;
-       if (kwStatements.InList(s))
-               iixx = 1;
-       s[0] = 's';     s[1] = 'e'; s[2] = 'r'; s[3] = 'v'; s[4] = 'e'; s[5] = 'r'; s[6] = 'n'; s[7] = 'a'; s[8] = 'm'; s[9] = 'e'; s[10] = 0;
-       if (kwGlobalVariables.InList(s))
-               iixx += 2;
-*/
        int state = initStyle;
        int prevState = initStyle;
        char chPrev = ' ';
@@ -315,6 +282,69 @@ static void ColouriseMSSQLDoc(unsigned int startPos, int length,
        styler.ColourTo(lengthDoc - 1, state);
 }
 
+static void FoldMSSQLDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+       bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+       bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+       unsigned int endPos = startPos + length;
+       int visibleChars = 0;
+       int lineCurrent = styler.GetLine(startPos);
+       int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int levelCurrent = levelPrev;
+       char chNext = styler[startPos];
+       bool inComment = (styler.StyleAt(startPos-1) == SCE_MSSQL_COMMENT);
+    char s[10];
+       for (unsigned int i = startPos; i < endPos; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               int style = styler.StyleAt(i);
+               bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+        // Comment folding
+               if (foldComment) {
+                       if (!inComment && (style == SCE_MSSQL_COMMENT))
+                               levelCurrent++;
+                       else if (inComment && (style != SCE_MSSQL_COMMENT))
+                               levelCurrent--;
+                       inComment = (style == SCE_MSSQL_COMMENT);
+               }
+        if (style == SCE_MSSQL_STATEMENT) {
+            // Folding between begin and end
+            if (ch == 'b' || ch == 'e') {
+                for (unsigned int j = 0; j < 5; j++) {
+                                       if (!iswordchar(styler[i + j])) {
+                                               break;
+                                       }
+                                       s[j] = styler[i + j];
+                                       s[j + 1] = '\0';
+                }
+                               if (strcmp(s, "begin") == 0) {
+                                       levelCurrent++;
+                               }
+                               if (strcmp(s, "end") == 0) {
+                                       levelCurrent--;
+                               }
+            }
+        }
+               if (atEOL) {
+                       int lev = levelPrev;
+                       if (visibleChars == 0 && foldCompact)
+                               lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visibleChars > 0))
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+                       if (lev != styler.LevelAt(lineCurrent)) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+                       lineCurrent++;
+                       levelPrev = levelCurrent;
+                       visibleChars = 0;
+               }
+               if (!isspacechar(ch))
+                       visibleChars++;
+       }
+       // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+       int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+       styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+}
+
 static const char * const sqlWordListDesc[] = {
        "Statements",
     "Data Types",
@@ -326,4 +356,4 @@ static const char * const sqlWordListDesc[] = {
        0,
 };
 
-LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", 0, sqlWordListDesc);
+LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", FoldMSSQLDoc, sqlWordListDesc);
index 7152229d668dad9aaaa43615e2077bb53824702f..b7d482c0f1d9a74e10b0907cd94176b06095e293 100644 (file)
@@ -160,8 +160,8 @@ static void ColouriseMETAPOSTDoc(
        int currentInterface = CheckMETAPOSTInterface(startPos,length,styler,defaultInterface) ;
 
        // 0  no keyword highlighting
-       // 1  metapost keyword highlighting
-       // 2+ metafun keyword highlighting
+       // 1  metapost keyword hightlighting
+       // 2+ metafun keyword hightlighting
 
        int extraInterface = 0 ;
 
index 0f969bbfb8c4d3c9b711dd8cc0bd66cc4de36f9b..6a7274ef59b2b7a2ab9764a093ec11c93a867a47 100644 (file)
@@ -2,8 +2,8 @@
 /** @file LexNsis.cxx
  ** Lexer for NSIS
  **/
-// Copyright 2003, 2004 by Angelo Mandato <angelo [at] spaceblue [dot] com>
-// Last Updated: 02/22/2004
+// Copyright 2003 - 2005 by Angelo Mandato <angelo [at] spaceblue [dot] com>
+// Last Updated: 03/13/2005
 // The License.txt file describes the conditions under which this software may be distributed.
 #include <stdlib.h>
 #include <string.h>
 #define SCE_NSIS_MACRODEF 12
 #define SCE_NSIS_STRINGVAR 13
 #define SCE_NSIS_NUMBER 14
+// ADDED for Scintilla v1.63
+#define SCE_NSIS_SECTIONGROUP 15
+#define SCE_NSIS_PAGEEX 16
+#define SCE_NSIS_FUNCTIONDEF 17
+#define SCE_NSIS_COMMENTBOX 18
 */
 
 static bool isNsisNumber(char ch)
@@ -55,6 +60,40 @@ static bool isNsisLetter(char ch)
   return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
 }
 
+static bool NsisNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler)
+{
+  int nNextLine = -1;
+  for( unsigned int i = start; i < end; i++ )
+  {
+    char cNext = styler.SafeGetCharAt( i );
+    if( cNext == '\n' )
+    {
+      nNextLine = i+1;
+      break;
+    }
+  }
+
+  if( nNextLine == -1 ) // We never foudn the next line...
+    return false;
+
+  for( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ )
+  {
+    char cNext = styler.SafeGetCharAt( firstChar );
+    if( cNext == ' ' )
+      continue;
+    if( cNext == '\t' )
+      continue;
+    if( cNext == '!' )
+    {
+      if( styler.Match(firstChar, "!else") )
+        return true;
+    }
+    break;
+  }
+
+  return false;
+}
+
 static int NsisCmp( char *s1, char *s2, bool bIgnoreCase )
 {
   if( bIgnoreCase )
@@ -63,25 +102,38 @@ static int NsisCmp( char *s1, char *s2, bool bIgnoreCase )
   return strcmp( s1, s2 );
 }
 
-static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler )
+static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse, bool foldUtilityCmd )
 {
+  int style = styler.StyleAt(end);
+
   // If the word is too long, it is not what we are looking for
-  if( end - start > 13 )
+  if( end - start > 20 )
     return foldlevel;
 
-  // Check the style at this point, if it is not valid, then return zero
-  if( styler.StyleAt(end) != SCE_NSIS_FUNCTION && styler.StyleAt(end) != SCE_NSIS_SECTIONDEF &&
-      styler.StyleAt(end) != SCE_NSIS_SUBSECTIONDEF && styler.StyleAt(end) != SCE_NSIS_IFDEFINEDEF &&
-      styler.StyleAt(end) != SCE_NSIS_MACRODEF )
-        return foldlevel;
+  if( foldUtilityCmd )
+  {
+    // Check the style at this point, if it is not valid, then return zero
+    if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF &&
+        style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_IFDEFINEDEF &&
+        style != SCE_NSIS_MACRODEF && style != SCE_NSIS_SECTIONGROUP &&
+        style != SCE_NSIS_PAGEEX )
+          return foldlevel;
+  }
+  else
+  { 
+    if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF &&
+        style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_SECTIONGROUP &&
+        style != SCE_NSIS_PAGEEX )
+          return foldlevel;
+  }
 
   int newFoldlevel = foldlevel;
   bool bIgnoreCase = false;
   if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
     bIgnoreCase = true;
 
-  char s[15]; // The key word we are looking for has atmost 13 characters
-  for (unsigned int i = 0; i < end - start + 1 && i < 14; i++)
+  char s[20]; // The key word we are looking for has atmost 13 characters
+  for (unsigned int i = 0; i < end - start + 1 && i < 19; i++)
        {
                s[i] = static_cast<char>( styler[ start + i ] );
                s[i + 1] = '\0';
@@ -93,15 +145,17 @@ static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel
       newFoldlevel++;
     else if( NsisCmp(s, "!endif", bIgnoreCase) == 0 || NsisCmp(s, "!macroend", bIgnoreCase ) == 0 )
       newFoldlevel--;
+    else if( bElse && NsisCmp(s, "!else", bIgnoreCase) == 0 )
+      newFoldlevel++;
   }
   else
   {
-    if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 )
+    if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionGroup", bIgnoreCase ) == 0 || NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 || NsisCmp(s, "PageEx", bIgnoreCase ) == 0 )
       newFoldlevel++;
-    else if( NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 )
+    else if( NsisCmp(s, "SectionGroupEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase ) == 0 )
       newFoldlevel--;
   }
-
+  
   return newFoldlevel;
 }
 
@@ -138,14 +192,23 @@ static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keyw
        if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 ||  NsisCmp(s, "!ifndef", bIgnoreCase) == 0 ||  NsisCmp(s, "!endif", bIgnoreCase) == 0 )
                return SCE_NSIS_IFDEFINEDEF;
 
+  if( NsisCmp(s, "!else", bIgnoreCase ) == 0 ) // ||  NsisCmp(s, "!ifndef", bIgnoreCase) == 0 ||  NsisCmp(s, "!endif", bIgnoreCase) == 0 )
+               return SCE_NSIS_IFDEFINEDEF;
+
+  if( NsisCmp(s, "SectionGroup", bIgnoreCase) == 0 || NsisCmp(s, "SectionGroupEnd", bIgnoreCase) == 0 ) // Covers SectionGroup and SectionGroupEnd
+    return SCE_NSIS_SECTIONGROUP;
+
        if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase) == 0 ) // Covers Section and SectionEnd
                return SCE_NSIS_SECTIONDEF;
 
        if( NsisCmp(s, "SubSection", bIgnoreCase) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd
                return SCE_NSIS_SUBSECTIONDEF;
 
-       if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd
-               return SCE_NSIS_FUNCTION;
+  if( NsisCmp(s, "PageEx", bIgnoreCase) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase) == 0 ) // Covers PageEx and PageExEnd
+    return SCE_NSIS_PAGEEX;
+
+       if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers Function and FunctionEnd
+               return SCE_NSIS_FUNCTIONDEF;
 
        if ( Functions.InList(s) )
                return SCE_NSIS_FUNCTION;
@@ -188,9 +251,6 @@ static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keyw
     bool bHasSimpleNsisNumber = true;
     for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
          {
-      if( s[j] == '\0' || s[j] == '\r' || s[j] == '\n' )
-        break;
-
       if( !isNsisNumber( s[j] ) )
       {
         bHasSimpleNsisNumber = false;
@@ -208,6 +268,9 @@ static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keyw
 static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
 {
        int state = SCE_NSIS_DEFAULT;
+  if( startPos > 0 )
+    state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox
+
        styler.StartAt( startPos );
        styler.GetLine( startPos );
 
@@ -270,35 +333,96 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k
 
                                        break;
                                }
+
+        if( cCurrChar == '/' && cNextChar == '*' )
+        {
+          styler.ColourTo(i-1,state);
+          state = SCE_NSIS_COMMENTBOX;
+          break;
+        }
+
                                break;
                        case SCE_NSIS_COMMENT:
                                if( cNextChar == '\n' || cNextChar == '\r' )
         {
-                                 styler.ColourTo(i,state);
-          state = SCE_NSIS_DEFAULT;
+          // Special case:
+          if( cCurrChar == '\\' )
+          {
+            styler.ColourTo(i-2,state);
+            styler.ColourTo(i,SCE_NSIS_DEFAULT);
+          }
+          else
+          {
+                                   styler.ColourTo(i,state);
+            state = SCE_NSIS_DEFAULT;
+          }
         }
                                break;
                        case SCE_NSIS_STRINGDQ:
-                               if( cCurrChar == '"' || cNextChar == '\r' || cNextChar == '\n' )
+      case SCE_NSIS_STRINGLQ:
+      case SCE_NSIS_STRINGRQ:
+
+        if( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' )
+          break; // Ignore the next character, even if it is a quote of some sort
+
+        if( cCurrChar == '"' && state == SCE_NSIS_STRINGDQ )
                                {
-                                       styler.ColourTo(i,SCE_NSIS_STRINGDQ);
+                                       styler.ColourTo(i,state);
                                  state = SCE_NSIS_DEFAULT;
+          break;
                                }
-                               break;
-                       case SCE_NSIS_STRINGLQ:
-                               if( cCurrChar == '`' || cNextChar == '\r' || cNextChar == '\n' )
-                               {
-                                       styler.ColourTo(i,SCE_NSIS_STRINGLQ);
+
+        if( cCurrChar == '`' && state == SCE_NSIS_STRINGLQ )
+        {
+                                       styler.ColourTo(i,state);
                                  state = SCE_NSIS_DEFAULT;
+          break;
                                }
-                               break;
-                       case SCE_NSIS_STRINGRQ:
-                               if( cCurrChar == '\'' || cNextChar == '\r' || cNextChar == '\n' )
+
+        if( cCurrChar == '\'' && state == SCE_NSIS_STRINGRQ )
                                {
-                                       styler.ColourTo(i,SCE_NSIS_STRINGRQ);
+                                       styler.ColourTo(i,state);
                                  state = SCE_NSIS_DEFAULT;
+          break;
                                }
+
+        if( cNextChar == '\r' || cNextChar == '\n' )
+        {
+          int nCurLine = styler.GetLine(i+1);
+          int nBack = i;
+          // We need to check if the previous line has a \ in it...
+          bool bNextLine = false;
+
+          while( nBack > 0 )
+          {
+            if( styler.GetLine(nBack) != nCurLine )
+              break;
+
+            char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here
+
+            if( cTemp == '\\' )
+            {
+              bNextLine = true;
+              break;
+            }
+            if( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' )
+              break;
+
+            nBack--;
+          }
+
+          if( bNextLine )
+          {
+            styler.ColourTo(i+1,state);
+          }
+          if( bNextLine == false )
+          {
+            styler.ColourTo(i,state);
+                                   state = SCE_NSIS_DEFAULT;
+          }
+        }
                                break;
+
                        case SCE_NSIS_FUNCTION:
 
                                // NSIS KeyWord:
@@ -308,7 +432,7 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k
           state = SCE_NSIS_DEFAULT;
                                else if( (isNsisChar(cCurrChar) && !isNsisChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' )
                                {
-                                       state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler);
+                                       state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler );
                                        styler.ColourTo( i, state);
                                        state = SCE_NSIS_DEFAULT;
                                }
@@ -343,9 +467,17 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k
           }
                                }
                                break;
+      case SCE_NSIS_COMMENTBOX:
+
+        if( styler.SafeGetCharAt(i-1) == '*' && cCurrChar == '/' )
+        {
+          styler.ColourTo(i,state);
+          state = SCE_NSIS_DEFAULT;
+        }
+        break;
                }
 
-               if( state == SCE_NSIS_COMMENT )
+               if( state == SCE_NSIS_COMMENT || state == SCE_NSIS_COMMENTBOX )
                {
                        styler.ColourTo(i,state);
                }
@@ -361,10 +493,11 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k
         bVarInString = false;
         bIngoreNextDollarSign = true;
       }
-      else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
+      else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) )
       {
+        styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
         bVarInString = false;
-        bIngoreNextDollarSign = true;
+        bIngoreNextDollarSign = false;
       }
 
       // Covers "$INSTDIR and user vars like $MYVAR"
@@ -401,19 +534,7 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k
        }
 
   // Colourise remaining document
-  switch( state )
-  {
-    case SCE_NSIS_COMMENT:
-    case SCE_NSIS_STRINGDQ:
-    case SCE_NSIS_STRINGLQ:
-    case SCE_NSIS_STRINGRQ:
-    case SCE_NSIS_VARIABLE:
-    case SCE_NSIS_STRINGVAR:
-      styler.ColourTo(nLengthDoc-1,state); break;
-
-    default:
-      styler.ColourTo(nLengthDoc-1,SCE_NSIS_DEFAULT); break;
-  }
+       styler.ColourTo(nLengthDoc-1,state);
 }
 
 static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
@@ -422,6 +543,10 @@ static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Ac
        if( styler.GetPropertyInt("fold") == 0 )
                return;
 
+  bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1;
+  bool foldUtilityCmd = styler.GetPropertyInt("nsis.foldutilcmd", 1) == 1;
+  bool blockComment = false;
+
   int lineCurrent = styler.GetLine(startPos);
   unsigned int safeStartPos = styler.LineStart( lineCurrent );
 
@@ -432,19 +557,48 @@ static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Ac
        if (lineCurrent > 0)
                levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
        int levelNext = levelCurrent;
+  int style = styler.StyleAt(safeStartPos);
+  if( style == SCE_NSIS_COMMENTBOX )
+  {
+    if( styler.SafeGetCharAt(safeStartPos) == '/' && styler.SafeGetCharAt(safeStartPos+1) == '*' )
+      levelNext++;
+    blockComment = true;
+  }
 
   for (unsigned int i = safeStartPos; i < startPos + length; i++)
        {
     char chCurr = styler.SafeGetCharAt(i);
+    style = styler.StyleAt(i);
+    if( blockComment && style != SCE_NSIS_COMMENTBOX )
+    {
+      levelNext--;
+      blockComment = false;
+    }
+    else if( !blockComment && style == SCE_NSIS_COMMENTBOX )
+    {
+      levelNext++;
+      blockComment = true;
+    }
 
-    if( bArg1 ) //&& chCurr != '\n' )
+    if( bArg1 && !blockComment)
     {
       if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') )
+      {
         nWordStart = i;
-      else if( !isNsisLetter(chCurr) && nWordStart > -1 )
+      }
+      else if( isNsisLetter(chCurr) == false && nWordStart > -1 )
       {
-        int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler );
-        if( newLevel != levelNext )
+        int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler, foldAtElse, foldUtilityCmd );
+
+        if( newLevel == levelNext )
+        {
+          if( foldAtElse && foldUtilityCmd )
+          {
+            if( NsisNextLineHasElse(i, startPos + length, styler) )
+              levelNext--;
+          }
+        }
+        else
           levelNext = newLevel;
         bArg1 = false;
       }
@@ -452,10 +606,16 @@ static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Ac
 
     if( chCurr == '\n' )
     {
+      if( bArg1 && foldAtElse && foldUtilityCmd && !blockComment )
+      {
+        if( NsisNextLineHasElse(i, startPos + length, styler) )
+          levelNext--;
+      }
+
       // If we are on a new line...
       int levelUse = levelCurrent;
                        int lev = levelUse | levelNext << 16;
-                       if (levelUse < levelNext)
+      if (levelUse < levelNext )
                                lev |= SC_FOLDLEVELHEADERFLAG;
                        if (lev != styler.LevelAt(lineCurrent))
                                styler.SetLevel(lineCurrent, lev);
@@ -484,3 +644,4 @@ static const char * const nsisWordLists[] = {
 
 
 LexerModule lmNsis(SCLEX_NSIS, ColouriseNsisDoc, "nsis", FoldNsisDoc, nsisWordLists);
+
index f777e300fa24ec132a68137cc899bc81762a8a62..4f4c1e3258fcabf2c106f7813c12bb48d2c11511 100644 (file)
@@ -30,7 +30,19 @@ static bool Is1To9(char ch) {
 
 static inline bool AtEOL(Accessor &styler, unsigned int i) {
        return (styler[i] == '\n') ||
-               ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
+              ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
+}
+
+// Tests for BATCH Operators
+static bool IsBOperator(char ch) {
+       return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') ||
+               (ch == '|') || (ch == '?') || (ch == '*');
+}
+
+// Tests for BATCH Separators
+static bool IsBSeparator(char ch) {
+       return (ch == ':') || (ch == '\\') || (ch == '.') || (ch == ';') ||
+               (ch == '\"') || (ch == '\'') || (ch == '/') || (ch == ')');
 }
 
 static void ColouriseBatchLine(
@@ -41,95 +53,391 @@ static void ColouriseBatchLine(
     WordList &keywords,
     Accessor &styler) {
 
-       unsigned int i = 0;
-       unsigned int state = SCE_BAT_DEFAULT;
+       unsigned int offset = 0;        // Line Buffer Offset
+       unsigned int enVarEnd;          // Environment Variable End point
+       unsigned int cmdLoc;            // External Command / Program Location
+       char wordBuffer[81];            // Word Buffer - large to catch long paths
+       unsigned int wbl;               // Word Buffer Length
+       unsigned int wbo;               // Word Buffer Offset - also Special Keyword Buffer Length
+       bool forFound = false;          // No Local Variable without FOR statement
+       // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
+       //   Toggling Regular Keyword Checking off improves readability
+       // Other Regular Keywords and External Commands / Programs might also benefit from toggling
+       //   Need a more robust algorithm to properly toggle Regular Keyword Checking
+       bool continueProcessing = true; // Used to toggle Regular Keyword Checking
+       // Special Keywords are those that allow certain characters without whitespace after the command
+       // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
+       // Special Keyword Buffer used to determine if the first n characters is a Keyword
+       char sKeywordBuffer[10];        // Special Keyword Buffer
+       bool sKeywordFound;             // Exit Special Keyword for-loop if found
 
-       while ((i < lengthLine) && isspacechar(lineBuffer[i])) {        // Skip initial spaces
-               i++;
-       }
-       if (lineBuffer[i] == '@') {     // Hide command (ECHO OFF)
-               styler.ColourTo(startLine + i, SCE_BAT_HIDE);
-               i++;
-               while ((i < lengthLine) && isspacechar(lineBuffer[i])) {        // Skip next spaces
-                       i++;
-               }
+       // Skip initial spaces
+       while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
+               offset++;
        }
-       if (lineBuffer[i] == ':') {
-               // Label
-               if (lineBuffer[i + 1] == ':') {
-                       // :: is a fake label, similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
+       // Colorize Default Text
+       styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
+       // Set External Command / Program Location
+       cmdLoc = offset;
+
+       // Check for Fake Label (Comment) or Real Label - return if found
+       if (lineBuffer[offset] == ':') {
+               if (lineBuffer[offset + 1] == ':') {
+                       // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
                        styler.ColourTo(endPos, SCE_BAT_COMMENT);
-               } else {        // Real label
+               } else {
+                       // Colorize Real Label
                        styler.ColourTo(endPos, SCE_BAT_LABEL);
                }
-       } else {
-               // Check if initial word is a keyword
-               char wordBuffer[21];
-               unsigned int wbl = 0, offset = i;
-               // Copy word in buffer
-               for (; offset < lengthLine && wbl < 20 &&
+               return;
+       // Check for Drive Change (Drive Change is internal command) - return if found
+       } else if ((isalpha(lineBuffer[offset])) &&
+               (lineBuffer[offset + 1] == ':') &&
+               ((isspacechar(lineBuffer[offset + 2])) ||
+               (((lineBuffer[offset + 2] == '\\')) &&
+               (isspacechar(lineBuffer[offset + 3]))))) {
+               // Colorize Regular Keyword
+               styler.ColourTo(endPos, SCE_BAT_WORD);
+               return;
+       }
+
+       // Check for Hide Command (@ECHO OFF/ON)
+       if (lineBuffer[offset] == '@') {
+               styler.ColourTo(startLine + offset, SCE_BAT_HIDE);
+               offset++;
+       // Check for Argument (%n) or Environment Variable (%x...%)
+       } else if (lineBuffer[offset] == '%') {
+               enVarEnd = offset + 1;
+               // Search end of word for second % (can be a long path)
+               while ((enVarEnd < lengthLine) &&
+                       (!isspacechar(lineBuffer[enVarEnd])) &&
+                       (lineBuffer[enVarEnd] != '%') &&
+                       (!IsBOperator(lineBuffer[enVarEnd])) &&
+                       (!IsBSeparator(lineBuffer[enVarEnd]))) {
+                       enVarEnd++;
+               }
+               // Check for Argument (%n)
+               if ((Is0To9(lineBuffer[offset + 1])) &&
+                       (lineBuffer[enVarEnd] != '%')) {
+                       // Colorize Argument
+                       styler.ColourTo(startLine + offset + 1, SCE_BAT_IDENTIFIER);
+                       offset += 2;
+                       // Check for External Command / Program
+                       if (!isspacechar(lineBuffer[offset])) {
+                               cmdLoc = offset;
+                       }
+               // Check for Environment Variable (%x...%)
+               } else if ((lineBuffer[offset + 1] != '%') &&
+                       (lineBuffer[enVarEnd] == '%')) {
+                       offset = enVarEnd;
+                       // Colorize Environment Variable
+                       styler.ColourTo(startLine + offset, SCE_BAT_IDENTIFIER);
+                       offset++;
+                       // Check for External Command / Program
+                       if (!isspacechar(lineBuffer[offset])) {
+                               cmdLoc = offset;
+                       }
+               }
+       }
+       // Skip next spaces
+       while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
+               offset++;
+       }
+
+       // Read remainder of line word-at-a-time or remainder-of-word-at-a-time
+       while (offset < lengthLine) {
+               if (offset > startLine) {
+                       // Colorize Default Text
+                       styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
+               }
+               // Copy word from Line Buffer into Word Buffer
+               wbl = 0;
+               for (; offset < lengthLine && wbl < 80 &&
                        !isspacechar(lineBuffer[offset]); wbl++, offset++) {
                        wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset]));
                }
                wordBuffer[wbl] = '\0';
-               // Check if it is a comment
+               wbo = 0;
+
+               // Check for Comment - return if found
                if (CompareCaseInsensitive(wordBuffer, "rem") == 0) {
                        styler.ColourTo(endPos, SCE_BAT_COMMENT);
-                       return ;
+                       return;
                }
-               // Check if it is in the list
-               if (keywords.InList(wordBuffer)) {
-                       styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD);  // Regular keyword
-               } else {
-                       // Search end of word (can be a long path)
-                       while (offset < lengthLine &&
-                               !isspacechar(lineBuffer[offset])) {
-                               offset++;
+               // Check for Separator
+               if (IsBSeparator(wordBuffer[0])) {
+                       // Check for External Command / Program
+                       if ((cmdLoc == offset - wbl) &&
+                               ((wordBuffer[0] == ':') ||
+                               (wordBuffer[0] == '\\') ||
+                               (wordBuffer[0] == '.'))) {
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 1);
+                               // Colorize External Command / Program
+                               styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
+                               // Reset External Command / Program Location
+                               cmdLoc = offset;
+                       } else {
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 1);
+                               // Colorize Default Text
+                               styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
+                       }
+               // Check for Regular Keyword in list
+               } else if ((keywords.InList(wordBuffer)) &&
+                       (continueProcessing)) {
+                       // Local Variables do not exist if no FOR statement
+                       if (CompareCaseInsensitive(wordBuffer, "for") == 0) {
+                               forFound = true;
+                       }
+                       // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
+                       if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "goto") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "prompt") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "set") == 0)) {
+                               continueProcessing = false;
+                       }
+                       // Identify External Command / Program Location for ERRORLEVEL, and EXIST
+                       if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "exist") == 0)) {
+                               // Reset External Command / Program Location
+                               cmdLoc = offset;
+                               // Skip next spaces
+                               while ((cmdLoc < lengthLine) &&
+                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
+                               }
+                               // Skip comparison
+                               while ((cmdLoc < lengthLine) &&
+                                       (!isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
+                               }
+                               // Skip next spaces
+                               while ((cmdLoc < lengthLine) &&
+                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
+                               }
+                       // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
+                       } else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "do") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "lh") == 0)) {
+                               // Reset External Command / Program Location
+                               cmdLoc = offset;
+                               // Skip next spaces
+                               while ((cmdLoc < lengthLine) &&
+                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
+                               }
+                       }
+                       // Colorize Regular keyword
+                       styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD);
+                       // No need to Reset Offset
+               // Check for Special Keyword in list, External Command / Program, or Default Text
+               } else if ((wordBuffer[0] != '%') &&
+                       (!IsBOperator(wordBuffer[0])) &&
+                       (continueProcessing)) {
+                       // Check for Special Keyword
+                       //     Affected Commands are in Length range 2-6
+                       //     Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected
+                       sKeywordFound = false;
+                       for (unsigned int keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) {
+                               wbo = 0;
+                               // Copy Keyword Length from Word Buffer into Special Keyword Buffer
+                               for (; wbo < keywordLength; wbo++) {
+                                       sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]);
+                               }
+                               sKeywordBuffer[wbo] = '\0';
+                               // Check for Special Keyword in list
+                               if ((keywords.InList(sKeywordBuffer)) &&
+                                       ((IsBOperator(wordBuffer[wbo])) ||
+                                       (IsBSeparator(wordBuffer[wbo])))) {
+                                       sKeywordFound = true;
+                                       // ECHO requires no further Regular Keyword Checking
+                                       if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) {
+                                               continueProcessing = false;
+                                       }
+                                       // Colorize Special Keyword as Regular Keyword
+                                       styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD);
+                                       // Reset Offset to re-process remainder of word
+                                       offset -= (wbl - wbo);
                        }
-                       styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);       // External command / program
                }
-               // Remainder of the line: colourise the variables.
-
-               while (offset < lengthLine) {
-                       if (state == SCE_BAT_DEFAULT && lineBuffer[offset] == '%') {
-                               styler.ColourTo(startLine + offset - 1, state);
-                               if (Is0To9(lineBuffer[offset + 1])) {
-                                       styler.ColourTo(startLine + offset + 1, SCE_BAT_IDENTIFIER);
-                                       offset += 2;
-                               } else if (lineBuffer[offset + 1] == '%' &&
-                                          !isspacechar(lineBuffer[offset + 2])) {
-                                       // Should be safe, as there is CRLF at the end of the line...
-                                       styler.ColourTo(startLine + offset + 2, SCE_BAT_IDENTIFIER);
-                                       offset += 3;
+                       // Check for External Command / Program or Default Text
+                       if (!sKeywordFound) {
+                               wbo = 0;
+                               // Check for External Command / Program
+                               if (cmdLoc == offset - wbl) {
+                                       // Read up to %, Operator or Separator
+                                       while ((wbo < wbl) &&
+                                               (wordBuffer[wbo] != '%') &&
+                                               (!IsBOperator(wordBuffer[wbo])) &&
+                                               (!IsBSeparator(wordBuffer[wbo]))) {
+                                               wbo++;
+                                       }
+                                       // Reset External Command / Program Location
+                                       cmdLoc = offset - (wbl - wbo);
+                                       // Reset Offset to re-process remainder of word
+                                       offset -= (wbl - wbo);
+                                       // CHOICE requires no further Regular Keyword Checking
+                                       if (CompareCaseInsensitive(wordBuffer, "choice") == 0) {
+                                               continueProcessing = false;
+                                       }
+                                       // Check for START (and its switches) - What follows is External Command \ Program
+                                       if (CompareCaseInsensitive(wordBuffer, "start") == 0) {
+                                               // Reset External Command / Program Location
+                                               cmdLoc = offset;
+                                               // Skip next spaces
+                                               while ((cmdLoc < lengthLine) &&
+                                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                                       cmdLoc++;
+                                               }
+                                               // Reset External Command / Program Location if command switch detected
+                                               if (lineBuffer[cmdLoc] == '/') {
+                                                       // Skip command switch
+                                                       while ((cmdLoc < lengthLine) &&
+                                                               (!isspacechar(lineBuffer[cmdLoc]))) {
+                                                               cmdLoc++;
+                                                       }
+                                                       // Skip next spaces
+                                                       while ((cmdLoc < lengthLine) &&
+                                                               (isspacechar(lineBuffer[cmdLoc]))) {
+                                                               cmdLoc++;
+                                                       }
+                                               }
+                                       }
+                                       // Colorize External command / program
+                                       styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
+                                       // No need to Reset Offset
+                               // Check for Default Text
                                } else {
-                                       state = SCE_BAT_IDENTIFIER;
+                                       // Read up to %, Operator or Separator
+                                       while ((wbo < wbl) &&
+                                               (wordBuffer[wbo] != '%') &&
+                                               (!IsBOperator(wordBuffer[wbo])) &&
+                                               (!IsBSeparator(wordBuffer[wbo]))) {
+                                               wbo++;
+                                       }
+                                       // Colorize Default Text
+                                       styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
+                                       // Reset Offset to re-process remainder of word
+                                       offset -= (wbl - wbo);
+                               }
+                       }
+               // Check for Argument  (%n), Environment Variable (%x...%) or Local Variable (%%a)
+               } else if (wordBuffer[0] == '%') {
+                       // Colorize Default Text
+                       styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
+                       wbo++;
+                       // Search to end of word for second % (can be a long path)
+                       while ((wbo < wbl) &&
+                               (wordBuffer[wbo] != '%') &&
+                               (!IsBOperator(wordBuffer[wbo])) &&
+                               (!IsBSeparator(wordBuffer[wbo]))) {
+                               wbo++;
+                       }
+                       // Check for Argument (%n)
+                       if ((Is0To9(wordBuffer[1])) &&
+                               (wordBuffer[wbo] != '%')) {
+                               // Check for External Command / Program
+                               if (cmdLoc == offset - wbl) {
+                                       cmdLoc = offset - (wbl - 2);
+                               }
+                               // Colorize Argument
+                               styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 2);
+                       // Check for Environment Variable (%x...%)
+                       } else if ((wordBuffer[1] != '%') &&
+                               (wordBuffer[wbo] == '%')) {
+                               wbo++;
+                               // Check for External Command / Program
+                               if (cmdLoc == offset - wbl) {
+                                       cmdLoc = offset - (wbl - wbo);
+                       }
+                               // Colorize Environment Variable
+                               styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - wbo);
+                       // Check for Local Variable (%%a)
+                       } else if ((forFound) &&
+                               (wordBuffer[1] == '%') &&
+                               (wordBuffer[2] != '%') &&
+                               (!IsBOperator(wordBuffer[2])) &&
+                               (!IsBSeparator(wordBuffer[2]))) {
+                               // Check for External Command / Program
+                               if (cmdLoc == offset - wbl) {
+                                       cmdLoc = offset - (wbl - 3);
+                               }
+                               // Colorize Local Variable
+                               styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 3);
+                       }
+               // Check for Operator
+               } else if (IsBOperator(wordBuffer[0])) {
+                       // Colorize Default Text
+                       styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
+                       // Check for Comparison Operator
+                       if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) {
+                               // Identify External Command / Program Location for IF
+                               cmdLoc = offset;
+                               // Skip next spaces
+                               while ((cmdLoc < lengthLine) &&
+                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
+                               }
+                               // Colorize Comparison Operator
+                               styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 2);
+                       // Check for Pipe Operator
+                       } else if (wordBuffer[0] == '|') {
+                               // Reset External Command / Program Location
+                               cmdLoc = offset - wbl + 1;
+                               // Skip next spaces
+                               while ((cmdLoc < lengthLine) &&
+                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
                                }
-                       } else if (state == SCE_BAT_IDENTIFIER && lineBuffer[offset] == '%') {
-                               styler.ColourTo(startLine + offset, state);
-                               state = SCE_BAT_DEFAULT;
-                       } else if (state == SCE_BAT_DEFAULT &&
-                                  (lineBuffer[offset] == '*' ||
-                                   lineBuffer[offset] == '?' ||
-                                   lineBuffer[offset] == '=' ||
-                                   lineBuffer[offset] == '<' ||
-                                   lineBuffer[offset] == '>' ||
-                                   lineBuffer[offset] == '|')) {
-                               styler.ColourTo(startLine + offset - 1, state);
-                               styler.ColourTo(startLine + offset, SCE_BAT_OPERATOR);
+                               // Colorize Pipe Operator
+                               styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 1);
+                       // Check for Other Operator
+                       } else {
+                               // Check for > Operator
+                               if (wordBuffer[0] == '>') {
+                                       // Turn Keyword and External Command / Program checking back on
+                                       continueProcessing = true;
+                               }
+                               // Colorize Other Operator
+                               styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 1);
+                       }
+               // Check for Default Text
+               } else {
+                       // Read up to %, Operator or Separator
+                       while ((wbo < wbl) &&
+                               (wordBuffer[wbo] != '%') &&
+                               (!IsBOperator(wordBuffer[wbo])) &&
+                               (!IsBSeparator(wordBuffer[wbo]))) {
+                               wbo++;
                        }
+                       // Colorize Default Text
+                       styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
+                       // Reset Offset to re-process remainder of word
+                       offset -= (wbl - wbo);
+               }
+               // Skip next spaces - nothing happens if Offset was Reset
+               while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
                        offset++;
                }
-               //              if (endPos > startLine + offset - 1) {
-               styler.ColourTo(endPos, SCE_BAT_DEFAULT);               // Remainder of line, currently not lexed
-               //              }
        }
-
+       // Colorize Default Text for remainder of line - currently not lexed
+       styler.ColourTo(endPos, SCE_BAT_DEFAULT);
 }
-// ToDo: (not necessarily at beginning of line) GOTO, [IF] NOT, ERRORLEVEL
-// IF [NO] (test) (command) -- test is EXIST (filename) | (string1)==(string2) | ERRORLEVEL (number)
-// FOR %%(variable) IN (set) DO (command) -- variable is [a-zA-Z] -- eg for %%X in (*.txt) do type %%X
-// ToDo: %n (parameters), %EnvironmentVariable% colourising
-// ToDo: Colourise = > >> < | "
 
 static void ColouriseBatchDoc(
     unsigned int startPos,
@@ -240,7 +548,7 @@ static void FoldDiffDoc(unsigned int startPos, int length, int, WordList*[], Acc
                int nextLevel = prevLevel;
                if (prevLevel & SC_FOLDLEVELHEADERFLAG)
                        nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1;
-               
+
                int lineType = styler.StyleAt(curLineStart);
                if (lineType == SCE_DIFF_COMMAND)
                        nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG;
@@ -248,13 +556,13 @@ static void FoldDiffDoc(unsigned int startPos, int length, int, WordList*[], Acc
                        nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG;
                } else if (lineType == SCE_DIFF_POSITION)
                        nextLevel = (SC_FOLDLEVELBASE + 3) | SC_FOLDLEVELHEADERFLAG;
-               
+
                if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel))
                        styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG);
 
                styler.SetLevel(curLine, nextLevel);
                prevLevel = nextLevel;
-               
+
                curLineStart = styler.LineStart(++curLine);
        } while (static_cast<int>(startPos) + length > curLineStart);
 }
@@ -372,7 +680,7 @@ static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], A
 
                        lineCurrent++;
                        visibleChars = 0;
-                       headerPoint=false;
+                       headerPoint = false;
                }
                if (!isspacechar(ch))
                        visibleChars++;
@@ -475,172 +783,207 @@ static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[
        }
 }
 
-static bool strstart(char *haystack, char *needle) {
+static bool strstart(const char *haystack, const char *needle) {
        return strncmp(haystack, needle, strlen(needle)) == 0;
 }
 
-static void ColouriseErrorListLine(
-    char *lineBuffer,
-    unsigned int lengthLine,
-    //         unsigned int startLine,
-    unsigned int endPos,
-    Accessor &styler) {
-       const int unRecognized = 99;
+static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine) {
        if (lineBuffer[0] == '>') {
                // Command or return status
-               styler.ColourTo(endPos, SCE_ERR_CMD);
+               return SCE_ERR_CMD;
        } else if (lineBuffer[0] == '<') {
                // Diff removal, but not interested. Trapped to avoid hitting CTAG cases.
-               styler.ColourTo(endPos, SCE_ERR_DEFAULT);
+               return SCE_ERR_DEFAULT;
        } else if (lineBuffer[0] == '!') {
-               styler.ColourTo(endPos, SCE_ERR_DIFF_CHANGED);
+               return SCE_ERR_DIFF_CHANGED;
        } else if (lineBuffer[0] == '+') {
-               styler.ColourTo(endPos, SCE_ERR_DIFF_ADDITION);
-       } else if (lineBuffer[0] == '-' && lineBuffer[1] == '-' && lineBuffer[2] == '-') {
-               styler.ColourTo(endPos, SCE_ERR_DIFF_MESSAGE);
+               if (strstart(lineBuffer, "+++ ")) {
+                       return SCE_ERR_DIFF_MESSAGE;
+               } else {
+                       return SCE_ERR_DIFF_ADDITION;
+               }
        } else if (lineBuffer[0] == '-') {
-               styler.ColourTo(endPos, SCE_ERR_DIFF_DELETION);
+               if (strstart(lineBuffer, "--- ")) {
+                       return SCE_ERR_DIFF_MESSAGE;
+               } else {
+                       return SCE_ERR_DIFF_DELETION;
+               }
        } else if (strstart(lineBuffer, "cf90-")) {
                // Absoft Pro Fortran 90/95 v8.2 error and/or warning message
-               styler.ColourTo(endPos, SCE_ERR_ABSF);
+               return SCE_ERR_ABSF;
        } else if (strstart(lineBuffer, "fortcom:")) {
                // Intel Fortran Compiler v8.0 error/warning message
-               styler.ColourTo(endPos, SCE_ERR_IFORT);
+               return SCE_ERR_IFORT;
        } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
-               styler.ColourTo(endPos, SCE_ERR_PYTHON);
+               return SCE_ERR_PYTHON;
        } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) {
-               styler.ColourTo(endPos, SCE_ERR_PHP);
+               return SCE_ERR_PHP;
        } else if ((strstart(lineBuffer, "Error ") ||
-               strstart(lineBuffer, "Warning ")) &&
-               strstr(lineBuffer, " at (") &&
-               strstr(lineBuffer, ") : ") &&
-               (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) {
+                   strstart(lineBuffer, "Warning ")) &&
+                  strstr(lineBuffer, " at (") &&
+                  strstr(lineBuffer, ") : ") &&
+                  (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) {
                // Intel Fortran Compiler error/warning message
-               styler.ColourTo(endPos, SCE_ERR_IFC);
+               return SCE_ERR_IFC;
        } else if (strstart(lineBuffer, "Error ")) {
                // Borland error message
-               styler.ColourTo(endPos, SCE_ERR_BORLAND);
+               return SCE_ERR_BORLAND;
        } else if (strstart(lineBuffer, "Warning ")) {
                // Borland warning message
-               styler.ColourTo(endPos, SCE_ERR_BORLAND);
+               return SCE_ERR_BORLAND;
        } else if (strstr(lineBuffer, "at line " ) &&
                   (strstr(lineBuffer, "at line " ) < (lineBuffer + lengthLine)) &&
                   strstr(lineBuffer, "file ") &&
                   (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) {
                // Lua 4 error message
-               styler.ColourTo(endPos, SCE_ERR_LUA);
+               return SCE_ERR_LUA;
        } else if (strstr(lineBuffer, " at " ) &&
                   (strstr(lineBuffer, " at " ) < (lineBuffer + lengthLine)) &&
                   strstr(lineBuffer, " line ") &&
                   (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) &&
-                          (strstr(lineBuffer, " at " ) < (strstr(lineBuffer, " line ")))) {
+                  (strstr(lineBuffer, " at " ) < (strstr(lineBuffer, " line ")))) {
                // perl error message
-               styler.ColourTo(endPos, SCE_ERR_PERL);
+               return SCE_ERR_PERL;
        } else if ((memcmp(lineBuffer, "   at ", 6) == 0) &&
-               strstr(lineBuffer, ":line ")) {
+                  strstr(lineBuffer, ":line ")) {
                // A .NET traceback
-               styler.ColourTo(endPos, SCE_ERR_NET);
+               return SCE_ERR_NET;
        } else if (strstart(lineBuffer, "Line ") &&
-               strstr(lineBuffer, ", file ")) {
+                  strstr(lineBuffer, ", file ")) {
                // Essential Lahey Fortran error message
-               styler.ColourTo(endPos, SCE_ERR_ELF);
+               return SCE_ERR_ELF;
        } else if (strstart(lineBuffer, "line ") &&
-                      strstr(lineBuffer, " column ")) {
+                  strstr(lineBuffer, " column ")) {
                // HTML tidy style: line 42 column 1
-               styler.ColourTo(endPos, SCE_ERR_TIDY);
+               return SCE_ERR_TIDY;
        } else if (strstart(lineBuffer, "\tat ") &&
-               strstr(lineBuffer, "(") &&
-               strstr(lineBuffer, ".java:")) {
+                  strstr(lineBuffer, "(") &&
+                  strstr(lineBuffer, ".java:")) {
                // Java stack back trace
-               styler.ColourTo(endPos, SCE_ERR_JAVA_STACK);
+               return SCE_ERR_JAVA_STACK;
        } else {
-               // Look for GCC <filename>:<line>:message
-               // Look for Microsoft <filename>(line) :message
-               // Look for Microsoft <filename>(line,pos)message
-               // Look for CTags \tmessage
-               // Look for Lua 5 traceback \t<filename>:<line>:message
+               // Look for one of the following formats:
+               // GCC: <filename>:<line>:<message>
+               // Microsoft: <filename>(<line>) :<message>
+               // Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal
+               // Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal
+               // Microsoft: <filename>(<line>,<column>)<message>
+               // CTags: \t<message>
+               // Lua 5 traceback: \t<filename>:<line>:<message>
                bool initialTab = (lineBuffer[0] == '\t');
-               int state = 0;
+               enum { stInitial, 
+                       stGccStart, stGccDigit, stGcc,
+                       stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet,
+                       stCtagsStart, stCtagsStartString, stCtagsStringDollar, stCtags,
+                       stUnrecognized
+               } state = stInitial;
                for (unsigned int i = 0; i < lengthLine; i++) {
                        char ch = lineBuffer[i];
                        char chNext = ' ';
-                       if ((i+1) < lengthLine)
-                               chNext = lineBuffer[i+1];
-                       if (state == 0) {
+                       if ((i + 1) < lengthLine)
+                               chNext = lineBuffer[i + 1];
+                       if (state == stInitial) {
                                if (ch == ':') {
                                        // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
                                        if ((chNext != '\\') && (chNext != '/')) {
                                                // This check is not completely accurate as may be on
                                                // GTK+ with a file name that includes ':'.
-                                               state = 1;
+                                               state = stGccStart;
                                        }
                                } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) {
                                        // May be Microsoft
                                        // Check against '0' often removes phone numbers
-                                       state = 10;
+                                       state = stMsStart;
                                } else if ((ch == '\t') && (!initialTab)) {
                                        // May be CTags
-                                       state = 20;
+                                       state = stCtagsStart;
                                }
-                       } else if (state == 1) {
-                               state = Is1To9(ch) ? 2 : unRecognized;
-                       } else if (state == 2) {
+                       } else if (state == stGccStart) {       // <filename>:
+                               state = Is1To9(ch) ? stGccDigit : stUnrecognized;
+                       } else if (state == stGccDigit) {       // <filename>:<line>
                                if (ch == ':') {
-                                       state = 3;      // :9.*: is GCC
+                                       state = stGcc;  // :9.*: is GCC
                                        break;
                                } else if (!Is0To9(ch)) {
-                                       state = unRecognized;
+                                       state = stUnrecognized;
                                }
-                       } else if (state == 10) {
-                               state = Is0To9(ch) ? 11 : unRecognized;
-                       } else if (state == 11) {
+                       } else if (state == stMsStart) {        // <filename>(
+                               state = Is0To9(ch) ? stMsDigit : stUnrecognized;
+                       } else if (state == stMsDigit) {        // <filename>(<line>
                                if (ch == ',') {
-                                       state = 14;
+                                       state = stMsDigitComma;
                                } else if (ch == ')') {
-                                       state = 12;
+                                       state = stMsBracket;
                                } else if ((ch != ' ') && !Is0To9(ch)) {
-                                       state = unRecognized;
+                                       state = stUnrecognized;
                                }
-                       } else if (state == 12) {
+                       } else if (state == stMsBracket) {      // <filename>(<line>)
                                if ((ch == ' ') && (chNext == ':')) {
-                                       state = 13;
+                                       state = stMsVc;
+                               } else if ((ch == ':' && chNext == ' ') || (ch == ' ')) {
+                                       // Possibly Delphi.. don't test against chNext as it's one of the strings below.
+                                       char word[512];
+                                       unsigned int j, chPos;
+                                       unsigned numstep;
+                                       chPos = 0;
+                                       if (ch == ' ')
+                                               numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i.
+                                       else
+                                               numstep = 2; // otherwise add 2.
+                                       for (j = i + numstep; j < lengthLine && isalpha(lineBuffer[j]) && chPos < sizeof(word) - 1; j++)
+                                               word[chPos++] = lineBuffer[j];
+                                       word[chPos] = 0;
+                                       if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") || 
+                                               !CompareCaseInsensitive(word, "fatal") || !CompareCaseInsensitive(word, "catastrophic") || 
+                                               !CompareCaseInsensitive(word, "note") || !CompareCaseInsensitive(word, "remark")) {
+                                               state = stMsVc;
+                                       } else
+                                               state = stUnrecognized;
                                } else {
-                                       state = unRecognized;
+                                       state = stUnrecognized;
                                }
-                       } else if (state == 14) {
+                       } else if (state == stMsDigitComma) {   // <filename>(<line>,
                                if (ch == ')') {
-                                       state = 15;
+                                       state = stMsDotNet;
                                        break;
                                } else if ((ch != ' ') && !Is0To9(ch)) {
-                                       state = unRecognized;
+                                       state = stUnrecognized;
                                }
-                       } else if (state == 20) {
-                               if ((lineBuffer[i-1] == '\t') &&
-                                       ((ch == '/' && lineBuffer[i+1] == '^') || Is0To9(ch))) {
-                                       state = 24;
+                       } else if (state == stCtagsStart) {
+                               if ((lineBuffer[i - 1] == '\t') &&
+                                       ((ch == '/' && lineBuffer[i + 1] == '^') || Is0To9(ch))) {
+                                       state = stCtags;
                                        break;
-                               } else if ((ch == '/') && (lineBuffer[i+1] == '^')) {
-                                       state = 21;
+                               } else if ((ch == '/') && (lineBuffer[i + 1] == '^')) {
+                                       state = stCtagsStartString;
                                }
-                       } else if ((state == 21) && ((lineBuffer[i] == '$') && (lineBuffer[i+1] == '/'))) {
-                               state = 22;
+                       } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) {
+                               state = stCtagsStringDollar;
                                break;
                        }
                }
-               if (state == 3) {
-                       styler.ColourTo(endPos, SCE_ERR_GCC);
-               } else if ((state == 13) || (state == 14) || (state == 15)) {
-                       styler.ColourTo(endPos, SCE_ERR_MS);
-               } else if ((state == 22) || (state == 24)) {
-                       styler.ColourTo(endPos, SCE_ERR_CTAG);
+               if (state == stGcc) {
+                       return SCE_ERR_GCC;
+               } else if ((state == stMsVc) || (state == stMsDotNet)) {
+                       return SCE_ERR_MS;
+               } else if ((state == stCtagsStringDollar) || (state == stCtags)) {
+                       return SCE_ERR_CTAG;
                } else {
-                       styler.ColourTo(endPos, SCE_ERR_DEFAULT);
+                       return SCE_ERR_DEFAULT;
                }
        }
 }
 
+static void ColouriseErrorListLine(
+    char *lineBuffer,
+    unsigned int lengthLine,
+    unsigned int endPos,
+    Accessor &styler) {
+       styler.ColourTo(endPos, RecogniseErrorListLine(lineBuffer, lengthLine));
+}
+
 static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
-       char lineBuffer[1024];
+       char lineBuffer[10000];
        styler.StartAt(startPos);
        styler.StartSegment(startPos);
        unsigned int linePos = 0;
index 0c1a21ab48bdd7c8fdc8f1c8e76a9184a939759c..5cc05ce6ab70f3a764d8d1acfb38363cf360930f 100644 (file)
@@ -3,7 +3,7 @@
  ** Lexer for POV-Ray SDL (Persistance of Vision Raytracer, Scene Description Language).
  ** Written by Philippe Lhoste but this is mostly a derivative of LexCPP...
  **/
-// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 // Some points that distinguish from a simple C lexer:
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-static inline bool IsAWordChar(const int ch) {
+static inline bool IsAWordChar(int ch) {
        return ch < 0x80 && (isalnum(ch) || ch == '_');
 }
 
-static inline bool IsAWordStart(const int ch) {
+static inline bool IsAWordStart(int ch) {
        return ch < 0x80 && isalpha(ch);
 }
 
-static inline bool IsANumberChar(const int ch) {
+static inline bool IsANumberChar(int ch) {
        // Not exactly following number definition (several dots are seen as OK, etc.)
        // but probably enough in most cases.
        return (ch < 0x80) &&
@@ -69,13 +69,14 @@ static void ColourisePovDoc(
        }
 
        // Do not leak onto next line
-       if (initStyle == SCE_POV_STRINGEOL) {
+       if (initStyle == SCE_POV_STRINGEOL || initStyle == SCE_POV_COMMENTLINE) {
                initStyle = SCE_POV_DEFAULT;
        }
 
-       StyleContext sc(startPos, length, initStyle, styler);
        short stringLen = 0;
 
+       StyleContext sc(startPos, length, initStyle, styler);
+
        for (; sc.More(); sc.Forward()) {
                if (sc.atLineEnd) {
                        // Update the line state, so it can be seen by next line
@@ -125,7 +126,8 @@ static void ColourisePovDoc(
                        }
                } else if (sc.state == SCE_POV_DIRECTIVE) {
                        if (!IsAWordChar(sc.ch)) {
-                               char s[100], *p;
+                               char s[100];
+                               char *p;
                                sc.GetCurrent(s, sizeof(s));
                                p = s;
                                // Skip # and whitespace between # and directive word
@@ -150,7 +152,7 @@ static void ColourisePovDoc(
                        }
                } else if (sc.state == SCE_POV_COMMENTLINE) {
                        if (sc.atLineEnd) {
-                               sc.SetState(SCE_POV_DEFAULT);
+                               sc.ForwardSetState(SCE_POV_DEFAULT);
                        }
                } else if (sc.state == SCE_POV_STRING) {
                        if (sc.ch == '\\') {
index a44f3cefcca362af5f0a2daa672a3fb448a7874a..3c75ae554d65bf05d28cecf9f4b197ac8b52a7e3 100644 (file)
@@ -11,7 +11,6 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <fcntl.h>
 
 #include "Platform.h"
 
index 67d60fc1ae8f5a290718a732147f04c950f0d706..cb9152ecaf2fd2b2301c199b514700d86196fc8a 100644 (file)
@@ -2,8 +2,8 @@
 /** @file LexPerl.cxx
  ** Lexer for subset of Perl.
  **/
-// Lexical analysis fixes by Kein-Hong Man <mkh@pl.jaring.my> 2003-2004
-// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
+// Lexical analysis fixes by Kein-Hong Man <mkh@pl.jaring.my>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-#define PERLNUM_DECIMAL 1
-#define PERLNUM_NON_DEC 2
-#define PERLNUM_FLOAT 3
-#define PERLNUM_VECTOR 4
-#define PERLNUM_V_VECTOR 5
+#define PERLNUM_BINARY 1    // order is significant: 1-4 cannot have a dot
+#define PERLNUM_HEX 2
+#define PERLNUM_OCTAL 3
+#define PERLNUM_FLOAT 4     // actually exponent part
+#define PERLNUM_DECIMAL 5   // 1-5 are numbers; 6-7 are strings
+#define PERLNUM_VECTOR 6
+#define PERLNUM_V_VECTOR 7
+#define PERLNUM_BAD 8
+
+#define BACK_NONE 0         // lookback state for bareword disambiguation:
+#define BACK_OPERATOR 1     // whitespace/comments are insignificant
+#define BACK_KEYWORD 2      // operators/keywords are needed for disambiguation
 
 #define HERE_DELIM_MAX 256
 
@@ -44,7 +51,7 @@ static inline bool isPerlOperator(char ch) {
                ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
                ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
                ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
-               ch == '>' || ch == ',' || 
+               ch == '>' || ch == ',' ||
                ch == '?' || ch == '!' || ch == '.' || ch == '~')
                return true;
        // these chars are already tested before this call
@@ -52,17 +59,13 @@ static inline bool isPerlOperator(char ch) {
        return false;
 }
 
-static int classifyWordPerl(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
+static bool isPerlKeyword(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
        char s[100];
-       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
-               s[i] = styler[start + i];
-               s[i + 1] = '\0';
-       }
-       char chAttr = SCE_PL_IDENTIFIER;
-       if (keywords.InList(s))
-               chAttr = SCE_PL_WORD;
-       styler.ColourTo(end, chAttr);
-       return chAttr;
+    unsigned int i, len = end - start;
+    if (len > 30) { len = 30; }
+       for (i = 0; i < len; i++, start++) s[i] = styler[start];
+    s[i] = '\0';
+       return keywords.InList(s);
 }
 
 static inline bool isEndVar(char ch) {
@@ -76,16 +79,12 @@ static inline bool isNonQuote(char ch) {
 }
 
 static inline char actualNumStyle(int numberStyle) {
-       switch (numberStyle) {
-       case PERLNUM_VECTOR:
-       case PERLNUM_V_VECTOR:
-               return SCE_PL_STRING;
-       case PERLNUM_DECIMAL:
-       case PERLNUM_NON_DEC:
-       case PERLNUM_FLOAT:
-       default:
-               return SCE_PL_NUMBER;
-       }
+    if (numberStyle == PERLNUM_VECTOR || numberStyle == PERLNUM_V_VECTOR) {
+        return SCE_PL_STRING;
+    } else if (numberStyle == PERLNUM_BAD) {
+        return SCE_PL_ERROR;
+    }
+    return SCE_PL_NUMBER;
 }
 
 static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) {
@@ -133,6 +132,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                char *Delimiter;        // the Delimiter, 256: sizeof PL_tokenbuf
                HereDocCls() {
                        State = 0;
+            Quote = 0;
+            Quoted = false;
                        DelimiterLength = 0;
                        Delimiter = new char[HERE_DELIM_MAX];
                        Delimiter[0] = '\0';
@@ -196,6 +197,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
        || state == SCE_PL_CHARACTER
        || state == SCE_PL_NUMBER
        || state == SCE_PL_IDENTIFIER
+    || state == SCE_PL_ERROR
        ) {
                while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) {
                        startPos--;
@@ -203,6 +205,22 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                state = SCE_PL_DEFAULT;
        }
 
+    // lookback at start of lexing to set proper state for backflag
+    // after this, they are updated when elements are lexed
+    int backflag = BACK_NONE;
+    unsigned int backPos = startPos;
+    if (backPos > 0) {
+        backPos--;
+        int sty = SCE_PL_DEFAULT;
+        while ((backPos > 0) && (sty = styler.StyleAt(backPos),
+               sty == SCE_PL_DEFAULT || sty == SCE_PL_COMMENTLINE))
+            backPos--;
+        if (sty == SCE_PL_OPERATOR)
+            backflag = BACK_OPERATOR;
+        else if (sty == SCE_PL_WORD)
+            backflag = BACK_KEYWORD;
+    }
+
        styler.StartAt(startPos);
        char chPrev = styler.SafeGetCharAt(startPos - 1);
        if (startPos == 0)
@@ -269,25 +287,34 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                        if (isdigit(ch) || (isdigit(chNext) &&
                                (ch == '.' || ch == 'v'))) {
                                state = SCE_PL_NUMBER;
+                backflag = BACK_NONE;
                                numState = PERLNUM_DECIMAL;
                                dotCount = 0;
                                if (ch == '0') {        // hex,bin,octal
-                                       if (chNext == 'x' || chNext == 'b' || isdigit(chNext)) {
-                                               numState = PERLNUM_NON_DEC;
-                                       }
+                                       if (chNext == 'x') {
+                                               numState = PERLNUM_HEX;
+                                       } else if (chNext == 'b') {
+                        numState = PERLNUM_BINARY;
+                    } else if (isdigit(chNext)) {
+                        numState = PERLNUM_OCTAL;
+                    }
+                    if (numState != PERLNUM_DECIMAL) {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = chNext2;
+                    }
                                } else if (ch == 'v') { // vector
                                        numState = PERLNUM_V_VECTOR;
                                }
                        } else if (iswordstart(ch)) {
-                               if (chPrev == '>' && styler.SafeGetCharAt(i - 2) == '-') {
-                                       state = SCE_PL_IDENTIFIER;      // part of "->" expr
-                                       if ((!iswordchar(chNext) && chNext != '\'')
-                                               || (chNext == '.' && chNext2 == '.')) {
-                                               // We need that if length of word == 1!
-                                               styler.ColourTo(i, SCE_PL_IDENTIFIER);
-                                               state = SCE_PL_DEFAULT;
-                                       }
-                               } else if (ch == 's' && !isNonQuote(chNext)) {
+                // if immediately prefixed by '::', always a bareword
+                state = SCE_PL_WORD;
+                if (chPrev == ':' && styler.SafeGetCharAt(i - 2) == ':') {
+                    state = SCE_PL_IDENTIFIER;
+                }
+                unsigned int kw = i + 1;
+                // first check for possible quote-like delimiter
+                               if (ch == 's' && !isNonQuote(chNext)) {
                                        state = SCE_PL_REGSUBST;
                                        Quote.New(2);
                                } else if (ch == 'm' && !isNonQuote(chNext)) {
@@ -302,36 +329,119 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                } else if (ch == 't' && chNext == 'r' && !isNonQuote(chNext2)) {
                                        state = SCE_PL_REGSUBST;
                                        Quote.New(2);
-                                       i++;
-                                       chNext = chNext2;
+                    kw++;
                                } else if (ch == 'q' && (chNext == 'q' || chNext == 'r' || chNext == 'w' || chNext == 'x') && !isNonQuote(chNext2)) {
                                        if      (chNext == 'q') state = SCE_PL_STRING_QQ;
                                        else if (chNext == 'x') state = SCE_PL_STRING_QX;
                                        else if (chNext == 'r') state = SCE_PL_STRING_QR;
                                        else if (chNext == 'w') state = SCE_PL_STRING_QW;
-                                       i++;
-                                       chNext = chNext2;
                                        Quote.New(1);
+                    kw++;
                                } else if (ch == 'x' && (chNext == '=' ||       // repetition
-                                          (chNext != '_' && !isalnum(chNext)) ||
-                                          (isdigit(chPrev) && isdigit(chNext)))) {
-                                       styler.ColourTo(i, SCE_PL_OPERATOR);
-                               } else {
-                                       state = SCE_PL_WORD;
-                                       if ((!iswordchar(chNext) && chNext != '\'')
-                                               || (chNext == '.' && chNext2 == '.')) {
-                                               // We need that if length of word == 1!
-                                               // This test is copied from the SCE_PL_WORD handler.
-                                               classifyWordPerl(styler.GetStartSegment(), i, keywords, styler);
-                                               state = SCE_PL_DEFAULT;
-                                       }
-                               }
+                           (chNext != '_' && !isalnum(chNext)) ||
+                           (isdigit(chPrev) && isdigit(chNext)))) {
+                    state = SCE_PL_OPERATOR;
+                }
+                // if potentially a keyword, scan forward and grab word, then check
+                // if it's really one; if yes, disambiguation test is performed
+                // otherwise it is always a bareword and we skip a lot of scanning
+                // note: keywords assumed to be limited to [_a-zA-Z] only
+                if (state == SCE_PL_WORD) {
+                    while (iswordstart(styler.SafeGetCharAt(kw))) kw++;
+                    if (!isPerlKeyword(styler.GetStartSegment(), kw, keywords, styler)) {
+                        state = SCE_PL_IDENTIFIER;
+                    }
+                }
+                // if already SCE_PL_IDENTIFIER, then no ambiguity, skip this
+                // for quote-like delimiters/keywords, attempt to disambiguate
+                // to select for bareword, change state -> SCE_PL_IDENTIFIER
+                if (state != SCE_PL_IDENTIFIER && i > 0) {
+                    unsigned int j = i;
+                    bool moreback = false;      // true if passed newline/comments
+                    bool brace = false;         // true if opening brace found
+                    char ch2;
+                    // first look backwards past whitespace/comments for EOLs
+                    // if BACK_NONE, neither operator nor keyword, so skip test
+                    if (backflag != BACK_NONE) {
+                        while (--j > backPos) {
+                            if (isEOLChar(styler.SafeGetCharAt(j)))
+                                moreback = true;
+                        }
+                        ch2 = styler.SafeGetCharAt(j);
+                        if (ch2 == '{' && !moreback) {
+                            // {bareword: possible variable spec
+                            brace = true;
+                        } else if ((ch2 == '&')
+                                // &bareword: subroutine call
+                                || (ch2 == '>' && styler.SafeGetCharAt(j - 1) == '-')
+                                // ->bareword: part of variable spec
+                                || (ch2 == 'b' && styler.Match(j - 2, "su"))) {
+                                // sub bareword: subroutine declaration
+                                // (implied BACK_KEYWORD, no keywords end in 'sub'!)
+                            state = SCE_PL_IDENTIFIER;
+                        }
+                        // if status still ambiguous, look forward after word past
+                        // tabs/spaces only; if ch2 isn't one of '[{(,' it can never
+                        // match anything, so skip the whole thing
+                        j = kw;
+                        if (state != SCE_PL_IDENTIFIER
+                            && (ch2 == '{' || ch2 == '(' || ch2 == '['|| ch2 == ',')
+                            && kw < lengthDoc) {
+                            while (ch2 = styler.SafeGetCharAt(j),
+                                   (ch2 == ' ' || ch2 == '\t') && j < lengthDoc) {
+                                j++;
+                            }
+                            if ((ch2 == '}' && brace)
+                             // {bareword}: variable spec
+                             || (ch2 == '=' && styler.SafeGetCharAt(j + 1) == '>')) {
+                             // [{(, bareword=>: hash literal
+                                state = SCE_PL_IDENTIFIER;
+                            }
+                        }
+                    }
+                }
+                backflag = BACK_NONE;
+                // an identifier or bareword
+                if (state == SCE_PL_IDENTIFIER) {
+                    if ((!iswordchar(chNext) && chNext != '\'')
+                        || (chNext == '.' && chNext2 == '.')) {
+                        // We need that if length of word == 1!
+                        // This test is copied from the SCE_PL_WORD handler.
+                        styler.ColourTo(i, SCE_PL_IDENTIFIER);
+                        state = SCE_PL_DEFAULT;
+                    }
+                // a keyword
+                } else if (state == SCE_PL_WORD) {
+                    i = kw - 1;
+                    if (ch == '_' && chNext == '_' &&
+                        (isMatch(styler, lengthDoc, styler.GetStartSegment(), "__DATA__")
+                      || isMatch(styler, lengthDoc, styler.GetStartSegment(), "__END__"))) {
+                        styler.ColourTo(i, SCE_PL_DATASECTION);
+                        state = SCE_PL_DATASECTION;
+                    } else {
+                        styler.ColourTo(i, SCE_PL_WORD);
+                        state = SCE_PL_DEFAULT;
+                        backflag = BACK_KEYWORD;
+                        backPos = i;
+                    }
+                    ch = styler.SafeGetCharAt(i);
+                    chNext = styler.SafeGetCharAt(i + 1);
+                // a repetition operator 'x'
+                } else if (state == SCE_PL_OPERATOR) {
+                    styler.ColourTo(i, SCE_PL_OPERATOR);
+                    state = SCE_PL_DEFAULT;
+                // quote-like delimiter, skip one char if double-char delimiter
+                } else {
+                    i = kw - 1;
+                    chNext = styler.SafeGetCharAt(i + 1);
+                }
                        } else if (ch == '#') {
                                state = SCE_PL_COMMENTLINE;
                        } else if (ch == '\"') {
                                state = SCE_PL_STRING;
                                Quote.New(1);
                                Quote.Open(ch);
+                backflag = BACK_NONE;
                        } else if (ch == '\'') {
                                if (chPrev == '&') {
                                        // Archaic call
@@ -341,10 +451,12 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        Quote.New(1);
                                        Quote.Open(ch);
                                }
+                backflag = BACK_NONE;
                        } else if (ch == '`') {
                                state = SCE_PL_BACKTICKS;
                                Quote.New(1);
                                Quote.Open(ch);
+                backflag = BACK_NONE;
                        } else if (ch == '$') {
                                if ((chNext == '{') || isspacechar(chNext)) {
                                        styler.ColourTo(i, SCE_PL_SCALAR);
@@ -360,28 +472,42 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                                chNext = chNext2;
                                        }
                                }
+                backflag = BACK_NONE;
                        } else if (ch == '@') {
                                if (isalpha(chNext) || chNext == '#' || chNext == '$'
-                                                   || chNext == '_' || chNext == '+') {
+                                       || chNext == '_' || chNext == '+' || chNext == '-') {
                                        state = SCE_PL_ARRAY;
                                } else if (chNext != '{' && chNext != '[') {
                                        styler.ColourTo(i, SCE_PL_ARRAY);
-                                       i++;
-                                       ch = ' ';
                                } else {
                                        styler.ColourTo(i, SCE_PL_ARRAY);
                                }
+                backflag = BACK_NONE;
                        } else if (ch == '%') {
-                               if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+                               if (isalpha(chNext) || chNext == '#' || chNext == '$'
+                    || chNext == '_' || chNext == '!' || chNext == '^') {
                                        state = SCE_PL_HASH;
+                    i++;
+                    ch = chNext;
+                    chNext = chNext2;
                                } else if (chNext == '{') {
                                        styler.ColourTo(i, SCE_PL_HASH);
                                } else {
                                        styler.ColourTo(i, SCE_PL_OPERATOR);
                                }
+                backflag = BACK_NONE;
                        } else if (ch == '*') {
-                               if (isalpha(chNext) || chNext == '_' || chNext == '{') {
+                char strch[2];
+                strch[0] = chNext;
+                strch[1] = '\0';
+                               if (isalpha(chNext) || chNext == '_' ||
+                    NULL != strstr("^/|,\\\";#%^:?<>)[]", strch)) {
                                        state = SCE_PL_SYMBOLTABLE;
+                    i++;
+                    ch = chNext;
+                    chNext = chNext2;
+                               } else if (chNext == '{') {
+                                       styler.ColourTo(i, SCE_PL_SYMBOLTABLE);
                                } else {
                                        if (chNext == '*') {    // exponentiation
                                                i++;
@@ -390,14 +516,22 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        }
                                        styler.ColourTo(i, SCE_PL_OPERATOR);
                                }
-                       } else if (ch == '/') {
+                backflag = BACK_NONE;
+                       } else if (ch == '/' || (ch == '<' && chNext == '<')) {
                                // Explicit backward peeking to set a consistent preferRE for
                                // any slash found, so no longer need to track preferRE state.
                                // Find first previous significant lexed element and interpret.
+                // Test for HERE doc start '<<' shares this code, helps to
+                // determine if it should be an operator.
                                bool preferRE = false;
+                bool isHereDoc = (ch == '<');
+                bool hereDocSpace = false;      // these are for corner case:
+                bool hereDocScalar = false;     // SCALAR [whitespace] '<<'
                                unsigned int bk = (i > 0)? i - 1: 0;
                                char bkch;
                                styler.Flush();
+                if (styler.StyleAt(bk) == SCE_PL_DEFAULT)
+                    hereDocSpace = true;
                                while ((bk > 0) && (styler.StyleAt(bk) == SCE_PL_DEFAULT ||
                                        styler.StyleAt(bk) == SCE_PL_COMMENTLINE)) {
                                        bk--;
@@ -494,9 +628,13 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                                        bk--;
                                                }
                                                break;
+                    case SCE_PL_SCALAR:     // for $var<< case
+                        hereDocScalar = true;
+                        break;
                                        // other styles uses the default, preferRE=false
                                        case SCE_PL_WORD:
                                        case SCE_PL_POD:
+                                       case SCE_PL_POD_VERB:
                                        case SCE_PL_HERE_Q:
                                        case SCE_PL_HERE_QQ:
                                        case SCE_PL_HERE_QX:
@@ -504,24 +642,39 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                                break;
                                        }
                                }
-                               if (preferRE) {
-                                       state = SCE_PL_REGEX;
-                                       Quote.New(1);
-                                       Quote.Open(ch);
-                               } else {
-                                       styler.ColourTo(i, SCE_PL_OPERATOR);
-                               }
-                       } else if (ch == '<' && chNext == '<') {
-                               state = SCE_PL_HERE_DELIM;
-                               HereDoc.State = 0;
+                if (isHereDoc) {    // handle HERE doc
+                    // if SCALAR whitespace '<<', *always* a HERE doc
+                    if (preferRE || (hereDocSpace && hereDocScalar)) {
+                        state = SCE_PL_HERE_DELIM;
+                        HereDoc.State = 0;
+                    } else {        // << operator
+                                               i++;
+                                               ch = chNext;
+                                               chNext = chNext2;
+                        styler.ColourTo(i, SCE_PL_OPERATOR);
+                    }
+                } else {            // handle regexp
+                    if (preferRE) {
+                        state = SCE_PL_REGEX;
+                        Quote.New(1);
+                        Quote.Open(ch);
+                    } else {        // / operator
+                        styler.ColourTo(i, SCE_PL_OPERATOR);
+                    }
+                }
+                backflag = BACK_NONE;
                        } else if (ch == '<') {
                                // looks forward for matching > on same line
                                unsigned int fw = i + 1;
                                while (fw < lengthDoc) {
                                        char fwch = styler.SafeGetCharAt(fw);
-                                       if (isEOLChar(fwch) || isspacechar(fwch))
+                                       if (fwch == ' ') {
+                                               if (styler.SafeGetCharAt(fw-1) != '\\' ||
+                                                   styler.SafeGetCharAt(fw-2) != '\\')
+                                               break;
+                                       } else if (isEOLChar(fwch) || isspacechar(fwch)) {
                                                break;
-                                       else if (fwch == '>') {
+                                       else if (fwch == '>') {
                                                if ((fw - i) == 2 &&    // '<=>' case
                                                    styler.SafeGetCharAt(fw-1) == '=') {
                                                        styler.ColourTo(fw, SCE_PL_OPERATOR);
@@ -535,10 +688,12 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        fw++;
                                }
                                styler.ColourTo(i, SCE_PL_OPERATOR);
+                backflag = BACK_NONE;
                        } else if (ch == '='    // POD
                                   && isalpha(chNext)
                                   && (isEOLChar(chPrev))) {
                                state = SCE_PL_POD;
+                backflag = BACK_NONE;
                                //sookedpos = 0;
                                //sooked[sookedpos] = '\0';
                        } else if (ch == '-'    // file test operators
@@ -549,6 +704,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                i++;
                                ch = chNext;
                                chNext = chNext2;
+                backflag = BACK_NONE;
                        } else if (isPerlOperator(ch)) {
                                if (ch == '.' && chNext == '.') { // .. and ...
                                        i++;
@@ -558,6 +714,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        chNext = styler.SafeGetCharAt(i + 1);
                                }
                                styler.ColourTo(i, SCE_PL_OPERATOR);
+                backflag = BACK_OPERATOR;
+                backPos = i;
                        } else {
                                // keep colouring defaults to make restart easier
                                styler.ColourTo(i, SCE_PL_DEFAULT);
@@ -567,7 +725,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                if (chNext == '.') {
                                        // double dot is always an operator
                                        goto numAtEnd;
-                               } else if (numState == PERLNUM_NON_DEC || numState == PERLNUM_FLOAT) {
+                               } else if (numState <= PERLNUM_FLOAT) {
                                        // non-decimal number or float exponent, consume next dot
                                        styler.ColourTo(i - 1, SCE_PL_NUMBER);
                                        styler.ColourTo(i, SCE_PL_OPERATOR);
@@ -594,7 +752,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) {
                                        if (isalpha(ch)) {
                                                if (dotCount == 0) { // change to word
-                                                       state = SCE_PL_WORD;
+                                                       state = SCE_PL_IDENTIFIER;
                                                } else { // vector then word
                                                        goto numAtEnd;
                                                }
@@ -614,9 +772,24 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        if (!isdigit(ch)) { // float then word
                                                goto numAtEnd;
                                        }
-                               } else {// (numState == PERLNUM_NON_DEC)
-                                       // allow alphanum for bin,hex,oct for now
-                               }
+                               } else if (numState == PERLNUM_OCTAL) {
+                    if (!isdigit(ch))
+                        goto numAtEnd;
+                    else if (ch > '7')
+                        numState = PERLNUM_BAD;
+                } else if (numState == PERLNUM_BINARY) {
+                    if (!isdigit(ch))
+                        goto numAtEnd;
+                    else if (ch > '1')
+                        numState = PERLNUM_BAD;
+                } else if (numState == PERLNUM_HEX) {
+                    int ch2 = toupper(ch);
+                    if (!isdigit(ch) && !(ch2 >= 'A' && ch2 <= 'F'))
+                        goto numAtEnd;
+                               } else {//(numState == PERLNUM_BAD) {
+                    if (!isdigit(ch))
+                        goto numAtEnd;
+                }
                        } else {
                                // complete current number or vector
                        numAtEnd:
@@ -624,25 +797,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                state = SCE_PL_DEFAULT;
                                goto restartLexer;
                        }
-               } else if (state == SCE_PL_WORD) {
-                       if ((!iswordchar(chNext) && chNext != '\'')
-                               || chNext == '.') {
-                               // ".." is always an operator if preceded by a SCE_PL_WORD.
-                               // "." never used in Perl variable names
-                               // Archaic Perl has quotes inside names
-                               if (isMatch(styler, lengthDoc, styler.GetStartSegment(), "__DATA__")
-                                || isMatch(styler, lengthDoc, styler.GetStartSegment(), "__END__")) {
-                                       styler.ColourTo(i, SCE_PL_DATASECTION);
-                                       state = SCE_PL_DATASECTION;
-                               } else {
-                                       classifyWordPerl(styler.GetStartSegment(), i, keywords, styler);
-                                       state = SCE_PL_DEFAULT;
-                                       ch = ' ';
-                               }
-                       }
                } else if (state == SCE_PL_IDENTIFIER) {
-                       if ((!iswordchar(chNext) && chNext != '\'')
-                               || chNext == '.') {
+                       if (!iswordstart(chNext) && chNext != '\'') {
                                styler.ColourTo(i, SCE_PL_IDENTIFIER);
                                state = SCE_PL_DEFAULT;
                                ch = ' ';
@@ -685,29 +841,46 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                // Whitespace acceptable after <<[-] operator.
                                //
                                if (HereDoc.State == 0) { // '<<' encountered
+                    bool gotspace = false;
+                    unsigned int oldi = i;
+                    if (chNext == ' ' || chNext == '\t') {
+                        // skip whitespace; legal for quoted delimiters
+                        gotspace = true;
+                        do {
+                            i++;
+                            chNext = styler.SafeGetCharAt(i + 1);
+                        } while ((i + 1 < lengthDoc) && (chNext == ' ' || chNext == '\t'));
+                        chNext2 = styler.SafeGetCharAt(i + 2);
+                    }
                                        HereDoc.State = 1;
                                        HereDoc.Quote = chNext;
                                        HereDoc.Quoted = false;
                                        HereDoc.DelimiterLength = 0;
                                        HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
-                                       if (chNext == '\'' || chNext == '"' || chNext == '`') { // a quoted here-doc delimiter
+                                       if (chNext == '\'' || chNext == '"' || chNext == '`') {
+                        // a quoted here-doc delimiter
                                                i++;
                                                ch = chNext;
                                                chNext = chNext2;
                                                HereDoc.Quoted = true;
-                                       } else if (isalpha(chNext) || chNext == '_') {
-                                               // an unquoted here-doc delimiter, no special handling
                                        } else if (isspacechar(chNext) || isdigit(chNext) || chNext == '\\'
-                                               || chNext == '=' || chNext == '$' || chNext == '@') {
+                                               || chNext == '=' || chNext == '$' || chNext == '@'
+                        || ((isalpha(chNext) || chNext == '_') && gotspace)) {
                                                // left shift << or <<= operator cases
+                        // restore position if operator
+                        i = oldi;
                                                styler.ColourTo(i, SCE_PL_OPERATOR);
                                                state = SCE_PL_DEFAULT;
                                                HereDoc.State = 0;
+                        goto restartLexer;
                                        } else {
+                                               // an unquoted here-doc delimiter, no special handling
+                        // (cannot be prefixed by spaces/tabs), or
                                                // symbols terminates; deprecated zero-length delimiter
                                        }
 
                                } else if (HereDoc.State == 1) { // collect the delimiter
+                    backflag = BACK_NONE;
                                        if (HereDoc.Quoted) { // a quoted here-doc delimiter
                                                if (ch == HereDoc.Quote) { // closing quote => end of delimiter
                                                        styler.ColourTo(i, state);
@@ -746,20 +919,31 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        if (isEOLChar(ch)) {
                                                styler.ColourTo(i - 1, state);
                                                state = SCE_PL_DEFAULT;
+                        backflag = BACK_NONE;
                                                HereDoc.State = 0;
                                                goto restartLexer;
                                        }
                                        chNext = styler.SafeGetCharAt(i + 1);
                                }
-                       } else if (state == SCE_PL_POD) {
-                               if (ch == '=' && isEOLChar(chPrev)) {
-                                       if (isMatch(styler, lengthDoc, i, "=cut")) {
-                                               styler.ColourTo(i - 1 + 4, state);
-                                               i += 4;
-                                               state = SCE_PL_DEFAULT;
-                                               ch = styler.SafeGetCharAt(i);
-                                               //chNext = styler.SafeGetCharAt(i + 1);
-                                               goto restartLexer;
+                       } else if (state == SCE_PL_POD
+                               || state == SCE_PL_POD_VERB) {
+                               if (isEOLChar(chPrev)) {
+                                       if (ch == ' ' || ch == '\t') {
+                                               styler.ColourTo(i - 1, state);
+                                               state = SCE_PL_POD_VERB;
+                                       } else {
+                                               styler.ColourTo(i - 1, state);
+                                               state = SCE_PL_POD;
+                                               if (ch == '=') {
+                                                       if (isMatch(styler, lengthDoc, i, "=cut")) {
+                                                               styler.ColourTo(i - 1 + 4, state);
+                                                               i += 4;
+                                                               state = SCE_PL_DEFAULT;
+                                                               ch = styler.SafeGetCharAt(i);
+                                                               //chNext = styler.SafeGetCharAt(i + 1);
+                                                               goto restartLexer;
+                                                       }
+                                               }
                                        }
                                }
                        } else if (state == SCE_PL_SCALAR       // variable names
@@ -772,8 +956,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        chNext = chNext2;
                                }
                                else if (isEndVar(ch)) {
-                                       if ((state == SCE_PL_SCALAR || state == SCE_PL_ARRAY)
-                                           && i == (styler.GetStartSegment() + 1)) {
+                                       if (i == (styler.GetStartSegment() + 1)) {
                                                // Special variable: $(, $_ etc.
                                                styler.ColourTo(i, state);
                                                state = SCE_PL_DEFAULT;
@@ -917,33 +1100,57 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
        styler.ColourTo(lengthDoc - 1, state);
 }
 
+static bool IsCommentLine(int line, Accessor &styler) {
+       int pos = styler.LineStart(line);
+       int eol_pos = styler.LineStart(line + 1) - 1;
+       for (int i = pos; i < eol_pos; i++) {
+               char ch = styler[i];
+        int style = styler.StyleAt(i);
+               if (ch == '#' && style == SCE_PL_COMMENTLINE)
+                       return true;
+               else if (ch != ' ' && ch != '\t')
+                       return false;
+       }
+       return false;
+}
+
 static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[],
                             Accessor &styler) {
        bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
        bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+       // Custom folding of POD and packages
+       bool foldPOD = styler.GetPropertyInt("fold.perl.pod", 1) != 0;
+       bool foldPackage = styler.GetPropertyInt("fold.perl.package", 1) != 0;
        unsigned int endPos = startPos + length;
        int visibleChars = 0;
        int lineCurrent = styler.GetLine(startPos);
-       int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int levelPrev = SC_FOLDLEVELBASE;
+       if (lineCurrent > 0)
+               levelPrev = styler.LevelAt(lineCurrent - 1) >> 16;
        int levelCurrent = levelPrev;
        char chNext = styler[startPos];
+       char chPrev = styler.SafeGetCharAt(startPos - 1);
        int styleNext = styler.StyleAt(startPos);
+       // Used at end of line to determine if the line was a package definition
+       bool isPackageLine = false;
+       bool isPodHeading = false;
        for (unsigned int i = startPos; i < endPos; i++) {
                char ch = chNext;
                chNext = styler.SafeGetCharAt(i + 1);
                int style = styleNext;
                styleNext = styler.StyleAt(i + 1);
                bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
-               if (foldComment && (style == SCE_PL_COMMENTLINE)) {
-                       if ((ch == '/') && (chNext == '/')) {
-                               char chNext2 = styler.SafeGetCharAt(i + 2);
-                               if (chNext2 == '{') {
-                                       levelCurrent++;
-                               } else if (chNext2 == '}') {
-                                       levelCurrent--;
-                               }
-                       }
-               }
+               bool atLineStart = isEOLChar(chPrev) || i == 0;
+        // Comment folding
+               if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
+        {
+            if (!IsCommentLine(lineCurrent - 1, styler)
+                && IsCommentLine(lineCurrent + 1, styler))
+                levelCurrent++;
+            else if (IsCommentLine(lineCurrent - 1, styler)
+                     && !IsCommentLine(lineCurrent+1, styler))
+                levelCurrent--;
+        }
                if (style == SCE_C_OPERATOR) {
                        if (ch == '{') {
                                levelCurrent++;
@@ -951,8 +1158,51 @@ static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[],
                                levelCurrent--;
                        }
                }
+               // Custom POD folding
+               if (foldPOD && atLineStart) {
+                       int stylePrevCh = (i) ? styler.StyleAt(i - 1):SCE_PL_DEFAULT;
+                       if (style == SCE_PL_POD) {
+                               if (stylePrevCh != SCE_PL_POD && stylePrevCh != SCE_PL_POD_VERB)
+                                       levelCurrent++;
+                               else if (styler.Match(i, "=cut"))
+                                       levelCurrent--;
+                               else if (styler.Match(i, "=head"))
+                                       isPodHeading = true;
+                       } else if (style == SCE_PL_DATASECTION) {
+                if (ch == '=' && isalpha(chNext) && levelCurrent == SC_FOLDLEVELBASE)
+                    levelCurrent++;
+                else if (styler.Match(i, "=cut") && levelCurrent > SC_FOLDLEVELBASE)
+                    levelCurrent--;
+                else if (styler.Match(i, "=head"))
+                                       isPodHeading = true;
+                // if package used or unclosed brace, level > SC_FOLDLEVELBASE!
+                // reset needed as level test is vs. SC_FOLDLEVELBASE
+                else if (styler.Match(i, "__END__"))
+                    levelCurrent = SC_FOLDLEVELBASE;
+            }
+               }
+               // Custom package folding
+               if (foldPackage && atLineStart) {
+                       if (style == SCE_PL_WORD && styler.Match(i, "package")) {
+                               isPackageLine = true;
+                       }
+               }
+
                if (atEOL) {
                        int lev = levelPrev;
+                       if (isPodHeading) {
+                lev = levelPrev - 1;
+                lev |= SC_FOLDLEVELHEADERFLAG;
+                isPodHeading = false;
+                       }
+                       // Check if line was a package declaration
+                       // because packages need "special" treatment
+                       if (isPackageLine) {
+                               lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
+                               levelCurrent = SC_FOLDLEVELBASE + 1;
+                               isPackageLine = false;
+                       }
+            lev |= levelCurrent << 16;
                        if (visibleChars == 0 && foldCompact)
                                lev |= SC_FOLDLEVELWHITEFLAG;
                        if ((levelCurrent > levelPrev) && (visibleChars > 0))
@@ -966,6 +1216,7 @@ static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[],
                }
                if (!isspacechar(ch))
                        visibleChars++;
+               chPrev = ch;
        }
        // Fill in the real level of the next line, keeping the current flags as they will be filled in later
        int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
index e13c6220d9c40be7efed0ef868639367a557ea5d..c1397b79130979b6390e9bb49357f2a66d1df17e 100644 (file)
@@ -109,6 +109,7 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
        }
 
        WordList &keywords = *keywordlists[0];
+       WordList &keywords2 = *keywordlists[1];
 
        const int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
 
@@ -186,6 +187,8 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
                                        style = SCE_P_CLASSNAME;
                                } else if (kwLast == kwDef) {
                                        style = SCE_P_DEFNAME;
+                               } else if (keywords2.InList(s)) {
+                                       style = SCE_P_WORD2;
                                }
                                sc.ChangeState(style);
                                sc.SetState(SCE_P_DEFAULT);
@@ -198,9 +201,7 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
                                                kwLast = kwImport;
                                        else
                                                kwLast = kwOther;
-                               } else if (style == SCE_P_CLASSNAME) {
-                                       kwLast = kwOther;
-                               } else if (style == SCE_P_DEFNAME) {
+                               } else {
                                        kwLast = kwOther;
                                }
                        }
@@ -208,6 +209,10 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
                        if (sc.ch == '\r' || sc.ch == '\n') {
                                sc.SetState(SCE_P_DEFAULT);
                        }
+               } else if (sc.state == SCE_P_DECORATOR) {
+                       if (sc.ch == '\r' || sc.ch == '\n') {
+                               sc.SetState(SCE_P_DEFAULT);
+                       }
                } else if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) {
                        if (sc.ch == '\\') {
                                if ((sc.chNext == '\r') && (sc.GetRelative(2) == '\n')) {
@@ -262,6 +267,8 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
                                sc.SetState(SCE_P_OPERATOR);
                        } else if (sc.ch == '#') {
                                sc.SetState(sc.chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE);
+                       } else if (sc.ch == '@') {
+                               sc.SetState(SCE_P_DECORATOR);
                        } else if (IsPyStringStart(sc.ch, sc.chNext, sc.GetRelative(2))) {
                                unsigned int nextIndex = 0;
                                sc.SetState(GetPyStringState(styler, sc.currentPos, &nextIndex));
@@ -432,6 +439,7 @@ static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unuse
 
 static const char * const pythonWordListDesc[] = {
        "Keywords",
+       "Highlighted identifiers",
        0
 };
 
diff --git a/contrib/src/stc/scintilla/src/LexRebol.cxx b/contrib/src/stc/scintilla/src/LexRebol.cxx
new file mode 100644 (file)
index 0000000..f829c1e
--- /dev/null
@@ -0,0 +1,319 @@
+// Scintilla source code edit control
+/** @file LexRebol.cxx
+ ** Lexer for REBOL.
+ ** Written by Pascal Hurni, inspired from LexLua by Paul Winwood & Marcos E. Wurzius & Philippe Lhoste
+ **
+ ** History:
+ **            2005-04-07      First release.
+ **            2005-04-10      Closing parens and brackets go now in default style
+ **                                    String and comment nesting should be more safe
+ **/
+// Copyright 2005 by Pascal Hurni <pascal_hurni@fastmail.fm>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+#include "StyleContext.h"
+
+
+static inline bool IsAWordChar(const int ch) {
+       return (isalnum(ch) || ch == '?' || ch == '!' || ch == '.' || ch == '\'' || ch == '+' || ch == '-' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~');
+}
+
+static inline bool IsAWordStart(const int ch, const int ch2) {
+       return ((ch == '+' || ch == '-' || ch == '.') && !isdigit(ch2)) ||
+               (isalpha(ch) || ch == '?' || ch == '!' || ch == '\'' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~');
+}
+
+static inline bool IsAnOperator(const int ch, const int ch2, const int ch3) {
+       // One char operators
+       if (IsASpaceOrTab(ch2)) {
+               return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '<' || ch == '>' || ch == '=' || ch == '?';
+       }
+
+       // Two char operators
+       if (IsASpaceOrTab(ch3)) {
+               return (ch == '*' && ch2 == '*') ||
+                          (ch == '/' && ch2 == '/') ||
+                          (ch == '<' && (ch2 == '=' || ch2 == '>')) ||
+                          (ch == '>' && ch2 == '=') ||
+                          (ch == '=' && (ch2 == '=' || ch2 == '?')) ||
+                          (ch == '?' && ch2 == '?');
+       }
+
+       return false;
+}
+
+static inline bool IsBinaryStart(const int ch, const int ch2, const int ch3, const int ch4) {
+       return (ch == '#' && ch2 == '{') ||
+                  (IsADigit(ch) && ch2 == '#' && ch3 == '{' ) ||
+                  (IsADigit(ch) && IsADigit(ch2) && ch3 == '#' && ch4 == '{' );
+}
+
+
+static void ColouriseRebolDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
+
+       WordList &keywords = *keywordlists[0];
+       WordList &keywords2 = *keywordlists[1];
+       WordList &keywords3 = *keywordlists[2];
+       WordList &keywords4 = *keywordlists[3];
+       WordList &keywords5 = *keywordlists[4];
+       WordList &keywords6 = *keywordlists[5];
+       WordList &keywords7 = *keywordlists[6];
+       WordList &keywords8 = *keywordlists[7];
+
+       int currentLine = styler.GetLine(startPos);
+       // Initialize the braced string {.. { ... } ..} nesting level, if we are inside such a string.
+       int stringLevel = 0;
+       if (initStyle == SCE_REBOL_BRACEDSTRING || initStyle == SCE_REBOL_COMMENTBLOCK) {
+               stringLevel = styler.GetLineState(currentLine - 1);
+       }
+
+       bool blockComment = initStyle == SCE_REBOL_COMMENTBLOCK;
+       int dotCount = 0;
+
+       // Do not leak onto next line
+       if (initStyle == SCE_REBOL_COMMENTLINE) {
+               initStyle = SCE_REBOL_DEFAULT;
+       }
+
+       StyleContext sc(startPos, length, initStyle, styler);
+       if (startPos == 0) {
+               sc.SetState(SCE_REBOL_PREFACE);
+       }
+       for (; sc.More(); sc.Forward()) {
+
+               //--- What to do at line end ?
+               if (sc.atLineEnd) {
+                       // Can be either inside a {} string or simply at eol
+                       if (sc.state != SCE_REBOL_BRACEDSTRING && sc.state != SCE_REBOL_COMMENTBLOCK &&
+                               sc.state != SCE_REBOL_BINARY && sc.state != SCE_REBOL_PREFACE)
+                               sc.SetState(SCE_REBOL_DEFAULT);
+
+                       // Update the line state, so it can be seen by next line
+                       currentLine = styler.GetLine(sc.currentPos);
+                       switch (sc.state) {
+                       case SCE_REBOL_BRACEDSTRING:
+                       case SCE_REBOL_COMMENTBLOCK:
+                               // Inside a braced string, we set the line state
+                               styler.SetLineState(currentLine, stringLevel);
+                               break;
+                       default:
+                               // Reset the line state
+                               styler.SetLineState(currentLine, 0);
+                               break;
+                       }
+
+                       // continue with next char
+                       continue;
+               }
+
+               //--- What to do on white-space ?
+               if (IsASpaceOrTab(sc.ch))
+               {
+                       // Return to default if any of these states
+                       if (sc.state == SCE_REBOL_OPERATOR || sc.state == SCE_REBOL_CHARACTER ||
+                               sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR ||
+                               sc.state == SCE_REBOL_TUPLE || sc.state == SCE_REBOL_FILE ||
+                               sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME ||
+                               sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE ||
+                               sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_EMAIL) {
+                               sc.SetState(SCE_REBOL_DEFAULT);
+                       }
+               }
+
+               //--- Specialize state ?
+               // URL, Email look like identifier
+               if (sc.state == SCE_REBOL_IDENTIFIER)
+               {
+                       if (sc.ch == ':' && !IsASpace(sc.chNext)) {
+                               sc.ChangeState(SCE_REBOL_URL);
+                       } else if (sc.ch == '@') {
+                               sc.ChangeState(SCE_REBOL_EMAIL);
+                       } else if (sc.ch == '$') {
+                               sc.ChangeState(SCE_REBOL_MONEY);
+                       }
+               }
+               // Words look like identifiers
+               if (sc.state == SCE_REBOL_IDENTIFIER || (sc.state >= SCE_REBOL_WORD && sc.state <= SCE_REBOL_WORD8)) {
+                       // Keywords ?
+                       if (!IsAWordChar(sc.ch) || sc.Match('/')) {
+                               char s[100];
+                               sc.GetCurrentLowered(s, sizeof(s));
+                               blockComment = strcmp(s, "comment") == 0;
+                               if (keywords8.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD8);
+                               } else if (keywords7.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD7);
+                               } else if (keywords6.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD6);
+                               } else if (keywords5.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD5);
+                               } else if (keywords4.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD4);
+                               } else if (keywords3.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD3);
+                               } else if (keywords2.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD2);
+                               } else if (keywords.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD);
+                               }
+                               // Keep same style if there are refinements
+                               if (!sc.Match('/')) {
+                                       sc.SetState(SCE_REBOL_DEFAULT);
+                               }
+                       }
+               // special numbers
+               } else if (sc.state == SCE_REBOL_NUMBER) {
+                       switch (sc.ch) {
+                       case 'x':       sc.ChangeState(SCE_REBOL_PAIR);
+                                               break;
+                       case ':':       sc.ChangeState(SCE_REBOL_TIME);
+                                               break;
+                       case '-':
+                       case '/':       sc.ChangeState(SCE_REBOL_DATE);
+                                               break;
+                       case '.':       if (++dotCount >= 2) sc.ChangeState(SCE_REBOL_TUPLE);
+                                               break;
+                       }
+               }
+
+               //--- Determine if the current state should terminate
+               if (sc.state == SCE_REBOL_QUOTEDSTRING || sc.state == SCE_REBOL_CHARACTER) {
+                       if (sc.ch == '^' && sc.chNext == '\"') {
+                               sc.Forward();
+                       } else if (sc.ch == '\"') {
+                               sc.ForwardSetState(SCE_REBOL_DEFAULT);
+                       }
+               } else if (sc.state == SCE_REBOL_BRACEDSTRING || sc.state == SCE_REBOL_COMMENTBLOCK) {
+                       if (sc.ch == '}') {
+                               if (--stringLevel == 0) {
+                                       sc.ForwardSetState(SCE_REBOL_DEFAULT);
+                               }
+                       } else if (sc.ch == '{') {
+                               stringLevel++;
+                       }
+               } else if (sc.state == SCE_REBOL_BINARY) {
+                       if (sc.ch == '}') {
+                               sc.ForwardSetState(SCE_REBOL_DEFAULT);
+                       }
+               } else if (sc.state == SCE_REBOL_TAG) {
+                       if (sc.ch == '>') {
+                               sc.ForwardSetState(SCE_REBOL_DEFAULT);
+                       }
+               } else if (sc.state == SCE_REBOL_PREFACE) {
+                       if (sc.MatchIgnoreCase("rebol"))
+                       {
+                               int i;
+                               for (i=5; IsASpaceOrTab(styler.SafeGetCharAt(sc.currentPos+i, 0)); i++);
+                               if (sc.GetRelative(i) == '[')
+                                       sc.SetState(SCE_REBOL_DEFAULT);
+                       }
+               }
+
+               //--- Parens and bracket changes to default style when the current is a number
+               if (sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR || sc.state == SCE_REBOL_TUPLE ||
+                       sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE || sc.state == SCE_REBOL_EMAIL ||
+                       sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME) {
+                       if (sc.ch == '(' || sc.ch == '[' || sc.ch == ')' || sc.ch == ']') {
+                               sc.SetState(SCE_REBOL_DEFAULT);
+                       }
+               }
+
+               //--- Determine if a new state should be entered.
+               if (sc.state == SCE_REBOL_DEFAULT) {
+                       if (IsAnOperator(sc.ch, sc.chNext, sc.GetRelative(2))) {
+                               sc.SetState(SCE_REBOL_OPERATOR);
+                       } else if (IsBinaryStart(sc.ch, sc.chNext, sc.GetRelative(2), sc.GetRelative(3))) {
+                               sc.SetState(SCE_REBOL_BINARY);
+                       } else if (IsAWordStart(sc.ch, sc.chNext)) {
+                               sc.SetState(SCE_REBOL_IDENTIFIER);
+                       } else if (IsADigit(sc.ch) || sc.ch == '+' || sc.ch == '-' || /*Decimal*/ sc.ch == '.' || sc.ch == ',') {
+                               dotCount = 0;
+                               sc.SetState(SCE_REBOL_NUMBER);
+                       } else if (sc.ch == '\"') {
+                               sc.SetState(SCE_REBOL_QUOTEDSTRING);
+                       } else if (sc.ch == '{') {
+                               sc.SetState(blockComment ? SCE_REBOL_COMMENTBLOCK : SCE_REBOL_BRACEDSTRING);
+                               ++stringLevel;
+                       } else if (sc.ch == ';') {
+                               sc.SetState(SCE_REBOL_COMMENTLINE);
+                       } else if (sc.ch == '$') {
+                               sc.SetState(SCE_REBOL_MONEY);
+                       } else if (sc.ch == '%') {
+                               sc.SetState(SCE_REBOL_FILE);
+                       } else if (sc.ch == '<') {
+                               sc.SetState(SCE_REBOL_TAG);
+                       } else if (sc.ch == '#' && sc.chNext == '"') {
+                               sc.SetState(SCE_REBOL_CHARACTER);
+                               sc.Forward();
+                       } else if (sc.ch == '#' && sc.chNext != '"' && sc.chNext != '{' ) {
+                               sc.SetState(SCE_REBOL_ISSUE);
+                       }
+               }
+       }
+       sc.Complete();
+}
+
+
+static void FoldRebolDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
+                            Accessor &styler) {
+       unsigned int lengthDoc = startPos + length;
+       int visibleChars = 0;
+       int lineCurrent = styler.GetLine(startPos);
+       int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int levelCurrent = levelPrev;
+       char chNext = styler[startPos];
+       int styleNext = styler.StyleAt(startPos);
+       for (unsigned int i = startPos; i < lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               int style = styleNext;
+               styleNext = styler.StyleAt(i + 1);
+               bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+               if (style == SCE_REBOL_DEFAULT) {
+                       if (ch == '[') {
+                               levelCurrent++;
+                       } else if (ch == ']') {
+                               levelCurrent--;
+                       }
+               }
+               if (atEOL) {
+                       int lev = levelPrev;
+                       if (visibleChars == 0)
+                               lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visibleChars > 0))
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+                       if (lev != styler.LevelAt(lineCurrent)) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+                       lineCurrent++;
+                       levelPrev = levelCurrent;
+                       visibleChars = 0;
+               }
+               if (!isspacechar(ch))
+                       visibleChars++;
+       }
+       // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+       int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+       styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+}
+
+static const char * const rebolWordListDesc[] = {
+       "Keywords",
+       0
+};
+
+LexerModule lmREBOL(SCLEX_REBOL, ColouriseRebolDoc, "rebol", FoldRebolDoc, rebolWordListDesc);
+
index 692a47adefe6c02def9653cb8944c5e0f49d2bc7..f5ad020f404e31eae5127a05cda5f3dc597da048 100644 (file)
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-static void ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) {
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+//XXX Identical to Perl, put in common area
+static inline bool isEOLChar(char ch) {
+       return (ch == '\r') || (ch == '\n');
+}
+
+#define isSafeASCII(ch) ((unsigned int)(ch) <= 127)
+// This one's redundant, but makes for more readable code
+#define isHighBitChar(ch) ((unsigned int)(ch) > 127)
+
+static inline bool isSafeAlpha(char ch) {
+    return (isSafeASCII(ch) && isalpha(ch)) || ch == '_';
+}
+
+static inline bool isSafeAlnum(char ch) {
+    return (isSafeASCII(ch) && isalnum(ch)) || ch == '_';
+}
+
+static inline bool isSafeAlnumOrHigh(char ch) {
+    return isHighBitChar(ch) || isalnum(ch) || ch == '_';
+}
+
+static inline bool isSafeDigit(char ch) {
+    return isSafeASCII(ch) && isdigit(ch);
+}
+
+static inline bool isSafeWordcharOrHigh(char ch) {
+    return isHighBitChar(ch) || iswordchar(ch);
+}
+
+static bool inline iswhitespace(char ch) {
+       return ch == ' ' || ch == '\t';
+}
+
+#define MAX_KEYWORD_LENGTH 200
+
+#define STYLE_MASK 63
+#define actual_style(style) (style & STYLE_MASK)
+
+static bool followsDot(unsigned int pos, Accessor &styler) {
+    styler.Flush();
+    for (; pos >= 1; --pos) {
+        int style = actual_style(styler.StyleAt(pos));
+        char ch;
+        switch (style) {
+            case SCE_RB_DEFAULT:
+                ch = styler[pos];
+                if (ch == ' ' || ch == '\t') {
+                    //continue
+                } else {
+                    return false;
+                }
+                break;
+                
+            case SCE_RB_OPERATOR:
+                return styler[pos] == '.';
+
+            default:
+                return false;
+        }
+    }
+    return false;
+}
+
+// Forward declarations
+static bool keywordIsAmbiguous(const char *prevWord);
+static bool keywordDoStartsLoop(int pos,
+                                Accessor &styler);
+static bool keywordIsModifier(const char *word,
+                              int pos,
+                              Accessor &styler);
+
+static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) {
        char s[100];
-       bool wordIsNumber = isdigit(styler[start]) != 0;
-       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
-               s[i] = styler[start + i];
-               s[i + 1] = '\0';
+    unsigned int i, j;
+       unsigned int lim = end - start + 1; // num chars to copy
+       if (lim >= MAX_KEYWORD_LENGTH) {
+               lim = MAX_KEYWORD_LENGTH - 1;
+       }
+       for (i = start, j = 0; j < lim; i++, j++) {
+               s[j] = styler[i];
        }
-       char chAttr = SCE_P_IDENTIFIER;
+    s[j] = '\0';
+       int chAttr;
        if (0 == strcmp(prevWord, "class"))
-               chAttr = SCE_P_CLASSNAME;
+               chAttr = SCE_RB_CLASSNAME;
        else if (0 == strcmp(prevWord, "module"))
-               chAttr = SCE_P_CLASSNAME;
+               chAttr = SCE_RB_MODULE_NAME;
        else if (0 == strcmp(prevWord, "def"))
-               chAttr = SCE_P_DEFNAME;
-       else if (wordIsNumber)
-               chAttr = SCE_P_NUMBER;
-       else if (keywords.InList(s))
-               chAttr = SCE_P_WORD;
-       // make sure that dot-qualifiers inside the word are lexed correct
-       else for (unsigned int i = 0; i < end - start + 1; i++) {
-               if (styler[start + i] == '.') {
-                       styler.ColourTo(start + i - 1, chAttr);
-                       styler.ColourTo(start + i, SCE_P_OPERATOR);
+               chAttr = SCE_RB_DEFNAME;
+    else if (keywords.InList(s) && !followsDot(start - 1, styler)) {
+        if (keywordIsAmbiguous(s)
+            && keywordIsModifier(s, start, styler)) {
+            
+            // Demoted keywords are colored as keywords,
+            // but do not affect changes in indentation.
+            //
+            // Consider the word 'if':
+            // 1. <<if test ...>> : normal
+            // 2. <<stmt if test>> : demoted
+            // 3. <<lhs = if ...>> : normal: start a new indent level
+            // 4. <<obj.if = 10>> : color as identifer, since it follows '.'
+            
+            chAttr = SCE_RB_WORD_DEMOTED;
+        } else {
+            chAttr = SCE_RB_WORD;
+        }
+       } else
+        chAttr = SCE_RB_IDENTIFIER;
+       styler.ColourTo(end, chAttr);
+       if (chAttr == SCE_RB_WORD) {
+               strcpy(prevWord, s);
+       } else {
+               prevWord[0] = 0;
+       }
+    return chAttr;
+}
+
+
+//XXX Identical to Perl, put in common area
+static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) {
+       if ((pos + static_cast<int>(strlen(val))) >= lengthDoc) {
+               return false;
+       }
+       while (*val) {
+               if (*val != styler[pos++]) {
+                       return false;
                }
+               val++;
        }
-       styler.ColourTo(end, chAttr);
-       strcpy(prevWord, s);
+       return true;
 }
 
-static bool IsRbComment(Accessor &styler, int pos, int len) {
-       return len>0 && styler[pos]=='#';
+// Do Ruby better -- find the end of the line, work back,
+// and then check for leading white space
+
+// Precondition: the here-doc target can be indented
+static bool lookingAtHereDocDelim(Accessor        &styler,
+                                  int                  pos,
+                                  int                  lengthDoc,
+                                  const char   *HereDocDelim)
+{
+    if (!isMatch(styler, lengthDoc, pos, HereDocDelim)) {
+        return false;
+    }
+    while (--pos > 0) {
+        char ch = styler[pos];
+        if (isEOLChar(ch)) {
+            return true;
+        } else if (ch != ' ' && ch != '\t') {
+            return false;
+        }
+    }
+    return false;
 }
 
-static bool IsRbStringStart(char ch, char chNext, char chNext2) {
-       if (ch == '\'' || ch == '"')
-               return true;
-       if (ch == 'u' || ch == 'U') {
-               if (chNext == '"' || chNext == '\'')
-                       return true;
-               if ((chNext == 'r' || chNext == 'R') && (chNext2 == '"' || chNext2 == '\''))
-                       return true;
-       }
-       if ((ch == 'r' || ch == 'R') && (chNext == '"' || chNext == '\''))
-               return true;
+//XXX Identical to Perl, put in common area
+static char opposite(char ch) {
+       if (ch == '(')
+               return ')';
+       if (ch == '[')
+               return ']';
+       if (ch == '{')
+               return '}';
+       if (ch == '<')
+               return '>';
+       return ch;
+}
+
+// Null transitions when we see we've reached the end
+// and need to relex the curr char.
 
-       return false;
+static void redo_char(int &i, char &ch, char &chNext, char &chNext2,
+                      int &state) {
+    i--;
+    chNext2 = chNext;
+    chNext = ch;
+    state = SCE_RB_DEFAULT;
 }
 
-static bool IsRbWordStart(char ch, char chNext, char chNext2) {
-       return (iswordchar(ch) && !IsRbStringStart(ch, chNext, chNext2));
+static void advance_char(int &i, char &ch, char &chNext, char &chNext2) {
+    i++;
+    ch = chNext;
+    chNext = chNext2;
 }
 
-/* Return the state to use for the string starting at i; *nextIndex will be set to the first index following the quote(s) */
-static int GetRbStringState(Accessor &styler, int i, int *nextIndex) {
-       char ch = styler.SafeGetCharAt(i);
-       char chNext = styler.SafeGetCharAt(i + 1);
+// precondition: startPos points to one after the EOL char
+static bool currLineContainsHereDelims(int& startPos,
+                                       Accessor &styler) {
+    if (startPos <= 1)
+        return false;
 
-       // Advance beyond r, u, or ur prefix, but bail if there are any unexpected chars
-       if (ch == 'r' || ch == 'R') {
-               i++;
-               ch = styler.SafeGetCharAt(i);
-               chNext = styler.SafeGetCharAt(i + 1);
-       }
-       else if (ch == 'u' || ch == 'U') {
-               if (chNext == 'r' || chNext == 'R')
-                       i += 2;
-               else
-                       i += 1;
-               ch = styler.SafeGetCharAt(i);
-               chNext = styler.SafeGetCharAt(i + 1);
-       }
+    int pos;
+    for (pos = startPos - 1; pos > 0; pos--) {
+        char ch = styler.SafeGetCharAt(pos);
+        if (isEOLChar(ch)) {
+            // Leave the pointers where they are -- there are no
+            // here doc delims on the current line, even if
+            // the EOL isn't default style
+            
+            return false;
+        } else {
+            styler.Flush();
+            if (actual_style(styler.StyleAt(pos)) == SCE_RB_HERE_DELIM) {
+                break;
+            }
+        }
+    }
+    if (pos == 0) {
+        return false;
+    }
+    // Update the pointers so we don't have to re-analyze the string
+    startPos = pos;
+    return true;
+}
 
-       if (ch != '"' && ch != '\'') {
-               *nextIndex = i + 1;
-               return SCE_P_DEFAULT;
-       }
 
-       if (i>0 && styler.SafeGetCharAt(i-1) == '$') {
-               *nextIndex = i + 1;
-               return SCE_P_DEFAULT;
-       }
+static bool isEmptyLine(int pos,
+                        Accessor &styler) {
+       int spaceFlags = 0;
+       int lineCurrent = styler.GetLine(pos);
+       int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+    return (indentCurrent & SC_FOLDLEVELWHITEFLAG) != 0;
+}
 
-       if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) {
-               *nextIndex = i + 3;
+static bool RE_CanFollowKeyword(const char *keyword) {
+    if (!strcmp(keyword, "and")
+        || !strcmp(keyword, "begin")
+        || !strcmp(keyword, "break")
+        || !strcmp(keyword, "case")
+        || !strcmp(keyword, "do")
+        || !strcmp(keyword, "else")
+        || !strcmp(keyword, "elsif")
+        || !strcmp(keyword, "if")
+        || !strcmp(keyword, "next")
+        || !strcmp(keyword, "return")
+        || !strcmp(keyword, "when")
+        || !strcmp(keyword, "unless")
+        || !strcmp(keyword, "until")
+        || !strcmp(keyword, "not")
+        || !strcmp(keyword, "or")) {
+        return true;
+    }
+    return false;
+}
 
-               if (ch == '"')
-                       return SCE_P_TRIPLEDOUBLE;
-               else
-                       return SCE_P_TRIPLE;
-       } else {
-               *nextIndex = i + 1;
+// Look at chars up to but not including endPos
+// Don't look at styles in case we're looking forward
 
-               if (ch == '"')
-                       return SCE_P_STRING;
-               else
-                       return SCE_P_CHARACTER;
-       }
+static int skipWhitespace(int startPos,
+                           int endPos,
+                           Accessor &styler) {
+    for (int i = startPos; i < endPos; i++) {
+        if (!iswhitespace(styler[i])) {
+            return i;
+        }
+    }
+    return endPos;
+}
+    
+// This routine looks for false positives like
+// undef foo, <<
+// There aren't too many.
+//
+// iPrev points to the start of <<
+
+static bool sureThisIsHeredoc(int iPrev, 
+                              Accessor &styler,
+                              char *prevWord) {
+                    
+    // Not so fast, since Ruby's so dynamic.  Check the context
+    // to make sure we're OK.
+    int prevStyle;
+    int lineStart = styler.GetLine(iPrev);
+    int lineStartPosn = styler.LineStart(lineStart);
+    styler.Flush();
+
+    // Find the first word after some whitespace
+    int firstWordPosn = skipWhitespace(lineStartPosn, iPrev, styler);
+    if (firstWordPosn >= iPrev) {
+        // Have something like {^     <<}
+               //XXX Look at the first previous non-comment non-white line
+               // to establish the context.  Not too likely though.
+        return true;
+    } else {
+        switch (prevStyle = styler.StyleAt(firstWordPosn)) {
+        case SCE_RB_WORD:
+        case SCE_RB_WORD_DEMOTED:
+        case SCE_RB_IDENTIFIER:
+            break;
+        default:
+            return true;
+        }
+    }
+    int firstWordEndPosn = firstWordPosn;
+    char *dst = prevWord;
+    for (;;) {
+        if (firstWordEndPosn >= iPrev ||
+            styler.StyleAt(firstWordEndPosn) != prevStyle) {
+            *dst = 0;
+            break;
+        }
+        *dst++ = styler[firstWordEndPosn];
+        firstWordEndPosn += 1;
+    }
+    //XXX Write a style-aware thing to regex scintilla buffer objects
+    if (!strcmp(prevWord, "undef")
+        || !strcmp(prevWord, "def")
+        || !strcmp(prevWord, "alias")) {
+        // These keywords are what we were looking for
+        return false;
+    }
+    return true;
+}
+
+// Routine that saves us from allocating a buffer for the here-doc target
+// targetEndPos points one past the end of the current target
+static bool haveTargetMatch(int currPos,
+                            int lengthDoc,
+                            int targetStartPos,
+                            int targetEndPos,
+                            Accessor &styler) {
+    if (lengthDoc - currPos < targetEndPos - targetStartPos) {
+        return false;
+    }
+    int i, j;
+    for (i = targetStartPos, j = currPos;
+         i < targetEndPos && j < lengthDoc;
+         i++, j++) {
+        if (styler[i] != styler[j]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+// We need a check because the form
+// [identifier] <<[target]
+// is ambiguous.  The Ruby lexer/parser resolves it by
+// looking to see if [identifier] names a variable or a
+// function.  If it's the first, it's the start of a here-doc.
+// If it's a var, it's an operator.  This lexer doesn't
+// maintain a symbol table, so it looks ahead to see what's
+// going on, in cases where we have
+// ^[white-space]*[identifier([.|::]identifier)*][white-space]*<<[target]
+//
+// If there's no occurrence of [target] on a line, assume we don't.
+
+// return true == yes, we have no heredocs
+
+static bool sureThisIsNotHeredoc(int lt2StartPos,
+                                 Accessor &styler) {
+    int prevStyle;
+     // Use full document, not just part we're styling
+    int lengthDoc = styler.Length();
+    int lineStart = styler.GetLine(lt2StartPos);
+    int lineStartPosn = styler.LineStart(lineStart);
+    styler.Flush();
+    const bool definitely_not_a_here_doc = true;
+    const bool looks_like_a_here_doc = false;
+    
+    // Find the first word after some whitespace
+    int firstWordPosn = skipWhitespace(lineStartPosn, lt2StartPos, styler);
+    if (firstWordPosn >= lt2StartPos) {
+        return definitely_not_a_here_doc;
+    }
+    prevStyle = styler.StyleAt(firstWordPosn);
+    // If we have '<<' following a keyword, it's not a heredoc
+    if (prevStyle != SCE_RB_IDENTIFIER) {
+        return definitely_not_a_here_doc;
+    }
+    int newStyle = prevStyle;
+    // Some compilers incorrectly warn about uninit newStyle
+    for (firstWordPosn += 1; firstWordPosn <= lt2StartPos; firstWordPosn += 1) {
+        // Inner loop looks at the name
+        for (; firstWordPosn <= lt2StartPos; firstWordPosn += 1) {
+            newStyle = styler.StyleAt(firstWordPosn);
+            if (newStyle != prevStyle) {
+                break;
+            }
+        }
+        // Do we have '::' or '.'?
+        if (firstWordPosn < lt2StartPos && newStyle == SCE_RB_OPERATOR) {
+            char ch = styler[firstWordPosn];
+            if (ch == '.') {
+                // yes
+            } else if (ch == ':') {
+                if (styler.StyleAt(++firstWordPosn) != SCE_RB_OPERATOR) {
+                    return definitely_not_a_here_doc;
+                } else if (styler[firstWordPosn] != ':') {
+                    return definitely_not_a_here_doc;
+                }
+            } else {
+                break;
+            }
+        } else {
+            break;
+        }
+    }
+    // Skip next batch of white-space
+    firstWordPosn = skipWhitespace(firstWordPosn, lt2StartPos, styler);
+    if (firstWordPosn != lt2StartPos) {
+        // Have [[^ws[identifier]ws[*something_else*]ws<<
+        return definitely_not_a_here_doc;
+    }
+    // OK, now 'j' will point to the current spot moving ahead
+       int j = firstWordPosn + 1;
+    if (styler.StyleAt(j) != SCE_RB_OPERATOR || styler[j] != '<') {
+        // This shouldn't happen
+        return definitely_not_a_here_doc;
+    }
+    int nextLineStartPosn = styler.LineStart(lineStart + 1);
+    if (nextLineStartPosn >= lengthDoc) {
+        return definitely_not_a_here_doc;
+    }
+    j = skipWhitespace(j + 1, nextLineStartPosn, styler);
+    if (j >= lengthDoc) {
+        return definitely_not_a_here_doc;
+    }
+    bool allow_indent;
+    int target_start, target_end;
+    // From this point on no more styling, since we're looking ahead
+    if (styler[j] == '-') {
+        allow_indent = true;
+        j++;
+    } else {
+        allow_indent = false;
+    }
+
+    // Allow for quoted targets.
+    char target_quote = 0;
+    switch (styler[j]) {
+    case '\'':
+    case '"':
+    case '`':
+        target_quote = styler[j];
+        j += 1;
+    }
+    
+    if (isSafeAlnum(styler[j])) {
+        // Init target_end because some compilers think it won't
+        // be initialized by the time it's used
+        target_start = target_end = j;
+        j++;
+    } else {
+        return definitely_not_a_here_doc;
+    }
+    for (; j < lengthDoc; j++) {
+        if (!isSafeAlnum(styler[j])) {
+            if (target_quote && styler[j] != target_quote) {
+                // unquoted end
+                return definitely_not_a_here_doc;
+            }
+
+            // And for now make sure that it's a newline
+            // don't handle arbitrary expressions yet
+            
+            target_end = j;
+                       if (target_quote) {
+                               // Now we can move to the character after the string delimiter.
+                               j += 1;
+                       }
+            j = skipWhitespace(j, lengthDoc, styler);
+            if (j >= lengthDoc) {
+                return definitely_not_a_here_doc;
+            } else {
+                char ch = styler[j];
+                if (ch == '#' || isEOLChar(ch)) {
+                    // This is OK, so break and continue;
+                    break;
+                } else {
+                    return definitely_not_a_here_doc;
+                }
+            }
+        }
+    }
+
+    // Just look at the start of each line
+    int last_line = styler.GetLine(lengthDoc - 1);
+    // But don't go too far
+    if (last_line > lineStart + 50) {
+        last_line = lineStart + 50;
+    }
+    for (int line_num = lineStart + 1; line_num <= last_line; line_num++) {
+        if (allow_indent) {
+            j = skipWhitespace(styler.LineStart(line_num), lengthDoc, styler);
+        } else {
+            j = styler.LineStart(line_num);
+        }
+        // target_end is one past the end
+        if (haveTargetMatch(j, lengthDoc, target_start, target_end, styler)) {
+            // We got it
+            return looks_like_a_here_doc;
+        }
+    }
+    return definitely_not_a_here_doc;
+}
+
+//todo: if we aren't looking at a stdio character,
+// move to the start of the first line that is not in a 
+// multi-line construct
+
+static void synchronizeDocStart(unsigned int& startPos,
+                                int &length,
+                                int &initStyle,
+                                Accessor &styler,
+                                bool skipWhiteSpace=false) {
+
+    styler.Flush();
+    int style = actual_style(styler.StyleAt(startPos));
+    switch (style) {
+        case SCE_RB_STDIN:
+        case SCE_RB_STDOUT:
+        case SCE_RB_STDERR:
+            // Don't do anything else with these.
+            return;
+    }
+    
+    int pos = startPos;
+    // Quick way to characterize each line
+    int lineStart;
+    for (lineStart = styler.GetLine(pos); lineStart > 0; lineStart--) {
+        // Now look at the style before the previous line's EOL
+        pos = styler.LineStart(lineStart) - 1;
+        if (pos <= 10) {
+            lineStart = 0;
+            break;
+        }
+        char ch = styler.SafeGetCharAt(pos);
+        char chPrev = styler.SafeGetCharAt(pos - 1);
+        if (ch == '\n' && chPrev == '\r') {
+            pos--;
+        }
+        if (styler.SafeGetCharAt(pos - 1) == '\\') {
+            // Continuation line -- keep going
+        } else if (actual_style(styler.StyleAt(pos)) != SCE_RB_DEFAULT) {
+            // Part of multi-line construct -- keep going
+        } else if (currLineContainsHereDelims(pos, styler)) {
+            // Keep going, with pos and length now pointing
+            // at the end of the here-doc delimiter
+        } else if (skipWhiteSpace && isEmptyLine(pos, styler)) {
+            // Keep going
+        } else {
+            break;
+        }
+    }
+    pos = styler.LineStart(lineStart);
+    length += (startPos - pos);
+    startPos = pos;
+    initStyle = SCE_RB_DEFAULT;
 }
 
 static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle,
                                                   WordList *keywordlists[], Accessor &styler) {
 
-       int lengthDoc = startPos + length;
+       // Lexer for Ruby often has to backtrack to start of current style to determine
+       // which characters are being used as quotes, how deeply nested is the
+       // start position and what the termination string is for here documents
+    
+       WordList &keywords = *keywordlists[0];
 
-       // Backtrack to previous line in case need to fix its tab whinging
-       if (startPos > 0) {
-               int lineCurrent = styler.GetLine(startPos);
-               if (lineCurrent > 0) {
-                       startPos = styler.LineStart(lineCurrent-1);
-                       if (startPos == 0)
-                               initStyle = SCE_P_DEFAULT;
-                       else
-                               initStyle = styler.StyleAt(startPos-1);
+       class HereDocCls {
+       public:
+               int State;
+        // States
+        // 0: '<<' encountered
+               // 1: collect the delimiter
+        // 1b: text between the end of the delimiter and the EOL
+               // 2: here doc text (lines after the delimiter)
+               char Quote;             // the char after '<<'
+               bool Quoted;            // true if Quote in ('\'','"','`')
+               int DelimiterLength;    // strlen(Delimiter)
+               char Delimiter[256];    // the Delimiter, limit of 256: from Perl
+        bool CanBeIndented;
+               HereDocCls() {
+                       State = 0;
+                       DelimiterLength = 0;
+                       Delimiter[0] = '\0';
+            CanBeIndented = false;
                }
-       }
+       };
+       HereDocCls HereDoc;     
 
-       // Ruby uses a different mask because bad indentation is marked by oring with 32
-       styler.StartAt(startPos, 127);
+       class QuoteCls {
+               public:
+               int  Count;
+               char Up;
+               char Down;
+               QuoteCls() {
+                       this->New();
+               }
+               void New() {
+                       Count = 0;
+                       Up    = '\0';
+                       Down  = '\0';
+               }
+               void Open(char u) {
+                       Count++;
+                       Up    = u;
+                       Down  = opposite(Up);
+               }
+       };
+       QuoteCls Quote;
 
-       WordList &keywords = *keywordlists[0];
+    int numDots = 0;  // For numbers --
+                      // Don't start lexing in the middle of a num
+
+    synchronizeDocStart(startPos, length, initStyle, styler, // ref args
+                        false);
 
-       int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
-       char prevWord[200];
+       bool preferRE = true;
+    int state = initStyle;
+       int lengthDoc = startPos + length;
+
+       char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
        prevWord[0] = '\0';
        if (length == 0)
-               return ;
+               return;
 
-       int state = initStyle & 31;
-
-       int nextIndex = 0;
-       char chPrev = ' ';
-       char chPrev2 = ' ';
-       char chNext = styler[startPos];
+       char chPrev = styler.SafeGetCharAt(startPos - 1);
+       char chNext = styler.SafeGetCharAt(startPos);
+       // Ruby uses a different mask because bad indentation is marked by oring with 32
+       styler.StartAt(startPos, 127);
        styler.StartSegment(startPos);
-       bool atStartLine = true;
-       int spaceFlags = 0;
-       for (int i = startPos; i < lengthDoc; i++) {
-
-               if (atStartLine) {
-                       char chBad = static_cast<char>(64);
-                       char chGood = static_cast<char>(0);
-                       char chFlags = chGood;
-                       if (whingeLevel == 1) {
-                               chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood;
-                       } else if (whingeLevel == 2) {
-                               chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood;
-                       } else if (whingeLevel == 3) {
-                               chFlags = (spaceFlags & wsSpace) ? chBad : chGood;
-                       } else if (whingeLevel == 4) {
-                               chFlags = (spaceFlags & wsTab) ? chBad : chGood;
-                       }
-                       styler.SetFlags(chFlags, static_cast<char>(state));
-                       atStartLine = false;
-               }
 
+    static int q_states[] = {SCE_RB_STRING_Q,
+                             SCE_RB_STRING_QQ,
+                             SCE_RB_STRING_QR,
+                             SCE_RB_STRING_QW,
+                             SCE_RB_STRING_QW,
+                             SCE_RB_STRING_QX};
+    static const char* q_chars = "qQrwWx";
+    
+       for (int i = startPos; i < lengthDoc; i++) {
                char ch = chNext;
                chNext = styler.SafeGetCharAt(i + 1);
                char chNext2 = styler.SafeGetCharAt(i + 2);
 
-               if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {
-                       if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {
-                               // Perform colourisation of white space and triple quoted strings at end of each line to allow
-                               // tab marking to work inside white space and triple quoted strings
-                               styler.ColourTo(i, state);
-                       }
-                       atStartLine = true;
-               }
-
-               if (styler.IsLeadByte(ch)) {
-                       chNext = styler.SafeGetCharAt(i + 2);
+        if (styler.IsLeadByte(ch)) {
+                       chNext = chNext2;
                        chPrev = ' ';
-                       chPrev2 = ' ';
                        i += 1;
                        continue;
                }
+               
+        // skip on DOS/Windows
+        //No, don't, because some things will get tagged on,
+        // so we won't recognize keywords, for example
+#if 0
+               if (ch == '\r' && chNext == '\n') {
+               continue;
+        }
+#endif
+            
+        if (HereDoc.State == 1 && isEOLChar(ch)) {
+                       // Begin of here-doc (the line after the here-doc delimiter):
+                       HereDoc.State = 2;
+                       styler.ColourTo(i-1, state);
+            // Don't check for a missing quote, just jump into
+            // the here-doc state
+            state = SCE_RB_HERE_Q;
+        }
 
-               if (state == SCE_P_STRINGEOL) {
-                       if (ch != '\r' && ch != '\n') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_P_DEFAULT;
-                       }
-               }
-               if (state == SCE_P_DEFAULT) {
-                       if (IsRbWordStart(ch, chNext, chNext2)) {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_P_WORD;
+        // Regular transitions
+               if (state == SCE_RB_DEFAULT) {
+            if (isSafeDigit(ch)) {
+               styler.ColourTo(i - 1, state);
+                               state = SCE_RB_NUMBER;
+                numDots = 0;
+            } else if (isHighBitChar(ch) || iswordstart(ch)) {
+               styler.ColourTo(i - 1, state);
+                               state = SCE_RB_WORD;
                        } else if (ch == '#') {
                                styler.ColourTo(i - 1, state);
-                               state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
-                       } else if (ch == '=' && chNext == 'b') {
+                               state = SCE_RB_COMMENTLINE;
+                       } else if (ch == '=') {
                                // =begin indicates the start of a comment (doc) block
-                               if(styler.SafeGetCharAt(i + 2) == 'e' && styler.SafeGetCharAt(i + 3) == 'g' && styler.SafeGetCharAt(i + 4) == 'i' && styler.SafeGetCharAt(i + 5) == 'n') {
+                if (i == 0 || isEOLChar(chPrev)
+                    && chNext == 'b'
+                    && styler.SafeGetCharAt(i + 2) == 'e'
+                    && styler.SafeGetCharAt(i + 3) == 'g'
+                    && styler.SafeGetCharAt(i + 4) == 'i'
+                    && styler.SafeGetCharAt(i + 5) == 'n'
+                    && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6))) {
+                    styler.ColourTo(i - 1, state);
+                    state = SCE_RB_POD;
+                               } else {
                                        styler.ColourTo(i - 1, state);
-                                       state = SCE_P_TRIPLEDOUBLE; //SCE_C_COMMENT;
+                                       styler.ColourTo(i, SCE_RB_OPERATOR);
+                                       preferRE = true;
                                }
-                       }  else if (IsRbStringStart(ch, chNext, chNext2)) {
+                       } else if (ch == '"') {
                                styler.ColourTo(i - 1, state);
-                               state = GetRbStringState(styler, i, &nextIndex);
-                               if (nextIndex != i + 1) {
-                                       i = nextIndex - 1;
-                                       ch = ' ';
-                                       chPrev = ' ';
-                                       chNext = styler.SafeGetCharAt(i + 1);
-                               }
-                       } else if (isoperator(ch)) {
+                               state = SCE_RB_STRING;
+                               Quote.New();
+                               Quote.Open(ch);
+                       } else if (ch == '\'') {
+                styler.ColourTo(i - 1, state);
+                state = SCE_RB_CHARACTER;
+                Quote.New();
+                Quote.Open(ch);
+                       } else if (ch == '`') {
                                styler.ColourTo(i - 1, state);
-                               styler.ColourTo(i, SCE_P_OPERATOR);
-                       }
-                       } else if (state == SCE_P_WORD) {
-                       if (!iswordchar(ch)) {
-                               ClassifyWordRb(styler.GetStartSegment(), i - 1, keywords, styler, prevWord);
-                               state = SCE_P_DEFAULT;
-                               if (ch == '#') {
-                                       state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
-                               } else if (IsRbStringStart(ch, chNext, chNext2)) {
-                                       styler.ColourTo(i - 1, state);
-                                       state = GetRbStringState(styler, i, &nextIndex);
-                                       if (nextIndex != i + 1) {
-                                               i = nextIndex - 1;
-                                               ch = ' ';
-                                               chPrev = ' ';
+                               state = SCE_RB_BACKTICKS;
+                               Quote.New();
+                               Quote.Open(ch);
+                       } else if (ch == '@') {
+                // Instance or class var
+                               styler.ColourTo(i - 1, state);
+                if (chNext == '@') {
+                    state = SCE_RB_CLASS_VAR;
+                    advance_char(i, ch, chNext, chNext2); // pass by ref
+                } else {
+                    state = SCE_RB_INSTANCE_VAR;
+                }
+                       } else if (ch == '$') {
+                // Check for a builtin global
+                               styler.ColourTo(i - 1, state);
+                // Recognize it bit by bit
+                state = SCE_RB_GLOBAL;
+            } else if (ch == '/' && preferRE) {
+                // Ambigous operator
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_RB_REGEX;
+                Quote.New();
+                Quote.Open(ch);
+                       } else if (ch == '<' && chNext == '<' && chNext2 != '=') {
+
+                // Recognise the '<<' symbol - either a here document or a binary op
+                               styler.ColourTo(i - 1, state);
+                i++;
+                chNext = chNext2;
+                               styler.ColourTo(i, SCE_RB_OPERATOR);
+
+                if (! (strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) {
+                    // It's definitely not a here-doc,
+                    // based on Ruby's lexer/parser in the
+                    // heredoc_identifier routine.
+                    // Nothing else to do.
+                } else if (preferRE) {
+                    if (sureThisIsHeredoc(i - 1, styler, prevWord)) {
+                        state = SCE_RB_HERE_DELIM;
+                        HereDoc.State = 0;
+                    }
+                    // else leave it in default state
+                } else {
+                    if (sureThisIsNotHeredoc(i - 1, styler)) {
+                        // leave state as default
+                        // We don't have all the heuristics Perl has for indications
+                        // of a here-doc, because '<<' is overloadable and used
+                        // for so many other classes.
+                    } else {
+                        state = SCE_RB_HERE_DELIM;
+                        HereDoc.State = 0;
+                    }
+                }
+                preferRE = (state != SCE_RB_HERE_DELIM);
+            } else if (ch == ':') {
+                               styler.ColourTo(i - 1, state);
+                if (chNext == ':') {
+                    // Mark "::" as an operator, not symbol start
+                    styler.ColourTo(i + 1, SCE_RB_OPERATOR);
+                    advance_char(i, ch, chNext, chNext2); // pass by ref
+                    state = SCE_RB_DEFAULT;
+                                       preferRE = false;
+                } else if (isSafeWordcharOrHigh(chNext)) {
+                                       state = SCE_RB_SYMBOL;
+                } else if (strchr("[*!~+-*/%=<>&^|", chNext)) {
+                    // Do the operator analysis in-line, looking ahead
+                    // Based on the table in pickaxe 2nd ed., page 339
+                    bool doColoring = true;
+                    switch (chNext) {
+                    case '[':
+                        if (chNext2 == ']' ) {
+                            char ch_tmp = styler.SafeGetCharAt(i + 3);
+                            if (ch_tmp == '=') {
+                                i += 3;
+                                ch = ch_tmp;
+                                chNext = styler.SafeGetCharAt(i + 1);
+                            } else {
+                                i += 2;
+                                ch = chNext2;
+                                chNext = ch_tmp;
+                            }
+                        } else {
+                            doColoring = false;
+                        }
+                        break;
+
+                    case '*':
+                        if (chNext2 == '*') {
+                            i += 2;
+                            ch = chNext2;
+                            chNext = styler.SafeGetCharAt(i + 1);
+                        } else {
+                            advance_char(i, ch, chNext, chNext2);
+                        }
+                        break;
+
+                    case '!':
+                        if (chNext2 == '=' || chNext2 == '~') {
+                            i += 2;
+                            ch = chNext2;
+                            chNext = styler.SafeGetCharAt(i + 1);
+                        } else {
+                            advance_char(i, ch, chNext, chNext2);
+                        }
+                        break;
+
+                    case '<':
+                        if (chNext2 == '<') {
+                            i += 2;
+                            ch = chNext2;
+                            chNext = styler.SafeGetCharAt(i + 1);
+                        } else if (chNext2 == '=') {
+                            char ch_tmp = styler.SafeGetCharAt(i + 3);
+                            if (ch_tmp == '>') {  // <=> operator
+                                i += 3;
+                                ch = ch_tmp;
+                                chNext = styler.SafeGetCharAt(i + 1);
+                            } else {
+                                i += 2;
+                                ch = chNext2;
+                                chNext = ch_tmp;
+                            }
+                        } else {
+                            advance_char(i, ch, chNext, chNext2);
+                        }
+                        break;
+
+                    default:
+                        // Simple one-character operators
+                        advance_char(i, ch, chNext, chNext2);
+                        break;
+                    }
+                    if (doColoring) {
+                        styler.ColourTo(i, SCE_RB_SYMBOL);
+                        state = SCE_RB_DEFAULT;
+                    }
+                               } else if (!preferRE) {
+                                       // Don't color symbol strings (yet)
+                                       // Just color the ":" and color rest as string
+                                       styler.ColourTo(i, SCE_RB_SYMBOL);
+                                       state = SCE_RB_DEFAULT;
+                } else {
+                    styler.ColourTo(i, SCE_RB_OPERATOR);
+                    state = SCE_RB_DEFAULT;
+                    preferRE = true;
+                }
+            } else if (ch == '%') {
+                styler.ColourTo(i - 1, state);
+                bool have_string = false;
+                if (strchr(q_chars, chNext) && !isSafeWordcharOrHigh(chNext2)) {
+                    Quote.New();
+                    const char *hit = strchr(q_chars, chNext);
+                    if (hit != NULL) {
+                        state = q_states[hit - q_chars];
+                        Quote.Open(chNext2);
+                        i += 2;
+                        ch = chNext2;
                                                chNext = styler.SafeGetCharAt(i + 1);
+                        have_string = true;
+                    }
+                } else if (!isSafeWordcharOrHigh(chNext)) {
+                    // Ruby doesn't allow high bit chars here,
+                    // but the editor host might
+                    state = SCE_RB_STRING_QQ;
+                    Quote.Open(chNext);
+                    advance_char(i, ch, chNext, chNext2); // pass by ref
+                    have_string = true;
+                }
+                if (!have_string) {
+                    styler.ColourTo(i, SCE_RB_OPERATOR);
+                    // stay in default
+                    preferRE = true;
+                }
+            } else if (isoperator(ch) || ch == '.') {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_RB_OPERATOR);
+                // If we're ending an expression or block,
+                // assume it ends an object, and the ambivalent
+                // constructs are binary operators
+                //
+                // So if we don't have one of these chars,
+                // we aren't ending an object exp'n, and ops
+                // like : << / are unary operators.
+                
+                preferRE = (strchr(")}].", ch) == NULL);
+                // Stay in default state
+            } else if (isEOLChar(ch)) {
+                // Make sure it's a true line-end, with no backslash
+                if ((ch == '\r' || (ch == '\n' && chPrev != '\r'))
+                    && chPrev != '\\') {
+                    // Assume we've hit the end of the statement.
+                    preferRE = true;
+                }
+            }
+        } else if (state == SCE_RB_WORD) {
+            if (ch == '.' || !isSafeWordcharOrHigh(ch)) {
+                // Words include x? in all contexts,
+                // and <letters>= after either 'def' or a dot
+                // Move along until a complete word is on our left
+
+                // Default accessor treats '.' as word-chars,
+                // but we don't for now.
+                
+                if (ch == '='
+                    && isSafeWordcharOrHigh(chPrev)
+                    && (chNext == '('
+                        || strchr(" \t\n\r", chNext) != NULL)
+                    && (!strcmp(prevWord, "def")
+                        || followsDot(styler.GetStartSegment(), styler))) {
+                    // <name>= is a name only when being def'd -- Get it the next time
+                    // This means that <name>=<name> is always lexed as
+                    // <name>, (op, =), <name>
+                } else if ((ch == '?' || ch == '!')
+                           && isSafeWordcharOrHigh(chPrev)
+                           && !isSafeWordcharOrHigh(chNext)) {
+                    // <name>? is a name -- Get it the next time
+                    // But <name>?<name> is always lexed as
+                    // <name>, (op, ?), <name>
+                    // Same with <name>! to indicate a method that
+                    // modifies its target
+                } else if (isEOLChar(ch)
+                           && isMatch(styler, lengthDoc, i - 7, "__END__")) {
+                    styler.ColourTo(i, SCE_RB_DATASECTION);
+                    state = SCE_RB_DATASECTION;
+                    // No need to handle this state -- we'll just move to the end
+                    preferRE = false;
+                } else {
+                                       int wordStartPos = styler.GetStartSegment();
+                    int word_style = ClassifyWordRb(wordStartPos, i - 1, keywords, styler, prevWord);
+                    switch (word_style) {
+                        case SCE_RB_WORD:
+                            preferRE = RE_CanFollowKeyword(prevWord);
+                                                       break;
+                            
+                        case SCE_RB_WORD_DEMOTED:
+                            preferRE = true;
+                                                       break;
+                            
+                        case SCE_RB_IDENTIFIER:
+                            if (isMatch(styler, lengthDoc, wordStartPos, "print")) {
+                                preferRE = true;
+                            } else if (isEOLChar(ch)) {
+                                preferRE = true;
+                            } else {
+                                preferRE = false;
+                            }
+                                                       break;
+                        default:
+                            preferRE = false;
+                    }
+                    if (ch == '.') {
+                        // We might be redefining an operator-method
+                        preferRE = false;
+                    }
+                    // And if it's the first 
+                    redo_char(i, ch, chNext, chNext2, state); // pass by ref
+                }
+            }
+        } else if (state == SCE_RB_NUMBER) {
+            if (isSafeAlnumOrHigh(ch) || ch == '_') {
+                // Keep going
+            } else if (ch == '.' && ++numDots == 1) {
+                // Keep going
+            } else {
+                styler.ColourTo(i - 1, state);
+                redo_char(i, ch, chNext, chNext2, state); // pass by ref
+                preferRE = false;
+            }
+        } else if (state == SCE_RB_COMMENTLINE) {
+                       if (isEOLChar(ch)) {
+                styler.ColourTo(i - 1, state);
+                state = SCE_RB_DEFAULT;
+                // Use whatever setting we had going into the comment
+            }
+        } else if (state == SCE_RB_HERE_DELIM) {
+            // See the comment for SCE_RB_HERE_DELIM in LexPerl.cxx
+            // Slightly different: if we find an immediate '-',
+            // the target can appear indented.
+            
+                       if (HereDoc.State == 0) { // '<<' encountered
+                               HereDoc.State = 1;
+                HereDoc.DelimiterLength = 0;
+                if (ch == '-') {
+                    HereDoc.CanBeIndented = true;
+                    advance_char(i, ch, chNext, chNext2); // pass by ref
+                } else {
+                    HereDoc.CanBeIndented = false;
+                }
+                if (isEOLChar(ch)) {
+                    // Bail out of doing a here doc if there's no target
+                    state = SCE_RB_DEFAULT;
+                    preferRE = false;
+                } else {
+                    HereDoc.Quote = ch;
+                
+                    if (ch == '\'' || ch == '"' || ch == '`') {
+                        HereDoc.Quoted = true;
+                        HereDoc.Delimiter[0] = '\0';
+                    } else {
+                        HereDoc.Quoted = false;
+                        HereDoc.Delimiter[0] = ch;
+                        HereDoc.Delimiter[1] = '\0';
+                        HereDoc.DelimiterLength = 1;
+                    }
+                }
+                       } else if (HereDoc.State == 1) { // collect the delimiter
+                if (isEOLChar(ch)) {
+                    // End the quote now, and go back for more
+                    styler.ColourTo(i - 1, state);
+                    state = SCE_RB_DEFAULT;
+                    i--;
+                    chNext = ch;
+                    chNext2 = chNext;
+                    preferRE = false;
+                } else if (HereDoc.Quoted) {
+                                       if (ch == HereDoc.Quote) { // closing quote => end of delimiter
+                                               styler.ColourTo(i, state);
+                                               state = SCE_RB_DEFAULT;
+                        preferRE = false;
+                    } else {
+                                               if (ch == '\\' && !isEOLChar(chNext)) {
+                            advance_char(i, ch, chNext, chNext2);
+                                               }
+                                               HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
+                                               HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
+                    }
+                } else { // an unquoted here-doc delimiter
+                                       if (isSafeAlnumOrHigh(ch) || ch == '_') {
+                                               HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
+                                               HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
+                                       } else {
+                                               styler.ColourTo(i - 1, state);
+                        redo_char(i, ch, chNext, chNext2, state);
+                        preferRE = false;
                                        }
-                               } else if (isoperator(ch)) {
-                                       styler.ColourTo(i, SCE_P_OPERATOR);
-                               }
-                       }
-               } else {
-                       if (state == SCE_P_COMMENTLINE || state == SCE_P_COMMENTBLOCK) {
-                               if (ch == '\r' || ch == '\n') {
+                }
+                               if (HereDoc.DelimiterLength >= static_cast<int>(sizeof(HereDoc.Delimiter)) - 1) {
                                        styler.ColourTo(i - 1, state);
-                                       state = SCE_P_DEFAULT;
-                               }
-                       } else if (state == SCE_P_STRING) {
-                               if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
-                                       styler.ColourTo(i - 1, state);
-                                       state = SCE_P_STRINGEOL;
-                               } else if (ch == '\\') {
-                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
-                                               i++;
-                                               ch = chNext;
-                                               chNext = styler.SafeGetCharAt(i + 1);
-                                       }
-                               } else if (ch == '\"') {
-                                       styler.ColourTo(i, state);
-                                       state = SCE_P_DEFAULT;
+                                       state = SCE_RB_ERROR;
+                    preferRE = false;
                                }
-                       } else if (state == SCE_P_CHARACTER) {
-                               if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
-                                       styler.ColourTo(i - 1, state);
-                                       state = SCE_P_STRINGEOL;
-                               } else if (ch == '\\') {
-                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
-                                               i++;
+            }
+        } else if (state == SCE_RB_HERE_Q) {
+            // Not needed: HereDoc.State == 2
+            // Indentable here docs: look backwards
+            // Non-indentable: look forwards, like in Perl
+            //
+            // Why: so we can quickly resolve things like <<-" abc"
+
+            if (!HereDoc.CanBeIndented) {
+                if (isEOLChar(chPrev)
+                    && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) {
+                    styler.ColourTo(i - 1, state);
+                    i += HereDoc.DelimiterLength - 1;
+                    chNext = styler.SafeGetCharAt(i + 1);
+                    if (isEOLChar(chNext)) {
+                        styler.ColourTo(i, SCE_RB_HERE_DELIM);
+                        state = SCE_RB_DEFAULT;
+                        HereDoc.State = 0;
+                        preferRE = false;
+                    }
+                    // Otherwise we skipped through the here doc faster.
+                }
+            } else if (isEOLChar(chNext)
+                       && lookingAtHereDocDelim(styler,
+                                                i - HereDoc.DelimiterLength + 1,
+                                                lengthDoc,
+                                                HereDoc.Delimiter)) {
+                styler.ColourTo(i - 1 - HereDoc.DelimiterLength, state);
+                styler.ColourTo(i, SCE_RB_HERE_DELIM);
+                state = SCE_RB_DEFAULT;
+                preferRE = false;
+                HereDoc.State = 0;
+            }
+        } else if (state == SCE_RB_CLASS_VAR
+                   || state == SCE_RB_INSTANCE_VAR
+                   || state == SCE_RB_SYMBOL) {
+            if (!isSafeWordcharOrHigh(ch)) {
+                styler.ColourTo(i - 1, state);
+                redo_char(i, ch, chNext, chNext2, state); // pass by ref
+                preferRE = false;
+            }
+        } else if (state == SCE_RB_GLOBAL) {
+            if (!isSafeWordcharOrHigh(ch)) {
+                // handle special globals here as well
+                if (chPrev == '$') {
+                    if (ch == '-') {
+                        // Include the next char, like $-a
+                        advance_char(i, ch, chNext, chNext2);
+                    }
+                    styler.ColourTo(i, state);
+                    state = SCE_RB_DEFAULT;
+                } else {
+                    styler.ColourTo(i - 1, state);
+                    redo_char(i, ch, chNext, chNext2, state); // pass by ref
+                }
+                preferRE = false;
+            }
+        } else if (state == SCE_RB_POD) {
+            // PODs end with ^=end\s, -- any whitespace can follow =end
+            if (strchr(" \t\n\r", ch) != NULL
+                && i > 5
+                && isEOLChar(styler[i - 5])
+                && isMatch(styler, lengthDoc, i - 4, "=end")) {
+                styler.ColourTo(i - 1, state);
+                state = SCE_RB_DEFAULT;
+                preferRE = false;
+            }
+        } else if (state == SCE_RB_REGEX || state == SCE_RB_STRING_QR) {
+            if (ch == '\\' && Quote.Up != '\\') {
+                // Skip one
+                advance_char(i, ch, chNext, chNext2);
+            } else if (ch == Quote.Down) {
+                Quote.Count--;
+                if (Quote.Count == 0) {
+                    // Include the options
+                    while (isSafeAlpha(chNext)) {
+                        i++;
                                                ch = chNext;
-                                               chNext = styler.SafeGetCharAt(i + 1);
-                                       }
-                               } else if (ch == '\'') {
-                                       styler.ColourTo(i, state);
-                                       state = SCE_P_DEFAULT;
-                               }
-                       } else if (state == SCE_P_TRIPLE) {
-                               if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
-                                       styler.ColourTo(i, state);
-                                       state = SCE_P_DEFAULT;
-                               }
-                       } else if (state == SCE_P_TRIPLEDOUBLE) {
-                               // =end terminates the comment block
-                               if (ch == 'd' && chPrev == 'n' && chPrev2 == 'e') {
-                                       if  (styler.SafeGetCharAt(i - 3) == '=') {
-                                               styler.ColourTo(i, state);
-                                               state = SCE_P_DEFAULT;
-                                       }
-                               }
+                        chNext = styler.SafeGetCharAt(i + 1);
+                    }
+                    styler.ColourTo(i, state);
+                    state = SCE_RB_DEFAULT;
+                    preferRE = false;
+                }
+            } else if (ch == Quote.Up) {
+                // Only if close quoter != open quoter
+                Quote.Count++;
+                
+            } else if (ch == '#' ) {
+                //todo: distinguish comments from pound chars
+                // for now, handle as comment
+                styler.ColourTo(i - 1, state);
+                bool inEscape = false;
+                while (++i < lengthDoc) {
+                    ch = styler.SafeGetCharAt(i);
+                    if (ch == '\\') {
+                        inEscape = true;
+                    } else if (isEOLChar(ch)) {
+                        // Comment inside a regex
+                        styler.ColourTo(i - 1, SCE_RB_COMMENTLINE);
+                        break;
+                    } else if (inEscape) {
+                        inEscape = false;  // don't look at char
+                    } else if (ch == Quote.Down) {
+                        // Have the regular handler deal with this
+                        // to get trailing modifiers.
+                        i--;
+                        ch = styler[i];
+                                               break;
+                    }
+                }
+                chNext = styler.SafeGetCharAt(i + 1);
+                chNext2 = styler.SafeGetCharAt(i + 2);
+            }
+        // Quotes of all kinds...
+        } else if (state == SCE_RB_STRING_Q || state == SCE_RB_STRING_QQ || 
+                   state == SCE_RB_STRING_QX || state == SCE_RB_STRING_QW ||
+                   state == SCE_RB_STRING || state == SCE_RB_CHARACTER ||
+                   state == SCE_RB_BACKTICKS) {
+            if (!Quote.Down && !isspacechar(ch)) {
+                Quote.Open(ch);
+            } else if (ch == '\\' && Quote.Up != '\\') {
+                //Riddle me this: Is it safe to skip *every* escaped char?
+                advance_char(i, ch, chNext, chNext2);
+            } else if (ch == Quote.Down) {
+                Quote.Count--;
+                if (Quote.Count == 0) {
+                    styler.ColourTo(i, state);
+                    state = SCE_RB_DEFAULT;
+                    preferRE = false;
+                }
+            } else if (ch == Quote.Up) {
+                Quote.Count++;
+            }
+        }
+            
+        if (state == SCE_RB_ERROR) {
+            break;
+        }
+        chPrev = ch;
+    }
+    if (state == SCE_RB_WORD) {
+        // We've ended on a word, possibly at EOF, and need to
+        // classify it.
+        (void) ClassifyWordRb(styler.GetStartSegment(), lengthDoc - 1, keywords, styler, prevWord);
+    } else {
+        styler.ColourTo(lengthDoc - 1, state);
+    }
+}
+
+// Helper functions for folding, disambiguation keywords
+// Assert that there are no high-bit chars 
+
+static void getPrevWord(int pos,
+                        char *prevWord,
+                        Accessor &styler,
+                        int word_state)
+{
+    int i;
+    styler.Flush();
+    for (i = pos - 1; i > 0; i--) {
+        if (actual_style(styler.StyleAt(i)) != word_state) {
+            i++;
+            break;
+        }
+    }
+    if (i < pos - MAX_KEYWORD_LENGTH) // overflow
+        i = pos - MAX_KEYWORD_LENGTH;
+    char *dst = prevWord;
+    for (; i <= pos; i++) {
+        *dst++ = styler[i];
+    }
+       *dst = 0;
+}
+
+static bool keywordIsAmbiguous(const char *prevWord)
+{
+    // Order from most likely used to least likely
+    // Lots of ways to do a loop in Ruby besides 'while/until'
+    if (!strcmp(prevWord, "if")
+        || !strcmp(prevWord, "do")
+        || !strcmp(prevWord, "while")
+        || !strcmp(prevWord, "unless")
+        || !strcmp(prevWord, "until")) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+// Demote keywords in the following conditions:
+// if, while, unless, until modify a statement
+// do after a while or until, as a noise word (like then after if) 
+
+static bool keywordIsModifier(const char *word,
+                              int pos,
+                              Accessor &styler)
+{
+    if (word[0] == 'd' && word[1] == 'o' && !word[2]) {
+        return keywordDoStartsLoop(pos, styler);
+    }
+    char ch;
+    int style = SCE_RB_DEFAULT;
+       int lineStart = styler.GetLine(pos);
+    int lineStartPosn = styler.LineStart(lineStart);
+    styler.Flush();
+    while (--pos >= lineStartPosn) {
+        style = actual_style(styler.StyleAt(pos));
+               if (style == SCE_RB_DEFAULT) {
+                       if (iswhitespace(ch = styler[pos])) {
+                               //continue
+                       } else if (ch == '\r' || ch == '\n') {
+                               // Scintilla's LineStart() and GetLine() routines aren't
+                               // platform-independent, so if we have text prepared with
+                               // a different system we can't rely on it.
+                               return false;
                        }
+               } else {
+            break;
                }
-               chPrev2 = chPrev;
-               chPrev = ch;
-       }
-       if (state == SCE_P_WORD) {
-               ClassifyWordRb(styler.GetStartSegment(), lengthDoc-1, keywords, styler, prevWord);
-       } else {
-               styler.ColourTo(lengthDoc-1, state);
-       }
+    }
+    if (pos < lineStartPosn) {
+        return false; //XXX not quite right if the prev line is a continuation
+    }
+    // First things where the action is unambiguous
+    switch (style) {
+        case SCE_RB_DEFAULT:
+        case SCE_RB_COMMENTLINE:
+        case SCE_RB_POD:
+        case SCE_RB_CLASSNAME:
+        case SCE_RB_DEFNAME:
+        case SCE_RB_MODULE_NAME:
+            return false;
+        case SCE_RB_OPERATOR:
+            break;
+        case SCE_RB_WORD:
+            // Watch out for uses of 'else if'
+            //XXX: Make a list of other keywords where 'if' isn't a modifier
+            //     and can appear legitimately
+            // Formulate this to avoid warnings from most compilers
+            if (strcmp(word, "if") == 0) {
+                char prevWord[MAX_KEYWORD_LENGTH + 1];
+                getPrevWord(pos, prevWord, styler, SCE_RB_WORD);
+                return strcmp(prevWord, "else") != 0;
+            }
+            return true;
+        default:
+            return true;
+    }
+    // Assume that if the keyword follows an operator,
+    // usually it's a block assignment, like
+    // a << if x then y else z
+    
+    ch = styler[pos];
+    switch (ch) {
+        case ')':
+        case ']':
+        case '}':
+            return true;
+        default:
+            return false;
+    }
 }
 
-static void FoldRbDoc(unsigned int startPos, int length, int initStyle,
-                                                  WordList *[], Accessor &styler) {
-       int lengthDoc = startPos + length;
+#define WHILE_BACKWARDS "elihw"
+#define UNTIL_BACKWARDS "litnu"
+
+// Nothing fancy -- look to see if we follow a while/until somewhere
+// on the current line
+
+static bool keywordDoStartsLoop(int pos,
+                                Accessor &styler)
+{
+    char ch;
+    int style;
+       int lineStart = styler.GetLine(pos);
+    int lineStartPosn = styler.LineStart(lineStart);
+    styler.Flush();
+    while (--pos >= lineStartPosn) {
+        style = actual_style(styler.StyleAt(pos));
+               if (style == SCE_RB_DEFAULT) {
+                       if ((ch = styler[pos]) == '\r' || ch == '\n') {
+                               // Scintilla's LineStart() and GetLine() routines aren't
+                               // platform-independent, so if we have text prepared with
+                               // a different system we can't rely on it.
+                               return false;
+                       }
+               } else if (style == SCE_RB_WORD) {
+            // Check for while or until, but write the word in backwards
+            char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
+            char *dst = prevWord;
+            int wordLen = 0;
+            int start_word;
+            for (start_word = pos;
+                 start_word >= lineStartPosn && actual_style(styler.StyleAt(start_word)) == SCE_RB_WORD;
+                 start_word--) {
+                if (++wordLen < MAX_KEYWORD_LENGTH) {
+                    *dst++ = styler[start_word];
+                }
+            }
+            *dst = 0;
+            // Did we see our keyword?
+            if (!strcmp(prevWord, WHILE_BACKWARDS)
+                || !strcmp(prevWord, UNTIL_BACKWARDS)) {
+                return true;
+            }
+            // We can move pos to the beginning of the keyword, and then
+            // accept another decrement, as we can never have two contiguous
+            // keywords:
+            // word1 word2
+            //           ^
+            //        <-  move to start_word
+            //      ^
+            //      <- loop decrement
+            //     ^  # pointing to end of word1 is fine
+            pos = start_word;
+        }
+    }
+    return false;
+}
+
+/*
+ *  Folding Ruby
+ * 
+ *  The language is quite complex to analyze without a full parse.
+ *  For example, this line shouldn't affect fold level:
+ * 
+ *   print "hello" if feeling_friendly?
+ * 
+ *  Neither should this:
+ * 
+ *   print "hello" \
+ *      if feeling_friendly?
+ * 
+ * 
+ *  But this should:
+ * 
+ *   if feeling_friendly?  #++
+ *     print "hello" \
+ *     print "goodbye"
+ *   end                   #--
+ * 
+ *  So we cheat, by actually looking at the existing indentation
+ *  levels for each line, and just echoing it back.  Like Python.
+ *  Then if we get better at it, we'll take braces into consideration,
+ *  which always affect folding levels.
+
+ *  How the keywords should work:
+ *  No effect:
+ *  __FILE__ __LINE__ BEGIN END alias and 
+ *  defined? false in nil not or self super then
+ *  true undef
+
+ *  Always increment:
+ *  begin  class def do for module when {
+ * 
+ *  Always decrement:
+ *  end }
+ * 
+ *  Increment if these start a statement
+ *  if unless until while -- do nothing if they're modifiers
 
-       // Backtrack to previous line in case need to fix its fold status
+ *  These end a block if there's no modifier, but don't bother
+ *  break next redo retry return yield
+ * 
+ *  These temporarily de-indent, but re-indent
+ *  case else elsif ensure rescue
+ * 
+ *  This means that the folder reflects indentation rather
+ *  than setting it.  The language-service updates indentation
+ *  when users type return and finishes entering de-denters.
+ * 
+ *  Later offer to fold POD, here-docs, strings, and blocks of comments
+ */
+
+static void FoldRbDoc(unsigned int startPos, int length, int initStyle,
+                      WordList *[], Accessor &styler) {
+       const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+       bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+    
+    synchronizeDocStart(startPos, length, initStyle, styler, // ref args
+                        false);
+       unsigned int endPos = startPos + length;
+       int visibleChars = 0;
        int lineCurrent = styler.GetLine(startPos);
-       if (startPos > 0) {
-               if (lineCurrent > 0) {
-                       lineCurrent--;
-                       startPos = styler.LineStart(lineCurrent);
-                       if (startPos == 0)
-                               initStyle = SCE_P_DEFAULT;
-                       else
-                               initStyle = styler.StyleAt(startPos-1);
-               }
-       }
-       int state = initStyle & 31;
-       int spaceFlags = 0;
-       int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsRbComment);
-       if ((state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE))
-               indentCurrent |= SC_FOLDLEVELWHITEFLAG;
+       int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent)
+                                         & SC_FOLDLEVELNUMBERMASK
+                                         & ~SC_FOLDLEVELBASE);
+       int levelCurrent = levelPrev;
        char chNext = styler[startPos];
-       for (int i = startPos; i < lengthDoc; i++) {
+       int styleNext = styler.StyleAt(startPos);
+       int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1);
+    bool buffer_ends_with_eol = false;
+       for (unsigned int i = startPos; i < endPos; i++) {
                char ch = chNext;
                chNext = styler.SafeGetCharAt(i + 1);
-               int style = styler.StyleAt(i) & 31;
-
-               if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {
-                       int lev = indentCurrent;
-                       int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsRbComment);
-                       if ((style == SCE_P_TRIPLE) || (style== SCE_P_TRIPLEDOUBLE))
-                               indentNext |= SC_FOLDLEVELWHITEFLAG;
-                       if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
-                               // Only non whitespace lines can be headers
-                               if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
-                                       lev |= SC_FOLDLEVELHEADERFLAG;
-                               } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
-                                       // Line after is blank so check the next - maybe should continue further?
-                                       int spaceFlags2 = 0;
-                                       int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsRbComment);
-                                       if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
-                                               lev |= SC_FOLDLEVELHEADERFLAG;
-                                       }
+               int style = styleNext;
+               styleNext = styler.StyleAt(i + 1);
+               bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+        if (style == SCE_RB_COMMENTLINE) {
+            if (foldComment && stylePrev != SCE_RB_COMMENTLINE) {
+                if (chNext == '{') {
+                                       levelCurrent++;
+                               } else if (chNext == '}') {
+                                       levelCurrent--;
                                }
+            }
+        } else if (style == SCE_RB_OPERATOR) {
+                       if (strchr("[{(", ch)) {
+                               levelCurrent++;
+                       } else if (strchr(")}]", ch)) {
+                // Don't decrement below 0
+                if (levelCurrent > 0)
+                    levelCurrent--;
                        }
-                       indentCurrent = indentNext;
-                       styler.SetLevel(lineCurrent, lev);
+        } else if (style == SCE_RB_WORD && styleNext != SCE_RB_WORD) {
+            // Look at the keyword on the left and decide what to do
+            char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
+            prevWord[0] = 0;
+            getPrevWord(i, prevWord, styler, SCE_RB_WORD);
+            if (!strcmp(prevWord, "end")) {
+                // Don't decrement below 0
+                if (levelCurrent > 0)
+                    levelCurrent--;
+            } else if (   !strcmp(prevWord, "if")
+                       || !strcmp(prevWord, "def")
+                       || !strcmp(prevWord, "class")
+                       || !strcmp(prevWord, "module")
+                       || !strcmp(prevWord, "begin")
+                       || !strcmp(prevWord, "case")
+                       || !strcmp(prevWord, "do")
+                       || !strcmp(prevWord, "while")
+                       || !strcmp(prevWord, "unless")
+                       || !strcmp(prevWord, "until")
+                       || !strcmp(prevWord, "for")
+                          ) {
+                               levelCurrent++;
+            }
+        }
+               if (atEOL) {
+                       int lev = levelPrev;
+                       if (visibleChars == 0 && foldCompact)
+                               lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visibleChars > 0))
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+            styler.SetLevel(lineCurrent, lev|SC_FOLDLEVELBASE);
                        lineCurrent++;
-               }
-       }
+                       levelPrev = levelCurrent;
+                       visibleChars = 0;
+            buffer_ends_with_eol = true;
+               } else if (!isspacechar(ch)) {
+                       visibleChars++;
+            buffer_ends_with_eol = false;
+        }
+    }
+       // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+    if (!buffer_ends_with_eol) {
+        lineCurrent++;
+        int new_lev = levelCurrent;
+        if (visibleChars == 0 && foldCompact)
+            new_lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visibleChars > 0))
+                               new_lev |= SC_FOLDLEVELHEADERFLAG;
+            levelCurrent = new_lev;
+    }
+       styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE);
 }
 
 static const char * const rubyWordListDesc[] = {
index 8383eefb02efc556081b55b734ab2e521ad6aece..75a958cb60009664592d9871cd57feb311d59e24 100644 (file)
@@ -1,8 +1,8 @@
 // Scintilla source code edit control
 /** @file LexSQL.cxx
- ** Lexer for SQL.
+ ** Lexer for SQL, including PL/SQL and SQL*Plus.
  **/
-// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
 
 #include "PropSet.h"
 #include "Accessor.h"
+#include "StyleContext.h"
 #include "KeyWords.h"
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-static void classifyWordSQL(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
-       char s[100];
-       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
-       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
-               s[i] = static_cast<char>(tolower(styler[start + i]));
-               s[i + 1] = '\0';
-       }
-       char chAttr = SCE_C_IDENTIFIER;
-       if (wordIsNumber)
-               chAttr = SCE_C_NUMBER;
-       else {
-               if (keywords.InList(s))
-                       chAttr = SCE_C_WORD;
-       }
-       styler.ColourTo(end, chAttr);
+static inline bool IsAWordChar(int ch) {
+       return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
+}
+
+static inline bool IsAWordStart(int ch) {
+       return (ch < 0x80) && (isalpha(ch) || ch == '_');
 }
 
-static void ColouriseSQLDoc(unsigned int startPos, int length,
-                            int initStyle, WordList *keywordlists[], Accessor &styler) {
+static inline bool IsADoxygenChar(int ch) {
+       return (islower(ch) || ch == '$' || ch == '@' ||
+               ch == '\\' || ch == '&' || ch == '<' ||
+               ch == '>' || ch == '#' || ch == '{' ||
+               ch == '}' || ch == '[' || ch == ']');
+}
+
+static inline bool IsANumberChar(int ch) {
+       // Not exactly following number definition (several dots are seen as OK, etc.)
+       // but probably enough in most cases.
+       return (ch < 0x80) &&
+               (isdigit(ch) || toupper(ch) == 'E' ||
+             ch == '.' || ch == '-' || ch == '+');
+}
 
-       WordList &keywords = *keywordlists[0];
 
-       styler.StartAt(startPos);
+static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+                            Accessor &styler) {
+
+       WordList &keywords1 = *keywordlists[0];
+       WordList &keywords2 = *keywordlists[1];
+       WordList &kw_pldoc = *keywordlists[2];
+       WordList &kw_sqlplus = *keywordlists[3];
+       WordList &kw_user1 = *keywordlists[4];
+       WordList &kw_user2 = *keywordlists[5];
+       WordList &kw_user3 = *keywordlists[6];
+       WordList &kw_user4 = *keywordlists[7];
+
+       StyleContext sc(startPos, length, initStyle, styler);
 
-       bool fold = styler.GetPropertyInt("fold") != 0;
        bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0;
+       bool sqlBackticksIdentifier = styler.GetPropertyInt("lexer.sql.backticks.identifier", 0) != 0;
+       int styleBeforeDCKeyword = SCE_C_DEFAULT;
+       bool fold = styler.GetPropertyInt("fold") != 0;
        int lineCurrent = styler.GetLine(startPos);
-       int spaceFlags = 0;
-
-       int state = initStyle;
-       char chPrev = ' ';
-       char chNext = styler[startPos];
-       styler.StartSegment(startPos);
-       unsigned int lengthDoc = startPos + length;
-       for (unsigned int i = startPos; i < lengthDoc; i++) {
-               char ch = chNext;
-               chNext = styler.SafeGetCharAt(i + 1);
 
-               if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+       for (; sc.More(); sc.Forward()) {
+               // Fold based on indentation
+               if (sc.atLineStart) {
+                       int spaceFlags = 0;
                        int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
-                       int lev = indentCurrent;
+                       int level = indentCurrent;
                        if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
                                // Only non whitespace lines can be headers
                                int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
                                if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
-                                       lev |= SC_FOLDLEVELHEADERFLAG;
+                                       level |= SC_FOLDLEVELHEADERFLAG;
                                }
                        }
                        if (fold) {
-                               styler.SetLevel(lineCurrent, lev);
+                               styler.SetLevel(lineCurrent, level);
                        }
                }
 
-               if (styler.IsLeadByte(ch)) {
-                       chNext = styler.SafeGetCharAt(i + 2);
-                       chPrev = ' ';
-                       i += 1;
-                       continue;
+               // Determine if the current state should terminate.
+               switch (sc.state) {
+               case SCE_SQL_OPERATOR:
+                       sc.SetState(SCE_SQL_DEFAULT);
+                       break;
+               case SCE_SQL_NUMBER:
+                       // We stop the number definition on non-numerical non-dot non-eE non-sign char
+                       if (!IsANumberChar(sc.ch)) {
+                               sc.SetState(SCE_SQL_DEFAULT);
+                       }
+                       break;
+               case SCE_SQL_IDENTIFIER:
+                       if (!IsAWordChar(sc.ch)) {
+                               int nextState = SCE_SQL_DEFAULT;
+                               char s[1000];
+                               sc.GetCurrentLowered(s, sizeof(s));
+                               if (keywords1.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_WORD);
+                               } else if (keywords2.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_WORD2);
+                               } else if (kw_sqlplus.InListAbbreviated(s, '~')) {
+                                       sc.ChangeState(SCE_SQL_SQLPLUS);
+                                       if (strncmp(s, "rem", 3) == 0) {
+                                               nextState = SCE_SQL_SQLPLUS_COMMENT;
+                                       } else if (strncmp(s, "pro", 3) == 0) {
+                                               nextState = SCE_SQL_SQLPLUS_PROMPT;
+                                       }
+                               } else if (kw_user1.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_USER1);
+                               } else if (kw_user2.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_USER2);
+                               } else if (kw_user3.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_USER3);
+                               } else if (kw_user4.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_USER4);
+                               }
+                               sc.SetState(nextState);
+                       }
+                       break;
+               case SCE_SQL_QUOTEDIDENTIFIER:
+                       if (sc.ch == 0x60) {
+                               if (sc.chNext == 0x60) {
+                                       sc.Forward();   // Ignore it
+                               } else {
+                                       sc.ForwardSetState(SCE_SQL_DEFAULT);
+                               }
+                       }
+                       break;
+               case SCE_SQL_COMMENT:
+                       if (sc.Match('*', '/')) {
+                               sc.Forward();
+                               sc.ForwardSetState(SCE_SQL_DEFAULT);
+                       }
+                       break;
+               case SCE_SQL_COMMENTDOC:
+                       if (sc.Match('*', '/')) {
+                               sc.Forward();
+                               sc.ForwardSetState(SCE_SQL_DEFAULT);
+                       } else if (sc.ch == '@' || sc.ch == '\\') { // Doxygen support
+                               // Verify that we have the conditions to mark a comment-doc-keyword
+                               if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
+                                       styleBeforeDCKeyword = SCE_SQL_COMMENTDOC;
+                                       sc.SetState(SCE_SQL_COMMENTDOCKEYWORD);
+                               }
+                       }
+                       break;
+               case SCE_SQL_COMMENTLINE:
+               case SCE_SQL_COMMENTLINEDOC:
+               case SCE_SQL_SQLPLUS_COMMENT:
+               case SCE_SQL_SQLPLUS_PROMPT:
+                       if (sc.atLineStart) {
+                               sc.SetState(SCE_SQL_DEFAULT);
+                       }
+                       break;
+               case SCE_SQL_COMMENTDOCKEYWORD:
+                       if ((styleBeforeDCKeyword == SCE_SQL_COMMENTDOC) && sc.Match('*', '/')) {
+                               sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR);
+                               sc.Forward();
+                               sc.ForwardSetState(SCE_SQL_DEFAULT);
+                       } else if (!IsADoxygenChar(sc.ch)) {
+                               char s[100];
+                               sc.GetCurrentLowered(s, sizeof(s));
+                               if (!isspace(sc.ch) || !kw_pldoc.InList(s + 1)) {
+                                       sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR);
+                               }
+                               sc.SetState(styleBeforeDCKeyword);
+                       }
+                       break;
+               case SCE_SQL_CHARACTER:
+                       if (sqlBackslashEscapes && sc.ch == '\\') {
+                               sc.Forward();
+                       } else if (sc.ch == '\'') {
+                               if (sc.chNext == '\"') {
+                                       sc.Forward();
+                               } else {
+                                       sc.ForwardSetState(SCE_SQL_DEFAULT);
+                               }
+                       }
+                       break;
+               case SCE_SQL_STRING:
+                       if (sc.ch == '\\') {
+                               // Escape sequence
+                               sc.Forward();
+                       } else if (sc.ch == '\"') {
+                               if (sc.chNext == '\"') {
+                                       sc.Forward();
+                               } else {
+                                       sc.ForwardSetState(SCE_SQL_DEFAULT);
+                               }
+                       }
+                       break;
                }
 
-               if (state == SCE_C_DEFAULT) {
-                       if (iswordstart(ch)) {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_WORD;
-                       } else if (ch == '/' && chNext == '*') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_COMMENT;
-                       } else if (ch == '-' && chNext == '-') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_COMMENTLINE;
-                       } else if (ch == '#') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_COMMENTLINEDOC;
-                       } else if (ch == '\'') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_CHARACTER;
-                       } else if (ch == '"') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_STRING;
-                       } else if (isoperator(ch)) {
-                               styler.ColourTo(i - 1, state);
-                               styler.ColourTo(i, SCE_C_OPERATOR);
-                       }
-               } else if (state == SCE_C_WORD) {
-                       if (!iswordchar(ch)) {
-                               classifyWordSQL(styler.GetStartSegment(), i - 1, keywords, styler);
-                               state = SCE_C_DEFAULT;
-                               if (ch == '/' && chNext == '*') {
-                                       state = SCE_C_COMMENT;
-                               } else if (ch == '-' && chNext == '-') {
-                                       state = SCE_C_COMMENTLINE;
-                               } else if (ch == '#') {
-                                       state = SCE_C_COMMENTLINEDOC;
-                               } else if (ch == '\'') {
-                                       state = SCE_C_CHARACTER;
-                               } else if (ch == '"') {
-                                       state = SCE_C_STRING;
-                               } else if (isoperator(ch)) {
-                                       styler.ColourTo(i, SCE_C_OPERATOR);
+               // Determine if a new state should be entered.
+               if (sc.state == SCE_SQL_DEFAULT) {
+                       if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+                               sc.SetState(SCE_SQL_NUMBER);
+                       } else if (IsAWordStart(sc.ch)) {
+                               sc.SetState(SCE_SQL_IDENTIFIER);
+                       } else if (sc.ch == 0x60 && sqlBackticksIdentifier) {
+                               sc.SetState(SCE_SQL_QUOTEDIDENTIFIER);
+                       } else if (sc.Match('/', '*')) {
+                               if (sc.Match("/**") || sc.Match("/*!")) {       // Support of Doxygen doc. style
+                                       sc.SetState(SCE_SQL_COMMENTDOC);
+                               } else {
+                                       sc.SetState(SCE_SQL_COMMENT);
                                }
+                               sc.Forward();   // Eat the * so it isn't used for the end of the comment
+                       } else if (sc.Match('-', '-')) {
+                               // MySQL requires a space or control char after --
+                               // http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html
+                               // Perhaps we should enforce that with proper property:
+//~                    } else if (sc.Match("-- ")) {
+                               sc.SetState(SCE_SQL_COMMENTLINE);
+                       } else if (sc.ch == '#') {
+                               sc.SetState(SCE_SQL_COMMENTLINEDOC);
+                       } else if (sc.ch == '\'') {
+                               sc.SetState(SCE_SQL_CHARACTER);
+                       } else if (sc.ch == '\"') {
+                               sc.SetState(SCE_SQL_STRING);
+                       } else if (isoperator(static_cast<char>(sc.ch))) {
+                               sc.SetState(SCE_SQL_OPERATOR);
                        }
-               } else {
-                       if (state == SCE_C_COMMENT) {
-                               if (ch == '/' && chPrev == '*') {
-                                       if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_C_COMMENT) &&
-                                           (styler.GetStartSegment() == startPos)))) {
-                                               styler.ColourTo(i, state);
-                                               state = SCE_C_DEFAULT;
-                                       }
+               }
+       }
+       sc.Complete();
+}
+
+static bool IsStreamCommentStyle(int style) {
+       return style == SCE_SQL_COMMENT ||
+              style == SCE_SQL_COMMENTDOC ||
+              style == SCE_SQL_COMMENTDOCKEYWORD ||
+              style == SCE_SQL_COMMENTDOCKEYWORDERROR;
+}
+
+// Store both the current line's fold level and the next lines in the
+// level store to make it easy to pick up with each increment.
+static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
+                            WordList *[], Accessor &styler) {
+       bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+       bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+       unsigned int endPos = startPos + length;
+       int visibleChars = 0;
+       int lineCurrent = styler.GetLine(startPos);
+       int levelCurrent = SC_FOLDLEVELBASE;
+       if (lineCurrent > 0) {
+               levelCurrent = styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK;
+       }
+       int levelNext = levelCurrent;
+       char chNext = styler[startPos];
+       int styleNext = styler.StyleAt(startPos);
+       int style = initStyle;
+       bool endFound = false;
+       for (unsigned int i = startPos; i < endPos; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               int stylePrev = style;
+               style = styleNext;
+               styleNext = styler.StyleAt(i + 1);
+               bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+               if (foldComment && IsStreamCommentStyle(style)) {
+                       if (!IsStreamCommentStyle(stylePrev)) {
+                               levelNext++;
+                       } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
+                               // Comments don't end at end of line and the next character may be unstyled.
+                               levelNext--;
+                       }
+               }
+               if (foldComment && (style == SCE_SQL_COMMENTLINE)) {
+                       // MySQL needs -- comments to be followed by space or control char
+                       if ((ch == '-') && (chNext == '-')) {
+                               char chNext2 = styler.SafeGetCharAt(i + 2);
+                               char chNext3 = styler.SafeGetCharAt(i + 3);
+                               if (chNext2 == '{' || chNext3 == '{') {
+                                       levelNext++;
+                               } else if (chNext2 == '}' || chNext3 == '}') {
+                                       levelNext--;
                                }
-                       } else if (state == SCE_C_COMMENTLINE || state == SCE_C_COMMENTLINEDOC) {
-                               if (ch == '\r' || ch == '\n') {
-                                       styler.ColourTo(i - 1, state);
-                                       state = SCE_C_DEFAULT;
+                       }
+               }
+               if (style == SCE_SQL_OPERATOR) {
+                       if (ch == '(') {
+                               levelNext++;
+                       } else if (ch == ')') {
+                               levelNext--;
+                       }
+               }
+               // If new keyword (cannot trigger on elseif or nullif, does less tests)
+               if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) {
+                       const int MAX_KW_LEN = 6;       // Maximum length of folding keywords
+                       char s[MAX_KW_LEN + 2];
+                       unsigned int j = 0;
+                       for (; j < MAX_KW_LEN + 1; j++) {
+                               if (!iswordchar(styler[i + j])) {
+                                       break;
                                }
-                       } else if (state == SCE_C_CHARACTER) {
-                               if (sqlBackslashEscapes && ch == '\\') {
-                                       i++;
-                                       ch = chNext;
-                                       chNext = styler.SafeGetCharAt(i + 1);
-                               } else if (ch == '\'') {
-                                       if (chNext == '\'') {
-                                               i++;
-                                       } else {
-                                               styler.ColourTo(i, state);
-                                               state = SCE_C_DEFAULT;
-                                               i++;
-                                       }
-                                       ch = chNext;
-                                       chNext = styler.SafeGetCharAt(i + 1);
+                               s[j] = static_cast<char>(tolower(styler[i + j]));
+                       }
+                       if (j == MAX_KW_LEN + 1) {
+                               // Keyword too long, don't test it
+                               s[0] = '\0';
+                       } else {
+                               s[j] = '\0';
+                       }
+                       if (strcmp(s, "if") == 0 || strcmp(s, "loop") == 0) {
+                               if (endFound) {
+                                       // ignore
+                                       endFound = false;
+                               } else {
+                                       levelNext++;
                                }
-                       } else if (state == SCE_C_STRING) {
-                               if (ch == '"') {
-                                       if (chNext == '"') {
-                                               i++;
-                                       } else {
-                                               styler.ColourTo(i, state);
-                                               state = SCE_C_DEFAULT;
-                                               i++;
-                                       }
-                                       ch = chNext;
-                                       chNext = styler.SafeGetCharAt(i + 1);
+                       } else if (strcmp(s, "begin") == 0) {
+                               levelNext++;
+                       } else if (strcmp(s, "end") == 0 ||
+                                               // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS
+                                               strcmp(s, "exists") == 0) {
+                               endFound = true;
+                               levelNext--;
+                               if (levelNext < SC_FOLDLEVELBASE) {
+                                       levelNext = SC_FOLDLEVELBASE;
                                }
                        }
-                       if (state == SCE_C_DEFAULT) {    // One of the above succeeded
-                               if (ch == '/' && chNext == '*') {
-                                       state = SCE_C_COMMENT;
-                               } else if (ch == '-' && chNext == '-') {
-                                       state = SCE_C_COMMENTLINE;
-                               } else if (ch == '#') {
-                                       state = SCE_C_COMMENTLINEDOC;
-                               } else if (ch == '\'') {
-                                       state = SCE_C_CHARACTER;
-                               } else if (ch == '"') {
-                                       state = SCE_C_STRING;
-                               } else if (iswordstart(ch)) {
-                                       state = SCE_C_WORD;
-                               } else if (isoperator(ch)) {
-                                       styler.ColourTo(i, SCE_C_OPERATOR);
-                               }
+               }
+               if (atEOL) {
+                       int level = levelCurrent;
+                       if (visibleChars == 0 && foldCompact) {
+                               // Empty line
+                               level |= SC_FOLDLEVELWHITEFLAG;
                        }
+                       if (visibleChars > 0 && levelNext > levelCurrent) {
+                               level |= SC_FOLDLEVELHEADERFLAG;
+                       }
+                       if (level != styler.LevelAt(lineCurrent)) {
+                               styler.SetLevel(lineCurrent, level);
+                       }
+                       lineCurrent++;
+                       levelCurrent = levelNext;
+                       visibleChars = 0;
+                       endFound = false;
+               }
+               if (!isspacechar(ch)) {
+                       visibleChars++;
                }
-               chPrev = ch;
        }
-       styler.ColourTo(lengthDoc - 1, state);
 }
 
 static const char * const sqlWordListDesc[] = {
        "Keywords",
+       "Database Objects",
+       "PLDoc",
+       "SQL*Plus",
+       "User Keywords 1",
+       "User Keywords 2",
+       "User Keywords 3",
+       "User Keywords 4",
        0
 };
 
-LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", 0, sqlWordListDesc);
+LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", FoldSQLDoc, sqlWordListDesc);
diff --git a/contrib/src/stc/scintilla/src/LexSmalltalk.cxx b/contrib/src/stc/scintilla/src/LexSmalltalk.cxx
new file mode 100644 (file)
index 0000000..6f43ec3
--- /dev/null
@@ -0,0 +1,317 @@
+// Scintilla source code edit control
+/** @file LexSmalltalk.cxx
+ ** Lexer for Smalltalk language.
+ ** Written by Sergey Philippov, sphilippov-at-gmail-dot-com
+ **/
+// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+/*
+| lexTable classificationBlock charClasses |
+charClasses := #(#DecDigit #Letter #Special #Upper #BinSel).
+lexTable := ByteArray new: 128.
+classificationBlock := [ :charClass :chars |
+    | flag |
+    flag := 1 bitShift: (charClasses indexOf: charClass) - 1.
+    chars do: [ :char | lexTable at: char codePoint + 1 put: ((lexTable at: char codePoint + 1) bitOr: flag)]].
+
+classificationBlock
+    value: #DecDigit value: '0123456789';
+    value: #Letter value: '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    value: #Special value: '()[]{};.^:';
+    value: #BinSel value: '~@%&*-+=|\/,<>?!';
+    value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
+
+((String new: 500) streamContents: [ :stream |            
+    stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'.
+    lexTable keysAndValuesDo: [ :index :value |
+        ((index - 1) rem: 16) == 0 ifTrue: [
+            stream crLf; tab]
+        ifFalse: [
+            stream space].
+        stream print: value.
+        index ~= 256 ifTrue: [
+            stream nextPut: $,]].
+    stream crLf; nextPutAll: '};'; crLf.
+    
+    charClasses keysAndValuesDo: [ :index :name |
+        stream
+            crLf;
+            nextPutAll: (
+                ('static inline bool is<1s>(int ch) {return (ch > 0) && (ch %< 0x80) && ((ClassificationTable[ch] & <2p>) != 0);}')
+                    expandMacrosWith: name with: (1 bitShift: (index - 1)))
+    ]]) edit
+*/
+
+// autogenerated {{{{
+
+static int ClassificationTable[256] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 16, 0, 0, 0, 16, 16, 0, 4, 4, 16, 16, 16, 16, 4, 16,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 16, 16, 16, 16,
+    16, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 16, 4, 4, 2,
+    0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 16, 4, 16, 0,
+};
+
+static inline bool isDecDigit(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 1) != 0);}
+static inline bool isLetter(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 2) != 0);}
+static inline bool isSpecial(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 4) != 0);}
+static inline bool isUpper(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 8) != 0);}
+static inline bool isBinSel(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 16) != 0);}
+// autogenerated }}}}
+
+static inline bool isAlphaNumeric(int ch) {
+    return isDecDigit(ch) || isLetter(ch);
+}
+
+static inline bool isDigitOfRadix(int ch, int radix)
+{
+    if (isDecDigit(ch))
+        return (ch - '0') < radix;
+    else if (!isUpper(ch))
+        return false;
+    else
+        return (ch - 'A' + 10) < radix;
+}
+
+static inline void skipComment(StyleContext& sc)
+{    
+    while (sc.More() && sc.ch != '\"')
+        sc.Forward();
+}
+
+static inline void skipString(StyleContext& sc)
+{
+    while (sc.More()) {
+        if (sc.ch == '\'') {
+            if (sc.chNext != '\'')
+                return;
+            sc.Forward();
+        }
+        sc.Forward();
+    }
+}
+
+static void handleHash(StyleContext& sc)
+{
+    if (isSpecial(sc.chNext)) {
+        sc.SetState(SCE_ST_SPECIAL);
+        return;
+    }
+    
+    sc.SetState(SCE_ST_SYMBOL);
+    sc.Forward();
+    if (sc.ch == '\'') {
+        sc.Forward();
+        skipString(sc);
+    }
+    else {
+        if (isLetter(sc.ch)) {
+            while (isAlphaNumeric(sc.chNext) || sc.chNext == ':')
+                sc.Forward();
+        }
+        else if (isBinSel(sc.ch)) {
+            while (isBinSel(sc.chNext))
+                sc.Forward();
+        }
+    }
+}
+
+static inline void handleSpecial(StyleContext& sc)
+{
+    if (sc.ch == ':' && sc.chNext == '=') {
+        sc.SetState(SCE_ST_ASSIGN);
+        sc.Forward();
+    }
+    else {
+        if (sc.ch == '^')
+            sc.SetState(SCE_ST_RETURN);
+        else
+            sc.SetState(SCE_ST_SPECIAL);
+    }
+}
+
+static inline void skipInt(StyleContext& sc, int radix)
+{
+    while (isDigitOfRadix(sc.chNext, radix))
+        sc.Forward();
+}
+
+static void handleNumeric(StyleContext& sc)
+{
+    char num[256];
+    int nl;
+    int radix;
+    
+    sc.SetState(SCE_ST_NUMBER);
+    num[0] = static_cast<char>(sc.ch);
+    nl = 1;
+    while (isDecDigit(sc.chNext)) {
+        num[nl++] = static_cast<char>(sc.chNext);
+        sc.Forward();
+        if (nl+1 == sizeof(num)/sizeof(num[0])) // overrun check
+            break;
+    }
+    if (sc.chNext == 'r') {
+        num[nl] = 0;
+        if (num[0] == '-')
+            radix = atoi(num + 1);
+        else
+            radix = atoi(num);
+        sc.Forward();
+        if (sc.chNext == '-')
+            sc.Forward();
+        skipInt(sc, radix);
+    }
+    else
+        radix = 10;
+    if (sc.chNext != '.' || !isDigitOfRadix(sc.GetRelative(2), radix))
+        return;
+    sc.Forward();
+    skipInt(sc, radix);
+    if (sc.chNext == 's') {
+        // ScaledDecimal
+        sc.Forward();
+        while (isDecDigit(sc.chNext))
+            sc.Forward();
+        return;
+    }
+    else if (sc.chNext != 'e' && sc.chNext != 'd' && sc.chNext != 'q')
+        return;
+    sc.Forward();
+    if (sc.chNext == '+' || sc.chNext == '-')
+        sc.Forward();
+    skipInt(sc, radix);
+}
+
+static inline void handleBinSel(StyleContext& sc)
+{
+    sc.SetState(SCE_ST_BINARY);
+    while (isBinSel(sc.chNext))
+        sc.Forward();
+}
+
+static void handleLetter(StyleContext& sc, WordList* specialSelectorList)
+{
+    char ident[256];
+    int il;
+    int state;
+    bool doubleColonPresent;
+    
+    sc.SetState(SCE_ST_DEFAULT);
+
+    ident[0] = static_cast<char>(sc.ch);
+    il = 1;
+    while (isAlphaNumeric(sc.chNext)) {
+        ident[il++] = static_cast<char>(sc.chNext);
+        sc.Forward();
+        if (il+2 == sizeof(ident)/sizeof(ident[0])) // overrun check
+            break;
+    }
+
+    if (sc.chNext == ':') {
+        doubleColonPresent = true;
+        ident[il++] = ':';
+        sc.Forward();
+    }
+    else
+        doubleColonPresent = false;
+    ident[il] = 0;
+    
+    if (specialSelectorList->InList(ident))
+            state = SCE_ST_SPEC_SEL;
+    else if (doubleColonPresent)
+            state = SCE_ST_KWSEND;
+    else if (isUpper(ident[0]))
+        state = SCE_ST_GLOBAL;
+    else {
+        if (!strcmp(ident, "self"))
+            state = SCE_ST_SELF;
+        else if (!strcmp(ident, "super"))
+            state = SCE_ST_SUPER;
+        else if (!strcmp(ident, "nil"))
+            state = SCE_ST_NIL;
+        else if (!strcmp(ident, "true") || !strcmp(ident, "false"))
+            state = SCE_ST_BOOL;
+        else
+            state = SCE_ST_DEFAULT;
+    }
+    
+    sc.ChangeState(state);
+}
+
+static void colorizeSmalltalkDoc(unsigned int startPos, int length, int initStyle, WordList *wordLists[], Accessor &styler)
+{
+    StyleContext sc(startPos, length, initStyle, styler);
+
+    if (initStyle == SCE_ST_COMMENT) {
+        skipComment(sc);
+        if (sc.More())
+            sc.Forward();
+    }
+    else if (initStyle == SCE_ST_STRING) {
+        skipString(sc);
+        if (sc.More())
+            sc.Forward();
+    }
+
+    for (; sc.More(); sc.Forward()) {
+        int ch;
+        
+        ch = sc.ch;
+        if (ch == '\"') {
+            sc.SetState(SCE_ST_COMMENT);
+            sc.Forward();
+            skipComment(sc);
+        }
+        else if (ch == '\'') {
+            sc.SetState(SCE_ST_STRING);
+            sc.Forward();
+            skipString(sc);
+        }
+        else if (ch == '#')
+            handleHash(sc);
+        else if (ch == '$') {
+            sc.SetState(SCE_ST_CHARACTER);
+            sc.Forward();
+        }
+        else if (isSpecial(ch))
+            handleSpecial(sc);
+        else if (isDecDigit(ch))
+            handleNumeric(sc);
+        else if (isLetter(ch))
+            handleLetter(sc, wordLists[0]);
+        else if (isBinSel(ch)) {
+            if (ch == '-' && isDecDigit(sc.chNext))
+                handleNumeric(sc);
+            else
+                handleBinSel(sc);
+        }
+        else
+            sc.SetState(SCE_ST_DEFAULT);
+    }
+    sc.Complete();
+}
+
+static const char* const smalltalkWordListDesc[] = {
+    "Special selectors",
+    0
+};
+
+LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc);
diff --git a/contrib/src/stc/scintilla/src/LexTADS3.cxx b/contrib/src/stc/scintilla/src/LexTADS3.cxx
new file mode 100644 (file)
index 0000000..9938f63
--- /dev/null
@@ -0,0 +1,837 @@
+// Scintilla source code edit control
+/** @file LexTADS3.cxx
+ ** Lexer for TADS3.
+ **/
+/* Copyright 2005 by Michael Cartmell
+ * Parts copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+ * In particular FoldTADS3Doc is derived from FoldCppDoc
+ * The License.txt file describes the conditions under which this software may
+ * be distributed.
+ */
+
+/*
+ * TADS3 is a language designed by Michael J. Roberts for the writing of text
+ * based games.  TADS comes from Text Adventure Development System.  It has good
+ * support for the processing and outputting of formatted text and much of a
+ * TADS program listing consists of strings.
+ *
+ * TADS has two types of strings, those enclosed in single quotes (') and those
+ * enclosed in double quotes (").  These strings have different symantics and
+ * can be given different highlighting if desired.
+ *
+ * There can be embedded within both types of strings html tags
+ * ( <tag key=value> ), library directives ( <.directive> ), and message
+ * parameters ( {The doctor's/his} ).
+ *
+ * Double quoted strings can also contain interpolated expressions
+ * ( << rug.moved ? ' and a hole in the floor. ' : nil >> ).  These expressions
+ * may themselves contain single or double quoted strings, although the double
+ * quoted strings may not contain interpolated expressions.
+ *
+ * These embedded constructs influence the output and formatting and are an
+ * important part of a program and require highlighting.
+ *
+ * LINKS
+ * http://www.tads.org/
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+static const int T3_SINGLE_QUOTE = 1;
+static const int T3_INT_EXPRESSION = 2;
+
+static inline bool IsEOL(const int ch, const int chNext) {
+       return (ch == '\r' && chNext != '\n') || (ch == '\n');
+}
+
+static inline bool IsASpaceOrTab(const int ch) {
+       return ch == ' ' || ch == '\t';
+}
+
+static inline bool IsATADS3Operator(const int ch) {
+       return ch == '=' || ch == '{' || ch == '}' || ch == '(' || ch == ')'
+               || ch == '[' || ch == ']' || ch == ',' || ch == ':' || ch == ';'
+               || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%'
+               || ch == '?' || ch == '!' || ch == '<' || ch == '>' || ch == '|'
+               || ch == '@' || ch == '&' || ch == '~';
+}
+
+static inline bool IsAWordChar(const int ch) {
+       return isalnum(ch) || ch == '_' || ch == '.';
+}
+
+static inline bool IsAWordStart(const int ch) {
+       return isalpha(ch) || ch == '_';
+}
+
+static inline bool IsAHexDigit(const int ch) {
+       int lch = tolower(ch);
+       return isdigit(lch) || lch == 'a' || lch == 'b' || lch == 'c'
+               || lch == 'd' || lch == 'e' || lch == 'f';
+}
+
+static inline bool IsAnHTMLChar(int ch) {
+       return isalnum(ch) || ch == '-' || ch == '_' || ch == '.';
+}
+
+static inline bool IsADirectiveChar(int ch) {
+       return isalnum(ch) || isspace(ch) || ch == '-' || ch == '/';
+}
+
+static inline bool IsANumberStart(StyleContext &sc) {
+       return isdigit(sc.ch)
+               || (!isdigit(sc.chPrev) && sc.ch == '.' && isdigit(sc.chNext));
+}
+
+inline static void ColouriseTADS3Operator(StyleContext &sc) {
+       int initState = sc.state;
+       sc.SetState(SCE_T3_OPERATOR);
+       sc.ForwardSetState(initState);
+}
+
+static void ColouriseTADSHTMLString(StyleContext &sc, int &lineState) {
+       int endState = sc.state;
+       int chQuote = sc.ch;
+       if (endState == SCE_T3_HTML_STRING) {
+               if (lineState&T3_SINGLE_QUOTE) {
+                       endState = SCE_T3_S_STRING;
+                       chQuote = '"';
+               } else if (lineState&T3_INT_EXPRESSION) {
+                       endState = SCE_T3_X_STRING;
+                       chQuote = '\'';
+               } else {
+                       endState = SCE_T3_D_STRING;
+                       chQuote = '\'';
+               }
+       } else {
+               sc.SetState(SCE_T3_HTML_STRING);
+               sc.Forward();
+       }
+       int chString = chQuote == '"'? '\'': '"';
+
+       while (sc.More()) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               if (sc.ch == chQuote) {
+                       sc.ForwardSetState(endState);
+                       return;
+               }
+               if (sc.ch == chString) {
+                       sc.SetState(endState);
+                       return;
+               }
+               if (sc.Match('\\', static_cast<char>(chQuote))
+                       || sc.Match('\\', static_cast<char>(chString))) {
+                       sc.Forward(2);
+               } else {
+                       sc.Forward();
+               }
+       }
+}
+
+static void ColouriseTADS3HTMLTagStart(StyleContext &sc) {
+       sc.SetState(SCE_T3_HTML_TAG);
+       sc.Forward();
+       if (sc.ch == '/') {
+               sc.Forward();
+       }
+       while (IsAnHTMLChar(sc.ch)) {
+               sc.Forward();
+       }
+}
+
+static void ColouriseTADS3HTMLTag(StyleContext &sc, int &lineState) {
+       int endState = sc.state;
+       int chQuote = '"';
+       int chString = '\'';
+       switch (endState) {
+               case SCE_T3_S_STRING:
+                       ColouriseTADS3HTMLTagStart(sc);
+                       sc.SetState(SCE_T3_HTML_DEFAULT);
+                       chQuote = '\'';
+                       chString = '"';
+                       break;
+               case SCE_T3_D_STRING:
+               case SCE_T3_X_STRING:
+                       ColouriseTADS3HTMLTagStart(sc);
+                       sc.SetState(SCE_T3_HTML_DEFAULT);
+                       break;
+               case SCE_T3_HTML_DEFAULT:
+                       if (lineState&T3_SINGLE_QUOTE) {
+                               endState = SCE_T3_S_STRING;
+                               chQuote = '\'';
+                               chString = '"';
+                       } else if (lineState&T3_INT_EXPRESSION) {
+                               endState = SCE_T3_X_STRING;
+                       } else {
+                               endState = SCE_T3_D_STRING;
+                       }
+                       break;
+       }
+
+       while (sc.More()) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               if (sc.Match('/', '>')) {
+                       sc.SetState(SCE_T3_HTML_TAG);
+                       sc.Forward(2);
+                       sc.SetState(endState);
+                       return;
+               }
+               if (sc.ch == '>') {
+                       sc.SetState(SCE_T3_HTML_TAG);
+                       sc.ForwardSetState(endState);
+                       return;
+               }
+               if (sc.ch == chQuote) {
+                       sc.SetState(endState);
+                       return;
+               }
+               if (sc.ch == chString) {
+                       ColouriseTADSHTMLString(sc, lineState);
+               } else if (sc.ch == '=') {
+                       ColouriseTADS3Operator(sc);
+               } else {
+                       sc.Forward();
+               }
+       }
+}
+
+static void ColouriseTADS3Keyword(StyleContext &sc,
+                                                       WordList *keywordlists[],       unsigned int endPos) {
+       char s[250];
+       WordList &keywords = *keywordlists[0];
+       WordList &userwords1 = *keywordlists[1];
+       WordList &userwords2 = *keywordlists[2];
+       WordList &userwords3 = *keywordlists[3];
+       int initState = sc.state;
+       sc.SetState(SCE_T3_IDENTIFIER);
+       while (sc.More() && (IsAWordChar(sc.ch))) {
+               sc.Forward();
+       }
+       sc.GetCurrent(s, sizeof(s));
+       if ( strcmp(s, "is") == 0 || strcmp(s, "not") == 0) {
+               // have to find if "in" is next
+               int n = 1;
+               while (n + sc.currentPos < endPos && IsASpaceOrTab(sc.GetRelative(n)))
+                       n++;
+               if (sc.GetRelative(n) == 'i' && sc.GetRelative(n+1) == 'n') {
+                       sc.Forward(n+2);
+                       sc.ChangeState(SCE_T3_KEYWORD);
+               }
+       } else if (keywords.InList(s)) {
+               sc.ChangeState(SCE_T3_KEYWORD);
+       } else if (userwords3.InList(s)) {
+               sc.ChangeState(SCE_T3_USER3);
+       } else if (userwords2.InList(s)) {
+               sc.ChangeState(SCE_T3_USER2);
+       } else if (userwords1.InList(s)) {
+               sc.ChangeState(SCE_T3_USER1);
+       }
+       sc.SetState(initState);
+}
+
+static void ColouriseTADS3MsgParam(StyleContext &sc, int &lineState) {
+       int endState = sc.state;
+       int chQuote = '"';
+       switch (endState) {
+               case SCE_T3_S_STRING:
+                       sc.SetState(SCE_T3_MSG_PARAM);
+                       sc.Forward();
+                       chQuote = '\'';
+                       break;
+               case SCE_T3_D_STRING:
+               case SCE_T3_X_STRING:
+                       sc.SetState(SCE_T3_MSG_PARAM);
+                       sc.Forward();
+                       break;
+               case SCE_T3_MSG_PARAM:
+                       if (lineState&T3_SINGLE_QUOTE) {
+                               endState = SCE_T3_S_STRING;
+                               chQuote = '\'';
+                       } else if (lineState&T3_INT_EXPRESSION) {
+                               endState = SCE_T3_X_STRING;
+                       } else {
+                               endState = SCE_T3_D_STRING;
+                       }
+                       break;
+       }
+       while (sc.More() && sc.ch != '}' && sc.ch != chQuote) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               if (sc.ch == '\\') {
+                       sc.Forward();
+               }
+               sc.Forward();
+       }
+       if (sc.ch == chQuote) {
+               sc.SetState(endState);
+       } else {
+               sc.ForwardSetState(endState);
+       }
+}
+
+static void ColouriseTADS3LibDirective(StyleContext &sc, int &lineState) {
+       int initState = sc.state;
+       int chQuote = '"';
+       switch (initState) {
+               case SCE_T3_S_STRING:
+                       sc.SetState(SCE_T3_LIB_DIRECTIVE);
+                       sc.Forward(2);
+                       chQuote = '\'';
+                       break;
+               case SCE_T3_D_STRING:
+                       sc.SetState(SCE_T3_LIB_DIRECTIVE);
+                       sc.Forward(2);
+                       break;
+               case SCE_T3_LIB_DIRECTIVE:
+                       if (lineState&T3_SINGLE_QUOTE) {
+                               initState = SCE_T3_S_STRING;
+                               chQuote = '\'';
+                       } else {
+                               initState = SCE_T3_D_STRING;
+                       }
+                       break;
+       }
+       while (sc.More() && IsADirectiveChar(sc.ch)) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               sc.Forward();
+       };
+       if (sc.ch == '>' || !sc.More()) {
+               sc.ForwardSetState(initState);
+       } else if (sc.ch == chQuote) {
+               sc.SetState(initState);
+       } else {
+               sc.ChangeState(initState);
+               sc.Forward();
+       }
+}
+
+static void ColouriseTADS3String(StyleContext &sc, int &lineState) {
+       int chQuote = sc.ch;
+       int endState = sc.state;
+       switch (sc.state) {
+               case SCE_T3_DEFAULT:
+               case SCE_T3_X_DEFAULT:
+                       if (chQuote == '"') {
+                               if (sc.state == SCE_T3_DEFAULT) {
+                                       sc.SetState(SCE_T3_D_STRING);
+                               } else {
+                                       sc.SetState(SCE_T3_X_STRING);
+                               }
+                               lineState &= ~T3_SINGLE_QUOTE;
+                       } else {
+                               sc.SetState(SCE_T3_S_STRING);
+                               lineState |= T3_SINGLE_QUOTE;
+                       }
+                       sc.Forward();
+                       break;
+               case SCE_T3_S_STRING:
+                       chQuote = '\'';
+                       endState = lineState&T3_INT_EXPRESSION ?
+                               SCE_T3_X_DEFAULT : SCE_T3_DEFAULT;
+                       break;
+               case SCE_T3_D_STRING:
+                       chQuote = '"';
+                       endState = SCE_T3_DEFAULT;
+                       break;
+               case SCE_T3_X_STRING:
+                       chQuote = '"';
+                       endState = SCE_T3_X_DEFAULT;
+                       break;
+       }
+       while (sc.More()) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               if (sc.ch == chQuote) {
+                       sc.ForwardSetState(endState);
+                       return;
+               }
+               if (sc.state == SCE_T3_D_STRING && sc.Match('<', '<')) {
+                       lineState |= T3_INT_EXPRESSION;
+                       sc.SetState(SCE_T3_X_DEFAULT);
+                       sc.Forward(2);
+                       return;
+               }
+               if (sc.Match('\\', static_cast<char>(chQuote))) {
+                       sc.Forward(2);
+               } else if (sc.ch == '{') {
+                       ColouriseTADS3MsgParam(sc, lineState);
+               } else if (sc.Match('<', '.')) {
+                       ColouriseTADS3LibDirective(sc, lineState);
+               } else if (sc.ch == '<') {
+                       ColouriseTADS3HTMLTag(sc, lineState);
+               } else {
+                       sc.Forward();
+               }
+       }
+}
+
+static void ColouriseTADS3Comment(StyleContext &sc, int endState) {
+       sc.SetState(SCE_T3_BLOCK_COMMENT);
+       while (sc.More()) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               if (sc.Match('*', '/')) {
+                       sc.Forward(2);
+                       sc.SetState(endState);
+                       return;
+               }
+               sc.Forward();
+       }
+}
+
+static void ColouriseToEndOfLine(StyleContext &sc, int initState, int endState) {
+       sc.SetState(initState);
+       while (sc.More()) {
+               if (sc.ch == '\\') {
+                       sc.Forward();
+                       if (IsEOL(sc.ch, sc.chNext)) {
+                                       return;
+                       }
+               }
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       sc.SetState(endState);
+                       return;
+               }
+               sc.Forward();
+       }
+}
+
+static void ColouriseTADS3Number(StyleContext &sc) {
+       int endState = sc.state;
+       bool inHexNumber = false;
+       bool seenE = false;
+       bool seenDot = sc.ch == '.';
+       sc.SetState(SCE_T3_NUMBER);
+       if (sc.More()) {
+               sc.Forward();
+       }
+       if (sc.chPrev == '0' && tolower(sc.ch) == 'x') {
+               inHexNumber = true;
+               sc.Forward();
+       }
+       while (sc.More()) {
+               if (inHexNumber) {
+                       if (!IsAHexDigit(sc.ch)) {
+                               break;
+                       }
+               } else if (!isdigit(sc.ch)) {
+                       if (!seenE && tolower(sc.ch) == 'e') {
+                               seenE = true;
+                               seenDot = true;
+                               if (sc.chNext == '+' || sc.chNext == '-') {
+                                       sc.Forward();
+                               }
+                       } else if (!seenDot && sc.ch == '.') {
+                               seenDot = true;
+                       } else {
+                               break;
+                       }
+               }
+               sc.Forward();
+       }
+       sc.SetState(endState);
+}
+
+static void ColouriseTADS3Doc(unsigned int startPos, int length, int initStyle,
+                                                          WordList *keywordlists[], Accessor &styler) {
+       int visibleChars = 0;
+       int bracketLevel = 0;
+       int lineState = 0;
+       unsigned int endPos = startPos + length;
+       int lineCurrent = styler.GetLine(startPos);
+       if (lineCurrent > 0) {
+               lineState = styler.GetLineState(lineCurrent-1);
+       }
+       StyleContext sc(startPos, length, initStyle, styler);
+
+       while (sc.More()) {
+
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       styler.SetLineState(lineCurrent, lineState);
+                       lineCurrent++;
+                       visibleChars = 0;
+                       sc.Forward();
+                       if (sc.ch == '\n') {
+                               sc.Forward();
+                       }
+               }
+
+               switch(sc.state) {
+                       case SCE_T3_PREPROCESSOR:
+                       case SCE_T3_LINE_COMMENT:
+                               ColouriseToEndOfLine(sc, sc.state, lineState&T3_INT_EXPRESSION ?
+                                       SCE_T3_X_DEFAULT : SCE_T3_DEFAULT);
+                               break;
+                       case SCE_T3_S_STRING:
+                       case SCE_T3_D_STRING:
+                       case SCE_T3_X_STRING:
+                               ColouriseTADS3String(sc, lineState);
+                               visibleChars++;
+                               break;
+                       case SCE_T3_MSG_PARAM:
+                               ColouriseTADS3MsgParam(sc, lineState);
+                               break;
+                       case SCE_T3_LIB_DIRECTIVE:
+                               ColouriseTADS3LibDirective(sc, lineState);
+                               break;
+                       case SCE_T3_HTML_DEFAULT:
+                               ColouriseTADS3HTMLTag(sc, lineState);
+                               break;
+                       case SCE_T3_HTML_STRING:
+                               ColouriseTADSHTMLString(sc, lineState);
+                               break;
+                       case SCE_T3_BLOCK_COMMENT:
+                               ColouriseTADS3Comment(sc, lineState&T3_INT_EXPRESSION ?
+                                       SCE_T3_X_DEFAULT : SCE_T3_DEFAULT);
+                               break;
+                       case SCE_T3_DEFAULT:
+                       case SCE_T3_X_DEFAULT:
+                               if (IsASpaceOrTab(sc.ch)) {
+                                       sc.Forward();
+                               } else if (sc.ch == '#' && visibleChars == 0) {
+                                       ColouriseToEndOfLine(sc, SCE_T3_PREPROCESSOR, sc.state);
+                               } else if (sc.Match('/', '*')) {
+                                       ColouriseTADS3Comment(sc, sc.state);
+                                       visibleChars++;
+                               } else if (sc.Match('/', '/')) {
+                                       ColouriseToEndOfLine(sc, SCE_T3_LINE_COMMENT, sc.state);
+                               } else if (sc.ch == '"') {
+                                       bracketLevel = 0;
+                                       ColouriseTADS3String(sc, lineState);
+                                       visibleChars++;
+                               } else if (sc.ch == '\'') {
+                                       ColouriseTADS3String(sc, lineState);
+                                       visibleChars++;
+                               } else if (sc.state == SCE_T3_X_DEFAULT && bracketLevel == 0
+                                                  && sc.Match('>', '>')) {
+                                       sc.Forward(2);
+                                       sc.SetState(SCE_T3_D_STRING);
+                                       lineState &= ~(T3_SINGLE_QUOTE|T3_INT_EXPRESSION);
+                               } else if (IsATADS3Operator(sc.ch)) {
+                                       if (sc.state == SCE_T3_X_DEFAULT) {
+                                               if (sc.ch == '(') {
+                                                       bracketLevel++;
+                                               } else if (sc.ch == ')') {
+                                                       bracketLevel--;
+                                               }
+                                       }
+                                       ColouriseTADS3Operator(sc);
+                                       visibleChars++;
+                               } else if (IsANumberStart(sc)) {
+                                       ColouriseTADS3Number(sc);
+                                       visibleChars++;
+                               } else if (IsAWordStart(sc.ch)) {
+                                       ColouriseTADS3Keyword(sc, keywordlists, endPos);
+                                       visibleChars++;
+                               } else if (sc.Match("...")) {
+                                       sc.SetState(SCE_T3_IDENTIFIER);
+                                       sc.Forward(3);
+                                       sc.SetState(SCE_T3_DEFAULT);
+                               } else {
+                                       sc.Forward();
+                                       visibleChars++;
+                               }
+                               break;
+                       default:
+                               sc.SetState(SCE_T3_DEFAULT);
+                               sc.Forward();
+               }
+       }
+       sc.Complete();
+}
+
+/*
+ TADS3 has two styles of top level block (TLB). Eg
+
+ // default style
+ silverKey : Key 'small silver key' 'small silver key'
+       "A small key glints in the sunlight. "
+ ;
+
+ and
+
+ silverKey : Key {
+       'small silver key'
+       'small silver key'
+       "A small key glints in the sunlight. "
+ }
+
+ Some constructs mandate one or the other, but usually the author has may choose
+ either.
+
+ T3_SEENSTART is used to indicate that a braceless TLB has been (potentially)
+ seen and is also used to match the closing ';' of the default style.
+
+ T3_EXPECTINGIDENTIFIER and T3_EXPECTINGPUNCTUATION are used to keep track of
+ what characters may be seen without incrementing the block level.  The general
+ pattern is identifier <punc> identifier, acceptable punctuation characters
+ are ':', ',', '(' and ')'.  No attempt is made to ensure that punctuation
+ characters are syntactically correct, eg parentheses match. A ')' always
+ signifies the start of a block.  We just need to check if it is followed by a
+ '{', in which case we let the brace handling code handle the folding level.
+
+ expectingIdentifier == false && expectingIdentifier == false
+ Before the start of a TLB.
+
+ expectingIdentifier == true && expectingIdentifier == true
+ Currently in an identifier.  Will accept identifier or punctuation.
+
+ expectingIdentifier == true && expectingIdentifier == false
+ Just seen a punctuation character & now waiting for an identifier to start.
+
+ expectingIdentifier == false && expectingIdentifier == truee
+ We were in an identifier and have seen space.  Now waiting to see a punctuation
+ character
+
+ Space, comments & preprocessor directives are always acceptable and are
+ equivalent.
+*/
+
+static const int T3_SEENSTART = 1 << 12;
+static const int T3_EXPECTINGIDENTIFIER = 1 << 13;
+static const int T3_EXPECTINGPUNCTUATION = 1 << 14;
+
+static inline bool IsStringTransition(int s1, int s2) {
+       return s1 != s2
+               && (s1 == SCE_T3_S_STRING || s1 == SCE_T3_X_STRING
+                       || s1 == SCE_T3_D_STRING && s2 != SCE_T3_X_DEFAULT)
+               && s2 != SCE_T3_LIB_DIRECTIVE
+               && s2 != SCE_T3_MSG_PARAM
+               && s2 != SCE_T3_HTML_TAG
+               && s2 != SCE_T3_HTML_STRING;
+}
+
+static inline bool IsATADS3Punctuation(const int ch) {
+       return ch == ':' || ch == ',' || ch == '(' || ch == ')';
+}
+
+static inline bool IsAnIdentifier(const int style) {
+       return style == SCE_T3_IDENTIFIER
+               || style == SCE_T3_USER1
+               || style == SCE_T3_USER2
+               || style == SCE_T3_USER3;
+}
+
+static inline bool IsSpaceEquivalent(const int ch, const int style) {
+       return isspace(ch)
+               || style == SCE_T3_BLOCK_COMMENT
+               || style == SCE_T3_LINE_COMMENT
+               || style == SCE_T3_PREPROCESSOR;
+}
+
+static char peekAhead(unsigned int startPos, unsigned int endPos,
+                                         Accessor &styler) {
+       for (unsigned int i = startPos; i < endPos; i++) {
+               int style = styler.StyleAt(i);
+               char ch = styler[i];
+               if (!IsSpaceEquivalent(ch, style)) {
+                       if (IsAnIdentifier(style)) {
+                               return 'a';
+                       }
+                       if (IsATADS3Punctuation(ch)) {
+                               return ':';
+                       }
+                       if (ch == '{') {
+                               return '{';
+                       }
+                       return '*';
+               }
+       }
+       return ' ';
+}
+
+static void FoldTADS3Doc(unsigned int startPos, int length, int initStyle,
+                            WordList *[], Accessor &styler) {
+       unsigned int endPos = startPos + length;
+       int lineCurrent = styler.GetLine(startPos);
+       int levelCurrent = SC_FOLDLEVELBASE;
+       if (lineCurrent > 0)
+               levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
+       int seenStart = levelCurrent & T3_SEENSTART;
+       int expectingIdentifier = levelCurrent & T3_EXPECTINGIDENTIFIER;
+       int expectingPunctuation = levelCurrent & T3_EXPECTINGPUNCTUATION;
+       levelCurrent &= SC_FOLDLEVELNUMBERMASK;
+       int levelMinCurrent = levelCurrent;
+       int levelNext = levelCurrent;
+       char chNext = styler[startPos];
+       int styleNext = styler.StyleAt(startPos);
+       int style = initStyle;
+       char ch = chNext;
+       int stylePrev = style;
+       bool redo = false;
+       for (unsigned int i = startPos; i < endPos; i++) {
+               if (redo) {
+                       redo = false;
+                       i--;
+               } else {
+                       ch = chNext;
+                       chNext = styler.SafeGetCharAt(i + 1);
+                       stylePrev = style;
+                       style = styleNext;
+                       styleNext = styler.StyleAt(i + 1);
+               }
+               bool atEOL = IsEOL(ch, chNext);
+
+               if (levelNext == SC_FOLDLEVELBASE) {
+                       if (IsSpaceEquivalent(ch, style)) {
+                               if (expectingPunctuation) {
+                                       expectingIdentifier = 0;
+                               }
+                               if (style == SCE_T3_BLOCK_COMMENT) {
+                                       levelNext++;
+                               }
+                       } else if (ch == '{') {
+                               levelNext++;
+                               seenStart = 0;
+                       } else if (ch == '\'' || ch == '"' || ch == '[') {
+                               levelNext++;
+                               if (seenStart) {
+                                       redo = true;
+                               }
+                       } else if (ch == ';') {
+                               seenStart = 0;
+                               expectingIdentifier = 0;
+                               expectingPunctuation = 0;
+                       } else if (expectingIdentifier && expectingPunctuation) {
+                               if (IsATADS3Punctuation(ch)) {
+                                       if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') {
+                                               levelNext++;
+                                       } else {
+                                               expectingPunctuation = 0;
+                                       }
+                               } else if (!IsAnIdentifier(style)) {
+                                       levelNext++;
+                               }
+                       } else if (expectingIdentifier && !expectingPunctuation) {
+                               if (!IsAnIdentifier(style)) {
+                                       levelNext++;
+                               } else {
+                                       expectingPunctuation = T3_EXPECTINGPUNCTUATION;
+                               }
+                       } else if (!expectingIdentifier && expectingPunctuation) {
+                               if (!IsATADS3Punctuation(ch)) {
+                                       levelNext++;
+                               } else {
+                                       if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') {
+                                               levelNext++;
+                                       } else {
+                                               expectingIdentifier = T3_EXPECTINGIDENTIFIER;
+                                               expectingPunctuation = 0;
+                                       }
+                               }
+                       } else if (!expectingIdentifier && !expectingPunctuation) {
+                               if (IsAnIdentifier(style)) {
+                                       seenStart = T3_SEENSTART;
+                                       expectingIdentifier = T3_EXPECTINGIDENTIFIER;
+                                       expectingPunctuation = T3_EXPECTINGPUNCTUATION;
+                               }
+                       }
+
+                       if (levelNext != SC_FOLDLEVELBASE && style != SCE_T3_BLOCK_COMMENT) {
+                               expectingIdentifier = 0;
+                               expectingPunctuation = 0;
+                       }
+
+               } else if (levelNext == SC_FOLDLEVELBASE+1 && seenStart
+                                  && ch == ';' && style == SCE_T3_OPERATOR ) {
+                       levelNext--;
+                       seenStart = 0;
+               } else if (style == SCE_T3_BLOCK_COMMENT) {
+                       if (stylePrev != SCE_T3_BLOCK_COMMENT) {
+                               levelNext++;
+                       } else if (styleNext != SCE_T3_BLOCK_COMMENT && !atEOL) {
+                               // Comments don't end at end of line and the next character may be unstyled.
+                               levelNext--;
+                       }
+               } else if (ch == '\'' || ch == '"') {
+                       if (IsStringTransition(style, stylePrev)) {
+                               if (levelMinCurrent > levelNext) {
+                                       levelMinCurrent = levelNext;
+                               }
+                               levelNext++;
+                       } else if (IsStringTransition(style, styleNext)) {
+                               levelNext--;
+                       }
+               } else if (style == SCE_T3_OPERATOR) {
+                       if (ch == '{' || ch == '[') {
+                               // Measure the minimum before a '{' to allow
+                               // folding on "} else {"
+                               if (levelMinCurrent > levelNext) {
+                                       levelMinCurrent = levelNext;
+                               }
+                               levelNext++;
+                       } else if (ch == '}' || ch == ']') {
+                               levelNext--;
+                       }
+               }
+
+               if (atEOL) {
+                       if (seenStart && levelNext == SC_FOLDLEVELBASE) {
+                               switch (peekAhead(i+1, endPos, styler)) {
+                                       case ' ':
+                                       case '{':
+                                               break;
+                                       case '*':
+                                               levelNext++;
+                                               break;
+                                       case 'a':
+                                               if (expectingPunctuation) {
+                                                       levelNext++;
+                                               }
+                                               break;
+                                       case ':':
+                                               if (expectingIdentifier) {
+                                                       levelNext++;
+                                               }
+                                               break;
+                               }
+                               if (levelNext != SC_FOLDLEVELBASE) {
+                                       expectingIdentifier = 0;
+                                       expectingPunctuation = 0;
+                               }
+                       }
+                       int lev = levelMinCurrent | (levelNext | expectingIdentifier
+                               | expectingPunctuation | seenStart) << 16;
+                       if (levelMinCurrent < levelNext)
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+                       if (lev != styler.LevelAt(lineCurrent)) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+                       lineCurrent++;
+                       levelCurrent = levelNext;
+                       levelMinCurrent = levelCurrent;
+               }
+       }
+}
+
+static const char * const tads3WordList[] = {
+       "TADS3 Keywords",
+       "User defined 1",
+       "User defined 2",
+       "User defined 3",
+       0
+};
+
+LexerModule lmTADS3(SCLEX_TADS3, ColouriseTADS3Doc, "tads3", FoldTADS3Doc, tads3WordList);
index a5b09467019282f8f7036a94ce7d09bae9aedc73..65e530adb8b443a4faed89106d508ad5c5ea82d1 100644 (file)
@@ -275,7 +275,7 @@ static void ColouriseTeXDoc(
 // Hooks into the system:
 
 static const char * const texWordListDesc[] = {
-    "TeX, eTeX, pdfTeX, Omega"
+    "TeX, eTeX, pdfTeX, Omega",
     "ConTeXt Dutch",
     "ConTeXt English",
     "ConTeXt German",
index 93bdedbd897b77c946d6527e972dd266e9ca50fe..d9f02862913e405ad46234b2ab54557d57477381 100644 (file)
@@ -2,7 +2,7 @@
 /** @file LexVB.cxx
  ** Lexer for Visual Basic and VBScript.
  **/
-// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
 #include "Scintilla.h"
 #include "SciLexer.h"
 
+// Internal state, highlighted as number
+#define SCE_B_FILENUMBER SCE_B_DEFAULT+100
+
+
 static bool IsVBComment(Accessor &styler, int pos, int len) {
-       return len>0 && styler[pos]=='\'';
+       return len > 0 && styler[pos] == '\'';
 }
 
 static inline bool IsTypeCharacter(int ch) {
@@ -36,12 +40,15 @@ static inline bool IsAWordChar(int ch) {
 
 static inline bool IsAWordStart(int ch) {
        return ch >= 0x80 ||
-              (isalnum(ch) || ch == '_');
+              (isalpha(ch) || ch == '_');
 }
 
-static inline bool IsADateCharacter(const int ch) {
+static inline bool IsANumberChar(int ch) {
+       // Not exactly following number definition (several dots are seen as OK, etc.)
+       // but probably enough in most cases.
        return (ch < 0x80) &&
-               (isalnum(ch) || ch == '|' || ch == '-' || ch == '/' || ch == ':' || ch == ' ' || ch == '\t');
+               (isdigit(ch) || toupper(ch) == 'E' ||
+             ch == '.' || ch == '-' || ch == '+');
 }
 
 static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
@@ -55,6 +62,12 @@ static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
        styler.StartAt(startPos);
 
        int visibleChars = 0;
+       int fileNbDigits = 0;
+
+       // Do not leak onto next line
+       if (initStyle == SCE_B_STRINGEOL || initStyle == SCE_B_COMMENT || initStyle == SCE_B_PREPROCESSOR) {
+               initStyle = SCE_B_DEFAULT;
+       }
 
        StyleContext sc(startPos, length, initStyle, styler);
 
@@ -96,7 +109,9 @@ static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
                                }
                        }
                } else if (sc.state == SCE_B_NUMBER) {
-                       if (!IsAWordChar(sc.ch)) {
+                       // We stop the number definition on non-numerical non-dot non-eE non-sign char
+                       // Also accepts A-F for hex. numbers
+                       if (!IsANumberChar(sc.ch) && !(tolower(sc.ch) >= 'a' && tolower(sc.ch) <= 'f')) {
                                sc.SetState(SCE_B_DEFAULT);
                        }
                } else if (sc.state == SCE_B_STRING) {
@@ -113,14 +128,38 @@ static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
                        }
                } else if (sc.state == SCE_B_COMMENT) {
                        if (sc.atLineEnd) {
-                               sc.SetState(SCE_B_DEFAULT);
+                               sc.ForwardSetState(SCE_B_DEFAULT);
                        }
                } else if (sc.state == SCE_B_PREPROCESSOR) {
                        if (sc.atLineEnd) {
+                               sc.ForwardSetState(SCE_B_DEFAULT);
+                       }
+               } else if (sc.state == SCE_B_FILENUMBER) {
+                       if (IsADigit(sc.ch)) {
+                               fileNbDigits++;
+                               if (fileNbDigits > 3) {
+                                       sc.ChangeState(SCE_B_DATE);
+                               }
+                       } else if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ',') {
+                               // Regular uses: Close #1; Put #1, ...; Get #1, ... etc.
+                               // Too bad if date is format #27, Oct, 2003# or something like that...
+                               // Use regular number state
+                               sc.ChangeState(SCE_B_NUMBER);
                                sc.SetState(SCE_B_DEFAULT);
+                       } else if (sc.ch == '#') {
+                               sc.ChangeState(SCE_B_DATE);
+                               sc.ForwardSetState(SCE_B_DEFAULT);
+                       } else {
+                               sc.ChangeState(SCE_B_DATE);
+                       }
+                       if (sc.state != SCE_B_FILENUMBER) {
+                               fileNbDigits = 0;
                        }
                } else if (sc.state == SCE_B_DATE) {
-                       if (sc.ch == '#' || !IsADateCharacter(sc.chNext)) {
+                       if (sc.atLineEnd) {
+                               sc.ChangeState(SCE_B_STRINGEOL);
+                               sc.ForwardSetState(SCE_B_DEFAULT);
+                       } else if (sc.ch == '#') {
                                sc.ForwardSetState(SCE_B_DEFAULT);
                        }
                }
@@ -134,26 +173,24 @@ static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
                                // Preprocessor commands are alone on their line
                                sc.SetState(SCE_B_PREPROCESSOR);
                        } else if (sc.ch == '#') {
-                               int n = 1;
-                               int chSeek = ' ';
-                               while ((n < 100) && (chSeek == ' ' || chSeek == '\t')) {
-                                       chSeek = sc.GetRelative(n);
-                                       n++;
-                               }
-                               if (IsADigit(chSeek)) {
-                                       sc.SetState(SCE_B_DATE);
-                               } else {
-                                       sc.SetState(SCE_B_OPERATOR);
-                               }
+                               // It can be a date literal, ending with #, or a file number, from 1 to 511
+                               // The date literal depends on the locale, so anything can go between #'s.
+                               // Can be #January 1, 1993# or #1 Jan 93# or #05/11/2003#, etc.
+                               // So we set the FILENUMBER state, and switch to DATE if it isn't a file number
+                               sc.SetState(SCE_B_FILENUMBER);
                        } else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {
+                               // Hexadecimal number
                                sc.SetState(SCE_B_NUMBER);
+                               sc.Forward();
                        } else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {
+                               // Octal number
                                sc.SetState(SCE_B_NUMBER);
+                               sc.Forward();
                        } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
                                sc.SetState(SCE_B_NUMBER);
                        } else if (IsAWordStart(sc.ch) || (sc.ch == '[')) {
                                sc.SetState(SCE_B_IDENTIFIER);
-                       } else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {
+                       } else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {   // Integer division
                                sc.SetState(SCE_B_OPERATOR);
                        }
                }
index ec9c86f74f2f8c208fc03dd86b79895a2a8446b1..6ded13c73ac32b23e2a45265b0b2cf3815f4cb5f 100644 (file)
@@ -282,7 +282,7 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac
                        surface->LineTo(right - 5, centreY + 5);
                        right += 4;
                }
-       } else { // SC_MARK_SHORTARROW
+       } else if (markType == SC_MARK_SHORTARROW) {
                Point pts[] = {
                        Point(centreX, centreY + dimOn2),
                        Point(centreX + dimOn2, centreY),
@@ -295,5 +295,7 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac
                };
                surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                                fore.allocated, back.allocated);
+       } else { // SC_MARK_FULLRECT
+               surface->FillRectangle(rcWhole, back.allocated);
        }
 }
index 1e9920d79c5a0400ef2f71d65f2c5acd99dcd182..b4011a04c7e3ba7079571318326316445a17a153 100644 (file)
@@ -329,6 +329,8 @@ char *SContainer::StringAllocate(const char *s, lenpos_t len) {
 
 // End SString functions
 
+bool PropSet::caseSensitiveFilenames = false;
+
 PropSet::PropSet() {
        superPS = 0;
        for (int root = 0; root < hashRoots; root++)
@@ -459,7 +461,7 @@ struct VarChain {
        VarChain(const char*var_=NULL, const VarChain *link_=NULL): var(var_), link(link_) {}
 
        bool contains(const char *testVar) const {
-               return (var && (0 == strcmp(var, testVar))) 
+               return (var && (0 == strcmp(var, testVar)))
                        || (link && link->contains(testVar));
        }
 
@@ -536,16 +538,23 @@ bool isprefix(const char *target, const char *prefix) {
                return true;
 }
 
-static bool IsSuffixCaseInsensitive(const char *target, const char *suffix) {
+static bool IsSuffix(const char *target, const char *suffix, bool caseSensitive) {
        size_t lentarget = strlen(target);
        size_t lensuffix = strlen(suffix);
        if (lensuffix > lentarget)
                return false;
+       if (caseSensitive) {
+               for (int i = static_cast<int>(lensuffix) - 1; i >= 0; i--) {
+                       if (target[i + lentarget - lensuffix] != suffix[i])
+                               return false;
+               }
+       } else {
        for (int i = static_cast<int>(lensuffix) - 1; i >= 0; i--) {
                if (MakeUpperCase(target[i + lentarget - lensuffix]) !=
                        MakeUpperCase(suffix[i]))
                        return false;
        }
+       }
        return true;
 }
 
@@ -577,7 +586,7 @@ SString PropSet::GetWild(const char *keybase, const char *filename) {
                                        char delchr = *del;
                                        *del = '\0';
                                        if (*keyfile == '*') {
-                                               if (IsSuffixCaseInsensitive(filename, keyfile + 1)) {
+                                               if (IsSuffix(filename, keyfile + 1, caseSensitiveFilenames)) {
                                                        *del = delchr;
                                                        delete []keyptr;
                                                        return p->val;
@@ -790,11 +799,13 @@ void WordList::Clear() {
        list = 0;
        len = 0;
        sorted = false;
+       sortedNoCase = false;
 }
 
 void WordList::Set(const char *s) {
        list = StringDup(s);
        sorted = false;
+       sortedNoCase = false;
        words = ArrayFromWordList(list, &len, onlyLineEnds);
        wordsNoCase = new char * [len + 1];
        memcpy(wordsNoCase, words, (len + 1) * sizeof (*words));
@@ -808,6 +819,7 @@ char *WordList::Allocate(int size) {
 
 void WordList::SetFromAllocated() {
        sorted = false;
+       sortedNoCase = false;
        words = ArrayFromWordList(list, &len, onlyLineEnds);
        wordsNoCase = new char * [len + 1];
        memcpy(wordsNoCase, words, (len + 1) * sizeof (*words));
@@ -823,9 +835,12 @@ int cmpStringNoCase(const void *a1, const void *a2) {
        return CompareCaseInsensitive(*(char**)(a1), *(char**)(a2));
 }
 
-static void SortWordList(char **words, char **wordsNoCase, unsigned int len) {
+static void SortWordList(char **words, unsigned int len) {
        qsort(reinterpret_cast<void*>(words), len, sizeof(*words),
              cmpString);
+}
+
+static void SortWordListNoCase(char **wordsNoCase, unsigned int len) {
        qsort(reinterpret_cast<void*>(wordsNoCase), len, sizeof(*wordsNoCase),
              cmpStringNoCase);
 }
@@ -835,7 +850,7 @@ bool WordList::InList(const char *s) {
                return false;
        if (!sorted) {
                sorted = true;
-               SortWordList(words, wordsNoCase, len);
+               SortWordList(words, len);
                for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
                        starts[k] = -1;
                for (int l = len - 1; l >= 0; l--) {
@@ -877,6 +892,68 @@ bool WordList::InList(const char *s) {
        return false;
 }
 
+/** similar to InList, but word s can be a substring of keyword.
+ * eg. the keyword define is defined as def~ine. This means the word must start
+ * with def to be a keyword, but also defi, defin and define are valid.
+ * The marker is ~ in this case.
+ */
+bool WordList::InListAbbreviated(const char *s, const char marker) {
+       if (0 == words)
+               return false;
+       if (!sorted) {
+               sorted = true;
+               SortWordList(words, len);
+               for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
+                       starts[k] = -1;
+               for (int l = len - 1; l >= 0; l--) {
+                       unsigned char indexChar = words[l][0];
+                       starts[indexChar] = l;
+               }
+       }
+       unsigned char firstChar = s[0];
+       int j = starts[firstChar];
+       if (j >= 0) {
+               while (words[j][0] == firstChar) {
+                       bool isSubword = false;
+                       int start = 1;
+                       if (words[j][1] == marker) {
+                               isSubword = true;
+                               start++;
+                       }
+                       if (s[1] == words[j][start]) {
+                               const char *a = words[j] + start;
+                               const char *b = s + 1;
+                               while (*a && *a == *b) {
+                                       a++;
+                                       if (*a == marker) {
+                                               isSubword = true;
+                                               a++;
+                                       }
+                                       b++;
+                               }
+                               if ((!*a || isSubword) && !*b)
+                                       return true;
+                       }
+                       j++;
+               }
+       }
+       j = starts['^'];
+       if (j >= 0) {
+               while (words[j][0] == '^') {
+                       const char *a = words[j] + 1;
+                       const char *b = s;
+                       while (*a && *a == *b) {
+                               a++;
+                               b++;
+                       }
+                       if (!*a)
+                               return true;
+                       j++;
+               }
+       }
+       return false;
+}
+
 /**
  * Returns an element (complete) of the wordlist array which has
  * the same beginning as the passed string.
@@ -892,11 +969,11 @@ const char *WordList::GetNearestWord(const char *wordStart, int searchLen, bool
 
        if (0 == words)
                return NULL;
-       if (!sorted) {
-               sorted = true;
-               SortWordList(words, wordsNoCase, len);
-       }
        if (ignoreCase) {
+               if (!sortedNoCase) {
+                       sortedNoCase = true;
+                       SortWordListNoCase(wordsNoCase, len);
+               }
                while (start <= end) { // binary searching loop
                        pivot = (start + end) >> 1;
                        word = wordsNoCase[pivot];
@@ -912,7 +989,7 @@ const char *WordList::GetNearestWord(const char *wordStart, int searchLen, bool
                                while (end < len-1 && !CompareNCaseInsensitive(wordStart, wordsNoCase[end+1], searchLen)) {
                                        end++;
                                }
-                               
+
                                // Finds first word in a series of equal words
                                for (pivot = start; pivot <= end; pivot++) {
                                        word = wordsNoCase[pivot];
@@ -930,6 +1007,10 @@ const char *WordList::GetNearestWord(const char *wordStart, int searchLen, bool
                                end = pivot - 1;
                }
        } else { // preserve the letter case
+               if (!sorted) {
+                       sorted = true;
+                       SortWordList(words, len);
+               }
                while (start <= end) { // binary searching loop
                        pivot = (start + end) >> 1;
                        word = words[pivot];
@@ -945,7 +1026,7 @@ const char *WordList::GetNearestWord(const char *wordStart, int searchLen, bool
                                while (end < len-1 && !strncmp(wordStart, words[end+1], searchLen)) {
                                        end++;
                                }
-                               
+
                                // Finds first word in a series of equal words
                                pivot = start;
                                while (pivot <= end) {
@@ -1020,11 +1101,11 @@ char *WordList::GetNearestWords(
 
        if (0 == words)
                return NULL;
-       if (!sorted) {
-               sorted = true;
-               SortWordList(words, wordsNoCase, len);
-       }
        if (ignoreCase) {
+               if (!sortedNoCase) {
+                       sortedNoCase = true;
+                       SortWordListNoCase(wordsNoCase, len);
+               }
                while (start <= end) { // Binary searching loop
                        pivot = (start + end) / 2;
                        cond = CompareNCaseInsensitive(wordStart, wordsNoCase[pivot], searchLen);
@@ -1053,6 +1134,10 @@ char *WordList::GetNearestWords(
                        }
                }
        } else {        // Preserve the letter case
+               if (!sorted) {
+                       sorted = true;
+                       SortWordList(words, len);
+               }
                while (start <= end) { // Binary searching loop
                        pivot = (start + end) / 2;
                        cond = strncmp(wordStart, words[pivot], searchLen);
index 8ca9cd0b825608ebd24729430cdde3dbd3f471dc..a558b371d2542ad64f2f9abf840a5af43721d1cb 100644 (file)
@@ -20,6 +20,8 @@
 class CharacterIndexer {
 public: 
        virtual char CharAt(int index)=0;
+       virtual ~CharacterIndexer() {
+       }
 };
 
 class RESearch {
index 1d3867b7fe1510660dbfd4fa9a985f7ffc0202fa..6be8b74b533134932031686896dfc313572d4710 100644 (file)
 ScintillaBase::ScintillaBase() {
        displayPopupMenu = true;
        listType = 0;
+       maxListWidth = 0;
 #ifdef SCI_LEXER
        lexLanguage = SCLEX_CONTAINER;
+       performingStyle = false;
        lexCurrent = 0;
        for (int wl = 0;wl < numWordLists;wl++)
                keyWordLists[wl] = new WordList;
@@ -214,7 +216,8 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
                        return;
                }
        }
-       ac.Start(wMain, idAutoComplete, currentPos, lenEntered, vs.lineHeight, IsUnicodeMode());
+       ac.Start(wMain, idAutoComplete, currentPos, LocationFromPosition(currentPos),
+                               lenEntered, vs.lineHeight, IsUnicodeMode());
 
        PRectangle rcClient = GetClientRectangle();
        Point pt = LocationFromPosition(currentPos - lenEntered);
@@ -242,7 +245,8 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
        rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcClient.bottom);
        ac.lb->SetPositionRelative(rcac, wMain);
        ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font);
-       ac.lb->SetAverageCharWidth(vs.styles[STYLE_DEFAULT].aveCharWidth);
+       unsigned int aveCharWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
+       ac.lb->SetAverageCharWidth(aveCharWidth);
        ac.lb->SetDoubleClickAction(AutoCompleteDoubleClick, this);
 
        ac.SetList(list);
@@ -251,6 +255,8 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
        PRectangle rcList = ac.lb->GetDesiredRect();
        int heightAlloced = rcList.bottom - rcList.top;
        widthLB = Platform::Maximum(widthLB, rcList.right - rcList.left);
+       if (maxListWidth != 0)
+               widthLB = Platform::Minimum(widthLB, aveCharWidth*maxListWidth);
        // Make an allowance for large strings in list
        rcList.left = pt.x - ac.lb->CaretFromEdge();
        rcList.right = rcList.left + widthLB;
@@ -262,7 +268,7 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
        }
        rcList.bottom = rcList.top + heightAlloced;
        ac.lb->SetPositionRelative(rcList, wMain);
-       ac.Show();
+       ac.Show(true);
        if (lenEntered != 0) {
                AutoCompleteMoveToCurrentWord();
        }
@@ -312,25 +318,31 @@ void ScintillaBase::AutoCompleteCompleted() {
        selected[0] = '\0';
        if (item != -1) {
                ac.lb->GetValue(item, selected, sizeof(selected));
+       } else {
+               ac.Cancel();
+               return;
        }
-       ac.Cancel();
-       if (item == -1)
+
+       ac.Show(false);
+
+       listSelected = selected;
+       SCNotification scn = {0};
+       scn.nmhdr.code = listType > 0 ? SCN_USERLISTSELECTION : SCN_AUTOCSELECTION;
+       scn.message = 0;
+       scn.wParam = listType;
+       scn.listType = listType;
+       Position firstPos = ac.posStart - ac.startLen;
+       scn.lParam = firstPos;
+       scn.text = listSelected.c_str();
+       NotifyParent(scn);
+
+       if (!ac.Active())
                return;
+       ac.Cancel();
 
-       if (listType > 0) {
-               userListSelected = selected;
-               SCNotification scn;
-               scn.nmhdr.code = SCN_USERLISTSELECTION;
-               scn.message = 0;
-               scn.wParam = listType;
-               scn.listType = listType;
-               scn.lParam = 0;
-               scn.text = userListSelected.c_str();
-               NotifyParent(scn);
+       if (listType > 0)
                return;
-       }
 
-       Position firstPos = ac.posStart - ac.startLen;
        Position endPos = currentPos;
        if (ac.dropRestOfWord)
                endPos = pdoc->ExtendWordSelect(endPos, 1, true);
@@ -378,7 +390,7 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) {
 }
 
 void ScintillaBase::CallTipClick() {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_CALLTIPCLICK;
        scn.position = ct.clickPlace;
        NotifyParent(scn);
@@ -430,29 +442,38 @@ void ScintillaBase::SetLexerLanguage(const char *languageName) {
 }
 
 void ScintillaBase::Colourise(int start, int end) {
-       int lengthDoc = pdoc->Length();
-       if (end == -1)
-               end = lengthDoc;
-       int len = end - start;
-
-       PLATFORM_ASSERT(len >= 0);
-       PLATFORM_ASSERT(start + len <= lengthDoc);
-
-       //WindowAccessor styler(wMain.GetID(), props);
-       DocumentAccessor styler(pdoc, props, wMain.GetID());
-
-       int styleStart = 0;
-       if (start > 0)
-               styleStart = styler.StyleAt(start - 1);
-       styler.SetCodePage(pdoc->dbcsCodePage);
-
-       if (lexCurrent && (len > 0)) {  // Should always succeed as null lexer should always be available
-               lexCurrent->Lex(start, len, styleStart, keyWordLists, styler);
-               styler.Flush();
-               if (styler.GetPropertyInt("fold")) {
-                       lexCurrent->Fold(start, len, styleStart, keyWordLists, styler);
+       if (!performingStyle) {
+               // Protect against reentrance, which may occur, for example, when
+               // fold points are discovered while performing styling and the folding
+               // code looks for child lines which may trigger styling.
+               performingStyle = true;
+
+               int lengthDoc = pdoc->Length();
+               if (end == -1)
+                       end = lengthDoc;
+               int len = end - start;
+
+               PLATFORM_ASSERT(len >= 0);
+               PLATFORM_ASSERT(start + len <= lengthDoc);
+
+               //WindowAccessor styler(wMain.GetID(), props);
+               DocumentAccessor styler(pdoc, props, wMain.GetID());
+
+               int styleStart = 0;
+               if (start > 0)
+                       styleStart = styler.StyleAt(start - 1);
+               styler.SetCodePage(pdoc->dbcsCodePage);
+
+               if (lexCurrent && (len > 0)) {  // Should always succeed as null lexer should always be available
+                       lexCurrent->Lex(start, len, styleStart, keyWordLists, styler);
                        styler.Flush();
+                       if (styler.GetPropertyInt("fold")) {
+                               lexCurrent->Fold(start, len, styleStart, keyWordLists, styler);
+                               styler.Flush();
+                       }
                }
+
+               performingStyle = false;
        }
 }
 #endif
@@ -553,6 +574,20 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
        case SCI_AUTOCGETDROPRESTOFWORD:
                return ac.dropRestOfWord;
 
+       case SCI_AUTOCSETMAXHEIGHT:
+               ac.lb->SetVisibleRows(wParam);
+               break;
+
+       case SCI_AUTOCGETMAXHEIGHT:
+               return ac.lb->GetVisibleRows();
+
+       case SCI_AUTOCSETMAXWIDTH:
+               maxListWidth = wParam;
+               break;
+
+       case SCI_AUTOCGETMAXWIDTH:
+               return maxListWidth;
+
        case SCI_REGISTERIMAGE:
                ac.lb->RegisterImage(wParam, reinterpret_cast<const char *>(lParam));
                break;
@@ -616,7 +651,12 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
                return lexLanguage;
 
        case SCI_COLOURISE:
-               Colourise(wParam, lParam);
+               if (lexLanguage == SCLEX_CONTAINER) {
+                       pdoc->ModifiedAt(wParam);
+                       NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam);
+               } else {
+                       Colourise(wParam, lParam);
+               }
                Redraw();
                break;
 
@@ -625,6 +665,31 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
                          reinterpret_cast<const char *>(lParam));
                break;
 
+       case SCI_GETPROPERTY: {
+                       SString val = props.Get(reinterpret_cast<const char *>(wParam));
+                       const int n = val.length();
+                       if (lParam != 0) {
+                               char *ptr = reinterpret_cast<char *>(lParam);
+                               memcpy(ptr, val.c_str(), n);
+                               ptr[n] = '\0';  // terminate
+                       }
+                       return n;       // Not including NUL
+               }
+
+       case SCI_GETPROPERTYEXPANDED: {
+                       SString val = props.GetExpanded(reinterpret_cast<const char *>(wParam));
+                       const int n = val.length();
+                       if (lParam != 0) {
+                               char *ptr = reinterpret_cast<char *>(lParam);
+                               memcpy(ptr, val.c_str(), n);
+                               ptr[n] = '\0';  // terminate
+                       }
+                       return n;       // Not including NUL
+               }
+
+       case SCI_GETPROPERTYINT:
+               return props.GetInt(reinterpret_cast<const char *>(wParam), lParam);
+
        case SCI_SETKEYWORDS:
                if (wParam < numWordLists) {
                        keyWordLists[wParam]->Clear();
@@ -636,6 +701,8 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
                SetLexerLanguage(reinterpret_cast<const char *>(lParam));
                break;
 
+       case SCI_GETSTYLEBITSNEEDED:
+               return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5;
 #endif
 
        default:
index 6ea23ab5a3718bb1632182d5e0a4f96233c679f8..cb85b55b511e40163693709f944f7b3cae3cea87 100644 (file)
@@ -37,7 +37,10 @@ protected:
        CallTip ct;
 
        int listType;                   ///< 0 is an autocomplete list
-       SString userListSelected;       ///< Receives listbox selected string
+       SString listSelected;   ///< Receives listbox selected string
+       int maxListWidth;               /// Maximum width of list, in average character widths
+
+       bool performingStyle;   ///< Prevent reentrance
 
 #ifdef SCI_LEXER
        int lexLanguage;
index aedebbc012cba8ecb134fb735d37aa87dd333e35..36b50f9142f309d6d9ae1feaa95a715354df96d9 100644 (file)
@@ -45,7 +45,7 @@ public:
                currentPos(startPos),
                atLineStart(true),
                atLineEnd(false),
-               state(initStyle),
+               state(initStyle & chMask), // Mask off all bits which aren't in the chMask.
                chPrev(0),
                ch(0),
                chNext(0) {
@@ -104,7 +104,7 @@ public:
                return currentPos - styler.GetStartSegment();
        }
        int GetRelative(int n) {
-               return styler.SafeGetCharAt(currentPos+n);
+               return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n));
        }
        bool Match(char ch0) {
                return ch == ch0;
@@ -134,7 +134,8 @@ public:
                        return false;
                s++;
                for (int n=2; *s; n++) {
-                       if (*s != tolower((styler.SafeGetCharAt(currentPos+n))))
+                       if (*s !=
+                               tolower(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n))))
                                return false;
                        s++;
                }
index d3bbb4dcc12176b8a797a424cb8674f7ddfafb6d..36e7994f46c4dd9b562523c48df0db82de9f5363 100644 (file)
@@ -103,6 +103,11 @@ void XPM::Init(const char * const *linesForm) {
        height = atoi(line0);
        line0 = NextField(line0);
        nColours = atoi(line0);
+       line0 = NextField(line0);
+       if (atoi(line0) != 1) {
+               // Only one char per pixel is supported
+               return;
+       }
        codes = new char[nColours];
        colours = new ColourPair[nColours];
 
@@ -261,6 +266,7 @@ void XPMSet::Add(int id, const char *textForm) {
        for (int i = 0; i < len; i++) {
                if (set[i]->GetId() == id) {
                        set[i]->Init(textForm);
+                       set[i]->CopyDesiredColours();
                        return;
                }
        }
index ccf561d44cc63944bb3a8ace4ef82a049392e48a..1085b5346d12baefad173f006b5e54d91e0c9c32 100644 (file)
@@ -96,6 +96,7 @@ DEFINE_EVENT_TYPE( wxEVT_STC_ZOOM )
 DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_CLICK )
 DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_DCLICK )
 DEFINE_EVENT_TYPE( wxEVT_STC_CALLTIP_CLICK )
+DEFINE_EVENT_TYPE( wxEVT_STC_AUTOCOMP_SELECTION )    
 
 
 
@@ -529,6 +530,11 @@ void wxStyledTextCtrl::MarkerDefineBitmap(int markerNumber, const wxBitmap& bmp)
         
 }
 
+// Add a set of markers to a line.
+void wxStyledTextCtrl::MarkerAddSet(int line, int set) {
+    SendMsg(2466, line, set);
+}
+
 // Set a margin to be either numeric or symbolic.
 void wxStyledTextCtrl::SetMarginType(int margin, int marginType) {
     SendMsg(2240, margin, marginType);
@@ -926,6 +932,28 @@ void wxStyledTextCtrl::AutoCompSetTypeSeparator(int separatorCharacter) {
     SendMsg(2286, separatorCharacter, 0);
 }
 
+// Set the maximum width, in characters, of auto-completion and user lists.
+// Set to 0 to autosize to fit longest item, which is the default.
+void wxStyledTextCtrl::AutoCompSetMaxWidth(int characterCount) {
+    SendMsg(2208, characterCount, 0);
+}
+
+// Get the maximum width, in characters, of auto-completion and user lists.
+int wxStyledTextCtrl::AutoCompGetMaxWidth() {
+    return SendMsg(2209, 0, 0);
+}
+
+// Set the maximum height, in rows, of auto-completion and user lists.
+// The default is 5 rows.
+void wxStyledTextCtrl::AutoCompSetMaxHeight(int rowCount) {
+    SendMsg(2210, rowCount, 0);
+}
+
+// Set the maximum height, in rows, of auto-completion and user lists.
+int wxStyledTextCtrl::AutoCompGetMaxHeight() {
+    return SendMsg(2211, 0, 0);
+}
+
 // Set the number of spaces used for one level of indentation.
 void wxStyledTextCtrl::SetIndent(int indentSize) {
     SendMsg(2122, indentSize, 0);
@@ -1427,6 +1455,11 @@ int wxStyledTextCtrl::DocLineFromVisible(int lineDisplay) {
     return SendMsg(2221, lineDisplay, 0);
 }
 
+// The number of display lines needed to wrap a document line
+int wxStyledTextCtrl::WrapCount(int line) {
+    return SendMsg(2235, line, 0);
+}
+
 // Set the fold level of a line.
 // This encodes an integer level along with flags indicating whether the
 // line is a header and whether it is effectively white space.
@@ -1611,8 +1644,8 @@ void wxStyledTextCtrl::SetEndAtLastLine(bool endAtLastLine) {
 
 // Retrieve whether the maximum scroll position has the last
 // line at the bottom of the view.
-int wxStyledTextCtrl::GetEndAtLastLine() {
-    return SendMsg(2278, 0, 0);
+bool wxStyledTextCtrl::GetEndAtLastLine() {
+    return SendMsg(2278, 0, 0) != 0;
 }
 
 // Retrieve the height of a particular line of text in pixels.
@@ -2412,12 +2445,42 @@ void wxStyledTextCtrl::Allocate(int bytes) {
     SendMsg(2446, bytes, 0);
 }
 
-// Find the position of a column on a line taking into account tabs and 
+// Find the position of a column on a line taking into account tabs and
 // multi-byte characters. If beyond end of line, return line end position.
 int wxStyledTextCtrl::FindColumn(int line, int column) {
     return SendMsg(2456, line, column);
 }
 
+// Can the caret preferred x position only be changed by explicit movement commands?
+bool wxStyledTextCtrl::GetCaretSticky() {
+    return SendMsg(2457, 0, 0) != 0;
+}
+
+// Stop the caret preferred x position changing when the user types.
+void wxStyledTextCtrl::SetCaretSticky(bool useCaretStickyBehaviour) {
+    SendMsg(2458, useCaretStickyBehaviour, 0);
+}
+
+// Switch between sticky and non-sticky: meant to be bound to a key.
+void wxStyledTextCtrl::ToggleCaretSticky() {
+    SendMsg(2459, 0, 0);
+}
+
+// Enable/Disable convert-on-paste for line endings
+void wxStyledTextCtrl::SetPasteConvertEndings(bool convert) {
+    SendMsg(2467, convert, 0);
+}
+
+// Get convert-on-paste setting
+bool wxStyledTextCtrl::GetPasteConvertEndings() {
+    return SendMsg(2468, 0, 0) != 0;
+}
+
+// Duplicate the selection. If selection empty duplicate the line containing the caret.
+void wxStyledTextCtrl::SelectionDuplicate() {
+    SendMsg(2469, 0, 0);
+}
+
 // Start notifying the container of all key presses and commands.
 void wxStyledTextCtrl::StartRecord() {
     SendMsg(3001, 0, 0);
@@ -2458,6 +2521,44 @@ void wxStyledTextCtrl::SetLexerLanguage(const wxString& language) {
     SendMsg(4006, 0, (long)(const char*)wx2stc(language));
 }
 
+// Retrieve a 'property' value previously set with SetProperty.
+wxString wxStyledTextCtrl::GetProperty(const wxString& key) {
+         int len = SendMsg(SCI_GETPROPERTY, (long)(const char*)wx2stc(key), NULL);
+         if (!len) return wxEmptyString;
+
+         wxMemoryBuffer mbuf(len+1);
+         char* buf = (char*)mbuf.GetWriteBuf(len+1);
+         SendMsg(4008, (long)(const char*)wx2stc(key), (long)buf);
+         mbuf.UngetWriteBuf(len);
+         mbuf.AppendByte(0);
+         return stc2wx(buf);
+}
+
+// Retrieve a 'property' value previously set with SetProperty,
+// with '$()' variable replacement on returned buffer.
+wxString wxStyledTextCtrl::GetPropertyExpanded(const wxString& key) {
+         int len = SendMsg(SCI_GETPROPERTYEXPANDED, (long)(const char*)wx2stc(key), NULL);
+         if (!len) return wxEmptyString;
+
+         wxMemoryBuffer mbuf(len+1);
+         char* buf = (char*)mbuf.GetWriteBuf(len+1);
+         SendMsg(4009, (long)(const char*)wx2stc(key), (long)buf);
+         mbuf.UngetWriteBuf(len);
+         mbuf.AppendByte(0);
+         return stc2wx(buf);
+}
+
+// Retrieve a 'property' value previously set with SetProperty,
+// interpreted as an int AFTER any '$()' variable replacement.
+int wxStyledTextCtrl::GetPropertyInt(const wxString& key) {
+    return SendMsg(4010, (long)(const char*)wx2stc(key), 0);
+}
+
+// Retrieve the number of bits the current lexer needs for styling.
+int wxStyledTextCtrl::GetStyleBitsNeeded() {
+    return SendMsg(4011, 0, 0);
+}
+
 // END of generated section
 //----------------------------------------------------------------------
 
@@ -2634,6 +2735,14 @@ void wxStyledTextCtrl::StyleSetCharacterSet(int style, int characterSet)
         case wxSTC_CHARSET_THAI:
             encoding = wxFONTENCODING_ISO8859_11;
             break;
+
+        case wxSTC_CHARSET_CYRILLIC:
+            encoding = wxFONTENCODING_ISO8859_5;
+            break;
+                
+        case wxSTC_CHARSET_8859_15:
+            encoding = wxFONTENCODING_ISO8859_15;;
+            break;
     }
 
     // We just have Scintilla track the wxFontEncoding for us.  It gets used
@@ -3199,6 +3308,10 @@ void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
         evt.SetEventType(wxEVT_STC_CALLTIP_CLICK);
         break;
 
+    case SCN_AUTOCSELECTION:
+        evt.SetEventType(wxEVT_STC_AUTOCOMP_SELECTION);
+        break;
+        
     default:
         return;
     }
index b36707101257b8170a938fe101976187febac68e..b99563feded2b5962193e8d9c7be766baeb3cfb9 100644 (file)
@@ -96,6 +96,7 @@ DEFINE_EVENT_TYPE( wxEVT_STC_ZOOM )
 DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_CLICK )
 DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_DCLICK )
 DEFINE_EVENT_TYPE( wxEVT_STC_CALLTIP_CLICK )
+DEFINE_EVENT_TYPE( wxEVT_STC_AUTOCOMP_SELECTION )    
 
 
 
@@ -402,6 +403,14 @@ void wxStyledTextCtrl::StyleSetCharacterSet(int style, int characterSet)
         case wxSTC_CHARSET_THAI:
             encoding = wxFONTENCODING_ISO8859_11;
             break;
+
+        case wxSTC_CHARSET_CYRILLIC:
+            encoding = wxFONTENCODING_ISO8859_5;
+            break;
+                
+        case wxSTC_CHARSET_8859_15:
+            encoding = wxFONTENCODING_ISO8859_15;;
+            break;
     }
 
     // We just have Scintilla track the wxFontEncoding for us.  It gets used
@@ -967,6 +976,10 @@ void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
         evt.SetEventType(wxEVT_STC_CALLTIP_CLICK);
         break;
 
+    case SCN_AUTOCSELECTION:
+        evt.SetEventType(wxEVT_STC_AUTOCOMP_SELECTION);
+        break;
+        
     default:
         return;
     }
index ad50ff81bdd7b27b900dcb751a3aab79e3a69add..9dd1d5dfbdd2187d3ff12bbbc27245fb342bea8c 100644 (file)
@@ -445,6 +445,7 @@ BEGIN_DECLARE_EVENT_TYPES()
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_HOTSPOT_CLICK,      1673)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_HOTSPOT_DCLICK,     1674)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_CALLTIP_CLICK,      1675)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_AUTOCOMP_SELECTION, 1676)
 END_DECLARE_EVENT_TYPES()
 #else
     enum {
@@ -472,7 +473,8 @@ END_DECLARE_EVENT_TYPES()
         wxEVT_STC_ZOOM,
         wxEVT_STC_HOTSPOT_CLICK,
         wxEVT_STC_HOTSPOT_DCLICK,
-        wxEVT_STC_CALLTIP_CLICK
+        wxEVT_STC_CALLTIP_CLICK,
+        wxEVT_STC_AUTOCOMP_SELECTION
     };
 #endif
 
@@ -506,7 +508,7 @@ typedef void (wxEvtHandler::*wxStyledTextEventFunction)(wxStyledTextEvent&);
 #define EVT_STC_HOTSPOT_CLICK(id, fn)      DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_HOTSPOT_CLICK,         id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #define EVT_STC_HOTSPOT_DCLICK(id, fn)     DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_HOTSPOT_DCLICK,        id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #define EVT_STC_CALLTIP_CLICK(id, fn))     DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_CALLTIP_CLICK          id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
-
+#define EVT_STC_AUTOCOMP_SELECTION(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_AUTOCOMP_SELECTION     id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #endif
 
 //----------------------------------------------------------------------
@@ -515,9 +517,9 @@ typedef void (wxEvtHandler::*wxStyledTextEventFunction)(wxStyledTextEvent&);
 #ifndef SWIG
 #if wxUSE_UNICODE
 
-wxString stc2wx(const char* str);
-wxString stc2wx(const char* str, size_t len);
-const wxWX2MBbuf wx2stc(const wxString& str);
+WXDLLIMPEXP_STC wxString stc2wx(const char* str);
+WXDLLIMPEXP_STC wxString stc2wx(const char* str, size_t len);
+WXDLLIMPEXP_STC const wxWX2MBbuf wx2stc(const wxString& str);
 
 #else // not UNICODE
 
index 5bf0cc31de2f3f5edb8ce0e294240c3cec928e5f..3a1132d020e6e493c72d55ff8cfecf7c7284d385 100644 (file)
 #define wxSTC_MARK_DOTDOTDOT 23
 #define wxSTC_MARK_ARROWS 24
 #define wxSTC_MARK_PIXMAP 25
+#define wxSTC_MARK_FULLRECT 26
 #define wxSTC_MARK_CHARACTER 10000
 
 // Markers used for outlining column.
 #define wxSTC_CHARSET_MAC 77
 #define wxSTC_CHARSET_OEM 255
 #define wxSTC_CHARSET_RUSSIAN 204
+#define wxSTC_CHARSET_CYRILLIC 1251
 #define wxSTC_CHARSET_SHIFTJIS 128
 #define wxSTC_CHARSET_SYMBOL 2
 #define wxSTC_CHARSET_TURKISH 162
 #define wxSTC_CHARSET_ARABIC 178
 #define wxSTC_CHARSET_VIETNAMESE 163
 #define wxSTC_CHARSET_THAI 222
+#define wxSTC_CHARSET_8859_15 1000
 #define wxSTC_CASE_MIXED 0
 #define wxSTC_CASE_UPPER 1
 #define wxSTC_CASE_LOWER 2
 #define wxSTC_TIME_FOREVER 10000000
 #define wxSTC_WRAP_NONE 0
 #define wxSTC_WRAP_WORD 1
+#define wxSTC_WRAP_CHAR 2
 #define wxSTC_WRAPVISUALFLAG_NONE 0x0000
 #define wxSTC_WRAPVISUALFLAG_END 0x0001
 #define wxSTC_WRAPVISUALFLAG_START 0x0002
 #define wxSTC_PERFORMED_USER 0x10
 #define wxSTC_PERFORMED_UNDO 0x20
 #define wxSTC_PERFORMED_REDO 0x40
+#define wxSTC_MULTISTEPUNDOREDO 0x80
 #define wxSTC_LASTSTEPINUNDOREDO 0x100
 #define wxSTC_MOD_CHANGEMARKER 0x200
 #define wxSTC_MOD_BEFOREINSERT 0x400
 #define wxSTC_MOD_BEFOREDELETE 0x800
-#define wxSTC_MODEVENTMASKALL 0xF77
+#define wxSTC_MULTILINEUNDOREDO 0x1000
+#define wxSTC_MODEVENTMASKALL 0x1FFF
 
 // Symbolic key codes and modifier flags.
 // ASCII and other printable characters below 256.
 #define wxSTC_KEY_ADD 310
 #define wxSTC_KEY_SUBTRACT 311
 #define wxSTC_KEY_DIVIDE 312
+#define wxSTC_SCMOD_NORM 0
 #define wxSTC_SCMOD_SHIFT 1
 #define wxSTC_SCMOD_CTRL 2
 #define wxSTC_SCMOD_ALT 4
 #define wxSTC_LEX_NNCRONTAB 26
 #define wxSTC_LEX_BULLANT 27
 #define wxSTC_LEX_VBSCRIPT 28
-#define wxSTC_LEX_ASP 29
-#define wxSTC_LEX_PHP 30
 #define wxSTC_LEX_BAAN 31
 #define wxSTC_LEX_MATLAB 32
 #define wxSTC_LEX_SCRIPTOL 33
 #define wxSTC_LEX_BASH 62
 #define wxSTC_LEX_ASN1 63
 #define wxSTC_LEX_VHDL 64
+#define wxSTC_LEX_CAML 65
+#define wxSTC_LEX_BLITZBASIC 66
+#define wxSTC_LEX_PUREBASIC 67
+#define wxSTC_LEX_HASKELL 68
+#define wxSTC_LEX_PHPSCRIPT 69
+#define wxSTC_LEX_TADS3 70
+#define wxSTC_LEX_REBOL 71
+#define wxSTC_LEX_SMALLTALK 72
+#define wxSTC_LEX_FLAGSHIP 73
+#define wxSTC_LEX_CSOUND 74
+#define wxSTC_LEX_FREEBASIC 75
 
 // When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
 // value assigned in sequence from SCLEX_AUTOMATIC+1.
 #define wxSTC_P_IDENTIFIER 11
 #define wxSTC_P_COMMENTBLOCK 12
 #define wxSTC_P_STRINGEOL 13
+#define wxSTC_P_WORD2 14
+#define wxSTC_P_DECORATOR 15
 
 // Lexical states for SCLEX_CPP
 #define wxSTC_C_DEFAULT 0
 #define wxSTC_PL_ARRAY 13
 #define wxSTC_PL_HASH 14
 #define wxSTC_PL_SYMBOLTABLE 15
+#define wxSTC_PL_VARIABLE_INDEXER 16
 #define wxSTC_PL_REGEX 17
 #define wxSTC_PL_REGSUBST 18
 #define wxSTC_PL_LONGQUOTE 19
 #define wxSTC_PL_STRING_QX 28
 #define wxSTC_PL_STRING_QR 29
 #define wxSTC_PL_STRING_QW 30
+#define wxSTC_PL_POD_VERB 31
+
+// Lexical states for SCLEX_RUBY
+#define wxSTC_RB_DEFAULT 0
+#define wxSTC_RB_ERROR 1
+#define wxSTC_RB_COMMENTLINE 2
+#define wxSTC_RB_POD 3
+#define wxSTC_RB_NUMBER 4
+#define wxSTC_RB_WORD 5
+#define wxSTC_RB_STRING 6
+#define wxSTC_RB_CHARACTER 7
+#define wxSTC_RB_CLASSNAME 8
+#define wxSTC_RB_DEFNAME 9
+#define wxSTC_RB_OPERATOR 10
+#define wxSTC_RB_IDENTIFIER 11
+#define wxSTC_RB_REGEX 12
+#define wxSTC_RB_GLOBAL 13
+#define wxSTC_RB_SYMBOL 14
+#define wxSTC_RB_MODULE_NAME 15
+#define wxSTC_RB_INSTANCE_VAR 16
+#define wxSTC_RB_CLASS_VAR 17
+#define wxSTC_RB_BACKTICKS 18
+#define wxSTC_RB_DATASECTION 19
+#define wxSTC_RB_HERE_DELIM 20
+#define wxSTC_RB_HERE_Q 21
+#define wxSTC_RB_HERE_QQ 22
+#define wxSTC_RB_HERE_QX 23
+#define wxSTC_RB_STRING_Q 24
+#define wxSTC_RB_STRING_QQ 25
+#define wxSTC_RB_STRING_QX 26
+#define wxSTC_RB_STRING_QR 27
+#define wxSTC_RB_STRING_QW 28
+#define wxSTC_RB_WORD_DEMOTED 29
+#define wxSTC_RB_STDIN 30
+#define wxSTC_RB_STDOUT 31
+#define wxSTC_RB_STDERR 40
+#define wxSTC_RB_UPPER_BOUND 41
 
 // Lexical states for SCLEX_VB, SCLEX_VBSCRIPT, SCLEX_POWERBASIC
 #define wxSTC_B_DEFAULT 0
 #define wxSTC_B_KEYWORD4 12
 #define wxSTC_B_CONSTANT 13
 #define wxSTC_B_ASM 14
+#define wxSTC_B_LABEL 15
+#define wxSTC_B_ERROR 16
+#define wxSTC_B_HEXNUMBER 17
+#define wxSTC_B_BINNUMBER 18
 
 // Lexical states for SCLEX_PROPERTIES
 #define wxSTC_PROPS_DEFAULT 0
 #define wxSTC_LISP_COMMENT 1
 #define wxSTC_LISP_NUMBER 2
 #define wxSTC_LISP_KEYWORD 3
+#define wxSTC_LISP_KEYWORD_KW 4
+#define wxSTC_LISP_SYMBOL 5
 #define wxSTC_LISP_STRING 6
 #define wxSTC_LISP_STRINGEOL 8
 #define wxSTC_LISP_IDENTIFIER 9
 #define wxSTC_LISP_OPERATOR 10
+#define wxSTC_LISP_SPECIAL 11
+#define wxSTC_LISP_MULTI_COMMENT 12
 
 // Lexical states for SCLEX_EIFFEL and SCLEX_EIFFELKW
 #define wxSTC_EIFFEL_DEFAULT 0
 #define wxSTC_CSS_DOUBLESTRING 13
 #define wxSTC_CSS_SINGLESTRING 14
 #define wxSTC_CSS_IDENTIFIER2 15
+#define wxSTC_CSS_ATTRIBUTE 16
 
 // Lexical states for SCLEX_POV
 #define wxSTC_POV_DEFAULT 0
 #define wxSTC_NSIS_MACRODEF 12
 #define wxSTC_NSIS_STRINGVAR 13
 #define wxSTC_NSIS_NUMBER 14
+#define wxSTC_NSIS_SECTIONGROUP 15
+#define wxSTC_NSIS_PAGEEX 16
+#define wxSTC_NSIS_FUNCTIONDEF 17
+#define wxSTC_NSIS_COMMENTBOX 18
 
 // Lexical states for SCLEX_MMIXAL
 #define wxSTC_MMIXAL_LEADWS 0
 #define wxSTC_CLW_PICTURE_STRING 7
 #define wxSTC_CLW_KEYWORD 8
 #define wxSTC_CLW_COMPILER_DIRECTIVE 9
-#define wxSTC_CLW_BUILTIN_PROCEDURES_FUNCTION 10
-#define wxSTC_CLW_STRUCTURE_DATA_TYPE 11
-#define wxSTC_CLW_ATTRIBUTE 12
-#define wxSTC_CLW_STANDARD_EQUATE 13
-#define wxSTC_CLW_ERROR 14
+#define wxSTC_CLW_RUNTIME_EXPRESSIONS 10
+#define wxSTC_CLW_BUILTIN_PROCEDURES_FUNCTION 11
+#define wxSTC_CLW_STRUCTURE_DATA_TYPE 12
+#define wxSTC_CLW_ATTRIBUTE 13
+#define wxSTC_CLW_STANDARD_EQUATE 14
+#define wxSTC_CLW_ERROR 15
+#define wxSTC_CLW_DEPRECATED 16
 
 // Lexical states for SCLEX_LOT
 #define wxSTC_LOT_DEFAULT 0
 #define wxSTC_AU3_SENT 10
 #define wxSTC_AU3_PREPROCESSOR 11
 #define wxSTC_AU3_SPECIAL 12
+#define wxSTC_AU3_EXPAND 13
+#define wxSTC_AU3_COMOBJ 14
 
 // Lexical states for SCLEX_APDL
 #define wxSTC_APDL_DEFAULT 0
 #define wxSTC_VHDL_STDTYPE 13
 #define wxSTC_VHDL_USERWORD 14
 
+// Lexical states for SCLEX_CAML
+#define wxSTC_CAML_DEFAULT 0
+#define wxSTC_CAML_IDENTIFIER 1
+#define wxSTC_CAML_TAGNAME 2
+#define wxSTC_CAML_KEYWORD 3
+#define wxSTC_CAML_KEYWORD2 4
+#define wxSTC_CAML_KEYWORD3 5
+#define wxSTC_CAML_LINENUM 6
+#define wxSTC_CAML_OPERATOR 7
+#define wxSTC_CAML_NUMBER 8
+#define wxSTC_CAML_CHAR 9
+#define wxSTC_CAML_STRING 11
+#define wxSTC_CAML_COMMENT 12
+#define wxSTC_CAML_COMMENT1 13
+#define wxSTC_CAML_COMMENT2 14
+#define wxSTC_CAML_COMMENT3 15
+
+// Lexical states for SCLEX_HASKELL
+#define wxSTC_HA_DEFAULT 0
+#define wxSTC_HA_IDENTIFIER 1
+#define wxSTC_HA_KEYWORD 2
+#define wxSTC_HA_NUMBER 3
+#define wxSTC_HA_STRING 4
+#define wxSTC_HA_CHARACTER 5
+#define wxSTC_HA_CLASS 6
+#define wxSTC_HA_MODULE 7
+#define wxSTC_HA_CAPITAL 8
+#define wxSTC_HA_DATA 9
+#define wxSTC_HA_IMPORT 10
+#define wxSTC_HA_OPERATOR 11
+#define wxSTC_HA_INSTANCE 12
+#define wxSTC_HA_COMMENTLINE 13
+#define wxSTC_HA_COMMENTBLOCK 14
+#define wxSTC_HA_COMMENTBLOCK2 15
+#define wxSTC_HA_COMMENTBLOCK3 16
+
+// Lexical states of SCLEX_TADS3
+#define wxSTC_T3_DEFAULT 0
+#define wxSTC_T3_X_DEFAULT 1
+#define wxSTC_T3_PREPROCESSOR 2
+#define wxSTC_T3_BLOCK_COMMENT 3
+#define wxSTC_T3_LINE_COMMENT 4
+#define wxSTC_T3_OPERATOR 5
+#define wxSTC_T3_KEYWORD 6
+#define wxSTC_T3_NUMBER 7
+#define wxSTC_T3_IDENTIFIER 8
+#define wxSTC_T3_S_STRING 9
+#define wxSTC_T3_D_STRING 10
+#define wxSTC_T3_X_STRING 11
+#define wxSTC_T3_LIB_DIRECTIVE 12
+#define wxSTC_T3_MSG_PARAM 13
+#define wxSTC_T3_HTML_TAG 14
+#define wxSTC_T3_HTML_DEFAULT 15
+#define wxSTC_T3_HTML_STRING 16
+#define wxSTC_T3_USER1 17
+#define wxSTC_T3_USER2 18
+#define wxSTC_T3_USER3 19
+
+// Lexical states for SCLEX_REBOL
+#define wxSTC_REBOL_DEFAULT 0
+#define wxSTC_REBOL_COMMENTLINE 1
+#define wxSTC_REBOL_COMMENTBLOCK 2
+#define wxSTC_REBOL_PREFACE 3
+#define wxSTC_REBOL_OPERATOR 4
+#define wxSTC_REBOL_CHARACTER 5
+#define wxSTC_REBOL_QUOTEDSTRING 6
+#define wxSTC_REBOL_BRACEDSTRING 7
+#define wxSTC_REBOL_NUMBER 8
+#define wxSTC_REBOL_PAIR 9
+#define wxSTC_REBOL_TUPLE 10
+#define wxSTC_REBOL_BINARY 11
+#define wxSTC_REBOL_MONEY 12
+#define wxSTC_REBOL_ISSUE 13
+#define wxSTC_REBOL_TAG 14
+#define wxSTC_REBOL_FILE 15
+#define wxSTC_REBOL_EMAIL 16
+#define wxSTC_REBOL_URL 17
+#define wxSTC_REBOL_DATE 18
+#define wxSTC_REBOL_TIME 19
+#define wxSTC_REBOL_IDENTIFIER 20
+#define wxSTC_REBOL_WORD 21
+#define wxSTC_REBOL_WORD2 22
+#define wxSTC_REBOL_WORD3 23
+#define wxSTC_REBOL_WORD4 24
+#define wxSTC_REBOL_WORD5 25
+#define wxSTC_REBOL_WORD6 26
+#define wxSTC_REBOL_WORD7 27
+#define wxSTC_REBOL_WORD8 28
+
+// Lexical states for SCLEX_SQL
+#define wxSTC_SQL_DEFAULT 0
+#define wxSTC_SQL_COMMENT 1
+#define wxSTC_SQL_COMMENTLINE 2
+#define wxSTC_SQL_COMMENTDOC 3
+#define wxSTC_SQL_NUMBER 4
+#define wxSTC_SQL_WORD 5
+#define wxSTC_SQL_STRING 6
+#define wxSTC_SQL_CHARACTER 7
+#define wxSTC_SQL_SQLPLUS 8
+#define wxSTC_SQL_SQLPLUS_PROMPT 9
+#define wxSTC_SQL_OPERATOR 10
+#define wxSTC_SQL_IDENTIFIER 11
+#define wxSTC_SQL_SQLPLUS_COMMENT 13
+#define wxSTC_SQL_COMMENTLINEDOC 15
+#define wxSTC_SQL_WORD2 16
+#define wxSTC_SQL_COMMENTDOCKEYWORD 17
+#define wxSTC_SQL_COMMENTDOCKEYWORDERROR 18
+#define wxSTC_SQL_USER1 19
+#define wxSTC_SQL_USER2 20
+#define wxSTC_SQL_USER3 21
+#define wxSTC_SQL_USER4 22
+#define wxSTC_SQL_QUOTEDIDENTIFIER 23
+
+// Lexical states for SCLEX_SMALLTALK
+#define wxSTC_ST_DEFAULT 0
+#define wxSTC_ST_STRING 1
+#define wxSTC_ST_NUMBER 2
+#define wxSTC_ST_COMMENT 3
+#define wxSTC_ST_SYMBOL 4
+#define wxSTC_ST_BINARY 5
+#define wxSTC_ST_BOOL 6
+#define wxSTC_ST_SELF 7
+#define wxSTC_ST_SUPER 8
+#define wxSTC_ST_NIL 9
+#define wxSTC_ST_GLOBAL 10
+#define wxSTC_ST_RETURN 11
+#define wxSTC_ST_SPECIAL 12
+#define wxSTC_ST_KWSEND 13
+#define wxSTC_ST_ASSIGN 14
+#define wxSTC_ST_CHARACTER 15
+#define wxSTC_ST_SPEC_SEL 16
+
+// Lexical states for SCLEX_FLAGSHIP (clipper)
+#define wxSTC_FS_DEFAULT 0
+#define wxSTC_FS_COMMENT 1
+#define wxSTC_FS_COMMENTLINE 2
+#define wxSTC_FS_COMMENTDOC 3
+#define wxSTC_FS_COMMENTLINEDOC 4
+#define wxSTC_FS_COMMENTDOCKEYWORD 5
+#define wxSTC_FS_COMMENTDOCKEYWORDERROR 6
+#define wxSTC_FS_KEYWORD 7
+#define wxSTC_FS_KEYWORD2 8
+#define wxSTC_FS_KEYWORD3 9
+#define wxSTC_FS_KEYWORD4 10
+#define wxSTC_FS_NUMBER 11
+#define wxSTC_FS_STRING 12
+#define wxSTC_FS_PREPROCESSOR 13
+#define wxSTC_FS_OPERATOR 14
+#define wxSTC_FS_IDENTIFIER 15
+#define wxSTC_FS_DATE 16
+#define wxSTC_FS_STRINGEOL 17
+#define wxSTC_FS_CONSTANT 18
+#define wxSTC_FS_ASM 19
+#define wxSTC_FS_LABEL 20
+#define wxSTC_FS_ERROR 21
+#define wxSTC_FS_HEXNUMBER 22
+#define wxSTC_FS_BINNUMBER 23
+
+// Lexical states for SCLEX_CSOUND
+#define wxSTC_CSOUND_DEFAULT 0
+#define wxSTC_CSOUND_COMMENT 1
+#define wxSTC_CSOUND_NUMBER 2
+#define wxSTC_CSOUND_OPERATOR 3
+#define wxSTC_CSOUND_INSTR 4
+#define wxSTC_CSOUND_IDENTIFIER 5
+#define wxSTC_CSOUND_OPCODE 6
+#define wxSTC_CSOUND_HEADERSTMT 7
+#define wxSTC_CSOUND_USERKEYWORD 8
+#define wxSTC_CSOUND_COMMENTBLOCK 9
+#define wxSTC_CSOUND_PARAM 10
+#define wxSTC_CSOUND_ARATE_VAR 11
+#define wxSTC_CSOUND_KRATE_VAR 12
+#define wxSTC_CSOUND_IRATE_VAR 13
+#define wxSTC_CSOUND_GLOBAL_VAR 14
+#define wxSTC_CSOUND_STRINGEOL 15
+
 
 //-----------------------------------------
 // Commands that can be bound to keystrokes
@@ -1679,6 +1928,9 @@ public:
     // Define a marker from a bitmap
     void MarkerDefineBitmap(int markerNumber, const wxBitmap& bmp);
 
+    // Add a set of markers to a line.
+    void MarkerAddSet(int line, int set);
+
     // Set a margin to be either numeric or symbolic.
     void SetMarginType(int margin, int marginType);
 
@@ -1914,6 +2166,20 @@ public:
     // Default is '?' but can be changed if items contain '?'.
     void AutoCompSetTypeSeparator(int separatorCharacter);
 
+    // Set the maximum width, in characters, of auto-completion and user lists.
+    // Set to 0 to autosize to fit longest item, which is the default.
+    void AutoCompSetMaxWidth(int characterCount);
+
+    // Get the maximum width, in characters, of auto-completion and user lists.
+    int AutoCompGetMaxWidth();
+
+    // Set the maximum height, in rows, of auto-completion and user lists.
+    // The default is 5 rows.
+    void AutoCompSetMaxHeight(int rowCount);
+
+    // Set the maximum height, in rows, of auto-completion and user lists.
+    int AutoCompGetMaxHeight();
+
     // Set the number of spaces used for one level of indentation.
     void SetIndent(int indentSize);
 
@@ -2176,6 +2442,9 @@ public:
     // Find the document line of a display line taking hidden lines into account.
     int DocLineFromVisible(int lineDisplay);
 
+    // The number of display lines needed to wrap a document line
+    int WrapCount(int line);
+
     // Set the fold level of a line.
     // This encodes an integer level along with flags indicating whether the
     // line is a header and whether it is effectively white space.
@@ -2290,7 +2559,7 @@ public:
 
     // Retrieve whether the maximum scroll position has the last
     // line at the bottom of the view.
-    int GetEndAtLastLine();
+    bool GetEndAtLastLine();
 
     // Retrieve the height of a particular line of text in pixels.
     int TextHeight(int line);
@@ -2773,10 +3042,28 @@ public:
     // Enlarge the document to a particular size of text bytes.
     void Allocate(int bytes);
 
-    // Find the position of a column on a line taking into account tabs and 
+    // Find the position of a column on a line taking into account tabs and
     // multi-byte characters. If beyond end of line, return line end position.
     int FindColumn(int line, int column);
 
+    // Can the caret preferred x position only be changed by explicit movement commands?
+    bool GetCaretSticky();
+
+    // Stop the caret preferred x position changing when the user types.
+    void SetCaretSticky(bool useCaretStickyBehaviour);
+
+    // Switch between sticky and non-sticky: meant to be bound to a key.
+    void ToggleCaretSticky();
+
+    // Enable/Disable convert-on-paste for line endings
+    void SetPasteConvertEndings(bool convert);
+
+    // Get convert-on-paste setting
+    bool GetPasteConvertEndings();
+
+    // Duplicate the selection. If selection empty duplicate the line containing the caret.
+    void SelectionDuplicate();
+
     // Start notifying the container of all key presses and commands.
     void StartRecord();
 
@@ -2801,6 +3088,20 @@ public:
     // Set the lexing language of the document based on string name.
     void SetLexerLanguage(const wxString& language);
 
+    // Retrieve a 'property' value previously set with SetProperty.
+    wxString GetProperty(const wxString& key);
+
+    // Retrieve a 'property' value previously set with SetProperty,
+    // with '$()' variable replacement on returned buffer.
+    wxString GetPropertyExpanded(const wxString& key);
+
+    // Retrieve a 'property' value previously set with SetProperty,
+    // interpreted as an int AFTER any '$()' variable replacement.
+    int GetPropertyInt(const wxString& key);
+
+    // Retrieve the number of bits the current lexer needs for styling.
+    int GetStyleBitsNeeded();
+
 // END of generated section
 //----------------------------------------------------------------------
 // Others...
@@ -3131,6 +3432,7 @@ BEGIN_DECLARE_EVENT_TYPES()
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_HOTSPOT_CLICK,      1673)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_HOTSPOT_DCLICK,     1674)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_CALLTIP_CLICK,      1675)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_AUTOCOMP_SELECTION, 1676)
 END_DECLARE_EVENT_TYPES()
 #else
     enum {
@@ -3158,7 +3460,8 @@ END_DECLARE_EVENT_TYPES()
         wxEVT_STC_ZOOM,
         wxEVT_STC_HOTSPOT_CLICK,
         wxEVT_STC_HOTSPOT_DCLICK,
-        wxEVT_STC_CALLTIP_CLICK
+        wxEVT_STC_CALLTIP_CLICK,
+        wxEVT_STC_AUTOCOMP_SELECTION
     };
 #endif
 
@@ -3192,7 +3495,7 @@ typedef void (wxEvtHandler::*wxStyledTextEventFunction)(wxStyledTextEvent&);
 #define EVT_STC_HOTSPOT_CLICK(id, fn)      DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_HOTSPOT_CLICK,         id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #define EVT_STC_HOTSPOT_DCLICK(id, fn)     DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_HOTSPOT_DCLICK,        id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #define EVT_STC_CALLTIP_CLICK(id, fn))     DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_CALLTIP_CLICK          id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
-
+#define EVT_STC_AUTOCOMP_SELECTION(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_AUTOCOMP_SELECTION     id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #endif
 
 //----------------------------------------------------------------------
index 9662358d41076051c01c6c6a170675f3dee89ab1..ef6471fac45ca24ed8bdf9e02acc2f4827db6602 100644 (file)
@@ -82,19 +82,24 @@ STCDLL_OBJECTS =  \
        stcdll_LexAsn1.o \
        stcdll_LexBaan.o \
        stcdll_LexBash.o \
+       stcdll_LexBasic.o \
        stcdll_LexBullant.o \
        stcdll_LexCLW.o \
        stcdll_LexCPP.o \
        stcdll_LexCSS.o \
+       stcdll_LexCaml.o \
+       stcdll_LexCsound.o \
        stcdll_LexConf.o \
        stcdll_LexCrontab.o \
        stcdll_LexEScript.o \
        stcdll_LexEiffel.o \
        stcdll_LexErlang.o \
+       stcdll_LexFlagship.o \
        stcdll_LexForth.o \
        stcdll_LexFortran.o \
        stcdll_LexGui4Cli.o \
        stcdll_LexHTML.o \
+       stcdll_LexHaskell.o \
        stcdll_LexKix.o \
        stcdll_LexLisp.o \
        stcdll_LexLout.o \
@@ -112,8 +117,11 @@ STCDLL_OBJECTS =  \
        stcdll_LexPascal.o \
        stcdll_LexPerl.o \
        stcdll_LexPython.o \
+       stcdll_LexRebol.o \
        stcdll_LexRuby.o \
        stcdll_LexSQL.o \
+       stcdll_LexSmalltalk.o \
+       stcdll_LexTADS3.o \
        stcdll_LexScriptol.o \
        stcdll_LexSpecman.o \
        stcdll_LexTeX.o \
@@ -159,19 +167,24 @@ STCLIB_OBJECTS =  \
        stclib_LexAsn1.o \
        stclib_LexBaan.o \
        stclib_LexBash.o \
+       stclib_LexBasic.o \
        stclib_LexBullant.o \
        stclib_LexCLW.o \
        stclib_LexCPP.o \
        stclib_LexCSS.o \
+       stclib_LexCaml.o \
+       stclib_LexCsound.o \
        stclib_LexConf.o \
        stclib_LexCrontab.o \
        stclib_LexEScript.o \
        stclib_LexEiffel.o \
        stclib_LexErlang.o \
+       stclib_LexFlagship.o \
        stclib_LexForth.o \
        stclib_LexFortran.o \
        stclib_LexGui4Cli.o \
        stclib_LexHTML.o \
+       stclib_LexHaskell.o \
        stclib_LexKix.o \
        stclib_LexLisp.o \
        stclib_LexLout.o \
@@ -189,8 +202,11 @@ STCLIB_OBJECTS =  \
        stclib_LexPascal.o \
        stclib_LexPerl.o \
        stclib_LexPython.o \
+       stclib_LexRebol.o \
        stclib_LexRuby.o \
        stclib_LexSQL.o \
+       stclib_LexSmalltalk.o \
+       stclib_LexTADS3.o \
        stclib_LexScriptol.o \
        stclib_LexSpecman.o \
        stclib_LexTeX.o \
@@ -447,6 +463,9 @@ stcdll_LexBaan.o: $(srcdir)/scintilla/src/LexBaan.cxx
 stcdll_LexBash.o: $(srcdir)/scintilla/src/LexBash.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexBash.cxx
 
+stcdll_LexBasic.o: $(srcdir)/scintilla/src/LexBasic.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexBasic.cxx
+
 stcdll_LexBullant.o: $(srcdir)/scintilla/src/LexBullant.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexBullant.cxx
 
@@ -459,6 +478,12 @@ stcdll_LexCPP.o: $(srcdir)/scintilla/src/LexCPP.cxx
 stcdll_LexCSS.o: $(srcdir)/scintilla/src/LexCSS.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexCSS.cxx
 
+stcdll_LexCaml.o: $(srcdir)/scintilla/src/LexCaml.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexCaml.cxx
+
+stcdll_LexCsound.o: $(srcdir)/scintilla/src/LexCsound.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexCsound.cxx
+
 stcdll_LexConf.o: $(srcdir)/scintilla/src/LexConf.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexConf.cxx
 
@@ -474,6 +499,9 @@ stcdll_LexEiffel.o: $(srcdir)/scintilla/src/LexEiffel.cxx
 stcdll_LexErlang.o: $(srcdir)/scintilla/src/LexErlang.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexErlang.cxx
 
+stcdll_LexFlagship.o: $(srcdir)/scintilla/src/LexFlagship.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexFlagship.cxx
+
 stcdll_LexForth.o: $(srcdir)/scintilla/src/LexForth.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexForth.cxx
 
@@ -486,6 +514,9 @@ stcdll_LexGui4Cli.o: $(srcdir)/scintilla/src/LexGui4Cli.cxx
 stcdll_LexHTML.o: $(srcdir)/scintilla/src/LexHTML.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexHTML.cxx
 
+stcdll_LexHaskell.o: $(srcdir)/scintilla/src/LexHaskell.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexHaskell.cxx
+
 stcdll_LexKix.o: $(srcdir)/scintilla/src/LexKix.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexKix.cxx
 
@@ -537,12 +568,21 @@ stcdll_LexPerl.o: $(srcdir)/scintilla/src/LexPerl.cxx
 stcdll_LexPython.o: $(srcdir)/scintilla/src/LexPython.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexPython.cxx
 
+stcdll_LexRebol.o: $(srcdir)/scintilla/src/LexRebol.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexRebol.cxx
+
 stcdll_LexRuby.o: $(srcdir)/scintilla/src/LexRuby.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexRuby.cxx
 
 stcdll_LexSQL.o: $(srcdir)/scintilla/src/LexSQL.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexSQL.cxx
 
+stcdll_LexSmalltalk.o: $(srcdir)/scintilla/src/LexSmalltalk.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexSmalltalk.cxx
+
+stcdll_LexTADS3.o: $(srcdir)/scintilla/src/LexTADS3.cxx
+       $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexTADS3.cxx
+
 stcdll_LexScriptol.o: $(srcdir)/scintilla/src/LexScriptol.cxx
        $(CXXC) -c -o $@ $(STCDLL_CXXFLAGS) $(srcdir)/scintilla/src/LexScriptol.cxx
 
@@ -660,6 +700,9 @@ stclib_LexBaan.o: $(srcdir)/scintilla/src/LexBaan.cxx
 stclib_LexBash.o: $(srcdir)/scintilla/src/LexBash.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexBash.cxx
 
+stclib_LexBasic.o: $(srcdir)/scintilla/src/LexBasic.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexBasic.cxx
+
 stclib_LexBullant.o: $(srcdir)/scintilla/src/LexBullant.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexBullant.cxx
 
@@ -672,6 +715,12 @@ stclib_LexCPP.o: $(srcdir)/scintilla/src/LexCPP.cxx
 stclib_LexCSS.o: $(srcdir)/scintilla/src/LexCSS.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexCSS.cxx
 
+stclib_LexCaml.o: $(srcdir)/scintilla/src/LexCaml.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexCaml.cxx
+
+stclib_LexCsound.o: $(srcdir)/scintilla/src/LexCsound.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexCsound.cxx
+
 stclib_LexConf.o: $(srcdir)/scintilla/src/LexConf.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexConf.cxx
 
@@ -687,6 +736,9 @@ stclib_LexEiffel.o: $(srcdir)/scintilla/src/LexEiffel.cxx
 stclib_LexErlang.o: $(srcdir)/scintilla/src/LexErlang.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexErlang.cxx
 
+stclib_LexFlagship.o: $(srcdir)/scintilla/src/LexFlagship.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexFlagship.cxx
+
 stclib_LexForth.o: $(srcdir)/scintilla/src/LexForth.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexForth.cxx
 
@@ -699,6 +751,9 @@ stclib_LexGui4Cli.o: $(srcdir)/scintilla/src/LexGui4Cli.cxx
 stclib_LexHTML.o: $(srcdir)/scintilla/src/LexHTML.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexHTML.cxx
 
+stclib_LexHaskell.o: $(srcdir)/scintilla/src/LexHaskell.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexHaskell.cxx
+
 stclib_LexKix.o: $(srcdir)/scintilla/src/LexKix.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexKix.cxx
 
@@ -750,12 +805,21 @@ stclib_LexPerl.o: $(srcdir)/scintilla/src/LexPerl.cxx
 stclib_LexPython.o: $(srcdir)/scintilla/src/LexPython.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexPython.cxx
 
+stclib_LexRebol.o: $(srcdir)/scintilla/src/LexRebol.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexRebol.cxx
+
 stclib_LexRuby.o: $(srcdir)/scintilla/src/LexRuby.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexRuby.cxx
 
 stclib_LexSQL.o: $(srcdir)/scintilla/src/LexSQL.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexSQL.cxx
 
+stclib_LexSmalltalk.o: $(srcdir)/scintilla/src/LexSmalltalk.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexSmalltalk.cxx
+
+stclib_LexTADS3.o: $(srcdir)/scintilla/src/LexTADS3.cxx
+       $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexTADS3.cxx
+
 stclib_LexScriptol.o: $(srcdir)/scintilla/src/LexScriptol.cxx
        $(CXXC) -c -o $@ $(STCLIB_CXXFLAGS) $(srcdir)/scintilla/src/LexScriptol.cxx
 
index 81f172cd71c0c449f534dd379258fc7b0b51aa5b..5d7948423b3685ef92d4551c003ad19a278a87d5 100644 (file)
@@ -12,6 +12,7 @@
 #include "wx/mstream.h"
 #include "wx/image.h"
 #include "wx/imaglist.h"
+#include "wx/tokenzr.h"
 
 #include "Platform.h"
 #include "PlatWX.h"
@@ -686,7 +687,7 @@ private:
     CallBackAction      doubleClickAction;
     void*               doubleClickActionData;
 public:
-    wxSTCListBoxWin(wxWindow* parent, wxWindowID id) :
+    wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point location) :
         wxPopupWindow(parent, wxBORDER_NONE)
     {
         SetBackgroundColour(*wxBLACK);  // for our simple border
@@ -804,8 +805,8 @@ private:
     CallBackAction      doubleClickAction;
     void*               doubleClickActionData;
 public:
-    wxSTCListBoxWin(wxWindow* parent, wxWindowID id) :
-        wxWindow(parent, id, wxDefaultPosition, wxSize(0,0), wxSIMPLE_BORDER )
+    wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point location) :
+        wxWindow(parent, id, wxPoint(location.x, location.y), wxSize(0,0), wxSIMPLE_BORDER )
     {
 
         lv = new wxSTCListBox(this, id, wxDefaultPosition, wxDefaultSize,
@@ -919,6 +920,7 @@ private:
     int                 desiredVisibleRows;
     int                 aveCharWidth;
     int                 maxStrWidth;
+    Point               location;       // Caret location at which the list is opened
     wxImageList*        imgList;
     wxArrayInt*         imgTypeMap;
 
@@ -927,13 +929,15 @@ public:
     ~ListBoxImpl();
 
     virtual void SetFont(Font &font);
-    virtual void Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_);
+    virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_);
     virtual void SetAverageCharWidth(int width);
     virtual void SetVisibleRows(int rows);
+    virtual int GetVisibleRows() const;
     virtual PRectangle GetDesiredRect();
     virtual int CaretFromEdge();
     virtual void Clear();
     virtual void Append(char *s, int type = -1);
+            void Append(const wxString& text, int type);
     virtual int Length();
     virtual void Select(int n);
     virtual int GetSelection();
@@ -942,7 +946,7 @@ public:
     virtual void RegisterImage(int type, const char *xpm_data);
     virtual void ClearRegisteredImages();
     virtual void SetDoubleClickAction(CallBackAction, void *);
-
+    virtual void SetList(const char* list, char separator, char typesep);
 };
 
 
@@ -970,11 +974,12 @@ void ListBoxImpl::SetFont(Font &font) {
 }
 
 
-void ListBoxImpl::Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_) {
+void ListBoxImpl::Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_) {
+    location = location_;
     lineHeight =  lineHeight_;
     unicodeMode = unicodeMode_;
     maxStrWidth = 0;
-    id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID);
+    id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID, location);
     if (imgList != NULL)
         GETLB(id)->SetImageList(imgList, wxIMAGE_LIST_SMALL);
 }
@@ -990,10 +995,14 @@ void ListBoxImpl::SetVisibleRows(int rows) {
 }
 
 
+int ListBoxImpl::GetVisibleRows() const {
+    return desiredVisibleRows;
+}
+
 PRectangle ListBoxImpl::GetDesiredRect() {
     // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
     // the max size in Append and calculate it here...
-    int maxw = maxStrWidth;
+    int maxw = maxStrWidth * aveCharWidth;
     int maxh ;
 
     // give it a default if there are no lines, and/or add a bit more
@@ -1039,13 +1048,14 @@ void ListBoxImpl::Clear() {
 
 
 void ListBoxImpl::Append(char *s, int type) {
-    wxString text = stc2wx(s);
+    Append(stc2wx(s), type);
+}
+
+void ListBoxImpl::Append(const wxString& text, int type) {
     long count  = GETLB(id)->GetItemCount();
     long itemID  = GETLB(id)->InsertItem(count, wxEmptyString);
     GETLB(id)->SetItem(itemID, 1, text);
-    int itemWidth = 0;
-    GETLB(id)->GetTextExtent(text, &itemWidth, NULL);
-    maxStrWidth = wxMax(maxStrWidth, itemWidth);
+    maxStrWidth = wxMax(maxStrWidth, text.Length());
     if (type != -1) {
         wxCHECK_RET(imgTypeMap, wxT("Unexpected NULL imgTypeMap"));
         long idx = imgTypeMap->Item(type);
@@ -1053,6 +1063,23 @@ void ListBoxImpl::Append(char *s, int type) {
     }
 }
 
+void ListBoxImpl::SetList(const char* list, char separator, char typesep) {
+    GETLB(id)->Freeze();
+    Clear();    
+    wxStringTokenizer tkzr(stc2wx(list), (wxChar)separator);
+    while ( tkzr.HasMoreTokens() ) {
+        wxString token = tkzr.GetNextToken();
+        long type = -1;
+        int pos = token.Find(typesep);
+        if (pos != -1) {
+            token.Mid(pos+1).ToLong(&type);
+            token.Truncate(pos);
+        }
+        Append(token, (int)type);
+    }
+    GETLB(id)->Thaw();
+}
+
 
 int ListBoxImpl::Length() {
     return GETLB(id)->GetItemCount();
@@ -1133,7 +1160,6 @@ void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data) {
 }
 
 
-
 ListBox::ListBox() {
 }
 
index 4e0afbb12919223ce91886da00d085fc8315d8bc..62d7a455184e809c0e68b5bbabeae03f90d4db64 100644 (file)
@@ -293,7 +293,12 @@ methodOverrideMap = {
     'AutoCGetTypeSeparator' : ('AutoCompGetTypeSeparator', 0, 0, 0),
     'AutoCSetTypeSeparator' : ('AutoCompSetTypeSeparator', 0, 0, 0),
     'AutoCGetCurrent'       : ('AutoCompGetCurrent', 0, 0, 0),
-
+    'AutoCSetMaxWidth'      : ('AutoCompSetMaxWidth', 0, 0, 0),
+    'AutoCGetMaxWidth'      : ('AutoCompGetMaxWidth', 0, 0, 0),
+    'AutoCSetMaxHeight'     : ('AutoCompSetMaxHeight', 0, 0, 0),
+    'AutoCGetMaxHeight'     : ('AutoCompGetMaxHeight', 0, 0, 0),
+    'AutoCGetMaxHeight'     : ('AutoCompGetMaxHeight', 0, 0, 0),
+    
     'RegisterImage' :
     (0,
      '''void %s(int type, const wxBitmap& bmp);''',
@@ -519,7 +524,45 @@ methodOverrideMap = {
     'TargetAsUTF8' :       ( None, 0, 0, 0),
     'SetLengthForEncode' : ( None, 0, 0, 0),
     'EncodedFromUTF8' :    ( None, 0, 0, 0),
-    
+
+
+    'GetProperty' :
+    (0,
+     'wxString %s(const wxString& key);',
+
+     '''wxString %s(const wxString& key) {
+         int len = SendMsg(SCI_GETPROPERTY, (long)(const char*)wx2stc(key), NULL);
+         if (!len) return wxEmptyString;
+
+         wxMemoryBuffer mbuf(len+1);
+         char* buf = (char*)mbuf.GetWriteBuf(len+1);
+         SendMsg(%s, (long)(const char*)wx2stc(key), (long)buf);
+         mbuf.UngetWriteBuf(len);
+         mbuf.AppendByte(0);
+         return stc2wx(buf);''',
+     ("Retrieve a 'property' value previously set with SetProperty.",)),
+
+    'GetPropertyExpanded' :
+    (0,
+     'wxString %s(const wxString& key);',
+
+     '''wxString %s(const wxString& key) {
+         int len = SendMsg(SCI_GETPROPERTYEXPANDED, (long)(const char*)wx2stc(key), NULL);
+         if (!len) return wxEmptyString;
+
+         wxMemoryBuffer mbuf(len+1);
+         char* buf = (char*)mbuf.GetWriteBuf(len+1);
+         SendMsg(%s, (long)(const char*)wx2stc(key), (long)buf);
+         mbuf.UngetWriteBuf(len);
+         mbuf.AppendByte(0);
+         return stc2wx(buf);''',
+     ("Retrieve a 'property' value previously set with SetProperty,",
+      "with '$()' variable replacement on returned buffer.")),
+
+    'GetPropertyInt'   : (0, 0, 0,
+       ("Retrieve a 'property' value previously set with SetProperty,",
+        "interpreted as an int AFTER any '$()' variable replacement.")),
+
 
     'GetDocPointer' :
     (0,
index fce427d5d11dfc75b6bf312ea3f3198f8b021914..3dfc8698517e4711d3bec7152853bc8f88ad1f39 100644 (file)
@@ -3,5 +3,5 @@ scintilla/include directories from the Scintilla/SCiTE source
 distribution.  All other code needed to implement Scintilla on top of
 wxWindows is located in the directory above this one.
 
-The current version of the Scintilla code is 1.62
+The current version of the Scintilla code is 1.67
 
index df4e870c580f507203f57f61f2cc58a7af04a2fe..059ac0da0fd881dbe31aebe03c584cb368837f39 100644 (file)
@@ -20,21 +20,29 @@ protected:
        LexerFunction fnLexer;
        LexerFunction fnFolder;
        const char * const * wordListDescriptions;
+       int styleBits;
 
        static const LexerModule *base;
        static int nextLanguage;
 
 public:
        const char *languageName;
-       LexerModule(int language_, LexerFunction fnLexer_, 
-               const char *languageName_=0, LexerFunction fnFolder_=0,
-               const char * const wordListDescriptions_[] = NULL);
+       LexerModule(int language_, 
+               LexerFunction fnLexer_, 
+               const char *languageName_=0, 
+               LexerFunction fnFolder_=0,
+               const char * const wordListDescriptions_[] = NULL,
+               int styleBits_=5);
+       virtual ~LexerModule() {
+       }
        int GetLanguage() const { return language; }
 
        // -1 is returned if no WordList information is available
        int GetNumWordLists() const;
        const char *GetWordListDescription(int index) const;
 
+       int GetStyleBitsNeeded() const;
+
        virtual void Lex(unsigned int startPos, int lengthDoc, int initStyle,
                   WordList *keywordlists[], Accessor &styler) const;
        virtual void Fold(unsigned int startPos, int lengthDoc, int initStyle,
index 1e3bd69d752e263134a739f8cda9eb722a11505c..88a05272fdc66b0d577e5668c1b5bef4392e8096 100644 (file)
@@ -393,9 +393,10 @@ public:
        static ListBox *Allocate();
 
        virtual void SetFont(Font &font)=0;
-       virtual void Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_)=0;
+       virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_)=0;
        virtual void SetAverageCharWidth(int width)=0;
        virtual void SetVisibleRows(int rows)=0;
+       virtual int GetVisibleRows() const=0;
        virtual PRectangle GetDesiredRect()=0;
        virtual int CaretFromEdge()=0;
        virtual void Clear()=0;
@@ -408,6 +409,7 @@ public:
        virtual void RegisterImage(int type, const char *xpm_data)=0;
        virtual void ClearRegisteredImages()=0;
        virtual void SetDoubleClickAction(CallBackAction, void *)=0;
+       virtual void SetList(const char* list, char separator, char typesep)=0;
 };
 
 /**
index 32aea8a0c7f59ce6b7f7873d3d47593e44c9e060..e38de7dc408f106970257fff1feafcf300655b12 100644 (file)
@@ -29,6 +29,7 @@ protected:
        Property *props[hashRoots];
        Property *enumnext;
        int enumhash;
+       static bool caseSensitiveFilenames;
        static unsigned int HashString(const char *s, size_t len) {
                unsigned int ret = 0;
                while (len--) {
@@ -58,9 +59,12 @@ public:
        char *ToString();       // Caller must delete[] the return value
        bool GetFirst(char **key, char **val);
        bool GetNext(char **key, char **val);
+       static void SetCaseSensitiveFilenames(bool caseSensitiveFilenames_) {
+               caseSensitiveFilenames = caseSensitiveFilenames_;
+       }
 
 private:
-       // copy-value semantics not implemented 
+       // copy-value semantics not implemented
        PropSet(const PropSet &copy);
        void operator=(const PropSet &assign);
 };
@@ -76,9 +80,11 @@ public:
        int len;
        bool onlyLineEnds;      ///< Delimited by any white space or only line ends
        bool sorted;
+       bool sortedNoCase;
        int starts[256];
        WordList(bool onlyLineEnds_ = false) :
-               words(0), wordsNoCase(0), list(0), len(0), onlyLineEnds(onlyLineEnds_), sorted(false) {}
+               words(0), wordsNoCase(0), list(0), len(0), onlyLineEnds(onlyLineEnds_),
+               sorted(false), sortedNoCase(false) {}
        ~WordList() { Clear(); }
        operator bool() { return len ? true : false; }
        char *operator[](int ind) { return words[ind]; }
@@ -87,6 +93,7 @@ public:
        char *Allocate(int size);
        void SetFromAllocated();
        bool InList(const char *s);
+       bool InListAbbreviated(const char *s, const char marker);
        const char *GetNearestWord(const char *wordStart, int searchLen,
                bool ignoreCase = false, SString wordCharacters="", int wordIndex = -1);
        char *GetNearestWords(const char *wordStart, int searchLen,
index 5c2a93d33b7737cb1a28c3b3bbe8680f5bf35409..38a206ccf2240224ce1dbdd3236c727ab54babc9 100644 (file)
@@ -197,7 +197,7 @@ public:
        bool operator!=(const char *sOther) const {
                return !operator==(sOther);
        }
-       bool contains(char ch) {
+       bool contains(char ch) const {
                return (s && *s) ? strchr(s, ch) != 0 : false;
        }
        void setsizegrowth(lenpos_t sizeGrowth_) {
@@ -253,7 +253,7 @@ public:
        bool startswith(const char *prefix);
        bool endswith(const char *suffix);
        int search(const char *sFind, lenpos_t start=0) const;
-       bool contains(const char *sFind) {
+       bool contains(const char *sFind) const {
                return search(sFind) >= 0;
        }
        int substitute(char chFind, char chReplace);
index ce50a7fab5fed63a4140a473e85a4ee23f01af68..9c7fc8a7ddae27b2abe9c0cb09fab060ec36ab07 100644 (file)
@@ -43,8 +43,6 @@
 #define SCLEX_NNCRONTAB 26
 #define SCLEX_BULLANT 27
 #define SCLEX_VBSCRIPT 28
-#define SCLEX_ASP 29
-#define SCLEX_PHP 30
 #define SCLEX_BAAN 31
 #define SCLEX_MATLAB 32
 #define SCLEX_SCRIPTOL 33
 #define SCLEX_BASH 62
 #define SCLEX_ASN1 63
 #define SCLEX_VHDL 64
+#define SCLEX_CAML 65
+#define SCLEX_BLITZBASIC 66
+#define SCLEX_PUREBASIC 67
+#define SCLEX_HASKELL 68
+#define SCLEX_PHPSCRIPT 69
+#define SCLEX_TADS3 70
+#define SCLEX_REBOL 71
+#define SCLEX_SMALLTALK 72
+#define SCLEX_FLAGSHIP 73
+#define SCLEX_CSOUND 74
+#define SCLEX_FREEBASIC 75
 #define SCLEX_AUTOMATIC 1000
 #define SCE_P_DEFAULT 0
 #define SCE_P_COMMENTLINE 1
 #define SCE_P_IDENTIFIER 11
 #define SCE_P_COMMENTBLOCK 12
 #define SCE_P_STRINGEOL 13
+#define SCE_P_WORD2 14
+#define SCE_P_DECORATOR 15
 #define SCE_C_DEFAULT 0
 #define SCE_C_COMMENT 1
 #define SCE_C_COMMENTLINE 2
 #define SCE_PL_ARRAY 13
 #define SCE_PL_HASH 14
 #define SCE_PL_SYMBOLTABLE 15
+#define SCE_PL_VARIABLE_INDEXER 16
 #define SCE_PL_REGEX 17
 #define SCE_PL_REGSUBST 18
 #define SCE_PL_LONGQUOTE 19
 #define SCE_PL_STRING_QX 28
 #define SCE_PL_STRING_QR 29
 #define SCE_PL_STRING_QW 30
+#define SCE_PL_POD_VERB 31
+#define SCE_RB_DEFAULT 0
+#define SCE_RB_ERROR 1
+#define SCE_RB_COMMENTLINE 2
+#define SCE_RB_POD 3
+#define SCE_RB_NUMBER 4
+#define SCE_RB_WORD 5
+#define SCE_RB_STRING 6
+#define SCE_RB_CHARACTER 7
+#define SCE_RB_CLASSNAME 8
+#define SCE_RB_DEFNAME 9
+#define SCE_RB_OPERATOR 10
+#define SCE_RB_IDENTIFIER 11
+#define SCE_RB_REGEX 12
+#define SCE_RB_GLOBAL 13
+#define SCE_RB_SYMBOL 14
+#define SCE_RB_MODULE_NAME 15
+#define SCE_RB_INSTANCE_VAR 16
+#define SCE_RB_CLASS_VAR 17
+#define SCE_RB_BACKTICKS 18
+#define SCE_RB_DATASECTION 19
+#define SCE_RB_HERE_DELIM 20
+#define SCE_RB_HERE_Q 21
+#define SCE_RB_HERE_QQ 22
+#define SCE_RB_HERE_QX 23
+#define SCE_RB_STRING_Q 24
+#define SCE_RB_STRING_QQ 25
+#define SCE_RB_STRING_QX 26
+#define SCE_RB_STRING_QR 27
+#define SCE_RB_STRING_QW 28
+#define SCE_RB_WORD_DEMOTED 29
+#define SCE_RB_STDIN 30
+#define SCE_RB_STDOUT 31
+#define SCE_RB_STDERR 40
+#define SCE_RB_UPPER_BOUND 41
 #define SCE_B_DEFAULT 0
 #define SCE_B_COMMENT 1
 #define SCE_B_NUMBER 2
 #define SCE_B_KEYWORD4 12
 #define SCE_B_CONSTANT 13
 #define SCE_B_ASM 14
+#define SCE_B_LABEL 15
+#define SCE_B_ERROR 16
+#define SCE_B_HEXNUMBER 17
+#define SCE_B_BINNUMBER 18
 #define SCE_PROPS_DEFAULT 0
 #define SCE_PROPS_COMMENT 1
 #define SCE_PROPS_SECTION 2
 #define SCE_LISP_COMMENT 1
 #define SCE_LISP_NUMBER 2
 #define SCE_LISP_KEYWORD 3
+#define SCE_LISP_KEYWORD_KW 4
+#define SCE_LISP_SYMBOL 5
 #define SCE_LISP_STRING 6
 #define SCE_LISP_STRINGEOL 8
 #define SCE_LISP_IDENTIFIER 9
 #define SCE_LISP_OPERATOR 10
+#define SCE_LISP_SPECIAL 11
+#define SCE_LISP_MULTI_COMMENT 12
 #define SCE_EIFFEL_DEFAULT 0
 #define SCE_EIFFEL_COMMENTLINE 1
 #define SCE_EIFFEL_NUMBER 2
 #define SCE_CSS_DOUBLESTRING 13
 #define SCE_CSS_SINGLESTRING 14
 #define SCE_CSS_IDENTIFIER2 15
+#define SCE_CSS_ATTRIBUTE 16
 #define SCE_POV_DEFAULT 0
 #define SCE_POV_COMMENT 1
 #define SCE_POV_COMMENTLINE 2
 #define SCE_NSIS_MACRODEF 12
 #define SCE_NSIS_STRINGVAR 13
 #define SCE_NSIS_NUMBER 14
+#define SCE_NSIS_SECTIONGROUP 15
+#define SCE_NSIS_PAGEEX 16
+#define SCE_NSIS_FUNCTIONDEF 17
+#define SCE_NSIS_COMMENTBOX 18
 #define SCE_MMIXAL_LEADWS 0
 #define SCE_MMIXAL_COMMENT 1
 #define SCE_MMIXAL_LABEL 2
 #define SCE_CLW_PICTURE_STRING 7
 #define SCE_CLW_KEYWORD 8
 #define SCE_CLW_COMPILER_DIRECTIVE 9
-#define SCE_CLW_BUILTIN_PROCEDURES_FUNCTION 10
-#define SCE_CLW_STRUCTURE_DATA_TYPE 11
-#define SCE_CLW_ATTRIBUTE 12
-#define SCE_CLW_STANDARD_EQUATE 13
-#define SCE_CLW_ERROR 14
+#define SCE_CLW_RUNTIME_EXPRESSIONS 10
+#define SCE_CLW_BUILTIN_PROCEDURES_FUNCTION 11
+#define SCE_CLW_STRUCTURE_DATA_TYPE 12
+#define SCE_CLW_ATTRIBUTE 13
+#define SCE_CLW_STANDARD_EQUATE 14
+#define SCE_CLW_ERROR 15
+#define SCE_CLW_DEPRECATED 16
 #define SCE_LOT_DEFAULT 0
 #define SCE_LOT_HEADER 1
 #define SCE_LOT_BREAK 2
 #define SCE_AU3_SENT 10
 #define SCE_AU3_PREPROCESSOR 11
 #define SCE_AU3_SPECIAL 12
+#define SCE_AU3_EXPAND 13
+#define SCE_AU3_COMOBJ 14
 #define SCE_APDL_DEFAULT 0
 #define SCE_APDL_COMMENT 1
 #define SCE_APDL_COMMENTBLOCK 2
 #define SCE_VHDL_STDPACKAGE 12
 #define SCE_VHDL_STDTYPE 13
 #define SCE_VHDL_USERWORD 14
+#define SCE_CAML_DEFAULT 0
+#define SCE_CAML_IDENTIFIER 1
+#define SCE_CAML_TAGNAME 2
+#define SCE_CAML_KEYWORD 3
+#define SCE_CAML_KEYWORD2 4
+#define SCE_CAML_KEYWORD3 5
+#define SCE_CAML_LINENUM 6
+#define SCE_CAML_OPERATOR 7
+#define SCE_CAML_NUMBER 8
+#define SCE_CAML_CHAR 9
+#define SCE_CAML_STRING 11
+#define SCE_CAML_COMMENT 12
+#define SCE_CAML_COMMENT1 13
+#define SCE_CAML_COMMENT2 14
+#define SCE_CAML_COMMENT3 15
+#define SCE_HA_DEFAULT 0
+#define SCE_HA_IDENTIFIER 1
+#define SCE_HA_KEYWORD 2
+#define SCE_HA_NUMBER 3
+#define SCE_HA_STRING 4
+#define SCE_HA_CHARACTER 5
+#define SCE_HA_CLASS 6
+#define SCE_HA_MODULE 7
+#define SCE_HA_CAPITAL 8
+#define SCE_HA_DATA 9
+#define SCE_HA_IMPORT 10
+#define SCE_HA_OPERATOR 11
+#define SCE_HA_INSTANCE 12
+#define SCE_HA_COMMENTLINE 13
+#define SCE_HA_COMMENTBLOCK 14
+#define SCE_HA_COMMENTBLOCK2 15
+#define SCE_HA_COMMENTBLOCK3 16
+#define SCE_T3_DEFAULT 0
+#define SCE_T3_X_DEFAULT 1
+#define SCE_T3_PREPROCESSOR 2
+#define SCE_T3_BLOCK_COMMENT 3
+#define SCE_T3_LINE_COMMENT 4
+#define SCE_T3_OPERATOR 5
+#define SCE_T3_KEYWORD 6
+#define SCE_T3_NUMBER 7
+#define SCE_T3_IDENTIFIER 8
+#define SCE_T3_S_STRING 9
+#define SCE_T3_D_STRING 10
+#define SCE_T3_X_STRING 11
+#define SCE_T3_LIB_DIRECTIVE 12
+#define SCE_T3_MSG_PARAM 13
+#define SCE_T3_HTML_TAG 14
+#define SCE_T3_HTML_DEFAULT 15
+#define SCE_T3_HTML_STRING 16
+#define SCE_T3_USER1 17
+#define SCE_T3_USER2 18
+#define SCE_T3_USER3 19
+#define SCE_REBOL_DEFAULT 0
+#define SCE_REBOL_COMMENTLINE 1
+#define SCE_REBOL_COMMENTBLOCK 2
+#define SCE_REBOL_PREFACE 3
+#define SCE_REBOL_OPERATOR 4
+#define SCE_REBOL_CHARACTER 5
+#define SCE_REBOL_QUOTEDSTRING 6
+#define SCE_REBOL_BRACEDSTRING 7
+#define SCE_REBOL_NUMBER 8
+#define SCE_REBOL_PAIR 9
+#define SCE_REBOL_TUPLE 10
+#define SCE_REBOL_BINARY 11
+#define SCE_REBOL_MONEY 12
+#define SCE_REBOL_ISSUE 13
+#define SCE_REBOL_TAG 14
+#define SCE_REBOL_FILE 15
+#define SCE_REBOL_EMAIL 16
+#define SCE_REBOL_URL 17
+#define SCE_REBOL_DATE 18
+#define SCE_REBOL_TIME 19
+#define SCE_REBOL_IDENTIFIER 20
+#define SCE_REBOL_WORD 21
+#define SCE_REBOL_WORD2 22
+#define SCE_REBOL_WORD3 23
+#define SCE_REBOL_WORD4 24
+#define SCE_REBOL_WORD5 25
+#define SCE_REBOL_WORD6 26
+#define SCE_REBOL_WORD7 27
+#define SCE_REBOL_WORD8 28
+#define SCE_SQL_DEFAULT 0
+#define SCE_SQL_COMMENT 1
+#define SCE_SQL_COMMENTLINE 2
+#define SCE_SQL_COMMENTDOC 3
+#define SCE_SQL_NUMBER 4
+#define SCE_SQL_WORD 5
+#define SCE_SQL_STRING 6
+#define SCE_SQL_CHARACTER 7
+#define SCE_SQL_SQLPLUS 8
+#define SCE_SQL_SQLPLUS_PROMPT 9
+#define SCE_SQL_OPERATOR 10
+#define SCE_SQL_IDENTIFIER 11
+#define SCE_SQL_SQLPLUS_COMMENT 13
+#define SCE_SQL_COMMENTLINEDOC 15
+#define SCE_SQL_WORD2 16
+#define SCE_SQL_COMMENTDOCKEYWORD 17
+#define SCE_SQL_COMMENTDOCKEYWORDERROR 18
+#define SCE_SQL_USER1 19
+#define SCE_SQL_USER2 20
+#define SCE_SQL_USER3 21
+#define SCE_SQL_USER4 22
+#define SCE_SQL_QUOTEDIDENTIFIER 23
+#define SCE_ST_DEFAULT 0
+#define SCE_ST_STRING 1
+#define SCE_ST_NUMBER 2
+#define SCE_ST_COMMENT 3
+#define SCE_ST_SYMBOL 4
+#define SCE_ST_BINARY 5
+#define SCE_ST_BOOL 6
+#define SCE_ST_SELF 7
+#define SCE_ST_SUPER 8
+#define SCE_ST_NIL 9
+#define SCE_ST_GLOBAL 10
+#define SCE_ST_RETURN 11
+#define SCE_ST_SPECIAL 12
+#define SCE_ST_KWSEND 13
+#define SCE_ST_ASSIGN 14
+#define SCE_ST_CHARACTER 15
+#define SCE_ST_SPEC_SEL 16
+#define SCE_FS_DEFAULT 0
+#define SCE_FS_COMMENT 1
+#define SCE_FS_COMMENTLINE 2
+#define SCE_FS_COMMENTDOC 3
+#define SCE_FS_COMMENTLINEDOC 4
+#define SCE_FS_COMMENTDOCKEYWORD 5
+#define SCE_FS_COMMENTDOCKEYWORDERROR 6
+#define SCE_FS_KEYWORD 7
+#define SCE_FS_KEYWORD2 8
+#define SCE_FS_KEYWORD3 9
+#define SCE_FS_KEYWORD4 10
+#define SCE_FS_NUMBER 11
+#define SCE_FS_STRING 12
+#define SCE_FS_PREPROCESSOR 13
+#define SCE_FS_OPERATOR 14
+#define SCE_FS_IDENTIFIER 15
+#define SCE_FS_DATE 16
+#define SCE_FS_STRINGEOL 17
+#define SCE_FS_CONSTANT 18
+#define SCE_FS_ASM 19
+#define SCE_FS_LABEL 20
+#define SCE_FS_ERROR 21
+#define SCE_FS_HEXNUMBER 22
+#define SCE_FS_BINNUMBER 23
+#define SCE_CSOUND_DEFAULT 0
+#define SCE_CSOUND_COMMENT 1
+#define SCE_CSOUND_NUMBER 2
+#define SCE_CSOUND_OPERATOR 3
+#define SCE_CSOUND_INSTR 4
+#define SCE_CSOUND_IDENTIFIER 5
+#define SCE_CSOUND_OPCODE 6
+#define SCE_CSOUND_HEADERSTMT 7
+#define SCE_CSOUND_USERKEYWORD 8
+#define SCE_CSOUND_COMMENTBLOCK 9
+#define SCE_CSOUND_PARAM 10
+#define SCE_CSOUND_ARATE_VAR 11
+#define SCE_CSOUND_KRATE_VAR 12
+#define SCE_CSOUND_IRATE_VAR 13
+#define SCE_CSOUND_GLOBAL_VAR 14
+#define SCE_CSOUND_STRINGEOL 15
+#define SCLEX_ASP 29
+#define SCLEX_PHP 30
 //--Autogenerated -- end of section automatically generated from Scintilla.iface
 
 #endif
index fb6c674a7ad84bf29d41e68ea350a830004a0585..b4ed329f726618133d7604223b6660399d207c18 100644 (file)
 #ifndef SCINTILLA_H
 #define SCINTILLA_H
 
-#ifdef PLAT_WIN
+#if LCCWIN
+typedef BOOL bool;
+#endif
+
 #if PLAT_WIN
 // Return false on failure:
 bool Scintilla_RegisterClasses(void *hInstance);
 bool Scintilla_ReleaseResources();
 #endif
-#endif
 int Scintilla_LinkLexers();
 
 // Here should be placed typedefs for uptr_t, an unsigned integer type large enough to
 // hold a pointer and sptr_t, a signed integer large enough to hold a pointer.
 // May need to be changed for 64 bit platforms.
-#ifdef _MSC_VER
 #if _MSC_VER >= 1300
 #include <BaseTsd.h>
 #endif
-#endif
 #ifdef MAXULONG_PTR
 typedef ULONG_PTR uptr_t;
 typedef LONG_PTR sptr_t;
@@ -117,6 +117,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SC_MARK_DOTDOTDOT 23
 #define SC_MARK_ARROWS 24
 #define SC_MARK_PIXMAP 25
+#define SC_MARK_FULLRECT 26
 #define SC_MARK_CHARACTER 10000
 #define SC_MARKNUM_FOLDEREND 25
 #define SC_MARKNUM_FOLDEROPENMID 26
@@ -136,6 +137,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_MARKERNEXT 2047
 #define SCI_MARKERPREVIOUS 2048
 #define SCI_MARKERDEFINEPIXMAP 2049
+#define SCI_MARKERADDSET 2466
 #define SC_MARGIN_SYMBOL 0
 #define SC_MARGIN_NUMBER 1
 #define SCI_SETMARGINTYPEN 2240
@@ -165,6 +167,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SC_CHARSET_MAC 77
 #define SC_CHARSET_OEM 255
 #define SC_CHARSET_RUSSIAN 204
+#define SC_CHARSET_CYRILLIC 1251
 #define SC_CHARSET_SHIFTJIS 128
 #define SC_CHARSET_SYMBOL 2
 #define SC_CHARSET_TURKISH 162
@@ -173,6 +176,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SC_CHARSET_ARABIC 178
 #define SC_CHARSET_VIETNAMESE 163
 #define SC_CHARSET_THAI 222
+#define SC_CHARSET_8859_15 1000
 #define SCI_STYLECLEARALL 2050
 #define SCI_STYLESETFORE 2051
 #define SCI_STYLESETBACK 2052
@@ -255,6 +259,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_CLEARREGISTEREDIMAGES 2408
 #define SCI_AUTOCGETTYPESEPARATOR 2285
 #define SCI_AUTOCSETTYPESEPARATOR 2286
+#define SCI_AUTOCSETMAXWIDTH 2208
+#define SCI_AUTOCGETMAXWIDTH 2209
+#define SCI_AUTOCSETMAXHEIGHT 2210
+#define SCI_AUTOCGETMAXHEIGHT 2211
 #define SCI_SETINDENT 2122
 #define SCI_GETINDENT 2123
 #define SCI_SETUSETABS 2124
@@ -352,6 +360,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_CALLTIPSETFOREHLT 2207
 #define SCI_VISIBLEFROMDOCLINE 2220
 #define SCI_DOCLINEFROMVISIBLE 2221
+#define SCI_WRAPCOUNT 2235
 #define SC_FOLDLEVELBASE 0x400
 #define SC_FOLDLEVELWHITEFLAG 0x1000
 #define SC_FOLDLEVELHEADERFLAG 0x2000
@@ -390,6 +399,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_WORDENDPOSITION 2267
 #define SC_WRAP_NONE 0
 #define SC_WRAP_WORD 1
+#define SC_WRAP_CHAR 2
 #define SCI_SETWRAPMODE 2268
 #define SCI_GETWRAPMODE 2269
 #define SC_WRAPVISUALFLAG_NONE 0x0000
@@ -591,6 +601,12 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_SETLENGTHFORENCODE 2448
 #define SCI_ENCODEDFROMUTF8 2449
 #define SCI_FINDCOLUMN 2456
+#define SCI_GETCARETSTICKY 2457
+#define SCI_SETCARETSTICKY 2458
+#define SCI_TOGGLECARETSTICKY 2459
+#define SCI_SETPASTECONVERTENDINGS 2467
+#define SCI_GETPASTECONVERTENDINGS 2468
+#define SCI_SELECTIONDUPLICATE 2469
 #define SCI_STARTRECORD 3001
 #define SCI_STOPRECORD 3002
 #define SCI_SETLEXER 4001
@@ -601,6 +617,10 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCI_SETKEYWORDS 4005
 #define SCI_SETLEXERLANGUAGE 4006
 #define SCI_LOADLEXERLIBRARY 4007
+#define SCI_GETPROPERTY 4008
+#define SCI_GETPROPERTYEXPANDED 4009
+#define SCI_GETPROPERTYINT 4010
+#define SCI_GETSTYLEBITSNEEDED 4011
 #define SC_MOD_INSERTTEXT 0x1
 #define SC_MOD_DELETETEXT 0x2
 #define SC_MOD_CHANGESTYLE 0x4
@@ -608,11 +628,13 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SC_PERFORMED_USER 0x10
 #define SC_PERFORMED_UNDO 0x20
 #define SC_PERFORMED_REDO 0x40
+#define SC_MULTISTEPUNDOREDO 0x80
 #define SC_LASTSTEPINUNDOREDO 0x100
 #define SC_MOD_CHANGEMARKER 0x200
 #define SC_MOD_BEFOREINSERT 0x400
 #define SC_MOD_BEFOREDELETE 0x800
-#define SC_MODEVENTMASKALL 0xF77
+#define SC_MULTILINEUNDOREDO 0x1000
+#define SC_MODEVENTMASKALL 0x1FFF
 #define SCEN_CHANGE 768
 #define SCEN_SETFOCUS 512
 #define SCEN_KILLFOCUS 256
@@ -633,6 +655,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCK_ADD 310
 #define SCK_SUBTRACT 311
 #define SCK_DIVIDE 312
+#define SCMOD_NORM 0
 #define SCMOD_SHIFT 1
 #define SCMOD_CTRL 2
 #define SCMOD_ALT 4
@@ -657,6 +680,7 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
 #define SCN_HOTSPOTCLICK 2019
 #define SCN_HOTSPOTDOUBLECLICK 2020
 #define SCN_CALLTIPCLICK 2021
+#define SCN_AUTOCSELECTION 2022
 //--Autogenerated -- end of section automatically generated from Scintilla.iface
 
 // These structures are defined to be exactly the same shape as the Win32
@@ -695,11 +719,11 @@ struct RangeToFormat {
 #endif
 
 struct NotifyHeader {
-       // hwndFrom is really an environment specifc window handle or pointer
+       // Compatible with Windows NMHDR.
+       // hwndFrom is really an environment specific window handle or pointer
        // but most clients of Scintilla.h do not have this type visible.
-       //WindowID hwndFrom;
        void *hwndFrom;
-       unsigned int idFrom;
+       uptr_t idFrom;
        unsigned int code;
 };
 
@@ -709,7 +733,7 @@ struct SCNotification {
        int ch;         // SCN_CHARADDED, SCN_KEY
        int modifiers;  // SCN_KEY
        int modificationType;   // SCN_MODIFIED
-       const char *text;       // SCN_MODIFIED
+       const char *text;       // SCN_MODIFIED, SCN_USERLISTSELECTION, SCN_AUTOCSELECTION
        int length;             // SCN_MODIFIED
        int linesAdded; // SCN_MODIFIED
        int message;    // SCN_MACRORECORD
index 5be763f258d78f748efb24c8dc1469a6ac43e3be..a35f352e923382b56dc5e87085c405c1597221d8 100644 (file)
@@ -267,6 +267,7 @@ val SC_MARK_BACKGROUND=22
 val SC_MARK_DOTDOTDOT=23
 val SC_MARK_ARROWS=24
 val SC_MARK_PIXMAP=25
+val SC_MARK_FULLRECT=26
 
 val SC_MARK_CHARACTER=10000
 
@@ -312,6 +313,9 @@ fun int MarkerPrevious=2048(int lineStart, int markerMask)
 # Define a marker from a pixmap.
 fun void MarkerDefinePixmap=2049(int markerNumber, string pixmap)
 
+# Add a set of markers to a line.
+fun void MarkerAddSet=2466(int line, int set)
+
 enu MarginType=SC_MARGIN_
 val SC_MARGIN_SYMBOL=0
 val SC_MARGIN_NUMBER=1
@@ -366,6 +370,7 @@ val SC_CHARSET_HANGUL=129
 val SC_CHARSET_MAC=77
 val SC_CHARSET_OEM=255
 val SC_CHARSET_RUSSIAN=204
+val SC_CHARSET_CYRILLIC=1251
 val SC_CHARSET_SHIFTJIS=128
 val SC_CHARSET_SYMBOL=2
 val SC_CHARSET_TURKISH=162
@@ -374,6 +379,7 @@ val SC_CHARSET_HEBREW=177
 val SC_CHARSET_ARABIC=178
 val SC_CHARSET_VIETNAMESE=163
 val SC_CHARSET_THAI=222
+val SC_CHARSET_8859_15=1000
 
 # Clear all the styles and make equivalent to the global default style.
 set void StyleClearAll=2050(,)
@@ -607,6 +613,20 @@ get int AutoCGetTypeSeparator=2285(,)
 # Default is '?' but can be changed if items contain '?'.
 set void AutoCSetTypeSeparator=2286(int separatorCharacter,)
 
+# Set the maximum width, in characters, of auto-completion and user lists.
+# Set to 0 to autosize to fit longest item, which is the default.
+set void AutoCSetMaxWidth=2208(int characterCount,)
+
+# Get the maximum width, in characters, of auto-completion and user lists.
+get int AutoCGetMaxWidth=2209(,)
+
+# Set the maximum height, in rows, of auto-completion and user lists.
+# The default is 5 rows.
+set void AutoCSetMaxHeight=2210(int rowCount,)
+
+# Set the maximum height, in rows, of auto-completion and user lists.
+get int AutoCGetMaxHeight=2211(,)
+
 # Set the number of spaces used for one level of indentation.
 set void SetIndent=2122(int indentSize,)
 
@@ -905,6 +925,9 @@ fun int VisibleFromDocLine=2220(int line,)
 # Find the document line of a display line taking hidden lines into account.
 fun int DocLineFromVisible=2221(int lineDisplay,)
 
+# The number of display lines needed to wrap a document line
+fun int WrapCount=2235(int line,)
+
 enu FoldLevel=SC_FOLDLEVEL
 val SC_FOLDLEVELBASE=0x400
 val SC_FOLDLEVELWHITEFLAG=0x1000
@@ -994,6 +1017,7 @@ fun int WordEndPosition=2267(position pos, bool onlyWordCharacters)
 enu Wrap=SC_WRAP_
 val SC_WRAP_NONE=0
 val SC_WRAP_WORD=1
+val SC_WRAP_CHAR=2
 
 # Sets whether text is word wrapped.
 set void SetWrapMode=2268(int mode,)
@@ -1059,7 +1083,7 @@ set void SetEndAtLastLine=2277(bool endAtLastLine,)
 
 # Retrieve whether the maximum scroll position has the last
 # line at the bottom of the view.
-get int GetEndAtLastLine=2278(,)
+get bool GetEndAtLastLine=2278(,)
 
 # Retrieve the height of a particular line of text in pixels.
 fun int TextHeight=2279(int line,)
@@ -1588,7 +1612,7 @@ fun void Allocate=2446(int bytes,)
 fun int TargetAsUTF8=2447(, stringresult s)
 
 # Set the length of the utf8 argument for calling EncodedFromUTF8.
-# Set to 0 and the string will be measured to the first nul.
+# Set to -1 and the string will be measured to the first nul.
 fun void SetLengthForEncode=2448(int bytes,)
 
 # Translates a UTF8 string into the document encoding.
@@ -1596,10 +1620,28 @@ fun void SetLengthForEncode=2448(int bytes,)
 # On error return 0.
 fun int EncodedFromUTF8=2449(string utf8, stringresult encoded)
 
-# Find the position of a column on a line taking into account tabs and 
+# Find the position of a column on a line taking into account tabs and
 # multi-byte characters. If beyond end of line, return line end position.
 fun int FindColumn=2456(int line, int column)
 
+# Can the caret preferred x position only be changed by explicit movement commands?
+get bool GetCaretSticky=2457(,)
+
+# Stop the caret preferred x position changing when the user types.
+set void SetCaretSticky=2458(bool useCaretStickyBehaviour,)
+
+# Switch between sticky and non-sticky: meant to be bound to a key.
+fun void ToggleCaretSticky=2459(,)
+
+# Enable/Disable convert-on-paste for line endings
+set void SetPasteConvertEndings=2467(bool convert,)
+
+# Get convert-on-paste setting
+get bool GetPasteConvertEndings=2468(,)
+
+# Duplicate the selection. If selection empty duplicate the line containing the caret.
+fun void SelectionDuplicate=2469(,)
+
 # Start notifying the container of all key presses and commands.
 fun void StartRecord=3001(,)
 
@@ -1630,6 +1672,20 @@ set void SetLexerLanguage=4006(, string language)
 # Load a lexer library (dll / so).
 fun void LoadLexerLibrary=4007(, string path)
 
+# Retrieve a "property" value previously set with SetProperty.
+fun int GetProperty=4008(string key, stringresult buf)
+
+# Retrieve a "property" value previously set with SetProperty,
+# with "$()" variable replacement on returned buffer.
+fun int GetPropertyExpanded=4009(string key, stringresult buf)
+
+# Retrieve a "property" value previously set with SetProperty,
+# interpreted as an int AFTER any "$()" variable replacement.
+get int GetPropertyInt=4010(string key,)
+
+# Retrieve the number of bits the current lexer needs for styling.
+get int GetStyleBitsNeeded=4011(,)
+
 # Notifications
 # Type of modification and the action which caused the modification.
 # These are defined as a bit mask to make it easy to specify which notifications are wanted.
@@ -1642,11 +1698,13 @@ val SC_MOD_CHANGEFOLD=0x8
 val SC_PERFORMED_USER=0x10
 val SC_PERFORMED_UNDO=0x20
 val SC_PERFORMED_REDO=0x40
+val SC_MULTISTEPUNDOREDO=0x80
 val SC_LASTSTEPINUNDOREDO=0x100
 val SC_MOD_CHANGEMARKER=0x200
 val SC_MOD_BEFOREINSERT=0x400
 val SC_MOD_BEFOREDELETE=0x800
-val SC_MODEVENTMASKALL=0xF77
+val SC_MULTILINEUNDOREDO=0x1000
+val SC_MODEVENTMASKALL=0x1FFF
 
 # For compatibility, these go through the COMMAND notification rather than NOTIFY
 # and should have had exactly the same values as the EN_* constants.
@@ -1680,6 +1738,7 @@ val SCK_SUBTRACT=311
 val SCK_DIVIDE=312
 
 enu KeyMod=SCMOD_
+val SCMOD_NORM=0
 val SCMOD_SHIFT=1
 val SCMOD_CTRL=2
 val SCMOD_ALT=4
@@ -1716,8 +1775,6 @@ val SCLEX_TCL=25
 val SCLEX_NNCRONTAB=26
 val SCLEX_BULLANT=27
 val SCLEX_VBSCRIPT=28
-val SCLEX_ASP=29
-val SCLEX_PHP=30
 val SCLEX_BAAN=31
 val SCLEX_MATLAB=32
 val SCLEX_SCRIPTOL=33
@@ -1752,13 +1809,23 @@ val SCLEX_APDL=61
 val SCLEX_BASH=62
 val SCLEX_ASN1=63
 val SCLEX_VHDL=64
+val SCLEX_CAML=65
+val SCLEX_BLITZBASIC=66
+val SCLEX_PUREBASIC=67
+val SCLEX_HASKELL=68
+val SCLEX_PHPSCRIPT=69
+val SCLEX_TADS3=70
+val SCLEX_REBOL=71
+val SCLEX_SMALLTALK=72
+val SCLEX_FLAGSHIP=73
+val SCLEX_CSOUND=74
+val SCLEX_FREEBASIC=75
 
 # When a lexer specifies its language as SCLEX_AUTOMATIC it receives a
 # value assigned in sequence from SCLEX_AUTOMATIC+1.
 val SCLEX_AUTOMATIC=1000
 # Lexical states for SCLEX_PYTHON
 lex Python=SCLEX_PYTHON SCE_P_
-lex Ruby=SCLEX_RUBY SCE_P_
 val SCE_P_DEFAULT=0
 val SCE_P_COMMENTLINE=1
 val SCE_P_NUMBER=2
@@ -1773,9 +1840,10 @@ val SCE_P_OPERATOR=10
 val SCE_P_IDENTIFIER=11
 val SCE_P_COMMENTBLOCK=12
 val SCE_P_STRINGEOL=13
+val SCE_P_WORD2=14
+val SCE_P_DECORATOR=15
 # Lexical states for SCLEX_CPP
 lex Cpp=SCLEX_CPP SCE_C_
-lex SQL=SCLEX_SQL SCE_C_
 lex Pascal=SCLEX_PASCAL SCE_C_
 lex TCL=SCLEX_TCL SCE_C_
 lex BullAnt=SCLEX_BULLANT SCE_C_
@@ -1945,6 +2013,7 @@ val SCE_PL_SCALAR=12
 val SCE_PL_ARRAY=13
 val SCE_PL_HASH=14
 val SCE_PL_SYMBOLTABLE=15
+val SCE_PL_VARIABLE_INDEXER=16
 val SCE_PL_REGEX=17
 val SCE_PL_REGSUBST=18
 val SCE_PL_LONGQUOTE=19
@@ -1959,6 +2028,43 @@ val SCE_PL_STRING_QQ=27
 val SCE_PL_STRING_QX=28
 val SCE_PL_STRING_QR=29
 val SCE_PL_STRING_QW=30
+val SCE_PL_POD_VERB=31
+# Lexical states for SCLEX_RUBY
+lex Ruby=SCLEX_RUBY SCE_RB_
+val SCE_RB_DEFAULT=0
+val SCE_RB_ERROR=1
+val SCE_RB_COMMENTLINE=2
+val SCE_RB_POD=3
+val SCE_RB_NUMBER=4
+val SCE_RB_WORD=5
+val SCE_RB_STRING=6
+val SCE_RB_CHARACTER=7
+val SCE_RB_CLASSNAME=8
+val SCE_RB_DEFNAME=9
+val SCE_RB_OPERATOR=10
+val SCE_RB_IDENTIFIER=11
+val SCE_RB_REGEX=12
+val SCE_RB_GLOBAL=13
+val SCE_RB_SYMBOL=14
+val SCE_RB_MODULE_NAME=15
+val SCE_RB_INSTANCE_VAR=16
+val SCE_RB_CLASS_VAR=17
+val SCE_RB_BACKTICKS=18
+val SCE_RB_DATASECTION=19
+val SCE_RB_HERE_DELIM=20
+val SCE_RB_HERE_Q=21
+val SCE_RB_HERE_QQ=22
+val SCE_RB_HERE_QX=23
+val SCE_RB_STRING_Q=24
+val SCE_RB_STRING_QQ=25
+val SCE_RB_STRING_QX=26
+val SCE_RB_STRING_QR=27
+val SCE_RB_STRING_QW=28
+val SCE_RB_WORD_DEMOTED=29
+val SCE_RB_STDIN=30
+val SCE_RB_STDOUT=31
+val SCE_RB_STDERR=40
+val SCE_RB_UPPER_BOUND=41
 # Lexical states for SCLEX_VB, SCLEX_VBSCRIPT, SCLEX_POWERBASIC
 lex VB=SCLEX_VB SCE_B_
 lex VBScript=SCLEX_VBSCRIPT SCE_B_
@@ -1978,6 +2084,10 @@ val SCE_B_KEYWORD3=11
 val SCE_B_KEYWORD4=12
 val SCE_B_CONSTANT=13
 val SCE_B_ASM=14
+val SCE_B_LABEL=15
+val SCE_B_ERROR=16
+val SCE_B_HEXNUMBER=17
+val SCE_B_BINNUMBER=18
 # Lexical states for SCLEX_PROPERTIES
 lex Properties=SCLEX_PROPERTIES SCE_PROPS_
 val SCE_PROPS_DEFAULT=0
@@ -2127,10 +2237,14 @@ val SCE_LISP_DEFAULT=0
 val SCE_LISP_COMMENT=1
 val SCE_LISP_NUMBER=2
 val SCE_LISP_KEYWORD=3
+val SCE_LISP_KEYWORD_KW=4
+val SCE_LISP_SYMBOL=5
 val SCE_LISP_STRING=6
 val SCE_LISP_STRINGEOL=8
 val SCE_LISP_IDENTIFIER=9
 val SCE_LISP_OPERATOR=10
+val SCE_LISP_SPECIAL=11
+val SCE_LISP_MULTI_COMMENT=12
 # Lexical states for SCLEX_EIFFEL and SCLEX_EIFFELKW
 lex Eiffel=SCLEX_EIFFEL SCE_EIFFEL_
 lex EiffelKW=SCLEX_EIFFELKW SCE_EIFFEL_
@@ -2253,6 +2367,7 @@ val SCE_CSS_DIRECTIVE=12
 val SCE_CSS_DOUBLESTRING=13
 val SCE_CSS_SINGLESTRING=14
 val SCE_CSS_IDENTIFIER2=15
+val SCE_CSS_ATTRIBUTE=16
 # Lexical states for SCLEX_POV
 lex POV=SCLEX_POV SCE_POV_
 val SCE_POV_DEFAULT=0
@@ -2334,6 +2449,10 @@ val SCE_NSIS_IFDEFINEDEF=11
 val SCE_NSIS_MACRODEF=12
 val SCE_NSIS_STRINGVAR=13
 val SCE_NSIS_NUMBER=14
+val SCE_NSIS_SECTIONGROUP=15
+val SCE_NSIS_PAGEEX=16
+val SCE_NSIS_FUNCTIONDEF=17
+val SCE_NSIS_COMMENTBOX=18
 # Lexical states for SCLEX_MMIXAL
 lex MMIXAL=SCLEX_MMIXAL SCE_MMIXAL_
 val SCE_MMIXAL_LEADWS=0
@@ -2366,11 +2485,13 @@ val SCE_CLW_REAL_CONSTANT=6
 val SCE_CLW_PICTURE_STRING=7
 val SCE_CLW_KEYWORD=8
 val SCE_CLW_COMPILER_DIRECTIVE=9
-val SCE_CLW_BUILTIN_PROCEDURES_FUNCTION=10
-val SCE_CLW_STRUCTURE_DATA_TYPE=11
-val SCE_CLW_ATTRIBUTE=12
-val SCE_CLW_STANDARD_EQUATE=13
-val SCE_CLW_ERROR=14
+val SCE_CLW_RUNTIME_EXPRESSIONS=10
+val SCE_CLW_BUILTIN_PROCEDURES_FUNCTION=11
+val SCE_CLW_STRUCTURE_DATA_TYPE=12
+val SCE_CLW_ATTRIBUTE=13
+val SCE_CLW_STANDARD_EQUATE=14
+val SCE_CLW_ERROR=15
+val SCE_CLW_DEPRECATED=16
 # Lexical states for SCLEX_LOT
 lex LOT=SCLEX_LOT SCE_LOT_
 val SCE_LOT_DEFAULT=0
@@ -2518,6 +2639,8 @@ val SCE_AU3_VARIABLE=9
 val SCE_AU3_SENT=10
 val SCE_AU3_PREPROCESSOR=11
 val SCE_AU3_SPECIAL=12
+val SCE_AU3_EXPAND=13
+val SCE_AU3_COMOBJ=14
 # Lexical states for SCLEX_APDL
 lex APDL=SCLEX_APDL SCE_APDL_
 val SCE_APDL_DEFAULT=0
@@ -2579,6 +2702,182 @@ val SCE_VHDL_STDFUNCTION=11
 val SCE_VHDL_STDPACKAGE=12
 val SCE_VHDL_STDTYPE=13
 val SCE_VHDL_USERWORD=14
+# Lexical states for SCLEX_CAML
+lex Caml=SCLEX_CAML SCE_CAML_
+val SCE_CAML_DEFAULT=0
+val SCE_CAML_IDENTIFIER=1
+val SCE_CAML_TAGNAME=2
+val SCE_CAML_KEYWORD=3
+val SCE_CAML_KEYWORD2=4
+val SCE_CAML_KEYWORD3=5
+val SCE_CAML_LINENUM=6
+val SCE_CAML_OPERATOR=7
+val SCE_CAML_NUMBER=8
+val SCE_CAML_CHAR=9
+val SCE_CAML_STRING=11
+val SCE_CAML_COMMENT=12
+val SCE_CAML_COMMENT1=13
+val SCE_CAML_COMMENT2=14
+val SCE_CAML_COMMENT3=15
+# Lexical states for SCLEX_HASKELL
+lex Haskell=SCLEX_HASKELL SCE_HA_
+val SCE_HA_DEFAULT=0
+val SCE_HA_IDENTIFIER=1
+val SCE_HA_KEYWORD=2
+val SCE_HA_NUMBER=3
+val SCE_HA_STRING=4
+val SCE_HA_CHARACTER=5
+val SCE_HA_CLASS=6
+val SCE_HA_MODULE=7
+val SCE_HA_CAPITAL=8
+val SCE_HA_DATA=9
+val SCE_HA_IMPORT=10
+val SCE_HA_OPERATOR=11
+val SCE_HA_INSTANCE=12
+val SCE_HA_COMMENTLINE=13
+val SCE_HA_COMMENTBLOCK=14
+val SCE_HA_COMMENTBLOCK2=15
+val SCE_HA_COMMENTBLOCK3=16
+# Lexical states of SCLEX_TADS3
+lex TADS3=SCLEX_TADS3 SCE_T3_
+val SCE_T3_DEFAULT=0
+val SCE_T3_X_DEFAULT=1
+val SCE_T3_PREPROCESSOR=2
+val SCE_T3_BLOCK_COMMENT=3
+val SCE_T3_LINE_COMMENT=4
+val SCE_T3_OPERATOR=5
+val SCE_T3_KEYWORD=6
+val SCE_T3_NUMBER=7
+val SCE_T3_IDENTIFIER=8
+val SCE_T3_S_STRING=9
+val SCE_T3_D_STRING=10
+val SCE_T3_X_STRING=11
+val SCE_T3_LIB_DIRECTIVE=12
+val SCE_T3_MSG_PARAM=13
+val SCE_T3_HTML_TAG=14
+val SCE_T3_HTML_DEFAULT=15
+val SCE_T3_HTML_STRING=16
+val SCE_T3_USER1=17
+val SCE_T3_USER2=18
+val SCE_T3_USER3=19
+# Lexical states for SCLEX_REBOL
+lex Rebol=SCLEX_REBOL SCE_REBOL_
+val SCE_REBOL_DEFAULT=0
+val SCE_REBOL_COMMENTLINE=1
+val SCE_REBOL_COMMENTBLOCK=2
+val SCE_REBOL_PREFACE=3
+val SCE_REBOL_OPERATOR=4
+val SCE_REBOL_CHARACTER=5
+val SCE_REBOL_QUOTEDSTRING=6
+val SCE_REBOL_BRACEDSTRING=7
+val SCE_REBOL_NUMBER=8
+val SCE_REBOL_PAIR=9
+val SCE_REBOL_TUPLE=10
+val SCE_REBOL_BINARY=11
+val SCE_REBOL_MONEY=12
+val SCE_REBOL_ISSUE=13
+val SCE_REBOL_TAG=14
+val SCE_REBOL_FILE=15
+val SCE_REBOL_EMAIL=16
+val SCE_REBOL_URL=17
+val SCE_REBOL_DATE=18
+val SCE_REBOL_TIME=19
+val SCE_REBOL_IDENTIFIER=20
+val SCE_REBOL_WORD=21
+val SCE_REBOL_WORD2=22
+val SCE_REBOL_WORD3=23
+val SCE_REBOL_WORD4=24
+val SCE_REBOL_WORD5=25
+val SCE_REBOL_WORD6=26
+val SCE_REBOL_WORD7=27
+val SCE_REBOL_WORD8=28
+# Lexical states for SCLEX_SQL
+lex SQL=SCLEX_SQL SCE_SQL_
+val SCE_SQL_DEFAULT=0
+val SCE_SQL_COMMENT=1
+val SCE_SQL_COMMENTLINE=2
+val SCE_SQL_COMMENTDOC=3
+val SCE_SQL_NUMBER=4
+val SCE_SQL_WORD=5
+val SCE_SQL_STRING=6
+val SCE_SQL_CHARACTER=7
+val SCE_SQL_SQLPLUS=8
+val SCE_SQL_SQLPLUS_PROMPT=9
+val SCE_SQL_OPERATOR=10
+val SCE_SQL_IDENTIFIER=11
+val SCE_SQL_SQLPLUS_COMMENT=13
+val SCE_SQL_COMMENTLINEDOC=15
+val SCE_SQL_WORD2=16
+val SCE_SQL_COMMENTDOCKEYWORD=17
+val SCE_SQL_COMMENTDOCKEYWORDERROR=18
+val SCE_SQL_USER1=19
+val SCE_SQL_USER2=20
+val SCE_SQL_USER3=21
+val SCE_SQL_USER4=22
+val SCE_SQL_QUOTEDIDENTIFIER=23
+# Lexical states for SCLEX_SMALLTALK
+lex Smalltalk=SCLEX_SMALLTALK SCE_ST_
+val SCE_ST_DEFAULT=0
+val SCE_ST_STRING=1
+val SCE_ST_NUMBER=2
+val SCE_ST_COMMENT=3
+val SCE_ST_SYMBOL=4
+val SCE_ST_BINARY=5
+val SCE_ST_BOOL=6
+val SCE_ST_SELF=7
+val SCE_ST_SUPER=8
+val SCE_ST_NIL=9
+val SCE_ST_GLOBAL=10
+val SCE_ST_RETURN=11
+val SCE_ST_SPECIAL=12
+val SCE_ST_KWSEND=13
+val SCE_ST_ASSIGN=14
+val SCE_ST_CHARACTER=15
+val SCE_ST_SPEC_SEL=16
+# Lexical states for SCLEX_FLAGSHIP (clipper)
+lex FlagShip=SCLEX_FLAGSHIP SCE_B_
+val SCE_FS_DEFAULT=0
+val SCE_FS_COMMENT=1
+val SCE_FS_COMMENTLINE=2
+val SCE_FS_COMMENTDOC=3
+val SCE_FS_COMMENTLINEDOC=4
+val SCE_FS_COMMENTDOCKEYWORD=5
+val SCE_FS_COMMENTDOCKEYWORDERROR=6
+val SCE_FS_KEYWORD=7
+val SCE_FS_KEYWORD2=8
+val SCE_FS_KEYWORD3=9
+val SCE_FS_KEYWORD4=10
+val SCE_FS_NUMBER=11
+val SCE_FS_STRING=12
+val SCE_FS_PREPROCESSOR=13
+val SCE_FS_OPERATOR=14
+val SCE_FS_IDENTIFIER=15
+val SCE_FS_DATE=16
+val SCE_FS_STRINGEOL=17
+val SCE_FS_CONSTANT=18
+val SCE_FS_ASM=19
+val SCE_FS_LABEL=20
+val SCE_FS_ERROR=21
+val SCE_FS_HEXNUMBER=22
+val SCE_FS_BINNUMBER=23
+# Lexical states for SCLEX_CSOUND
+lex Csound=SCLEX_CSOUND SCE_CSOUND_
+val SCE_CSOUND_DEFAULT=0
+val SCE_CSOUND_COMMENT=1
+val SCE_CSOUND_NUMBER=2
+val SCE_CSOUND_OPERATOR=3
+val SCE_CSOUND_INSTR=4
+val SCE_CSOUND_IDENTIFIER=5
+val SCE_CSOUND_OPCODE=6
+val SCE_CSOUND_HEADERSTMT=7
+val SCE_CSOUND_USERKEYWORD=8
+val SCE_CSOUND_COMMENTBLOCK=9
+val SCE_CSOUND_PARAM=10
+val SCE_CSOUND_ARATE_VAR=11
+val SCE_CSOUND_KRATE_VAR=12
+val SCE_CSOUND_IRATE_VAR=13
+val SCE_CSOUND_GLOBAL_VAR=14
+val SCE_CSOUND_STRINGEOL=15
 
 # Events
 
@@ -2604,6 +2903,7 @@ evt void Zoom=2018(void)
 evt void HotSpotClick=2019(int modifiers, int position)
 evt void HotSpotDoubleClick=2020(int modifiers, int position)
 evt void CallTipClick=2021(int position)
+evt void AutoCSelection=2022(string text)
 
 cat Deprecated
 
@@ -2617,3 +2917,6 @@ val CARET_XJUMPS=0x10
 val SCN_CHECKBRACE=2007
 evt void PosChanged=2012(int position)
 
+# SCLEX_HTML should be used in preference to these.
+val SCLEX_ASP=29
+val SCLEX_PHP=30
index 765fd8594d159e6420d32fdcc3cc420711400b00..7f47de7e13c33fd31b7aec0bb10a8ad12a703d50 100644 (file)
@@ -34,9 +34,9 @@ struct _ScintillaClass {
        void (* notify) (ScintillaObject *ttt);
 };
 
-guint          scintilla_get_type      (void);
+GtkType                scintilla_get_type      (void);
 GtkWidget*     scintilla_new           (void);
-void           scintilla_set_id        (ScintillaObject *sci,int id);
+void           scintilla_set_id        (ScintillaObject *sci, uptr_t id);
 sptr_t         scintilla_send_message  (ScintillaObject *sci,unsigned int iMessage, uptr_t wParam, sptr_t lParam);
 void           scintilla_release_resources(void);
 
index adbd24d038fa5cdc6def23578b7c1ced63ad868e..753adca77978e624daf6c3ba9b0518001c231470 100644 (file)
@@ -43,12 +43,13 @@ bool AutoComplete::Active() {
        return active;
 }
 
-void AutoComplete::Start(Window &parent, int ctrlID, int position,
-       int startLen_, int lineHeight, bool unicodeMode) {
+void AutoComplete::Start(Window &parent, int ctrlID, 
+       int position, Point location, int startLen_, 
+       int lineHeight, bool unicodeMode) {
        if (active) {
                Cancel();
        }
-       lb->Create(parent, ctrlID, lineHeight, unicodeMode);
+       lb->Create(parent, ctrlID, location, lineHeight, unicodeMode);
        lb->Clear();
        active = true;
        startLen = startLen_;
@@ -90,41 +91,18 @@ char AutoComplete::GetTypesep() {
 }
 
 void AutoComplete::SetList(const char *list) {
-       lb->Clear();
-       char *words = new char[strlen(list) + 1];
-       if (words) {
-               strcpy(words, list);
-               char *startword = words;
-               char *numword = NULL;
-               int i = 0;
-               for (; words && words[i]; i++) {
-                       if (words[i] == separator) {
-                               words[i] = '\0';
-                               if (numword)
-                                       *numword = '\0';
-                               lb->Append(startword, numword?atoi(numword + 1):-1);
-                               startword = words + i + 1;
-                               numword = NULL;
-                       } else if (words[i] == typesep) {
-                               numword = words + i;
-                       }
-               }
-               if (startword) {
-                       if (numword)
-                               *numword = '\0';
-                       lb->Append(startword, numword?atoi(numword + 1):-1);
-               }
-               delete []words;
-       }
+       lb->SetList(list, separator, typesep);
 }
 
-void AutoComplete::Show() {
-       lb->Show();
-       lb->Select(0);
+void AutoComplete::Show(bool show) {
+       lb->Show(show);
+       if (show)
+               lb->Select(0);
 }
 
 void AutoComplete::Cancel() {
        if (lb->Created()) {
+               lb->Clear();
                lb->Destroy();
                active = false;
        }
@@ -170,6 +148,18 @@ void AutoComplete::Select(const char *word) {
                                --pivot;
                        }
                        location = pivot;
+                       if (ignoreCase) {
+                               // Check for exact-case match
+                               for (; pivot <= end; pivot++) {
+                                       lb->GetValue(pivot, item, maxItemLen);
+                                       if (!strncmp(word, item, lenWord)) {
+                                               location = pivot;
+                                               break;
+                                       }
+                                       if (CompareNCaseInsensitive(word, item, lenWord))
+                                               break;
+                               }
+                       }
                } else if (cond < 0) {
                        end = pivot - 1;
                } else if (cond > 0) {
index eedab5625e834af99c981e1594701ca641356198..10577ca38057c0f10d369eb2d2175e75781dbcf3 100644 (file)
@@ -15,7 +15,7 @@ class AutoComplete {
        char stopChars[256];
        char fillUpChars[256];
        char separator;
-       char typesep; // Type separator
+       char typesep; // Type seperator
 
 public:
        bool ignoreCase;
@@ -35,7 +35,7 @@ public:
        bool Active();
 
        /// Display the auto completion list positioned to be near a character position
-       void Start(Window &parent, int ctrlID, int position,
+       void Start(Window &parent, int ctrlID, int position, Point location,
                int startLen_, int lineHeight, bool unicodeMode);
 
        /// The stop chars are characters which, when typed, cause the auto completion list to disappear
@@ -50,14 +50,14 @@ public:
        void SetSeparator(char separator_);
        char GetSeparator();
 
-       /// The typesep character is used for separating the word from the type
+       /// The typesep character is used for seperating the word from the type
        void SetTypesep(char separator_);
        char GetTypesep();
 
        /// The list string contains a sequence of words separated by the separator character
        void SetList(const char *list);
 
-       void Show();
+       void Show(bool show);
        void Cancel();
 
        /// Move the current list element by delta, scrolling appropriately
index 003284c12df5f14e8ef85a4669f8d50c2f7b71f7..80fd55d7b85dc9cdd178cf42fb4203fe065116b2 100644 (file)
@@ -18,8 +18,8 @@ CallTip::CallTip() {
        inCallTipMode = false;
        posStartCallTip = 0;
        val = 0;
-       xUp = -100;
-       xDown = -100;
+       rectUp = PRectangle(0,0,0,0);
+       rectDown = PRectangle(0,0,0,0);
        lineHeight = 1;
        startHighlight = 0;
        endHighlight = 0;
@@ -75,12 +75,12 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
                        if (IsArrowCharacter(s[startSeg])) {
                                xEnd = x + widthArrow;
                                offsetMain = xEnd;
+                               rcClient.left = x;
+                               rcClient.right = xEnd;
                                if (draw) {
                                        const int halfWidth = widthArrow / 2 - 3;
                                        const int centreX = x + widthArrow / 2 - 1;
                                        const int centreY = (rcClient.top + rcClient.bottom) / 2;
-                                       rcClient.left = x;
-                                       rcClient.right = xEnd;
                                        surface->FillRectangle(rcClient, colourBG.allocated);
                                        PRectangle rcClientInner(rcClient.left+1, rcClient.top+1, rcClient.right-2, rcClient.bottom-1);
                                        surface->FillRectangle(rcClientInner, colourUnSel.allocated);
@@ -104,12 +104,11 @@ void CallTip::DrawChunk(Surface *surface, int &x, const char *s,
                                                surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                                                                colourBG.allocated, colourBG.allocated);
                                        }
-                               } else {
-                                       if (s[startSeg] == '\001') {
-                                               xUp = x+1;
-                                       } else {
-                                               xDown = x+1;
-                                       }
+                               }
+                               if (s[startSeg] == '\001') {
+                                       rectUp = rcClient;
+                               } else if (s[startSeg] == '\002') {
+                                       rectDown = rcClient;
                                }
                        } else {
                                xEnd = x + surface->WidthText(font, s+startSeg, endSeg - startSeg);
@@ -203,13 +202,10 @@ void CallTip::PaintCT(Surface *surfaceWindow) {
 
 void CallTip::MouseClick(Point pt) {
        clickPlace = 0;
-       if (pt.y < lineHeight) {
-               if ((pt.x > xUp) && (pt.x < xUp + widthArrow - 2)) {
-                       clickPlace = 1;
-               } else if ((pt.x > xDown) && (pt.x < xDown + widthArrow - 2)) {
-                       clickPlace = 2;
-               }
-       }
+       if (rectUp.Contains(pt))
+               clickPlace = 1;
+       if (rectDown.Contains(pt))
+               clickPlace = 2;
 }
 
 PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
@@ -240,8 +236,8 @@ PRectangle CallTip::CallTipStart(int pos, Point pt, const char *defn,
        int numLines = 1;
        const char *newline;
        const char *look = val;
-       xUp = -100;
-       xDown = -100;
+       rectUp = PRectangle(0,0,0,0);
+       rectDown = PRectangle(0,0,0,0);
        offsetMain = 5;
        int width = PaintContents(surfaceMeasure, false) + 5;
        while ((newline = strchr(look, '\n')) != NULL) {
index feff7ea0b1ef4355e9a65efdd6f62e538a85dfd4..53eec832a25e3a48128f8ffeebd650aff97b17e1 100644 (file)
@@ -15,8 +15,8 @@ class CallTip {
        int endHighlight;
        char *val;
        Font font;
-       int xUp;
-       int xDown;
+       PRectangle rectUp;
+       PRectangle rectDown;
        int lineHeight;
        int offsetMain;
        // Private so CallTip objects can not be copied
index 8183e4d8d3ca9fffc41ddbc983c85cb1b8557146..1109a17fbe54293c865c78d86cb17f0a5ae29bca 100644 (file)
@@ -254,13 +254,14 @@ void LineVector::Remove(int pos) {
                linesData[i] = linesData[i + 1];
        }
        if (levels) {
-               // Level information merges back onto previous line
-               int posAbove = pos - 1;
-               if (posAbove < 0)
-                       posAbove = 0;
-               for (int j = posAbove; j < lines; j++) {
+               // Move up following lines but merge header flag from this line
+               // to line before to avoid a temporary disappearence causing expansion.
+               int firstHeader = levels[pos] & SC_FOLDLEVELHEADERFLAG;
+               for (int j = pos; j < lines; j++) {
                        levels[j] = levels[j + 1];
                }
+               if (pos > 0)
+                       levels[pos-1] |= firstHeader;
        }
        lines--;
 }
@@ -464,7 +465,7 @@ void UndoHistory::AppendAction(actionType at, int position, char *data, int leng
                        } else if (currentAction == savePoint) {
                                currentAction++;
                        } else if ((at == insertAction) &&
-                                  (position != (actPrevious.position + actPrevious.lenData*2))) {
+                                  (position != (actPrevious.position + actPrevious.lenData))) {
                                // Insertions must be immediately after to coalesce
                                currentAction++;
                        } else if (!actions[currentAction].mayCoalesce) {
@@ -472,7 +473,7 @@ void UndoHistory::AppendAction(actionType at, int position, char *data, int leng
                                currentAction++;
                        } else if (at == removeAction) {
                                if ((lengthData == 1) || (lengthData == 2)){
-                                       if ((position + lengthData * 2) == actPrevious.position) {
+                                       if ((position + lengthData) == actPrevious.position) {
                                                ; // Backspace -> OK
                                        } else if (position == actPrevious.position) {
                                                ; // Delete -> OK
@@ -724,7 +725,7 @@ const char *CellBuffer::InsertString(int position, char *s, int insertLength) {
                        for (int i = 0; i < insertLength / 2; i++) {
                                data[i] = s[i * 2];
                        }
-                       uh.AppendAction(insertAction, position, data, insertLength / 2);
+                       uh.AppendAction(insertAction, position / 2, data, insertLength / 2);
                }
 
                BasicInsertString(position, s, insertLength);
@@ -732,13 +733,6 @@ const char *CellBuffer::InsertString(int position, char *s, int insertLength) {
        return data;
 }
 
-void CellBuffer::InsertCharStyle(int position, char ch, char style) {
-       char s[2];
-       s[0] = ch;
-       s[1] = style;
-       InsertString(position*2, s, 2);
-}
-
 bool CellBuffer::SetStyleAt(int position, char style, char mask) {
        style &= mask;
        char curVal = ByteAt(position * 2 + 1);
@@ -768,6 +762,7 @@ bool CellBuffer::SetStyleFor(int position, int lengthStyle, char style, char mas
 
 const char *CellBuffer::DeleteChars(int position, int deleteLength) {
        // InsertString and DeleteChars are the bottleneck though which all changes occur
+       PLATFORM_ASSERT(deleteLength > 0);
        char *data = 0;
        if (!readOnly) {
                if (collectingUndo) {
@@ -776,7 +771,7 @@ const char *CellBuffer::DeleteChars(int position, int deleteLength) {
                        for (int i = 0; i < deleteLength / 2; i++) {
                                data[i] = ByteAt(position + i * 2);
                        }
-                       uh.AppendAction(removeAction, position, data, deleteLength / 2);
+                       uh.AppendAction(removeAction, position / 2, data, deleteLength / 2);
                }
 
                BasicDeleteChars(position, deleteLength);
@@ -874,6 +869,7 @@ void CellBuffer::BasicInsertString(int position, char *s, int insertLength) {
        //Platform::DebugPrintf("Inserting at %d for %d\n", position, insertLength);
        if (insertLength == 0)
                return ;
+       PLATFORM_ASSERT(insertLength > 0);
        RoomFor(insertLength);
        GapTo(position);
 
@@ -1028,7 +1024,7 @@ void CellBuffer::DeleteUndoHistory() {
 }
 
 bool CellBuffer::CanUndo() {
-       return (!readOnly) && (uh.CanUndo());
+       return uh.CanUndo();
 }
 
 int CellBuffer::StartUndo() {
@@ -1042,21 +1038,21 @@ const Action &CellBuffer::GetUndoStep() const {
 void CellBuffer::PerformUndoStep() {
        const Action &actionStep = uh.GetUndoStep();
        if (actionStep.at == insertAction) {
-               BasicDeleteChars(actionStep.position, actionStep.lenData*2);
+               BasicDeleteChars(actionStep.position*2, actionStep.lenData*2);
        } else if (actionStep.at == removeAction) {
                char *styledData = new char[actionStep.lenData * 2];
                for (int i = 0; i < actionStep.lenData; i++) {
                        styledData[i*2] = actionStep.data[i];
                        styledData[i*2 + 1] = 0;
                }
-               BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
+               BasicInsertString(actionStep.position*2, styledData, actionStep.lenData*2);
                delete []styledData;
        }
        uh.CompletedUndoStep();
 }
 
 bool CellBuffer::CanRedo() {
-       return (!readOnly) && (uh.CanRedo());
+       return uh.CanRedo();
 }
 
 int CellBuffer::StartRedo() {
@@ -1075,10 +1071,10 @@ void CellBuffer::PerformRedoStep() {
                        styledData[i*2] = actionStep.data[i];
                        styledData[i*2 + 1] = 0;
                }
-               BasicInsertString(actionStep.position, styledData, actionStep.lenData*2);
+               BasicInsertString(actionStep.position*2, styledData, actionStep.lenData*2);
                delete []styledData;
        } else if (actionStep.at == removeAction) {
-               BasicDeleteChars(actionStep.position, actionStep.lenData*2);
+               BasicDeleteChars(actionStep.position*2, actionStep.lenData*2);
        }
        uh.CompletedRedoStep();
 }
index b16eef5e51a745f92ed3ae10d5098fd9b0c2818c..bb81fd5722d3784d697a1705140183bbaf1505a7 100644 (file)
@@ -191,7 +191,6 @@ public:
        int LineStart(int line);
        int LineFromPosition(int pos) { return lv.LineFromPosition(pos); }
        const char *InsertString(int position, char *s, int insertLength);
-       void InsertCharStyle(int position, char ch, char style);
 
        /// Setting styles for positions outside the range of the buffer is safe and has no effect.
        /// @return true if the style of a character is changed.
index 76fa456ccb613e44366b2205081e91d4bac74150..a88468cb1a8b26431c99864764564e68a43a1bcf 100644 (file)
@@ -103,26 +103,40 @@ void Document::SetSavePoint() {
 
 int Document::AddMark(int line, int markerNum) {
        int prev = cb.AddMark(line, markerNum);
-       DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0);
+       DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+       mh.line = line;
        NotifyModified(mh);
        return prev;
 }
 
+void Document::AddMarkSet(int line, int valueSet) {
+       unsigned int m = valueSet;
+       for (int i = 0; m; i++, m >>= 1)
+               if (m & 1)
+                       cb.AddMark(line, i);
+       DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+       mh.line = line;
+       NotifyModified(mh);
+}
+
 void Document::DeleteMark(int line, int markerNum) {
        cb.DeleteMark(line, markerNum);
-       DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0);
+       DocModification mh(SC_MOD_CHANGEMARKER, LineStart(line), 0, 0, 0, line);
+       mh.line = line;
        NotifyModified(mh);
 }
 
 void Document::DeleteMarkFromHandle(int markerHandle) {
        cb.DeleteMarkFromHandle(markerHandle);
        DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
+       mh.line = -1;
        NotifyModified(mh);
 }
 
 void Document::DeleteAllMarks(int markerNum) {
        cb.DeleteAllMarks(markerNum);
        DocModification mh(SC_MOD_CHANGEMARKER, 0, 0, 0, 0);
+       mh.line = -1;
        NotifyModified(mh);
 }
 
@@ -266,7 +280,7 @@ int Document::LenChar(int pos) {
                return 1;
        }
 }
-#include <assert.h>
+
 // Normalise a position so that it is not halfway through a two byte character.
 // This can occur in two situations -
 // When lines are terminated with \r\n pairs which should be treated as one character.
@@ -280,7 +294,7 @@ int Document::MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd) {
        if (pos >= Length())
                return Length();
 
-       // assert pos > 0 && pos < Length()
+       // PLATFORM_ASSERT(pos > 0 && pos < Length());
        if (checkLineEnd && IsCrLf(pos - 1)) {
                if (moveDir > 0)
                        return pos + 1;
@@ -336,6 +350,14 @@ void Document::ModifiedAt(int pos) {
                endStyled = pos;
 }
 
+void Document::CheckReadOnly() {
+       if (cb.IsReadOnly() && enteredReadOnlyCount == 0) {
+               enteredReadOnlyCount++;
+               NotifyModifyAttempt();
+               enteredReadOnlyCount--;
+       }
+}
+
 // Document only modified by gateways DeleteChars, InsertStyledString, Undo, Redo, and SetStyleAt.
 // SetStyleAt does not change the persistent state of a document
 
@@ -345,11 +367,7 @@ bool Document::DeleteChars(int pos, int len) {
                return false;
        if ((pos + len) > Length())
                return false;
-       if (cb.IsReadOnly() && enteredReadOnlyCount == 0) {
-               enteredReadOnlyCount++;
-               NotifyModifyAttempt();
-               enteredReadOnlyCount--;
-       }
+       CheckReadOnly();
        if (enteredCount != 0) {
                return false;
        } else {
@@ -384,11 +402,7 @@ bool Document::DeleteChars(int pos, int len) {
  * Insert a styled string (char/style pairs) with a length.
  */
 bool Document::InsertStyledString(int position, char *s, int insertLength) {
-       if (cb.IsReadOnly() && enteredReadOnlyCount == 0) {
-               enteredReadOnlyCount++;
-               NotifyModifyAttempt();
-               enteredReadOnlyCount--;
-       }
+       CheckReadOnly();
        if (enteredCount != 0) {
                return false;
        } else {
@@ -417,86 +431,110 @@ bool Document::InsertStyledString(int position, char *s, int insertLength) {
 }
 
 int Document::Undo() {
-       int newPos = 0;
+       int newPos = -1;
+       CheckReadOnly();
        if (enteredCount == 0) {
                enteredCount++;
-               bool startSavePoint = cb.IsSavePoint();
-               int steps = cb.StartUndo();
-               //Platform::DebugPrintf("Steps=%d\n", steps);
-               for (int step = 0; step < steps; step++) {
-                       int prevLinesTotal = LinesTotal();
-                       const Action &action = cb.GetUndoStep();
-                       if (action.at == removeAction) {
-                               NotifyModified(DocModification(
-                                                  SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action));
-                       } else {
-                               NotifyModified(DocModification(
-                                                  SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action));
-                       }
-                       cb.PerformUndoStep();
-                       int cellPosition = action.position / 2;
-                       ModifiedAt(cellPosition);
-                       newPos = cellPosition;
-
-                       int modFlags = SC_PERFORMED_UNDO;
-                       // With undo, an insertion action becomes a deletion notification
-                       if (action.at == removeAction) {
-                               newPos += action.lenData;
-                               modFlags |= SC_MOD_INSERTTEXT;
-                       } else {
-                               modFlags |= SC_MOD_DELETETEXT;
+               if (!cb.IsReadOnly()) {
+                       bool startSavePoint = cb.IsSavePoint();
+                       bool multiLine = false;
+                       int steps = cb.StartUndo();
+                       //Platform::DebugPrintf("Steps=%d\n", steps);
+                       for (int step = 0; step < steps; step++) {
+                               const int prevLinesTotal = LinesTotal();
+                               const Action &action = cb.GetUndoStep();
+                               if (action.at == removeAction) {
+                                       NotifyModified(DocModification(
+                                                                       SC_MOD_BEFOREINSERT | SC_PERFORMED_UNDO, action));
+                               } else {
+                                       NotifyModified(DocModification(
+                                                                       SC_MOD_BEFOREDELETE | SC_PERFORMED_UNDO, action));
+                               }
+                               cb.PerformUndoStep();
+                               int cellPosition = action.position;
+                               ModifiedAt(cellPosition);
+                               newPos = cellPosition;
+
+                               int modFlags = SC_PERFORMED_UNDO;
+                               // With undo, an insertion action becomes a deletion notification
+                               if (action.at == removeAction) {
+                                       newPos += action.lenData;
+                                       modFlags |= SC_MOD_INSERTTEXT;
+                               } else {
+                                       modFlags |= SC_MOD_DELETETEXT;
+                               }
+                               if (steps > 1)
+                                       modFlags |= SC_MULTISTEPUNDOREDO;
+                               const int linesAdded = LinesTotal() - prevLinesTotal;
+                               if (linesAdded != 0)
+                                       multiLine = true;
+                               if (step == steps - 1) {
+                                       modFlags |= SC_LASTSTEPINUNDOREDO;
+                                       if (multiLine)
+                                               modFlags |= SC_MULTILINEUNDOREDO;
+                               }
+                               NotifyModified(DocModification(modFlags, cellPosition, action.lenData,
+                                                                                          linesAdded, action.data));
                        }
-                       if (step == steps - 1)
-                               modFlags |= SC_LASTSTEPINUNDOREDO;
-                       NotifyModified(DocModification(modFlags, cellPosition, action.lenData,
-                                                      LinesTotal() - prevLinesTotal, action.data));
-               }
 
-               bool endSavePoint = cb.IsSavePoint();
-               if (startSavePoint != endSavePoint)
-                       NotifySavePoint(endSavePoint);
+                       bool endSavePoint = cb.IsSavePoint();
+                       if (startSavePoint != endSavePoint)
+                               NotifySavePoint(endSavePoint);
+               }
                enteredCount--;
        }
        return newPos;
 }
 
 int Document::Redo() {
-       int newPos = 0;
+       int newPos = -1;
+       CheckReadOnly();
        if (enteredCount == 0) {
                enteredCount++;
-               bool startSavePoint = cb.IsSavePoint();
-               int steps = cb.StartRedo();
-               for (int step = 0; step < steps; step++) {
-                       int prevLinesTotal = LinesTotal();
-                       const Action &action = cb.GetRedoStep();
-                       if (action.at == insertAction) {
-                               NotifyModified(DocModification(
-                                                  SC_MOD_BEFOREINSERT | SC_PERFORMED_REDO, action));
-                       } else {
-                               NotifyModified(DocModification(
-                                                  SC_MOD_BEFOREDELETE | SC_PERFORMED_REDO, action));
-                       }
-                       cb.PerformRedoStep();
-                       ModifiedAt(action.position / 2);
-                       newPos = action.position / 2;
-
-                       int modFlags = SC_PERFORMED_REDO;
-                       if (action.at == insertAction) {
-                               newPos += action.lenData;
-                               modFlags |= SC_MOD_INSERTTEXT;
-                       } else {
-                               modFlags |= SC_MOD_DELETETEXT;
+               if (!cb.IsReadOnly()) {
+                       bool startSavePoint = cb.IsSavePoint();
+                       bool multiLine = false;
+                       int steps = cb.StartRedo();
+                       for (int step = 0; step < steps; step++) {
+                               const int prevLinesTotal = LinesTotal();
+                               const Action &action = cb.GetRedoStep();
+                               if (action.at == insertAction) {
+                                       NotifyModified(DocModification(
+                                                                       SC_MOD_BEFOREINSERT | SC_PERFORMED_REDO, action));
+                               } else {
+                                       NotifyModified(DocModification(
+                                                                       SC_MOD_BEFOREDELETE | SC_PERFORMED_REDO, action));
+                               }
+                               cb.PerformRedoStep();
+                               ModifiedAt(action.position);
+                               newPos = action.position;
+
+                               int modFlags = SC_PERFORMED_REDO;
+                               if (action.at == insertAction) {
+                                       newPos += action.lenData;
+                                       modFlags |= SC_MOD_INSERTTEXT;
+                               } else {
+                                       modFlags |= SC_MOD_DELETETEXT;
+                               }
+                               if (steps > 1)
+                                       modFlags |= SC_MULTISTEPUNDOREDO;
+                               const int linesAdded = LinesTotal() - prevLinesTotal;
+                               if (linesAdded != 0)
+                                       multiLine = true;
+                               if (step == steps - 1) {
+                                       modFlags |= SC_LASTSTEPINUNDOREDO;
+                                       if (multiLine)
+                                               modFlags |= SC_MULTILINEUNDOREDO;
+                               }
+                               NotifyModified(
+                                       DocModification(modFlags, action.position, action.lenData,
+                                                                       linesAdded, action.data));
                        }
-                       if (step == steps - 1)
-                               modFlags |= SC_LASTSTEPINUNDOREDO;
-                       NotifyModified(
-                           DocModification(modFlags, action.position / 2, action.lenData,
-                                           LinesTotal() - prevLinesTotal, action.data));
-               }
 
-               bool endSavePoint = cb.IsSavePoint();
-               if (startSavePoint != endSavePoint)
-                       NotifySavePoint(endSavePoint);
+                       bool endSavePoint = cb.IsSavePoint();
+                       if (startSavePoint != endSavePoint)
+                               NotifySavePoint(endSavePoint);
+               }
                enteredCount--;
        }
        return newPos;
@@ -524,15 +562,17 @@ bool Document::InsertString(int position, const char *s) {
  */
 bool Document::InsertString(int position, const char *s, size_t insertLength) {
        bool changed = false;
-       char *sWithStyle = new char[insertLength * 2];
-       if (sWithStyle) {
-               for (size_t i = 0; i < insertLength; i++) {
-                       sWithStyle[i*2] = s[i];
-                       sWithStyle[i*2 + 1] = 0;
+       if (insertLength > 0) {
+               char *sWithStyle = new char[insertLength * 2];
+               if (sWithStyle) {
+                       for (size_t i = 0; i < insertLength; i++) {
+                               sWithStyle[i*2] = s[i];
+                               sWithStyle[i*2 + 1] = 0;
+                       }
+                       changed = InsertStyledString(position*2, sWithStyle,
+                               static_cast<int>(insertLength*2));
+                       delete []sWithStyle;
                }
-               changed = InsertStyledString(position*2, sWithStyle,
-                       static_cast<int>(insertLength*2));
-               delete []sWithStyle;
        }
        return changed;
 }
@@ -611,8 +651,10 @@ void Document::SetLineIndentation(int line, int indent) {
                CreateIndentation(linebuf, sizeof(linebuf), indent, tabInChars, !useTabs);
                int thisLineStart = LineStart(line);
                int indentPos = GetLineIndentPosition(line);
+               BeginUndoAction();
                DeleteChars(thisLineStart, indentPos - thisLineStart);
                InsertString(thisLineStart, linebuf);
+               EndUndoAction();
        }
 }
 
@@ -675,10 +717,13 @@ void Document::Indent(bool forwards, int lineBottom, int lineTop) {
        // Dedent - suck white space off the front of the line to dedent by equivalent of a tab
        for (int line = lineBottom; line >= lineTop; line--) {
                int indentOfLine = GetLineIndentation(line);
-               if (forwards)
-                       SetLineIndentation(line, indentOfLine + IndentSize());
-               else
+               if (forwards) {
+                       if (LineStart(line) < LineEnd(line)) {
+                               SetLineIndentation(line, indentOfLine + IndentSize());
+                       }
+               } else {
                        SetLineIndentation(line, indentOfLine - IndentSize());
+               }
        }
 }
 
@@ -718,7 +763,7 @@ void Document::ConvertLineEnds(int eolModeSet) {
 
        for (int pos = 0; pos < Length(); pos++) {
                if (cb.CharAt(pos) == '\r') {
-                       if (cb.CharAt(pos + 1) == '\n') { 
+                       if (cb.CharAt(pos + 1) == '\n') {
                                // CRLF
                                if (eolModeSet == SC_EOL_CR) {
                                        DeleteChars(pos + 1, 1); // Delete the LF
@@ -727,7 +772,7 @@ void Document::ConvertLineEnds(int eolModeSet) {
                                } else {
                                        pos++;
                                }
-                       } else { 
+                       } else {
                                // CR
                                if (eolModeSet == SC_EOL_CRLF) {
                                        InsertString(pos + 1, "\n", 1); // Insert LF
@@ -752,33 +797,45 @@ void Document::ConvertLineEnds(int eolModeSet) {
        EndUndoAction();
 }
 
-int Document::ParaDown(int pos) {
-       int line = LineFromPosition(pos);
-       while (line < LinesTotal() && LineStart(line) != LineEnd(line)) { // skip non-empty lines
-               line++;
-       }
-       while (line < LinesTotal() && LineStart(line) == LineEnd(line)) { // skip empty lines
-               line++;
+bool Document::IsWhiteLine(int line) {
+       int currentChar = LineStart(line);
+       int endLine = LineEnd(line);
+       while (currentChar < endLine) {
+               if (cb.CharAt(currentChar) != ' ' && cb.CharAt(currentChar) != '\t') {
+                       return false;
+               }
+               ++currentChar;
        }
-       if (line < LinesTotal())
-               return LineStart(line);
-       else // end of a document
-               return LineEnd(line-1);
+       return true;
 }
 
 int Document::ParaUp(int pos) {
        int line = LineFromPosition(pos);
        line--;
-       while (line >= 0 && LineStart(line) == LineEnd(line)) { // skip empty lines
+       while (line >= 0 && IsWhiteLine(line)) { // skip empty lines
                line--;
        }
-       while (line >= 0 && LineStart(line) != LineEnd(line)) { // skip non-empty lines
+       while (line >= 0 && !IsWhiteLine(line)) { // skip non-empty lines
                line--;
        }
        line++;
        return LineStart(line);
 }
 
+int Document::ParaDown(int pos) {
+       int line = LineFromPosition(pos);
+       while (line < LinesTotal() && !IsWhiteLine(line)) { // skip non-empty lines
+               line++;
+       }
+       while (line < LinesTotal() && IsWhiteLine(line)) { // skip empty lines
+               line++;
+       }
+       if (line < LinesTotal())
+               return LineStart(line);
+       else // end of a document
+               return LineEnd(line-1);
+}
+
 Document::charClassification Document::WordCharClass(unsigned char ch) {
        if ((SC_CP_UTF8 == dbcsCodePage) && (ch >= 0x80))
                return ccWord;
@@ -926,6 +983,9 @@ public:
                pdoc(pdoc_), end(end_) {
        }
 
+       virtual ~DocumentIndexer() {
+       }
+
        virtual char CharAt(int index) {
                if (index < 0 || index >= end)
                        return 0;
@@ -1001,7 +1061,7 @@ long Document::FindText(int minPos, int maxPos, const char *s,
                                if (line == lineRangeStart) {
                                        if ((startPos != endOfLine) && (searchEnd == '$'))
                                                continue;       // Can't match end of line if start position before end of line
-                                       endOfLine = startPos+1;
+                                       endOfLine = startPos;
                                }
                        }
 
@@ -1013,10 +1073,10 @@ long Document::FindText(int minPos, int maxPos, const char *s,
                                if (increment == -1) {
                                        // Check for the last match on this line.
                                        int repetitions = 1000; // Break out of infinite loop
-                                       while (success && (pre->eopat[0] <= (endOfLine+1)) && (repetitions--)) {
-                                               success = pre->Execute(di, pos+1, endOfLine+1);
+                                       while (success && (pre->eopat[0] <= endOfLine) && (repetitions--)) {
+                                               success = pre->Execute(di, pos+1, endOfLine);
                                                if (success) {
-                                                       if (pre->eopat[0] <= (minPos+1)) {
+                                                       if (pre->eopat[0] <= minPos) {
                                                                pos = pre->bopat[0];
                                                                lenRet = pre->eopat[0] - pre->bopat[0];
                                                        } else {
@@ -1052,12 +1112,13 @@ long Document::FindText(int minPos, int maxPos, const char *s,
                char firstChar = s[0];
                if (!caseSensitive)
                        firstChar = static_cast<char>(MakeUpperCase(firstChar));
-               int pos = startPos;
+               int pos = forward ? startPos : (startPos - 1);
                while (forward ? (pos < endSearch) : (pos >= endSearch)) {
                        char ch = CharAt(pos);
                        if (caseSensitive) {
                                if (ch == firstChar) {
                                        bool found = true;
+                                       if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false;
                                        for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
                                                ch = CharAt(pos + posMatch);
                                                if (ch != s[posMatch])
@@ -1073,6 +1134,7 @@ long Document::FindText(int minPos, int maxPos, const char *s,
                        } else {
                                if (MakeUpperCase(ch) == firstChar) {
                                        bool found = true;
+                                       if (pos + lengthFind > Platform::Maximum(startPos, endPos)) found = false;
                                        for (int posMatch = 1; posMatch < lengthFind && found; posMatch++) {
                                                ch = CharAt(pos + posMatch);
                                                if (MakeUpperCase(ch) != MakeUpperCase(s[posMatch]))
@@ -1185,11 +1247,9 @@ int Document::LinesTotal() {
 }
 
 void Document::ChangeCase(Range r, bool makeUpperCase) {
-       for (int pos = r.start; pos < r.end; pos++) {
+       for (int pos = r.start; pos < r.end;) {
                int len = LenChar(pos);
-               if (dbcsCodePage && (len > 1)) {
-                       pos += len;
-               } else {
+               if (len == 1) {
                        char ch = CharAt(pos);
                        if (makeUpperCase) {
                                if (IsLowerCase(ch)) {
@@ -1201,6 +1261,7 @@ void Document::ChangeCase(Range r, bool makeUpperCase) {
                                }
                        }
                }
+               pos += len;
        }
 }
 
@@ -1265,19 +1326,22 @@ bool Document::SetStyles(int length, char *styles) {
                return false;
        } else {
                enteredCount++;
-               int prevEndStyled = endStyled;
                bool didChange = false;
-               int lastChange = 0;
+               int startMod = 0;
+               int endMod = 0;
                for (int iPos = 0; iPos < length; iPos++, endStyled++) {
                        PLATFORM_ASSERT(endStyled < Length());
                        if (cb.SetStyleAt(endStyled, styles[iPos], stylingMask)) {
+                               if (!didChange) {
+                                       startMod = endStyled;
+                               }
                                didChange = true;
-                               lastChange = iPos;
+                               endMod = endStyled;
                        }
                }
                if (didChange) {
                        DocModification mh(SC_MOD_CHANGESTYLE | SC_PERFORMED_USER,
-                                          prevEndStyled, lastChange);
+                                          startMod, endMod - startMod + 1);
                        NotifyModified(mh);
                }
                enteredCount--;
@@ -1475,3 +1539,55 @@ int Document::ExtendStyleRange(int pos, int delta, bool singleLine) {
        }
        return pos;
 }
+
+static char BraceOpposite(char ch) {
+       switch (ch) {
+       case '(':
+               return ')';
+       case ')':
+               return '(';
+       case '[':
+               return ']';
+       case ']':
+               return '[';
+       case '{':
+               return '}';
+       case '}':
+               return '{';
+       case '<':
+               return '>';
+       case '>':
+               return '<';
+       default:
+               return '\0';
+       }
+}
+
+// TODO: should be able to extend styled region to find matching brace
+int Document::BraceMatch(int position, int /*maxReStyle*/) {
+       char chBrace = CharAt(position);
+       char chSeek = BraceOpposite(chBrace);
+       if (chSeek == '\0')
+               return - 1;
+       char styBrace = static_cast<char>(StyleAt(position) & stylingBitsMask);
+       int direction = -1;
+       if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<')
+               direction = 1;
+       int depth = 1;
+       position = position + direction;
+       while ((position >= 0) && (position < Length())) {
+               position = MovePositionOutsideChar(position, direction);
+               char chAtPos = CharAt(position);
+               char styAtPos = static_cast<char>(StyleAt(position) & stylingBitsMask);
+               if ((position > GetEndStyled()) || (styAtPos == styBrace)) {
+                       if (chAtPos == chBrace)
+                               depth++;
+                       if (chAtPos == chSeek)
+                               depth--;
+                       if (depth == 0)
+                               return position;
+               }
+               position = position + direction;
+       }
+       return - 1;
+}
index ce27ffc47611e638e8365ef78285abd5e0d05df8..6ff858b9238b517fb90b438e3e3425f016685c2c 100644 (file)
@@ -134,6 +134,7 @@ public:
        int MovePositionOutsideChar(int pos, int moveDir, bool checkLineEnd=true);
 
        // Gateways to modifying document
+       void ModifiedAt(int pos);
        bool DeleteChars(int pos, int len);
        bool InsertStyledString(int position, char *s, int insertLength);
        int Undo();
@@ -175,6 +176,7 @@ public:
        char StyleAt(int position) { return cb.StyleAt(position); }
        int GetMark(int line) { return cb.GetMark(line); }
        int AddMark(int line, int markerNum);
+       void AddMarkSet(int line, int valueSet);
        void DeleteMark(int line, int markerNum);
        void DeleteMarkFromHandle(int markerHandle);
        void DeleteAllMarks(int markerNum);
@@ -228,16 +230,19 @@ public:
        int WordPartLeft(int pos);
        int WordPartRight(int pos);
        int ExtendStyleRange(int pos, int delta, bool singleLine = false);
+       bool IsWhiteLine(int line);
        int ParaUp(int pos);
        int ParaDown(int pos);
        int IndentSize() { return actualIndentInChars; }
+       int BraceMatch(int position, int maxReStyle);
 
 private:
+       void CheckReadOnly();
+
        charClassification WordCharClass(unsigned char ch);
        bool IsWordStartAt(int pos);
        bool IsWordEndAt(int pos);
        bool IsWordAt(int start, int end);
-       void ModifiedAt(int pos);
 
        void NotifyModifyAttempt();
        void NotifySavePoint(bool atSavePoint);
@@ -261,19 +266,19 @@ public:
        int foldLevelPrev;
 
        DocModification(int modificationType_, int position_=0, int length_=0,
-               int linesAdded_=0, const char *text_=0) :
+               int linesAdded_=0, const char *text_=0, int line_=0) :
                modificationType(modificationType_),
                position(position_),
                length(length_),
                linesAdded(linesAdded_),
                text(text_),
-               line(0),
+               line(line_),
                foldLevelNow(0),
                foldLevelPrev(0) {}
 
-    DocModification(int modificationType_, const Action &act, int linesAdded_=0) :
+       DocModification(int modificationType_, const Action &act, int linesAdded_=0) :
                modificationType(modificationType_),
-               position(act.position / 2),
+               position(act.position),
                length(act.lenData),
                linesAdded(linesAdded_),
                text(act.data),
index 738eca7a07695a3f6be0e9ecb1dbd4fe189f7f94..f479ce0259258fe9d668a32c6efb3558c628721b 100644 (file)
@@ -58,7 +58,8 @@ bool DocumentAccessor::Match(int pos, const char *s) {
 }
 
 char DocumentAccessor::StyleAt(int position) {
-       return pdoc->StyleAt(position);
+       // Mask off all bits which aren't in the 'mask'.
+       return static_cast<char>(pdoc->StyleAt(position) & mask);
 }
 
 int DocumentAccessor::GetLine(int position) {
@@ -88,6 +89,8 @@ int DocumentAccessor::SetLineState(int line, int state) {
 }
 
 void DocumentAccessor::StartAt(unsigned int start, char chMask) {
+       // Store the mask specified for use with StyleAt.
+       mask = chMask;
        pdoc->StartStyling(start, chMask);
        startPosStyling = start;
 }
index dc591d13ec3142c08216f5451b18e752db0fb6e1..7406520452313cb6ed8106037b2952b3eab689e0 100644 (file)
@@ -27,6 +27,7 @@ protected:
        char chWhile;
        unsigned int startSeg;
        int startPosStyling;
+       int mask;
 
        bool InternalIsLeadByte(char ch);
        void Fill(int position);
@@ -35,7 +36,8 @@ public:
        DocumentAccessor(Document *pdoc_, PropSet &props_, WindowID id_=0) : 
                Accessor(), pdoc(pdoc_), props(props_), id(id_),
                lenDoc(-1), validLen(0), chFlags(0), chWhile(0), 
-               startSeg(0), startPosStyling(0) {
+               startSeg(0), startPosStyling(0),
+               mask(127) { // Initialize the mask to be big enough for any lexer.
        }
        ~DocumentAccessor();
        bool Match(int pos, const char *s);
index d32022ff118bfdc60ca6760c284dcf3dd0547469..0aa2a651c63278332608969654a6653dddf64fbf 100644 (file)
 #include "Document.h"
 #include "Editor.h"
 
+/*
+       return whether this modification represents an operation that
+       may reasonably be deferred (not done now OR [possibly] at all)
+*/
+static bool CanDeferToLastStep(const DocModification& mh) {
+       if (mh.modificationType & (SC_MOD_BEFOREINSERT|SC_MOD_BEFOREDELETE))
+               return true;    // CAN skip
+       if (!(mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO)))
+               return false;   // MUST do
+       if (mh.modificationType & SC_MULTISTEPUNDOREDO)
+               return true;    // CAN skip
+       return false;           // PRESUMABLY must do
+}
+
+static bool CanEliminate(const DocModification& mh) {
+       return
+               (mh.modificationType & (SC_MOD_BEFOREINSERT|SC_MOD_BEFOREDELETE)) != 0;
+}
+
+/*
+       return whether this modification represents the FINAL step
+       in a [possibly lengthy] multi-step Undo/Redo sequence
+*/
+static bool IsLastStep(const DocModification& mh) {
+       return
+               (mh.modificationType & (SC_PERFORMED_UNDO|SC_PERFORMED_REDO)) != 0
+               && (mh.modificationType & SC_MULTISTEPUNDOREDO) != 0
+               && (mh.modificationType & SC_LASTSTEPINUNDOREDO) != 0
+               && (mh.modificationType & SC_MULTILINEUNDOREDO) != 0;
+}
+
 Caret::Caret() :
 active(false), on(false), period(500) {}
 
@@ -54,6 +85,7 @@ LineLayout::LineLayout(int maxLineLength_) :
        edgeColumn(0),
        chars(0),
        styles(0),
+       styleBitsSet(0),
        indicators(0),
        positions(0),
        hsStart(0),
@@ -157,7 +189,7 @@ void LineLayout::RestoreBracesHighlight(Range rangeLine, Position braces[]) {
 
 LineLayoutCache::LineLayoutCache() :
        level(0), length(0), size(0), cache(0),
-       allInvalidated(false), styleClock(-1) {
+       allInvalidated(false), styleClock(-1), useCount(0) {
        Allocate(0);
 }
 
@@ -166,6 +198,7 @@ LineLayoutCache::~LineLayoutCache() {
 }
 
 void LineLayoutCache::Allocate(int length_) {
+       PLATFORM_ASSERT(cache == NULL);
        allInvalidated = false;
        length = length_;
        size = length;
@@ -180,6 +213,7 @@ void LineLayoutCache::Allocate(int length_) {
 }
 
 void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) {
+       PLATFORM_ASSERT(useCount == 0);
        int lengthForLevel = 0;
        if (level == llcCaret) {
                lengthForLevel = 1;
@@ -190,23 +224,28 @@ void LineLayoutCache::AllocateForLevel(int linesOnScreen, int linesInDoc) {
        }
        if (lengthForLevel > size) {
                Deallocate();
-       } else if (lengthForLevel < length) {
-               for (int i = lengthForLevel; i < length; i++) {
-                       delete cache[i];
-                       cache[i] = 0;
-               }
-       }
-       if (!cache) {
                Allocate(lengthForLevel);
+       } else {
+               if (lengthForLevel < length) {
+                       for (int i = lengthForLevel; i < length; i++) {
+                               delete cache[i];
+                               cache[i] = 0;
+                       }
+               }
+               length = lengthForLevel;
        }
+       PLATFORM_ASSERT(length == lengthForLevel);
+       PLATFORM_ASSERT(cache != NULL || length == 0);
 }
 
 void LineLayoutCache::Deallocate() {
+       PLATFORM_ASSERT(useCount == 0);
        for (int i = 0; i < length; i++)
                delete cache[i];
        delete []cache;
        cache = 0;
        length = 0;
+       size = 0;
 }
 
 void LineLayoutCache::Invalidate(LineLayout::validLevel validity_) {
@@ -244,14 +283,15 @@ LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChar
                pos = 0;
        } else if (level == llcPage) {
                if (lineNumber == lineCaret) {
-                       pos = length;
+                       pos = 0;
                } else {
-                       pos = lineNumber % length;
+                       pos = 1 + (lineNumber % (length - 1));
                }
        } else if (level == llcDocument) {
                pos = lineNumber;
        }
        if (pos >= 0) {
+               PLATFORM_ASSERT(useCount == 0);
                if (cache && (pos < length)) {
                        if (cache[pos]) {
                                if ((cache[pos]->lineNumber != lineNumber) ||
@@ -267,6 +307,7 @@ LineLayout *LineLayoutCache::Retrieve(int lineNumber, int lineCaret, int maxChar
                                cache[pos]->lineNumber = lineNumber;
                                cache[pos]->inCache = true;
                                ret = cache[pos];
+                               useCount++;
                        }
                }
        }
@@ -284,7 +325,9 @@ void LineLayoutCache::Dispose(LineLayout *ll) {
        if (ll) {
                if (!ll->inCache) {
                        delete ll;
-               }
+               } else {
+                       useCount--;
+               }
        }
 }
 
@@ -344,6 +387,7 @@ Editor::Editor() {
        scrollWidth = 2000;
        verticalScrollBarVisible = true;
        endAtLastLine = true;
+       caretSticky = false;
 
        pixmapLine = Surface::Allocate();
        pixmapSelMargin = Surface::Allocate();
@@ -361,7 +405,7 @@ Editor::Editor() {
        topLine = 0;
        posTopLine = 0;
 
-       lengthForEncode = 0;
+       lengthForEncode = -1;
 
        needUpdateUI = true;
        braces[0] = invalidPosition;
@@ -392,6 +436,8 @@ Editor::Editor() {
        wrapVisualStartIndent = 0;
        actualWrapVisualStartIndent = 0;
 
+       convertPastes = true;
+
        hsStart = -1;
        hsEnd = -1;
 
@@ -420,6 +466,7 @@ void Editor::DropGraphics() {
        pixmapSelMargin->Release();
        pixmapSelPattern->Release();
        pixmapIndentGuide->Release();
+       pixmapIndentGuideHighlight->Release();
 }
 
 void Editor::InvalidateStyleData() {
@@ -842,13 +889,19 @@ void Editor::Redraw() {
        //wMain.InvalidateAll();
 }
 
-void Editor::RedrawSelMargin() {
+void Editor::RedrawSelMargin(int line) {
        if (!AbandonPaint()) {
                if (vs.maskInLine) {
                        Redraw();
                } else {
                        PRectangle rcSelMargin = GetClientRectangle();
                        rcSelMargin.right = vs.fixedColumnWidth;
+                       if (line != -1) {
+                               int position = pdoc->LineStart(line);
+                               PRectangle rcLine = RectangleFromRange(position, position);
+                               rcSelMargin.top = rcLine.top;
+                               rcSelMargin.bottom = rcLine.bottom;
+                       }
                        wMain.InvalidateRectangle(rcSelMargin);
                }
        }
@@ -899,6 +952,13 @@ int Editor::SelectionEnd() {
        return Platform::Maximum(currentPos, anchor);
 }
 
+void Editor::SetRectangularRange() {
+       if (selType == selRectangle) {
+               xStartSelect = XFromPosition(anchor);
+               xEndSelect = XFromPosition(currentPos);
+       }
+}
+
 void Editor::InvalidateSelection(int currentPos_, int anchor_) {
        int firstAffected = anchor;
        if (firstAffected > currentPos)
@@ -926,10 +986,7 @@ void Editor::SetSelection(int currentPos_, int anchor_) {
                currentPos = currentPos_;
                anchor = anchor_;
        }
-       if (selType == selRectangle) {
-               xStartSelect = XFromPosition(anchor);
-               xEndSelect = XFromPosition(currentPos);
-       }
+       SetRectangularRange();
        ClaimSelection();
 }
 
@@ -939,10 +996,7 @@ void Editor::SetSelection(int currentPos_) {
                InvalidateSelection(currentPos_, currentPos_);
                currentPos = currentPos_;
        }
-       if (selType == selRectangle) {
-               xStartSelect = XFromPosition(anchor);
-               xEndSelect = XFromPosition(currentPos);
-       }
+       SetRectangularRange();
        ClaimSelection();
 }
 
@@ -1065,11 +1119,15 @@ void Editor::ScrollTo(int line, bool moveThumb) {
                SetTopLine(topLineNew);
                ShowCaretAtCurrentPosition();
                // Perform redraw rather than scroll if many lines would be redrawn anyway.
+#ifndef UNDER_CE
                if (abs(linesToMove) <= 10) {
                        ScrollText(linesToMove);
                } else {
                        Redraw();
                }
+#else
+               Redraw();
+#endif
                if (moveThumb) {
                        SetVerticalScrollPos();
                }
@@ -1872,39 +1930,41 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
                posLineEnd = posLineStart + ll->maxLineLength;
        }
        if (ll->validity == LineLayout::llCheckTextAndStyle) {
-               int lineLength = 0;
-               for (int cid = posLineStart; cid < posLineEnd; cid++) {
-                       char chDoc = pdoc->CharAt(cid);
-                       if (vstyle.viewEOL || (!IsEOLChar(chDoc))) {
-                               lineLength++;
+               int lineLength = posLineEnd - posLineStart;
+               if (!vstyle.viewEOL) {
+                       int cid = posLineEnd - 1;
+                       while ((cid > posLineStart) && IsEOLChar(pdoc->CharAt(cid))) {
+                               cid--;
+                               lineLength--;
                        }
                }
                if (lineLength == ll->numCharsInLine) {
-                       int numCharsInLine = 0;
                        // See if chars, styles, indicators, are all the same
                        bool allSame = true;
                        const int styleMask = pdoc->stylingBitsMask;
                        // Check base line layout
-                       for (int charInDoc = posLineStart; allSame && (charInDoc < posLineEnd); charInDoc++) {
+                       char styleByte = 0;
+                       int numCharsInLine = 0;
+                       while (numCharsInLine < lineLength) {
+                               int charInDoc = numCharsInLine + posLineStart;
                                char chDoc = pdoc->CharAt(charInDoc);
-                               if (vstyle.viewEOL || (!IsEOLChar(chDoc))) {
-                                       char styleByte = pdoc->StyleAt(charInDoc);
+                               styleByte = pdoc->StyleAt(charInDoc);
+                               allSame = allSame &&
+                                               (ll->styles[numCharsInLine] == static_cast<unsigned char>(styleByte & styleMask));
+                               allSame = allSame &&
+                                               (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask));
+                               if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseMixed)
                                        allSame = allSame &&
-                                                 (ll->styles[numCharsInLine] == static_cast<char>(styleByte & styleMask));
+                                                       (ll->chars[numCharsInLine] == chDoc);
+                               else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
                                        allSame = allSame &&
-                                                 (ll->indicators[numCharsInLine] == static_cast<char>(styleByte & ~styleMask));
-                                       if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseUpper)
-                                               allSame = allSame &&
-                                                         (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
-                                       else if (vstyle.styles[ll->styles[numCharsInLine]].caseForce == Style::caseLower)
-                                               allSame = allSame &&
-                                                         (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
-                                       else
-                                               allSame = allSame &&
-                                                         (ll->chars[numCharsInLine] == chDoc);
-                                       numCharsInLine++;
-                               }
+                                                       (ll->chars[numCharsInLine] == static_cast<char>(tolower(chDoc)));
+                               else    // Style::caseUpper
+                                       allSame = allSame &&
+                                                       (ll->chars[numCharsInLine] == static_cast<char>(toupper(chDoc)));
+                               numCharsInLine++;
                        }
+                       allSame = allSame && (ll->styles[numCharsInLine] == styleByte); // For eolFilled
                        if (allSame) {
                                ll->validity = LineLayout::llPositions;
                        } else {
@@ -1929,10 +1989,12 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
 
                char styleByte = 0;
                int styleMask = pdoc->stylingBitsMask;
+               ll->styleBitsSet = 0;
                // Fill base line layout
                for (int charInDoc = posLineStart; charInDoc < posLineEnd; charInDoc++) {
                        char chDoc = pdoc->CharAt(charInDoc);
                        styleByte = pdoc->StyleAt(charInDoc);
+                       ll->styleBitsSet |= styleByte;
                        if (vstyle.viewEOL || (!IsEOLChar(chDoc))) {
                                ll->chars[numCharsInLine] = chDoc;
                                ll->styles[numCharsInLine] = static_cast<char>(styleByte & styleMask);
@@ -1959,6 +2021,7 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
                bool lastSegItalics = false;
                Font &ctrlCharsFont = vstyle.styles[STYLE_CONTROLCHAR].font;
 
+               int ctrlCharWidth[32] = {0};
                bool isControlNext = IsControlCharacter(ll->chars[0]);
                for (int charInLine = 0; charInLine < numCharsInLine; charInLine++) {
                        bool isControl = isControlNext;
@@ -1972,9 +2035,13 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
                                                        ll->positions[charInLine + 1] = ((((startsegx + 2) /
                                                                                           tabWidth) + 1) * tabWidth) - startsegx;
                                                } else if (controlCharSymbol < 32) {
-                                                       const char *ctrlChar = ControlCharacterString(ll->chars[charInLine]);
-                                                       // +3 For a blank on front and rounded edge each side:
-                                                       ll->positions[charInLine + 1] = surface->WidthText(ctrlCharsFont, ctrlChar, istrlen(ctrlChar)) + 3;
+                                                       if (ctrlCharWidth[ll->chars[charInLine]] == 0) {
+                                                               const char *ctrlChar = ControlCharacterString(ll->chars[charInLine]);
+                                                               // +3 For a blank on front and rounded edge each side:
+                                                               ctrlCharWidth[ll->chars[charInLine]] =
+                                                                       surface->WidthText(ctrlCharsFont, ctrlChar, istrlen(ctrlChar)) + 3;
+                                                       }
+                                                       ll->positions[charInLine + 1] = ctrlCharWidth[ll->chars[charInLine]];
                                                } else {
                                                        char cc[2] = { static_cast<char>(controlCharSymbol), '\0' };
                                                        surface->MeasureWidths(ctrlCharsFont, cc, 1,
@@ -2059,7 +2126,12 @@ void Editor::LayoutLine(int line, Surface *surface, ViewStyle &vstyle, LineLayou
                                        continue;
                                }
                                if (p > 0) {
-                                       if (ll->styles[p] != ll->styles[p - 1]) {
+                                       if (wrapState == eWrapChar){
+                                               lastGoodBreak = pdoc->MovePositionOutsideChar(p + posLineStart, -1)
+                                                                                               - posLineStart;
+                                               p = pdoc->MovePositionOutsideChar(p + 1 + posLineStart, 1) - posLineStart;
+                                               continue;
+                                       } else if (ll->styles[p] != ll->styles[p - 1]) {
                                                lastGoodBreak = p;
                                        } else if (IsSpaceOrTab(ll->chars[p - 1]) && !IsSpaceOrTab(ll->chars[p])) {
                                                lastGoodBreak = p;
@@ -2358,6 +2430,8 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
                                                }
                                        }
                                }
+                       } else if (rcSegment.left > rcLine.right) {
+                               break;
                        }
                        startseg = i + 1;
                }
@@ -2520,41 +2594,46 @@ void Editor::DrawLine(Surface *surface, ViewStyle &vsDraw, int line, int lineVis
                                        rcUL.bottom = rcUL.top + 1;
                                        surface->FillRectangle(rcUL, textFore);
                                }
+                       } else if (rcSegment.left > rcLine.right) {
+                               break;
                        }
                        startseg = i + 1;
                }
        }
 
        // Draw indicators
-       int indStart[INDIC_MAX + 1] = {0};
-       for (int indica = 0; indica <= INDIC_MAX; indica++)
-               indStart[indica] = 0;
-
-       for (int indicPos = lineStart; indicPos <= lineEnd; indicPos++) {
-               if ((indicPos == lineStart) || (indicPos == lineEnd) ||
-                       (ll->indicators[indicPos] != ll->indicators[indicPos + 1])) {
-                       int mask = 1 << pdoc->stylingBits;
-                       for (int indicnum = 0; mask < 0x100; indicnum++) {
-                               if ((indicPos == lineStart) || (indicPos == lineEnd)) {
-                                       indStart[indicnum] = ll->positions[indicPos];
-                               } else if ((ll->indicators[indicPos + 1] & mask) && !(ll->indicators[indicPos] & mask)) {
-                                       indStart[indicnum] = ll->positions[indicPos + 1];
-                               }
-                               if ((ll->indicators[indicPos] & mask) &&
-                                       ((indicPos == lineEnd) || !(ll->indicators[indicPos + 1] & mask))) {
-                                       int endIndicator = indicPos;
-                                       if (endIndicator >= lineEnd)
-                                               endIndicator = lineEnd-1;
+       // foreach indicator...
+       for (int indicnum = 0, mask = 1 << pdoc->stylingBits; mask < 0x100; indicnum++) {
+               if (!(mask & ll->styleBitsSet)) {
+                       mask <<= 1;
+                       continue;
+               }
+               int startPos = -1;
+               // foreach style pos in line...
+               for (int indicPos = lineStart; indicPos <= lineEnd; indicPos++) {
+                       // look for starts...
+                       if (startPos < 0) {
+                               // NOT in indicator run, looking for START
+                               if (indicPos < lineEnd && (ll->indicators[indicPos] & mask))
+                                       startPos = indicPos;
+                       }
+                       // ... or ends
+                       if (startPos >= 0) {
+                               // IN indicator run, looking for END
+                               if (indicPos >= lineEnd || !(ll->indicators[indicPos] & mask)) {
+                                       // AT end of indicator run, DRAW it!
                                        PRectangle rcIndic(
-                                               indStart[indicnum] + xStart - subLineStart,
+                                               ll->positions[startPos] + xStart - subLineStart,
                                                rcLine.top + vsDraw.maxAscent,
-                                               ll->positions[endIndicator + 1] + xStart - subLineStart,
+                                               ll->positions[indicPos] + xStart - subLineStart,
                                                rcLine.top + vsDraw.maxAscent + 3);
                                        vsDraw.indicators[indicnum].Draw(surface, rcIndic, rcLine);
+                                       // RESET control var
+                                       startPos = -1;
                                }
-                               mask = mask << 1;
                        }
                }
+               mask <<= 1;
        }
        // End of the drawing of the current line
        if (!twoPhaseDraw) {
@@ -2629,7 +2708,7 @@ void Editor::RefreshPixMaps(Surface *surfaceWindow) {
        if (bufferedDraw) {
                if (!pixmapLine->Initialised()) {
                        PRectangle rcClient = GetClientRectangle();
-                       pixmapLine->InitPixMap(rcClient.Width(), rcClient.Height(),
+                       pixmapLine->InitPixMap(rcClient.Width(), vs.lineHeight,
                                               surfaceWindow, wMain.GetID());
                        pixmapSelMargin->InitPixMap(vs.fixedColumnWidth,
                                                    rcClient.Height(), surfaceWindow, wMain.GetID());
@@ -2760,6 +2839,8 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
                        //ElapsedTime et;
                        if (lineDoc != lineDocPrevious) {
                                ll.Set(0);
+                               // For rectangular selection this accesses the layout cache so should be after layout returned.
+                               lineIterator.SetAt(lineDoc);
                                ll.Set(RetrieveLineLayout(lineDoc));
                                LayoutLine(lineDoc, surface, vs, ll, wrapWidth);
                                lineDocPrevious = lineDoc;
@@ -2771,7 +2852,6 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
                                        ll->selStart = SelectionStart();
                                        ll->selEnd = SelectionEnd();
                                } else {
-                                       lineIterator.SetAt(lineDoc);
                                        ll->selStart = lineIterator.startPos;
                                        ll->selEnd = lineIterator.endPos;
                                }
@@ -2920,6 +3000,7 @@ void Editor::Paint(Surface *surfaceWindow, PRectangle rcArea) {
                        visibleLine++;
                        //gdk_flush();
                }
+               ll.Set(0);
                //if (durPaint < 0.00000001)
                //      durPaint = 0.00000001;
 
@@ -3160,6 +3241,9 @@ void Editor::SetScrollBars() {
        int nMax = MaxScrollPos();
        int nPage = LinesOnScreen();
        bool modified = ModifyScrollBars(nMax + nPage - 1, nPage);
+       if (modified) {
+               DwellEnd(true);
+       }
 
        // TODO: ensure always showing as many lines as possible
        // May not be, if, for example, window made larger
@@ -3199,9 +3283,12 @@ void Editor::AddChar(char ch) {
 void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
        bool wasSelection = currentPos != anchor;
        ClearSelection();
+       bool charReplaceAction = false;
        if (inOverstrike && !wasSelection && !RangeContainsProtected(currentPos, currentPos + 1)) {
                if (currentPos < (pdoc->Length())) {
                        if (!IsEOLChar(pdoc->CharAt(currentPos))) {
+                               charReplaceAction = true;
+                               pdoc->BeginUndoAction();
                                pdoc->DelChar(currentPos);
                        }
                }
@@ -3209,10 +3296,15 @@ void Editor::AddCharUTF(char *s, unsigned int len, bool treatAsDBCS) {
        if (pdoc->InsertString(currentPos, s, len)) {
                SetEmptySelection(currentPos + len);
        }
+       if (charReplaceAction) {
+               pdoc->EndUndoAction();
+       }
        EnsureCaretVisible();
        // Avoid blinking during rapid typing:
        ShowCaretAtCurrentPosition();
-       SetLastXChosen();
+       if (!caretSticky) {
+               SetLastXChosen();
+       }
 
        if (treatAsDBCS) {
                NotifyChar((static_cast<unsigned char>(s[0]) << 8) |
@@ -3292,7 +3384,7 @@ void Editor::ClearAll() {
        currentPos = 0;
        SetTopLine(0);
        SetVerticalScrollPos();
-        InvalidateStyleRedraw();        // RPD: patch #1106564
+       InvalidateStyleRedraw();
 }
 
 void Editor::ClearDocumentStyle() {
@@ -3371,7 +3463,8 @@ void Editor::Undo() {
        if (pdoc->CanUndo()) {
                InvalidateCaret();
                int newPos = pdoc->Undo();
-               SetEmptySelection(newPos);
+               if (newPos >= 0)
+                       SetEmptySelection(newPos);
                EnsureCaretVisible();
        }
 }
@@ -3379,7 +3472,8 @@ void Editor::Undo() {
 void Editor::Redo() {
        if (pdoc->CanRedo()) {
                int newPos = pdoc->Redo();
-               SetEmptySelection(newPos);
+               if (newPos >= 0)
+                       SetEmptySelection(newPos);
                EnsureCaretVisible();
        }
 }
@@ -3425,7 +3519,7 @@ void Editor::DelCharBack(bool allowLineStartDeletion) {
 void Editor::NotifyFocus(bool) {}
 
 void Editor::NotifyStyleToNeeded(int endStyleNeeded) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_STYLENEEDED;
        scn.position = endStyleNeeded;
        NotifyParent(scn);
@@ -3436,7 +3530,7 @@ void Editor::NotifyStyleNeeded(Document*, void *, int endStyleNeeded) {
 }
 
 void Editor::NotifyChar(int ch) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_CHARADDED;
        scn.ch = ch;
        NotifyParent(scn);
@@ -3449,7 +3543,7 @@ void Editor::NotifyChar(int ch) {
 }
 
 void Editor::NotifySavePoint(bool isSavePoint) {
-       SCNotification scn;
+       SCNotification scn = {0};
        if (isSavePoint) {
                scn.nmhdr.code = SCN_SAVEPOINTREACHED;
        } else {
@@ -3459,19 +3553,19 @@ void Editor::NotifySavePoint(bool isSavePoint) {
 }
 
 void Editor::NotifyModifyAttempt() {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_MODIFYATTEMPTRO;
        NotifyParent(scn);
 }
 
 void Editor::NotifyDoubleClick(Point, bool) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_DOUBLECLICK;
        NotifyParent(scn);
 }
 
 void Editor::NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, bool alt) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_HOTSPOTDOUBLECLICK;
        scn.position = position;
        scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
@@ -3480,7 +3574,7 @@ void Editor::NotifyHotSpotDoubleClicked(int position, bool shift, bool ctrl, boo
 }
 
 void Editor::NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_HOTSPOTCLICK;
        scn.position = position;
        scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
@@ -3489,13 +3583,13 @@ void Editor::NotifyHotSpotClicked(int position, bool shift, bool ctrl, bool alt)
 }
 
 void Editor::NotifyUpdateUI() {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_UPDATEUI;
        NotifyParent(scn);
 }
 
 void Editor::NotifyPainted() {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_PAINTED;
        NotifyParent(scn);
 }
@@ -3509,7 +3603,7 @@ bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
                x += vs.ms[margin].width;
        }
        if ((marginClicked >= 0) && vs.ms[marginClicked].sensitive) {
-               SCNotification scn;
+               SCNotification scn = {0};
                scn.nmhdr.code = SCN_MARGINCLICK;
                scn.modifiers = (shift ? SCI_SHIFT : 0) | (ctrl ? SCI_CTRL : 0) |
                                (alt ? SCI_ALT : 0);
@@ -3523,7 +3617,7 @@ bool Editor::NotifyMarginClick(Point pt, bool shift, bool ctrl, bool alt) {
 }
 
 void Editor::NotifyNeedShown(int pos, int len) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_NEEDSHOWN;
        scn.position = pos;
        scn.length = len;
@@ -3531,7 +3625,7 @@ void Editor::NotifyNeedShown(int pos, int len) {
 }
 
 void Editor::NotifyDwelling(Point pt, bool state) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = state ? SCN_DWELLSTART : SCN_DWELLEND;
        scn.position = PositionFromLocationClose(pt);
        scn.x = pt.x;
@@ -3540,7 +3634,7 @@ void Editor::NotifyDwelling(Point pt, bool state) {
 }
 
 void Editor::NotifyZoom() {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_ZOOM;
        NotifyParent(scn);
 }
@@ -3552,7 +3646,7 @@ void Editor::NotifyModifyAttempt(Document*, void *) {
 }
 
 void Editor::NotifyMove(int position) {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_POSCHANGED;
        scn.position = position;
        NotifyParent(scn);
@@ -3564,8 +3658,7 @@ void Editor::NotifySavePoint(Document*, void *, bool atSavePoint) {
 }
 
 void Editor::CheckModificationForWrap(DocModification mh) {
-       if ((mh.modificationType & SC_MOD_INSERTTEXT) ||
-               (mh.modificationType & SC_MOD_DELETETEXT)) {
+       if (mh.modificationType & (SC_MOD_INSERTTEXT|SC_MOD_DELETETEXT)) {
                llc.Invalidate(LineLayout::llCheckTextAndStyle);
                if (wrapState != eWrapNone) {
                        int lineDoc = pdoc->LineFromPosition(mh.position);
@@ -3641,7 +3734,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
                        // Some lines are hidden so may need shown.
                        // TODO: check if the modified area is hidden.
                        if (mh.modificationType & SC_MOD_BEFOREINSERT) {
-                               NotifyNeedShown(mh.position, mh.length);
+                               NotifyNeedShown(mh.position, 0);
                        } else if (mh.modificationType & SC_MOD_BEFOREDELETE) {
                                NotifyNeedShown(mh.position, mh.length);
                        }
@@ -3659,7 +3752,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
                CheckModificationForWrap(mh);
                if (mh.linesAdded != 0) {
                        // Avoid scrolling of display if change before current display
-                       if (mh.position < posTopLine) {
+                       if (mh.position < posTopLine && !CanDeferToLastStep(mh)) {
                                int newTop = Platform::Clamp(topLine + mh.linesAdded, 0, MaxScrollPos());
                                if (newTop != topLine) {
                                        SetTopLine(newTop);
@@ -3670,28 +3763,39 @@ 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) {
+                       if (paintState == notPainting && !CanDeferToLastStep(mh)) {
                                Redraw();
                        }
                } else {
                        //Platform::DebugPrintf("** %x Line Changed %d .. %d\n", this,
                        //      mh.position, mh.position + mh.length);
-                       if (paintState == notPainting) {
+                       if (paintState == notPainting && mh.length && !CanEliminate(mh)) {
                                InvalidateRange(mh.position, mh.position + mh.length);
                        }
                }
        }
 
-       if (mh.linesAdded != 0) {
+       if (mh.linesAdded != 0 && !CanDeferToLastStep(mh)) {
                SetScrollBars();
        }
 
        if (mh.modificationType & SC_MOD_CHANGEMARKER) {
-               if (paintState == notPainting) {
-                       RedrawSelMargin();
+               if ((paintState == notPainting) || !PaintContainsMargin()) {
+                       if (mh.modificationType & SC_MOD_CHANGEFOLD) {
+                               // Fold changes can affect the drawing of following lines so redraw whole margin
+                               RedrawSelMargin();
+                       } else {
+                               RedrawSelMargin(mh.line);
+                       }
                }
        }
 
+       // NOW pay the piper WRT "deferred" visual updates
+       if (IsLastStep(mh)) {
+               SetScrollBars();
+               Redraw();
+       }
+
        // If client wants to see this modification
        if (mh.modificationType & modEventMask) {
                if ((mh.modificationType & SC_MOD_CHANGESTYLE) == 0) {
@@ -3699,7 +3803,7 @@ void Editor::NotifyModified(Document*, DocModification mh, void *) {
                        NotifyChange(); // Send EN_CHANGE
                }
 
-               SCNotification scn;
+               SCNotification scn = {0};
                scn.nmhdr.code = SCN_MODIFIED;
                scn.position = mh.position;
                scn.modificationType = mh.modificationType;
@@ -3717,7 +3821,7 @@ void Editor::NotifyDeleted(Document *, void *) {
        /* Do nothing */
 }
 
-void Editor::NotifyMacroRecord(unsigned int iMessage, unsigned long wParam, long lParam) {
+void Editor::NotifyMacroRecord(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
 
        // Enumerates all macroable messages
        switch (iMessage) {
@@ -3818,6 +3922,7 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, unsigned long wParam, long
        case SCI_LINEENDRECTEXTEND:
        case SCI_PAGEUPRECTEXTEND:
        case SCI_PAGEDOWNRECTEXTEND:
+       case SCI_SELECTIONDUPLICATE:
                break;
 
        // Filter out all others like display changes. Also, newlines are redundant
@@ -3829,7 +3934,7 @@ void Editor::NotifyMacroRecord(unsigned int iMessage, unsigned long wParam, long
        }
 
        // Send notification
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_MACRORECORD;
        scn.message = iMessage;
        scn.wParam = wParam;
@@ -3931,15 +4036,26 @@ void Editor::LineTranspose() {
        }
 }
 
-void Editor::LineDuplicate() {
-       int line = pdoc->LineFromPosition(currentPos);
-       int start = pdoc->LineStart(line);
-       int end = pdoc->LineEnd(line);
-       char *thisLine = CopyRange(start, end);
-       const char *eol = StringFromEOLMode(pdoc->eolMode);
-       pdoc->InsertString(end, eol);
-       pdoc->InsertString(end + istrlen(eol), thisLine, end - start);
-       delete []thisLine;
+void Editor::Duplicate(bool forLine) {
+       int start = SelectionStart();
+       int end = SelectionEnd();
+       if (start == end) {
+               forLine = true;
+       }
+       if (forLine) {
+               int line = pdoc->LineFromPosition(currentPos);
+               start = pdoc->LineStart(line);
+               end = pdoc->LineEnd(line);
+       }
+       char *text = CopyRange(start, end);
+       if (forLine) {
+               const char *eol = StringFromEOLMode(pdoc->eolMode);
+               pdoc->InsertString(end, eol);
+               pdoc->InsertString(end + istrlen(eol), text, end - start);
+       } else {
+               pdoc->InsertString(end, text, end - start);
+       }
+       delete []text;
 }
 
 void Editor::CancelModes() {
@@ -3963,6 +4079,8 @@ void Editor::NewLine() {
        }
        SetLastXChosen();
        EnsureCaretVisible();
+       // Avoid blinking during rapid typing:
+       ShowCaretAtCurrentPosition();
 }
 
 void Editor::CursorUpOrDown(int direction, selTypes sel) {
@@ -3983,6 +4101,22 @@ void Editor::CursorUpOrDown(int direction, selTypes sel) {
        MovePositionTo(posNew, sel);
 }
 
+void Editor::ParaUpOrDown(int direction, selTypes sel) {
+       int lineDoc, savedPos = currentPos;
+       do {
+               MovePositionTo(direction > 0 ? pdoc->ParaDown(currentPos) : pdoc->ParaUp(currentPos), sel);
+               lineDoc = pdoc->LineFromPosition(currentPos);
+               if (direction > 0) {
+                       if (currentPos >= pdoc->Length() && !cs.GetVisible(lineDoc)) {
+                               if (sel == noSel) {
+                                       MovePositionTo(pdoc->LineEndPosition(savedPos));
+                               }
+                               break;
+                       }
+               }
+       } while (!cs.GetVisible(lineDoc));
+}
+
 int Editor::StartEndDisplayLine(int pos, bool start) {
        RefreshStyleData();
        int line = pdoc->LineFromPosition(pos);
@@ -4027,10 +4161,10 @@ int Editor::KeyCommand(unsigned int iMessage) {
                CursorUpOrDown(1, selRectangle);
                break;
        case SCI_PARADOWN:
-               MovePositionTo(pdoc->ParaDown(currentPos));
+               ParaUpOrDown(1);
                break;
        case SCI_PARADOWNEXTEND:
-               MovePositionTo(pdoc->ParaDown(currentPos), selStream);
+               ParaUpOrDown(1, selStream);
                break;
        case SCI_LINESCROLLDOWN:
                ScrollTo(topLine + 1);
@@ -4046,10 +4180,10 @@ int Editor::KeyCommand(unsigned int iMessage) {
                CursorUpOrDown(-1, selRectangle);
                break;
        case SCI_PARAUP:
-               MovePositionTo(pdoc->ParaUp(currentPos));
+               ParaUpOrDown(-1);
                break;
        case SCI_PARAUPEXTEND:
-               MovePositionTo(pdoc->ParaUp(currentPos), selStream);
+               ParaUpOrDown(-1, selStream);
                break;
        case SCI_LINESCROLLUP:
                ScrollTo(topLine - 1);
@@ -4239,22 +4373,30 @@ int Editor::KeyCommand(unsigned int iMessage) {
                break;
        case SCI_DELETEBACK:
                DelCharBack(true);
-               SetLastXChosen();
+               if (!caretSticky) {
+                       SetLastXChosen();
+               }
                EnsureCaretVisible();
                break;
        case SCI_DELETEBACKNOTLINE:
                DelCharBack(false);
-               SetLastXChosen();
+               if (!caretSticky) {
+                       SetLastXChosen();
+               }
                EnsureCaretVisible();
                break;
        case SCI_TAB:
                Indent(true);
-               SetLastXChosen();
+               if (!caretSticky) {
+                       SetLastXChosen();
+               }
                EnsureCaretVisible();
                break;
        case SCI_BACKTAB:
                Indent(false);
-               SetLastXChosen();
+               if (!caretSticky) {
+                       SetLastXChosen();
+               }
                EnsureCaretVisible();
                break;
        case SCI_NEWLINE:
@@ -4361,7 +4503,10 @@ int Editor::KeyCommand(unsigned int iMessage) {
                LineTranspose();
                break;
        case SCI_LINEDUPLICATE:
-               LineDuplicate();
+               Duplicate(true);
+               break;
+       case SCI_SELECTIONDUPLICATE:
+               Duplicate(false);
                break;
        case SCI_LOWERCASE:
                ChangeCaseOfSelection(false);
@@ -4978,7 +5123,7 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b
                                NotifyHotSpotClicked(newPos, shift, ctrl, alt);
                        }
                        if (!shift) {
-                               inDragDrop = PointInSelection(pt);
+                               inDragDrop = PointInSelection(pt) && !SelectionEmpty();
                        }
                        if (inDragDrop) {
                                SetMouseCapture(false);
@@ -4992,9 +5137,9 @@ void Editor::ButtonDown(Point pt, unsigned int curTime, bool shift, bool ctrl, b
                                        SetEmptySelection(newPos);
                                }
                                selType = alt ? selRectangle : selStream;
-                               xStartSelect = xEndSelect = pt.x - vs.fixedColumnWidth + xOffset;
                                selectionType = selChar;
                                originalAnchorPos = currentPos;
+                               SetRectangularRange();
                        }
                }
        }
@@ -5131,7 +5276,7 @@ void Editor::ButtonMove(Point pt) {
                        }
                }
                // Display regular (drag) cursor over selection
-               if (PointInSelection(pt)) {
+               if (PointInSelection(pt) && !SelectionEmpty()) {
                        DisplayCursor(Window::cursorArrow);
                } else if (PointIsHotspot(pt)) {
                        DisplayCursor(Window::cursorHand);
@@ -5144,7 +5289,7 @@ void Editor::ButtonMove(Point pt) {
 }
 
 void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
-       //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture());
+        //Platform::DebugPrintf("ButtonUp %d\n", HaveMouseCapture());
        if (HaveMouseCapture()) {
                if (PointInSelMargin(pt)) {
                        DisplayCursor(Window::cursorReverseArrow);
@@ -5188,9 +5333,7 @@ void Editor::ButtonUp(Point pt, unsigned int curTime, bool ctrl) {
                                SetSelection(newPos);
                        }
                }
-               // Now we rely on the current pos to compute rectangular selection
-               xStartSelect = XFromPosition(anchor);
-               xEndSelect = XFromPosition(currentPos);
+               SetRectangularRange();
                lastClickTime = curTime;
                lastClick = pt;
                lastXChosen = pt.x;
@@ -5214,7 +5357,9 @@ void Editor::Tick() {
                if (timer.ticksToWait <= 0) {
                        caret.on = !caret.on;
                        timer.ticksToWait = caret.period;
-                       InvalidateCaret();
+                       if (caret.active) {
+                               InvalidateCaret();
+                       }
                }
        }
        if ((dwellDelay < SC_TIME_FOREVER) &&
@@ -5263,16 +5408,14 @@ void Editor::SetFocusState(bool focusState) {
        }
 }
 
-static bool IsIn(int a, int minimum, int maximum) {
-       return (a >= minimum) && (a <= maximum);
+bool Editor::PaintContains(PRectangle rc) {
+       return rcPaint.Contains(rc);
 }
 
-static bool IsOverlap(int mina, int maxa, int minb, int maxb) {
-       return
-           IsIn(mina, minb, maxb) ||
-           IsIn(maxa, minb, maxb) ||
-           IsIn(minb, mina, maxa) ||
-           IsIn(maxb, mina, maxa);
+bool Editor::PaintContainsMargin() {
+       PRectangle rcSelMargin = GetClientRectangle();
+       rcSelMargin.right = vs.fixedColumnWidth;
+       return PaintContains(rcSelMargin);
 }
 
 void Editor::CheckForChangeOutsidePaint(Range r) {
@@ -5281,99 +5424,21 @@ void Editor::CheckForChangeOutsidePaint(Range r) {
                if (!r.Valid())
                        return;
 
+               PRectangle rcRange = RectangleFromRange(r.start, r.end);
                PRectangle rcText = GetTextRectangle();
-               // Determine number of lines displayed including a possible partially displayed last line
-               int linesDisplayed = (rcText.bottom - rcText.top - 1) / vs.lineHeight + 1;
-               int bottomLine = topLine + linesDisplayed - 1;
-
-               int lineRangeStart = cs.DisplayFromDoc(pdoc->LineFromPosition(r.start));
-               int lineRangeEnd = cs.DisplayFromDoc(pdoc->LineFromPosition(r.end));
-               if (!IsOverlap(topLine, bottomLine, lineRangeStart, lineRangeEnd)) {
-                       //Platform::DebugPrintf("No overlap (%d-%d) with window(%d-%d)\n",
-                       //              lineRangeStart, lineRangeEnd, topLine, bottomLine);
-                       return;
+               if (rcRange.top < rcText.top) {
+                       rcRange.top = rcText.top;
                }
-
-               // Assert rcPaint contained within or equal to rcText
-               if (rcPaint.top > rcText.top) {
-                       // does range intersect rcText.top .. rcPaint.top
-                       int paintTopLine = ((rcPaint.top - rcText.top - 1) / vs.lineHeight) + topLine;
-                       // paintTopLine is the top line of the paint rectangle or the line just above if that line is completely inside the paint rectangle
-                       if (IsOverlap(topLine, paintTopLine, lineRangeStart, lineRangeEnd)) {
-                               //Platform::DebugPrintf("Change (%d-%d) in top npv(%d-%d)\n",
-                               //      lineRangeStart, lineRangeEnd, topLine, paintTopLine);
-                               AbandonPaint();
-                               return;
-                       }
+               if (rcRange.bottom > rcText.bottom) {
+                       rcRange.bottom = rcText.bottom;
                }
-               if (rcPaint.bottom < rcText.bottom) {
-                       // does range intersect rcPaint.bottom .. rcText.bottom
-                       int paintBottomLine = ((rcPaint.bottom - rcText.top - 1) / vs.lineHeight + 1) + topLine;
-                       // paintTopLine is the bottom line of the paint rectangle or the line just below if that line is completely inside the paint rectangle
-                       if (IsOverlap(paintBottomLine, bottomLine, lineRangeStart, lineRangeEnd)) {
-                               //Platform::DebugPrintf("Change (%d-%d) in bottom npv(%d-%d)\n",
-                               //      lineRangeStart, lineRangeEnd, paintBottomLine, bottomLine);
-                               AbandonPaint();
-                               return;
-                       }
+
+               if (!PaintContains(rcRange)) {
+                       AbandonPaint();
                }
        }
 }
 
-char BraceOpposite(char ch) {
-       switch (ch) {
-       case '(':
-               return ')';
-       case ')':
-               return '(';
-       case '[':
-               return ']';
-       case ']':
-               return '[';
-       case '{':
-               return '}';
-       case '}':
-               return '{';
-       case '<':
-               return '>';
-       case '>':
-               return '<';
-       default:
-               return '\0';
-       }
-}
-
-// TODO: should be able to extend styled region to find matching brace
-// TODO: may need to make DBCS safe
-// so should be moved into Document
-int Editor::BraceMatch(int position, int /*maxReStyle*/) {
-       char chBrace = pdoc->CharAt(position);
-       char chSeek = BraceOpposite(chBrace);
-       if (chSeek == '\0')
-               return - 1;
-       char styBrace = static_cast<char>(
-                           pdoc->StyleAt(position) & pdoc->stylingBitsMask);
-       int direction = -1;
-       if (chBrace == '(' || chBrace == '[' || chBrace == '{' || chBrace == '<')
-               direction = 1;
-       int depth = 1;
-       position = position + direction;
-       while ((position >= 0) && (position < pdoc->Length())) {
-               char chAtPos = pdoc->CharAt(position);
-               char styAtPos = static_cast<char>(pdoc->StyleAt(position) & pdoc->stylingBitsMask);
-               if ((position > pdoc->GetEndStyled()) || (styAtPos == styBrace)) {
-                       if (chAtPos == chBrace)
-                               depth++;
-                       if (chAtPos == chSeek)
-                               depth--;
-                       if (depth == 0)
-                               return position;
-               }
-               position = position + direction;
-       }
-       return - 1;
-}
-
 void Editor::SetBraceHighlight(Position pos0, Position pos1, int matchStyle) {
        if ((pos0 != braces[0]) || (pos1 != braces[1]) || (matchStyle != bracesMatchStyle)) {
                if ((braces[0] != pos0) || (matchStyle != bracesMatchStyle)) {
@@ -5421,8 +5486,8 @@ void Editor::SetDocPointer(Document *document) {
        NeedWrapping();
 
        pdoc->AddWatcher(this, 0);
-       Redraw();
        SetScrollBars();
+       Redraw();
 }
 
 /**
@@ -5558,6 +5623,18 @@ int Editor::CodePage() const {
                return 0;
 }
 
+int Editor::WrapCount(int line) {
+       AutoSurface surface(this);
+       AutoLineLayout ll(llc, RetrieveLineLayout(line));
+
+       if (surface && ll) {
+               LayoutLine(line, surface, vs, ll, wrapWidth);
+               return ll->lines;
+       } else {
+               return 1;
+       }
+}
+
 static bool ValidMargin(unsigned long wParam) {
        return wParam < ViewStyle::margins;
 }
@@ -5621,7 +5698,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
 
        case SCI_PASTE:
                Paste();
-               SetLastXChosen();
+               if (!caretSticky) {
+                       SetLastXChosen();
+               }
                EnsureCaretVisible();
                break;
 
@@ -5637,7 +5716,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                break;
 
        case SCI_CANUNDO:
-               return pdoc->CanUndo() ? 1 : 0;
+               return (pdoc->CanUndo() && !pdoc->IsReadOnly()) ? 1 : 0;
 
        case SCI_EMPTYUNDOBUFFER:
                pdoc->DeleteUndoHistory();
@@ -6066,7 +6145,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                }
 
        case SCI_CANREDO:
-               return pdoc->CanRedo() ? 1 : 0;
+               return (pdoc->CanRedo() && !pdoc->IsReadOnly()) ? 1 : 0;
 
        case SCI_MARKERLINEFROMHANDLE:
                return pdoc->LineFromHandle(wParam);
@@ -6106,6 +6185,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                        if (lParam == 0) {
                                return 1 + lineEnd - lineStart;
                        }
+                       PLATFORM_ASSERT(wParam > 0);
                        char *ptr = CharPtrFromSPtr(lParam);
                        unsigned int iPlace = 0;
                        for (unsigned int iChar = lineStart; iChar < lineEnd && iPlace < wParam - 1; iChar++) {
@@ -6225,7 +6305,17 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                return pdoc->ExtendWordSelect(wParam, 1, lParam != 0);
 
        case SCI_SETWRAPMODE:
-               wrapState = (wParam == SC_WRAP_WORD) ? eWrapWord : eWrapNone;
+               switch(wParam){
+                       case SC_WRAP_WORD:
+                               wrapState = eWrapWord;
+                               break;
+                       case SC_WRAP_CHAR:
+                               wrapState = eWrapChar;
+                               break;
+                       default:
+                               wrapState = eWrapNone;
+                               break;
+               }
                xOffset = 0;
                InvalidateStyleRedraw();
                ReconfigureScrollBars();
@@ -6311,6 +6401,20 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
        case SCI_GETENDATLASTLINE:
                return endAtLastLine;
 
+       case SCI_SETCARETSTICKY:
+               PLATFORM_ASSERT((wParam == 0) || (wParam == 1));
+               if (caretSticky != (wParam != 0)) {
+                       caretSticky = wParam != 0;
+               }
+               break;
+
+       case SCI_GETCARETSTICKY:
+               return caretSticky;
+
+       case SCI_TOGGLECARETSTICKY:
+               caretSticky = !caretSticky;
+               break;
+
        case SCI_GETCOLUMN:
                return pdoc->GetColumn(wParam);
 
@@ -6399,6 +6503,10 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                        int markerID = pdoc->AddMark(wParam, lParam);
                        return markerID;
                }
+       case SCI_MARKERADDSET:
+               if (lParam != 0)
+                       pdoc->AddMarkSet(wParam, lParam);
+               break;
 
        case SCI_MARKERDELETE:
                pdoc->DeleteMark(wParam, lParam);
@@ -6618,6 +6726,9 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
        case SCI_DOCLINEFROMVISIBLE:
                return cs.DocFromDisplay(wParam);
 
+       case SCI_WRAPCOUNT:
+               return WrapCount(wParam);
+
        case SCI_SETFOLDLEVEL: {
                        int prev = pdoc->SetLevel(wParam, lParam);
                        if (prev != lParam)
@@ -6873,6 +6984,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
        case SCI_LINEENDRECTEXTEND:
        case SCI_PAGEUPRECTEXTEND:
        case SCI_PAGEDOWNRECTEXTEND:
+       case SCI_SELECTIONDUPLICATE:
                return KeyCommand(iMessage);
 
        case SCI_BRACEHIGHLIGHT:
@@ -6886,7 +6998,7 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
        case SCI_BRACEMATCH:
                // wParam is position of char to find brace for,
                // lParam is maximum amount of text to restyle to find it
-               return BraceMatch(wParam, lParam);
+               return pdoc->BraceMatch(wParam, lParam);
 
        case SCI_GETVIEWEOL:
                return vs.viewEOL;
@@ -7103,6 +7215,13 @@ sptr_t Editor::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) {
                InvalidateStyleRedraw();
                break;
 
+       case SCI_SETPASTECONVERTENDINGS:
+               convertPastes = wParam != 0;
+               break;
+
+       case SCI_GETPASTECONVERTENDINGS:
+               return convertPastes ? 1 : 0;
+
        default:
                return DefWndProc(iMessage, wParam, lParam);
        }
index e14cb5ed95c125891c6a4f16cea35c3365ebaa47..9243d3a2f42cf433ade40a24c2b170208b0c975d 100644 (file)
@@ -64,6 +64,7 @@ public:
        int edgeColumn;
        char *chars;
        unsigned char *styles;
+       int styleBitsSet;
        char *indicators;
        int *positions;
        char bracePreviousStyles[2];
@@ -105,6 +106,7 @@ class LineLayoutCache {
        LineLayout **cache;
        bool allInvalidated;
        int styleClock;
+       int useCount;
        void Allocate(int length_);
        void AllocateForLevel(int linesOnScreen, int linesInDoc);
 public:
@@ -218,6 +220,7 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        int scrollWidth;
        bool verticalScrollBarVisible;
        bool endAtLastLine;
+       bool caretSticky;
 
        Surface *pixmapLine;
        Surface *pixmapSelMargin;
@@ -301,7 +304,7 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        int hsEnd;
 
        // Wrapping support
-       enum { eWrapNone, eWrapWord } wrapState;
+       enum { eWrapNone, eWrapWord, eWrapChar } wrapState;
        bool backgroundWrapEnabled;
        int wrapWidth;
        int docLineLastWrapped;
@@ -311,6 +314,8 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        int wrapVisualStartIndent;
        int actualWrapVisualStartIndent;
 
+       bool convertPastes;
+
        Document *pdoc;
 
        Editor();
@@ -341,7 +346,7 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        bool AbandonPaint();
        void RedrawRect(PRectangle rc);
        void Redraw();
-       void RedrawSelMargin();
+       void RedrawSelMargin(int line=-1);
        PRectangle RectangleFromRange(int start, int end);
        void InvalidateRange(int start, int end);
 
@@ -349,6 +354,7 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        bool SelectionEmpty();
        int SelectionStart();
        int SelectionEnd();
+       void SetRectangularRange();
        void InvalidateSelection(int currentPos_, int anchor_);
        void SetSelection(int currentPos_, int anchor_);
        void SetSelection(int currentPos_);
@@ -450,10 +456,11 @@ protected:        // ScintillaBase subclass needs access to much of Editor
        void PageMove(int direction, selTypes sel=noSel, bool stuttered = false);
        void ChangeCaseOfSelection(bool makeUpperCase);
        void LineTranspose();
-       void LineDuplicate();
+       void Duplicate(bool forLine);
        virtual void CancelModes();
        void NewLine();
        void CursorUpOrDown(int direction, selTypes sel=noSel);
+       void ParaUpOrDown(int direction, selTypes sel=noSel);
        int StartEndDisplayLine(int pos, bool start);
        virtual int KeyCommand(unsigned int iMessage);
        virtual int KeyDefault(int /* key */, int /*modifiers*/);
@@ -499,8 +506,9 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        virtual bool HaveMouseCapture() = 0;
        void SetFocusState(bool focusState);
 
+       virtual bool PaintContains(PRectangle rc);
+       bool PaintContainsMargin();
        void CheckForChangeOutsidePaint(Range r);
-       int BraceMatch(int position, int maxReStyle);
        void SetBraceHighlight(Position pos0, Position pos1, int matchStyle);
 
        void SetDocPointer(Document *document);
@@ -516,6 +524,7 @@ protected:  // ScintillaBase subclass needs access to much of Editor
        void GetHotSpotRange(int& hsStart, int& hsEnd);
 
        int CodePage() const;
+       int WrapCount(int line);
 
        virtual sptr_t DefWndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam) = 0;
 
index 950916bd08dc14764a96de579e8983bdfcd03939..bfa6e2d7899294cbec83e45ed1f8963bcd1427d5 100644 (file)
@@ -140,7 +140,7 @@ const KeyToCommand KeyMap::MapDefault[] = {
     {'L',                      SCI_CSHIFT,     SCI_LINEDELETE},
     {'T',                      SCI_CSHIFT,     SCI_LINECOPY},
     {'T',                      SCI_CTRL,       SCI_LINETRANSPOSE},
-    {'D',                      SCI_CTRL,       SCI_LINEDUPLICATE},
+    {'D',                      SCI_CTRL,       SCI_SELECTIONDUPLICATE},
     {'U',                      SCI_CTRL,       SCI_LOWERCASE},
     {'U',                      SCI_CSHIFT,     SCI_UPPERCASE},
     {0,0,0},
index 67e52ec11ad312874d7947bec42730176016b43d..1ffc4fb5f89e73cb59b1c917c840481d46f48b12 100644 (file)
 const LexerModule *LexerModule::base = 0;
 int LexerModule::nextLanguage = SCLEX_AUTOMATIC+1;
 
-LexerModule::LexerModule(int language_, LexerFunction fnLexer_,
-       const char *languageName_, LexerFunction fnFolder_,
-       const char * const wordListDescriptions_[]) :
+LexerModule::LexerModule(int language_,
+       LexerFunction fnLexer_,
+       const char *languageName_,
+       LexerFunction fnFolder_,
+       const char * const wordListDescriptions_[],
+       int styleBits_) :
        language(language_),
        fnLexer(fnLexer_),
        fnFolder(fnFolder_),
        wordListDescriptions(wordListDescriptions_),
+       styleBits(styleBits_),
        languageName(languageName_) {
        next = base;
        base = this;
@@ -52,7 +56,7 @@ int LexerModule::GetNumWordLists() const {
        }
 }
 
-const char * LexerModule::GetWordListDescription(int index) const {
+const char *LexerModule::GetWordListDescription(int index) const {
        static const char *emptyStr = "";
 
        PLATFORM_ASSERT(index < GetNumWordLists());
@@ -63,6 +67,10 @@ const char * LexerModule::GetWordListDescription(int index) const {
        }
 }
 
+int LexerModule::GetStyleBitsNeeded() const {
+       return styleBits;
+}
+
 const LexerModule *LexerModule::Find(int language) {
        const LexerModule *lm = base;
        while (lm) {
@@ -130,67 +138,78 @@ int Scintilla_LinkLexers() {
 //++Autogenerated -- run src/LexGen.py to regenerate
 //**\(\tLINK_LEXER(\*);\n\)
        LINK_LEXER(lmAda);
+       LINK_LEXER(lmAns1);
        LINK_LEXER(lmAPDL);
        LINK_LEXER(lmAsm);
-       LINK_LEXER(lmAsn1);
+       LINK_LEXER(lmASP);
        LINK_LEXER(lmAU3);
        LINK_LEXER(lmAVE);
        LINK_LEXER(lmBaan);
        LINK_LEXER(lmBash);
+       LINK_LEXER(lmBatch);
+       LINK_LEXER(lmBlitzBasic);
        LINK_LEXER(lmBullant);
+       LINK_LEXER(lmCaml);
        LINK_LEXER(lmClw);
        LINK_LEXER(lmClwNoCase);
        LINK_LEXER(lmConf);
        LINK_LEXER(lmCPP);
        LINK_LEXER(lmCPPNoCase);
-       LINK_LEXER(lmTCL);
-       LINK_LEXER(lmNncrontab);
+       LINK_LEXER(lmCsound);
        LINK_LEXER(lmCss);
+       LINK_LEXER(lmDiff);
        LINK_LEXER(lmEiffel);
        LINK_LEXER(lmEiffelkw);
        LINK_LEXER(lmErlang);
+       LINK_LEXER(lmErrorList);
        LINK_LEXER(lmESCRIPT);
+       LINK_LEXER(lmF77);
+       LINK_LEXER(lmFlagShip);
        LINK_LEXER(lmForth);
        LINK_LEXER(lmFortran);
-       LINK_LEXER(lmF77);
+       LINK_LEXER(lmFreeBasic);
        LINK_LEXER(lmGui4Cli);
+       LINK_LEXER(lmHaskell);
        LINK_LEXER(lmHTML);
-       LINK_LEXER(lmXML);
-       LINK_LEXER(lmASP);
-       LINK_LEXER(lmPHP);
        LINK_LEXER(lmKix);
+       LINK_LEXER(lmLatex);
        LINK_LEXER(lmLISP);
+       LINK_LEXER(lmLot);
        LINK_LEXER(lmLout);
        LINK_LEXER(lmLua);
+       LINK_LEXER(lmMake);
        LINK_LEXER(lmMatlab);
-       LINK_LEXER(lmOctave);
        LINK_LEXER(lmMETAPOST);
        LINK_LEXER(lmMMIXAL);
-       LINK_LEXER(lmLot);
        LINK_LEXER(lmMSSQL);
+       LINK_LEXER(lmNncrontab);
        LINK_LEXER(lmNsis);
-       LINK_LEXER(lmBatch);
-       LINK_LEXER(lmDiff);
-       LINK_LEXER(lmProps);
-       LINK_LEXER(lmMake);
-       LINK_LEXER(lmErrorList);
-       LINK_LEXER(lmLatex);
        LINK_LEXER(lmNull);
+       LINK_LEXER(lmOctave);
        LINK_LEXER(lmPascal);
        LINK_LEXER(lmPB);
        LINK_LEXER(lmPerl);
+       LINK_LEXER(lmPHP);
+       LINK_LEXER(lmPHPSCRIPT);
        LINK_LEXER(lmPOV);
+       LINK_LEXER(lmProps);
        LINK_LEXER(lmPS);
+       LINK_LEXER(lmPureBasic);
        LINK_LEXER(lmPython);
+       LINK_LEXER(lmREBOL);
        LINK_LEXER(lmRuby);
        LINK_LEXER(lmScriptol);
+       LINK_LEXER(lmSmalltalk);
        LINK_LEXER(lmSpecman);
        LINK_LEXER(lmSQL);
+       LINK_LEXER(lmTADS3);
+       LINK_LEXER(lmTCL);
        LINK_LEXER(lmTeX);
        LINK_LEXER(lmVB);
        LINK_LEXER(lmVBScript);
        LINK_LEXER(lmVerilog);
        LINK_LEXER(lmVHDL);
+       LINK_LEXER(lmXML);
        LINK_LEXER(lmYAML);
 
 //--Autogenerated -- end of automatically generated section
index 31e4ee52d2d78be5a5ce611d5e1cd1702eca52ed..ee547f497fb0665a0fa1bf1ce1b746356b8b0899 100644 (file)
 //                  Added fold.compact support set with fold.compact=1
 //                  Changed folding inside of #cs-#ce. Default is no keyword folding inside comment blocks when fold.comment=1
 //                        it will now only happen when fold.comment=2.
-// 
+// Sep 5, 2004    - Added logic to handle colourizing words on the last line. 
+//                        Typed Characters now show as "default" till they match any table.
+// Oct 10, 2004   - Added logic to show Comments in "Special" directives. 
+// Nov  1, 2004   - Added better testing for Numbers supporting x and e notation.
+// Nov 28, 2004   - Added logic to handle continuation lines for syntax highlighting.
+// Jan 10, 2005   - Added Abbreviations Keyword used for expansion
+// Mar 24, 2005   - Updated Abbreviations Keywords to fix when followed by Operator.
+// Apr 18, 2005   - Updated #CE/#Comment-End logic to take a linecomment ";" into account
+//                - Added folding support for With...EndWith
+//                - Added support for a DOT in variable names
+//                - Fixed Underscore in CommentBlock
+// May 23, 2005   - Fixed the SentKey lexing in case of a missing }
+// Aug 11, 2005   - Fixed possible bug with s_save length > 100.
+// Aug 23, 2005   - Added Switch/endswitch support to the folding logic.
+//
 // Copyright for Scintilla: 1998-2001 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 // Scintilla source code edit control
@@ -56,7 +70,7 @@ static inline bool IsAWordChar(const int ch)
 
 static inline bool IsAWordStart(const int ch)
 {
-    return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$');
+    return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '@' || ch == '#' || ch == '$' || ch == '.');
 }
 
 static inline bool IsAOperator(char ch) {
@@ -88,7 +102,11 @@ static int GetSendKey(const char *szLine, char *szKey)
        // split the portion of the sendkey in the part before and after the spaces
        while ( ( (cTemp = szLine[nPos]) != '\0'))
        {
-               if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space
+               // skip leading Ctrl/Shift/ALt state
+               if ((cTemp == '#' || cTemp == '!' || cTemp == '^') && (szLine[nPos+1] == '{') ) 
+               {
+               }       
+               else if ((cTemp == ' ') && (nFlag == 0) ) // get the stuff till first space
                {
                        nFlag = 1;
                        // Add } to the end of the first bit for table lookup later.
@@ -132,6 +150,34 @@ static int GetSendKey(const char *szLine, char *szKey)
 
 } // GetSendKey() 
 
+//
+// Routine to check the last "none comment" character on a line to see if its a continuation
+// 
+static bool IsContinuationLine(unsigned int szLine, Accessor &styler)
+{
+       int nsPos = styler.LineStart(szLine);
+       int nePos = styler.LineStart(szLine+1) - 2;
+       //int stylech = styler.StyleAt(nsPos);
+       while (nsPos < nePos)
+       {
+               //stylech = styler.StyleAt(nePos);
+               int stylech = styler.StyleAt(nsPos);
+               if (!(stylech == SCE_AU3_COMMENT)) {
+                       char ch = styler.SafeGetCharAt(nePos);
+                       if (!isspacechar(ch)) {
+                               if (ch == '_')
+                                       return true;
+                               else
+                                       return false;
+                       }
+               }
+               nePos--; // skip to next char
+       } // End While
+       return false;
+} // IsContinuationLine()
+
+//
+// syntax highlighting logic
 static void ColouriseAU3Doc(unsigned int startPos, 
                                                        int length, int initStyle,
                                                        WordList *keywordlists[],
@@ -143,25 +189,78 @@ static void ColouriseAU3Doc(unsigned int startPos,
     WordList &keywords4 = *keywordlists[3];
     WordList &keywords5 = *keywordlists[4];
     WordList &keywords6 = *keywordlists[5];
+    WordList &keywords7 = *keywordlists[6];
+       // find the first previous line without continuation character at the end
+       int lineCurrent = styler.GetLine(startPos);
+       int s_startPos = startPos;
+       // When not inside a Block comment: find First line without _
+       if (!(initStyle==SCE_AU3_COMMENTBLOCK)) {
+               while ((lineCurrent > 0 && IsContinuationLine(lineCurrent,styler)) ||
+                          (lineCurrent > 1 && IsContinuationLine(lineCurrent-1,styler))) {
+                       lineCurrent--;
+                       startPos = styler.LineStart(lineCurrent); // get start position
+                       initStyle =  0;                           // reset the start style to 0 
+               }
+       }
+       // Set the new length to include it from the start and set the start position
+       length = length + s_startPos - startPos;      // correct the total length to process
     styler.StartAt(startPos);
-
+       
     StyleContext sc(startPos, length, initStyle, styler);
        char si;     // string indicator "=1 '=2
-       si=0;
+       char ni;     // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 Enot=3
+       char ci;     // comment indicator 0=not linecomment(;) 
+       char s_save[100];
+       si=0;  
+       ni=0;
+       ci=0;
        //$$$
     for (; sc.More(); sc.Forward()) {
                char s[100];
                sc.GetCurrentLowered(s, sizeof(s));
+               // **********************************************
+               // save the total current word for eof processing 
+               if (IsAWordChar(sc.ch) || sc.ch == '}') 
+               {
+                       strcpy(s_save,s);
+                       int tp = strlen(s_save);
+                       if (tp < 99) {
+                               s_save[tp] = static_cast<char>(tolower(sc.ch));
+                               s_save[tp+1] = '\0';
+                       }
+               }
+               // **********************************************
+               //
                switch (sc.state)
         {
             case SCE_AU3_COMMENTBLOCK:
             {
-                               if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0)))
-                               {
+                               //Reset at line end
+                               if (sc.atLineEnd) {
+                                       ci=0;
+                                       sc.SetState(SCE_AU3_COMMENTBLOCK);
+                               }
+                               //skip rest of line when a ; is encountered
+                               if (sc.chPrev == ';') {
+                                       ci=2;
+                                       sc.SetState(SCE_AU3_COMMENTBLOCK);
+                               }
+                               // skip rest of the line
+                               if (ci==2) 
+                                       break;
+                               // check when first character is detected on the line 
+                               if (ci==0) {
+                                       if (IsAWordStart(static_cast<char>(sc.ch)) || IsAOperator(static_cast<char>(sc.ch))) {
+                                               ci=1;
+                                               sc.SetState(SCE_AU3_COMMENTBLOCK);
+                                       }
+                                       break;
+                               }
+                               if (!(IsAWordChar(sc.ch) || (sc.ch == '-' && strcmp(s, "#comments") == 0))) {
                                        if ((strcmp(s, "#ce")== 0 || strcmp(s, "#comments-end")== 0)) 
-                                       {sc.SetState(SCE_AU3_COMMENT);}  // set to comment line for the rest of the line
+                                               sc.SetState(SCE_AU3_COMMENT);  // set to comment line for the rest of the line
                                        else
-                                       {sc.SetState(SCE_AU3_COMMENTBLOCK);}
+                                               ci=2;  // line doesn't begin with #CE so skip the rest of the line
                                }
                 break;
                        }
@@ -172,12 +271,19 @@ static void ColouriseAU3Doc(unsigned int startPos,
             }
             case SCE_AU3_OPERATOR:
             {
-                sc.SetState(SCE_AU3_DEFAULT);
+                // check if its a COMobject 
+                               if (sc.chPrev == '.' && IsAWordChar(sc.ch)) {
+                                       sc.SetState(SCE_AU3_COMOBJ);
+                               }       
+                               else {
+                                       sc.SetState(SCE_AU3_DEFAULT);
+                               }
                 break;
             }
             case SCE_AU3_SPECIAL:
             {
-                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
+                if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
+                               if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
                 break;
             }
             case SCE_AU3_KEYWORD:
@@ -215,6 +321,10 @@ static void ColouriseAU3Doc(unsigned int startPos,
                                                        sc.ChangeState(SCE_AU3_SPECIAL);
                                                        sc.SetState(SCE_AU3_SPECIAL);
                                                }
+                                               else if ((keywords7.InList(s)) && (!IsAOperator(static_cast<char>(sc.ch)))) {
+                                                       sc.ChangeState(SCE_AU3_EXPAND);
+                                                       sc.SetState(SCE_AU3_DEFAULT);
+                                               }
                                                else if (strcmp(s, "_") == 0) {
                                                        sc.ChangeState(SCE_AU3_OPERATOR);
                                                        sc.SetState(SCE_AU3_DEFAULT);
@@ -225,18 +335,74 @@ static void ColouriseAU3Doc(unsigned int startPos,
                                                }
                                        }
                                }       
-                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
+                if (sc.atLineEnd) {
+                                       sc.SetState(SCE_AU3_DEFAULT);}
                 break;
             }
-            case SCE_AU3_NUMBER:
+                       case SCE_AU3_NUMBER:
             {
-                if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_AU3_DEFAULT);}
-                break;
+                               // Numeric indicator error=9 normal=0 normal+dec=1 hex=2 E-not=3
+                               //
+                               // test for Hex notation
+                               if (strcmp(s, "0") == 0 && (sc.ch == 'x' || sc.ch == 'X') && ni == 0)
+                               {
+                                       ni = 2;
+                                       break;
+                               }
+                               // test for E notation
+                               if (IsADigit(sc.chPrev) && (sc.ch == 'e' || sc.ch == 'E') && ni <= 1)
+                               {
+                                       ni = 3;
+                                       break;
+                               }
+                               //  Allow Hex characters inside hex numeric strings
+                               if ((ni == 2) &&
+                                       (sc.ch == 'a' || sc.ch == 'b' || sc.ch == 'c' || sc.ch == 'd' || sc.ch == 'e' || sc.ch == 'f' ||
+                                        sc.ch == 'A' || sc.ch == 'B' || sc.ch == 'C' || sc.ch == 'D' || sc.ch == 'E' || sc.ch == 'F' ))
+                               {
+                                       break;
+                               }
+                               // test for 1 dec point only
+                               if (sc.ch == '.')
+                               {
+                                       if (ni==0)
+                                       {
+                                               ni=1;
+                                       }
+                                       else
+                                       {
+                                               ni=9;
+                                       }
+                                       break;
+                               }
+                               // end of numeric string ?
+                               if (!(IsADigit(sc.ch)))
+                               {
+                                       if (ni==9)
+                                       {
+                                               sc.ChangeState(SCE_AU3_DEFAULT);
+                                       }
+                                       sc.SetState(SCE_AU3_DEFAULT);
+                               }
+                               break;
+                       }
+                       case SCE_AU3_VARIABLE:
+                       {
+                               // Check if its a COMObject
+                               if (sc.ch == '.' && !IsADigit(sc.chNext)) {
+                                       sc.SetState(SCE_AU3_OPERATOR);
+                               }
+                               else if (!IsAWordChar(sc.ch)) {
+                                       sc.SetState(SCE_AU3_DEFAULT);
+                               }
+                               break;
             }
-            case SCE_AU3_VARIABLE:
-            {
-                if (!IsAWordChar(sc.ch)) {sc.SetState(SCE_AU3_DEFAULT);}
-                break;
+                       case SCE_AU3_COMOBJ:
+                       {
+                               if (!(IsAWordChar(sc.ch))) {
+                                       sc.SetState(SCE_AU3_DEFAULT);
+                               }
+                               break;
             }
             case SCE_AU3_STRING:
             {
@@ -246,7 +412,15 @@ static void ColouriseAU3Doc(unsigned int startPos,
                                {
                                        sc.ForwardSetState(SCE_AU3_DEFAULT);
                                }
-                if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
+                if (sc.atLineEnd)
+                               {
+                                       // at line end and not found a continuation char then reset to default
+                                       int lineCurrent = styler.GetLine(sc.currentPos);
+                                       if (!IsContinuationLine(lineCurrent,styler)) 
+                                       {
+                                               sc.SetState(SCE_AU3_DEFAULT);
+                                       }
+                               }
                                // find Sendkeys in a STRING
                                if (sc.ch == '{') {sc.SetState(SCE_AU3_SENT);}
                                if (sc.ch == '+' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
@@ -288,10 +462,11 @@ static void ColouriseAU3Doc(unsigned int startPos,
                                // check if next portion is again a sendkey
                                if (sc.atLineEnd) 
                                {
+                                       sc.ChangeState(SCE_AU3_STRING);
                                        sc.SetState(SCE_AU3_DEFAULT);
                                        si = 0;  // reset string indicator
                                }
-                               if (sc.ch == '{' && sc.chPrev != '{') {sc.SetState(SCE_AU3_SENT);}
+                               //if (sc.ch == '{' && sc.chPrev != '{') {sc.SetState(SCE_AU3_SENT);}
                                if (sc.ch == '+' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
                                if (sc.ch == '!' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
                                if (sc.ch == '^' && sc.chNext == '{') {sc.SetState(SCE_AU3_SENT);}
@@ -314,6 +489,7 @@ static void ColouriseAU3Doc(unsigned int startPos,
             if (sc.ch == ';') {sc.SetState(SCE_AU3_COMMENT);}
             else if (sc.ch == '#') {sc.SetState(SCE_AU3_KEYWORD);}
             else if (sc.ch == '$') {sc.SetState(SCE_AU3_VARIABLE);}
+            else if (sc.ch == '.' && !IsADigit(sc.chNext)) {sc.SetState(SCE_AU3_OPERATOR);}
             else if (sc.ch == '@') {sc.SetState(SCE_AU3_KEYWORD);}
             else if (sc.ch == '<' && si==3) {sc.SetState(SCE_AU3_STRING);}  // string after #include 
             else if (sc.ch == '\"') {
@@ -322,13 +498,94 @@ static void ColouriseAU3Doc(unsigned int startPos,
             else if (sc.ch == '\'') {
                                sc.SetState(SCE_AU3_STRING);
                                si = 2; }
-            else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {sc.SetState(SCE_AU3_NUMBER);}
+            else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) 
+                       {
+                               sc.SetState(SCE_AU3_NUMBER);
+                               ni = 0;
+                       }
             else if (IsAWordStart(sc.ch)) {sc.SetState(SCE_AU3_KEYWORD);}
             else if (IsAOperator(static_cast<char>(sc.ch))) {sc.SetState(SCE_AU3_OPERATOR);}
                        else if (sc.atLineEnd) {sc.SetState(SCE_AU3_DEFAULT);}
         }
     }      //for (; sc.More(); sc.Forward())
-    sc.Complete();
+
+       //*************************************
+       // Colourize the last word correctly 
+       //*************************************
+       if (sc.state == SCE_AU3_KEYWORD)
+               {
+               if (strcmp(s_save, "#cs")== 0 || strcmp(s_save, "#comments-start")== 0 )
+               {
+                       sc.ChangeState(SCE_AU3_COMMENTBLOCK);
+                       sc.SetState(SCE_AU3_COMMENTBLOCK);
+               }
+               else if (keywords.InList(s_save)) {
+                       sc.ChangeState(SCE_AU3_KEYWORD);
+                       sc.SetState(SCE_AU3_KEYWORD);
+               }
+               else if (keywords2.InList(s_save)) {
+                       sc.ChangeState(SCE_AU3_FUNCTION);
+                       sc.SetState(SCE_AU3_FUNCTION);
+               }
+               else if (keywords3.InList(s_save)) {
+                       sc.ChangeState(SCE_AU3_MACRO);
+                       sc.SetState(SCE_AU3_MACRO);
+               }
+               else if (keywords5.InList(s_save)) {
+                       sc.ChangeState(SCE_AU3_PREPROCESSOR);
+                       sc.SetState(SCE_AU3_PREPROCESSOR);
+               }
+               else if (keywords6.InList(s_save)) {
+                       sc.ChangeState(SCE_AU3_SPECIAL);
+                       sc.SetState(SCE_AU3_SPECIAL);
+               }
+               else if (keywords7.InList(s_save) && sc.atLineEnd) {
+                       sc.ChangeState(SCE_AU3_EXPAND);
+                       sc.SetState(SCE_AU3_EXPAND);
+               }
+               else {
+                       sc.ChangeState(SCE_AU3_DEFAULT);
+                       sc.SetState(SCE_AU3_DEFAULT);
+               }
+       }
+       if (sc.state == SCE_AU3_SENT)
+    {
+               // Send key string ended 
+               if (sc.chPrev == '}' && sc.ch != '}') 
+               {
+                       // set color to SENDKEY when valid sendkey .. else set back to regular string
+                       char sk[100];
+                       // split {111 222} and return {111} and check if 222 is valid.
+                       // if return code = 1 then invalid 222 so must be string
+                       if (GetSendKey(s_save,sk))   
+                       {
+                               sc.ChangeState(SCE_AU3_STRING);
+                       }
+                       // if single char between {?} then its ok as sendkey for a single character
+                       else if (strlen(sk) == 3)  
+                       {
+                               sc.ChangeState(SCE_AU3_SENT);
+                       }
+                       // if sendkey {111} is in table then ok as sendkey
+                       else if (keywords4.InList(sk)) 
+                       {
+                               sc.ChangeState(SCE_AU3_SENT);
+                       }
+                       else
+                       {
+                               sc.ChangeState(SCE_AU3_STRING);
+                       }
+                       sc.SetState(SCE_AU3_STRING);
+               }
+               // check if next portion is again a sendkey
+               if (sc.atLineEnd) 
+               {
+                       sc.ChangeState(SCE_AU3_STRING);
+                       sc.SetState(SCE_AU3_DEFAULT);
+               }
+    }
+       //*************************************
+       sc.Complete();
 }
 
 //
@@ -352,32 +609,6 @@ static int GetStyleFirstWord(unsigned int szLine, Accessor &styler)
 
 } // GetStyleFirstWord()
 
-//
-// Routine to check the last "none comment" character on a line to see if its a continuation
-// 
-static bool IsContinuationLine(unsigned int szLine, Accessor &styler)
-{
-       int nsPos = styler.LineStart(szLine);
-       int nePos = styler.LineStart(szLine+1) - 2;
-       //int stylech = styler.StyleAt(nsPos);
-       while (nsPos < nePos)
-       {
-               //stylech = styler.StyleAt(nePos);
-               int stylech = styler.StyleAt(nsPos);
-               if (!(stylech == SCE_AU3_COMMENT)) {
-                       char ch = styler.SafeGetCharAt(nePos);
-                       if (!isspacechar(ch)) {
-                               if (ch == '_')
-                                       return true;
-                               else
-                                       return false;
-                       }
-               }
-               nePos--; // skip to next char
-       } // End While
-       return false;
-} // IsContinuationLine()
-
 
 //
 static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
@@ -496,18 +727,18 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc
                                // create new fold for these words 
                                if (strcmp(szKeyword,"do") == 0   || strcmp(szKeyword,"for") == 0 ||
                                        strcmp(szKeyword,"func") == 0 || strcmp(szKeyword,"while") == 0||
-                                       strcmp(szKeyword,"#region") == 0 ) {
+                                       strcmp(szKeyword,"with") == 0 || strcmp(szKeyword,"#region") == 0 ) {
                                                levelNext++;
                                }
-                               // create double Fold for select because Case will subtract one of the current level
-                               if (strcmp(szKeyword,"select") == 0) {
+                               // create double Fold for select&switch because Case will subtract one of the current level
+                               if (strcmp(szKeyword,"select") == 0 || strcmp(szKeyword,"switch") == 0) {
                                                levelNext++;
                                                levelNext++;
                                }
                                // end the fold for these words before the current line
                                if (strcmp(szKeyword,"endfunc") == 0 || strcmp(szKeyword,"endif") == 0 ||
                                        strcmp(szKeyword,"next") == 0    || strcmp(szKeyword,"until") == 0 || 
-                                       strcmp(szKeyword,"wend") == 0){
+                                       strcmp(szKeyword,"endwith") == 0 ||strcmp(szKeyword,"wend") == 0){
                                                levelNext--;
                                                levelCurrent--;
                                }
@@ -517,7 +748,7 @@ static void FoldAU3Doc(unsigned int startPos, int length, int, WordList *[], Acc
                                                levelCurrent--;
                                }
                                // end the double fold for this word before the current line
-                               if (strcmp(szKeyword,"endselect") == 0 ) {
+                               if (strcmp(szKeyword,"endselect") == 0 || strcmp(szKeyword,"endswitch") == 0 ) {
                                                levelNext--;
                                                levelNext--;
                                                levelCurrent--;
@@ -609,6 +840,7 @@ static const char * const AU3WordLists[] = {
     "#autoit Sent keys",
     "#autoit Pre-processors",
     "#autoit Special",
+    "#autoit Expand",
     0
 };
 LexerModule lmAU3(SCLEX_AU3, ColouriseAU3Doc, "au3", FoldAU3Doc , AU3WordLists);
index 900aea317cfedb83d63b87269714b81326185bd0..e30ee7dc9e9c05b8b8ba1b6116862179a6d4c27f 100644 (file)
@@ -12,7 +12,6 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <fcntl.h>
 
 #include "Platform.h"
 
@@ -183,7 +182,9 @@ static void FoldAveDoc(unsigned int startPos, int length, int /* initStyle */, W
                                if ((strcmp(s, "then") == 0) || (strcmp(s, "for") == 0) || (strcmp(s, "while") == 0)) {
                                        levelCurrent++;
                                }
-                               if ((strcmp(s, "end") == 0)) {
+                               if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) {
+                                       // Normally "elseif" and "then" will be on the same line and will cancel
+                                       // each other out.  // As implemented, this does not support fold.at.else.
                                        levelCurrent--;
                                }
                        }
index be6c3f2aeacc89b9c5a75c4e8b34bb775ae5a52f..1600e6329d461bf3cf8253fa329f2785332b5f56 100644 (file)
@@ -178,4 +178,4 @@ static const char * const asn1WordLists[] = {
        0, };
 
 
-LexerModule lmAsn1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists);
+LexerModule lmAns1(SCLEX_ASN1, ColouriseAsn1Doc, "asn1", FoldAsn1Doc, asn1WordLists);
index abd02c46b386e9510b16dc059403a6367e8c3858..903d793bb0b7b5551cbbcabe39eda665ffb083f1 100644 (file)
@@ -2,7 +2,7 @@
 /** @file LexBash.cxx
  ** Lexer for Bash.
  **/
-// Copyright 2004 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 2004-2005 by Neil Hodgson <neilh@scintilla.org>
 // Adapted from LexPerl by Kein-Hong Man <mkh@pl.jaring.my> 2004
 // The License.txt file describes the conditions under which this software may be distributed.
 
@@ -144,6 +144,9 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
                char *Delimiter;        // the Delimiter, 256: sizeof PL_tokenbuf
                HereDocCls() {
                        State = 0;
+            Quote = 0;
+            Quoted = false;
+            Indent = 0;
                        DelimiterLength = 0;
                        Delimiter = new char[HERE_DELIM_MAX];
                        Delimiter[0] = '\0';
@@ -442,7 +445,7 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
                                        HereDoc.Quoted = false;
                                        HereDoc.DelimiterLength = 0;
                                        HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
-                                       if (chNext == '\'') {   // a quoted here-doc delimiter (' only)
+                                       if (chNext == '\'' || chNext == '\"') { // a quoted here-doc delimiter (' or ")
                                                i++;
                                                ch = chNext;
                                                chNext = chNext2;
@@ -451,8 +454,9 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
                                                HereDoc.Indent = true;
                                                HereDoc.State = 0;
                                        } else if (isalpha(chNext) || chNext == '_' || chNext == '\\'
-                                               || chNext == '-' || chNext == '+') {
+                                               || chNext == '-' || chNext == '+' || chNext == '!') {
                                                // an unquoted here-doc delimiter, no special handling
+                        // TODO check what exactly bash considers part of the delim
                                        } else if (chNext == '<') {     // HERE string <<<
                                                i++;
                                                ch = chNext;
@@ -486,7 +490,7 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
                                                        HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
                                                }
                                        } else { // an unquoted here-doc delimiter
-                                               if (isalnum(ch) || ch == '_' || ch == '-' || ch == '+') {
+                                               if (isalnum(ch) || ch == '_' || ch == '-' || ch == '+' || ch == '!') {
                                                        HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
                                                        HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
                                                } else if (ch == '\\') {
@@ -582,6 +586,19 @@ static void ColouriseBashDoc(unsigned int startPos, int length, int initStyle,
        styler.ColourTo(lengthDoc - 1, state);
 }
 
+static bool IsCommentLine(int line, Accessor &styler) {
+       int pos = styler.LineStart(line);
+       int eol_pos = styler.LineStart(line + 1) - 1;
+       for (int i = pos; i < eol_pos; i++) {
+               char ch = styler[i];
+               if (ch == '#')
+                       return true;
+               else if (ch != ' ' && ch != '\t')
+                       return false;
+       }
+       return false;
+}
+
 static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[],
                             Accessor &styler) {
        bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
@@ -599,16 +616,16 @@ static void FoldBashDoc(unsigned int startPos, int length, int, WordList *[],
                int style = styleNext;
                styleNext = styler.StyleAt(i + 1);
                bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
-               if (foldComment && (style == SCE_SH_COMMENTLINE)) {
-                       if ((ch == '/') && (chNext == '/')) {
-                               char chNext2 = styler.SafeGetCharAt(i + 2);
-                               if (chNext2 == '{') {
-                                       levelCurrent++;
-                               } else if (chNext2 == '}') {
-                                       levelCurrent--;
-                               }
-                       }
-               }
+        // Comment folding
+               if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
+        {
+            if (!IsCommentLine(lineCurrent - 1, styler)
+                && IsCommentLine(lineCurrent + 1, styler))
+                levelCurrent++;
+            else if (IsCommentLine(lineCurrent - 1, styler)
+                     && !IsCommentLine(lineCurrent+1, styler))
+                levelCurrent--;
+        }
                if (style == SCE_C_OPERATOR) {
                        if (ch == '{') {
                                levelCurrent++;
diff --git a/src/stc/scintilla/src/LexBasic.cxx b/src/stc/scintilla/src/LexBasic.cxx
new file mode 100644 (file)
index 0000000..4a1843a
--- /dev/null
@@ -0,0 +1,364 @@
+// Scintilla source code edit control
+/** @file LexBasic.cxx
+ ** Lexer for BlitzBasic and PureBasic.
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+// This tries to be a unified Lexer/Folder for all the BlitzBasic/BlitzMax/PurBasic basics
+// and derivatives. Once they diverge enough, might want to split it into multiple
+// lexers for more code clearity.
+//
+// Mail me (elias <at> users <dot> sf <dot> net) for any bugs.
+
+// Folding only works for simple things like functions or types.
+
+// You may want to have a look at my ctags lexer as well, if you additionally to coloring
+// and folding need to extract things like label tags in your editor.
+
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+/* Bits:
+ * 1  - whitespace
+ * 2  - operator
+ * 4  - identifier
+ * 8  - decimal digit
+ * 16 - hex digit
+ * 32 - bin digit
+ */
+static int character_classification[128] =
+{
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  1,  0,  0,  1,  0,  0,
+    0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    1,  2,  0,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  2,  10, 2,
+    60, 60, 28, 28, 28, 28, 28, 28, 28, 28, 2,  2,  2,  2,  2,  2,
+    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  4,
+    2,  20, 20, 20, 20, 20, 20, 4,  4,  4,  4,  4,  4,  4,  4,  4,
+    4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  2,  2,  2,  2,  0
+};
+
+static bool IsSpace(int c) {
+       return c < 128 && (character_classification[c] & 1);
+}
+
+static bool IsOperator(int c) {
+       return c < 128 && (character_classification[c] & 2);
+}
+
+static bool IsIdentifier(int c) {
+       return c < 128 && (character_classification[c] & 4);
+}
+
+static bool IsDigit(int c) {
+       return c < 128 && (character_classification[c] & 8);
+}
+
+static bool IsHexDigit(int c) {
+       return c < 128 && (character_classification[c] & 16);
+}
+
+static bool IsBinDigit(int c) {
+       return c < 128 && (character_classification[c] & 32);
+}
+
+static int LowerCase(int c)
+{
+       if (c >= 'A' && c <= 'Z')
+               return 'a' + c - 'A';
+       return c;
+}
+
+static void ColouriseBasicDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler, char comment_char) {
+       bool wasfirst = true, isfirst = true; // true if first token in a line
+       styler.StartAt(startPos);
+
+       StyleContext sc(startPos, length, initStyle, styler);
+
+       // Can't use sc.More() here else we miss the last character
+       for (; ; sc.Forward()) {
+               if (sc.state == SCE_B_IDENTIFIER) {
+                       if (!IsIdentifier(sc.ch)) {
+                               // Labels
+                               if (wasfirst && sc.Match(':')) {
+                                       sc.ChangeState(SCE_B_LABEL);
+                                       sc.ForwardSetState(SCE_B_DEFAULT);
+                               } else {
+                                       char s[100];
+                                       int kstates[4] = {
+                                               SCE_B_KEYWORD,
+                                               SCE_B_KEYWORD2,
+                                               SCE_B_KEYWORD3,
+                                               SCE_B_KEYWORD4,
+                                       };
+                                       sc.GetCurrentLowered(s, sizeof(s));
+                                       for (int i = 0; i < 4; i++) {
+                                               if (keywordlists[i]->InList(s)) {
+                                                       sc.ChangeState(kstates[i]);
+                                               }
+                                       }
+                                       // Types, must set them as operator else they will be
+                                       // matched as number/constant
+                                       if (sc.Match('.') || sc.Match('$') || sc.Match('%') ||
+                                               sc.Match('#')) {
+                                               sc.SetState(SCE_B_OPERATOR);
+                                       } else {
+                                               sc.SetState(SCE_B_DEFAULT);
+                                       }
+                               }
+                       }
+               } else if (sc.state == SCE_B_OPERATOR) {
+                       if (!IsOperator(sc.ch) || sc.Match('#'))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_LABEL) {
+                       if (!IsIdentifier(sc.ch))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_CONSTANT) {
+                       if (!IsIdentifier(sc.ch))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_NUMBER) {
+                       if (!IsDigit(sc.ch))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_HEXNUMBER) {
+                       if (!IsHexDigit(sc.ch))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_BINNUMBER) {
+                       if (!IsBinDigit(sc.ch))
+                               sc.SetState(SCE_B_DEFAULT);
+               } else if (sc.state == SCE_B_STRING) {
+                       if (sc.ch == '"') {
+                               sc.ForwardSetState(SCE_B_DEFAULT);
+                       }
+                       if (sc.atLineEnd) {
+                               sc.ChangeState(SCE_B_ERROR);
+                               sc.SetState(SCE_B_DEFAULT);
+                       }
+               } else if (sc.state == SCE_B_COMMENT) {
+                       if (sc.atLineEnd) {
+                               sc.SetState(SCE_B_DEFAULT);
+                       }
+               }
+
+               if (sc.atLineStart)
+                       isfirst = true;
+
+               if (sc.state == SCE_B_DEFAULT || sc.state == SCE_B_ERROR) {
+                       if (isfirst && sc.Match('.')) {
+                               sc.SetState(SCE_B_LABEL);
+                       } else if (isfirst && sc.Match('#')) {
+                               wasfirst = isfirst;
+                               sc.SetState(SCE_B_IDENTIFIER);
+                       } else if (sc.Match(comment_char)) {
+                               sc.SetState(SCE_B_COMMENT);
+                       } else if (sc.Match('"')) {
+                               sc.SetState(SCE_B_STRING);
+                       } else if (IsDigit(sc.ch)) {
+                               sc.SetState(SCE_B_NUMBER);
+                       } else if (sc.Match('$')) {
+                               sc.SetState(SCE_B_HEXNUMBER);
+                       } else if (sc.Match('%')) {
+                               sc.SetState(SCE_B_BINNUMBER);
+                       } else if (sc.Match('#')) {
+                               sc.SetState(SCE_B_CONSTANT);
+                       } else if (IsOperator(sc.ch)) {
+                               sc.SetState(SCE_B_OPERATOR);
+                       } else if (IsIdentifier(sc.ch)) {
+                               wasfirst = isfirst;
+                               sc.SetState(SCE_B_IDENTIFIER);
+                       } else if (!IsSpace(sc.ch)) {
+                               sc.SetState(SCE_B_ERROR);
+                       }
+               }
+
+               if (!IsSpace(sc.ch))
+                       isfirst = false;
+
+               if (!sc.More())
+                       break;
+       }
+       sc.Complete();
+}
+
+static int CheckBlitzFoldPoint(char const *token, int &level) {
+       if (!strcmp(token, "function") ||
+               !strcmp(token, "type")) {
+               level |= SC_FOLDLEVELHEADERFLAG;
+               return 1;
+       }
+       if (!strcmp(token, "end function") ||
+               !strcmp(token, "end type")) {
+               return -1;
+       }
+       return 0;
+}
+
+static int CheckPureFoldPoint(char const *token, int &level) {
+       if (!strcmp(token, "procedure") ||
+               !strcmp(token, "enumeration") ||
+               !strcmp(token, "interface") ||
+               !strcmp(token, "structure")) {
+               level |= SC_FOLDLEVELHEADERFLAG;
+               return 1;
+       }
+       if (!strcmp(token, "endprocedure") ||
+               !strcmp(token, "endenumeration") ||
+               !strcmp(token, "endinterface") ||
+               !strcmp(token, "endstructure")) {
+               return -1;
+       }
+       return 0;
+}
+
+static int CheckFreeFoldPoint(char const *token, int &level) {
+       if (!strcmp(token, "function") ||
+               !strcmp(token, "sub") ||
+               !strcmp(token, "type")) {
+               level |= SC_FOLDLEVELHEADERFLAG;
+               return 1;
+       }
+       if (!strcmp(token, "end function") ||
+               !strcmp(token, "end sub") ||
+               !strcmp(token, "end type")) {
+               return -1;
+       }
+       return 0;
+}
+
+static void FoldBasicDoc(unsigned int startPos, int length,
+       Accessor &styler, int (*CheckFoldPoint)(char const *, int &)) {
+       int line = styler.GetLine(startPos);
+       int level = styler.LevelAt(line);
+       int go = 0, done = 0;
+       int endPos = startPos + length;
+       char word[256];
+       int wordlen = 0;
+       int i;
+        bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+       // Scan for tokens at the start of the line (they may include
+       // whitespace, for tokens like "End Function"
+       for (i = startPos; i < endPos; i++) {
+               int c = styler.SafeGetCharAt(i);
+               if (!done && !go) {
+                       if (wordlen) { // are we scanning a token already?
+                               word[wordlen] = static_cast<char>(LowerCase(c));
+                               if (!IsIdentifier(c)) { // done with token
+                                       word[wordlen] = '\0';
+                                       go = CheckFoldPoint(word, level);
+                                       if (!go) {
+                                               // Treat any whitespace as single blank, for
+                                               // things like "End   Function".
+                                               if (IsSpace(c) && IsIdentifier(word[wordlen - 1])) {
+                                                       word[wordlen] = ' ';
+                                                       if (wordlen < 255)
+                                                               wordlen++;
+                                               }
+                                               else // done with this line
+                                                       done = 1;
+                                       }
+                               } else if (wordlen < 255) {
+                                       wordlen++;
+                               }
+                       } else { // start scanning at first non-whitespace character
+                               if (!IsSpace(c)) {
+                                       if (IsIdentifier(c)) {
+                                               word[0] = static_cast<char>(LowerCase(c));
+                                               wordlen = 1;
+                                       } else // done with this line
+                                               done = 1;
+                               }
+                       }
+               }
+               if (c == '\n') { // line end
+                       if (!done && wordlen == 0 && foldCompact) // line was only space
+                               level |= SC_FOLDLEVELWHITEFLAG;
+                       if (level != styler.LevelAt(line))
+                               styler.SetLevel(line, level);
+                       level += go;
+                       line++;
+                       // reset state
+                       wordlen = 0;
+                       level &= ~SC_FOLDLEVELHEADERFLAG;
+                       level &= ~SC_FOLDLEVELWHITEFLAG;
+                       go = 0;
+                       done = 0;
+               }
+       }
+}
+
+static void ColouriseBlitzBasicDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler) {
+       ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';');
+}
+
+static void ColourisePureBasicDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler) {
+       ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, ';');
+}
+
+static void ColouriseFreeBasicDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler) {
+       ColouriseBasicDoc(startPos, length, initStyle, keywordlists, styler, '\'');
+}
+
+static void FoldBlitzBasicDoc(unsigned int startPos, int length, int,
+       WordList *[], Accessor &styler) {
+       FoldBasicDoc(startPos, length, styler, CheckBlitzFoldPoint);
+}
+
+static void FoldPureBasicDoc(unsigned int startPos, int length, int,
+       WordList *[], Accessor &styler) {
+       FoldBasicDoc(startPos, length, styler, CheckPureFoldPoint);
+}
+
+static void FoldFreeBasicDoc(unsigned int startPos, int length, int,
+       WordList *[], Accessor &styler) {
+       FoldBasicDoc(startPos, length, styler, CheckFreeFoldPoint);
+}
+
+static const char * const blitzbasicWordListDesc[] = {
+       "BlitzBasic Keywords",
+       "user1",
+       "user2",
+       "user3",
+       0
+};
+
+static const char * const purebasicWordListDesc[] = {
+       "PureBasic Keywords",
+       "PureBasic PreProcessor Keywords",
+       "user defined 1",
+       "user defined 2",
+       0
+};
+
+static const char * const freebasicWordListDesc[] = {
+       "FreeBasic Keywords",
+       "FreeBasic PreProcessor Keywords",
+       "user defined 1",
+       "user defined 2",
+       0
+};
+
+LexerModule lmBlitzBasic(SCLEX_BLITZBASIC, ColouriseBlitzBasicDoc, "blitzbasic",
+       FoldBlitzBasicDoc, blitzbasicWordListDesc);
+
+LexerModule lmPureBasic(SCLEX_PUREBASIC, ColourisePureBasicDoc, "purebasic",
+       FoldPureBasicDoc, purebasicWordListDesc);
+
+LexerModule lmFreeBasic(SCLEX_FREEBASIC, ColouriseFreeBasicDoc, "freebasic",
+       FoldFreeBasicDoc, freebasicWordListDesc);
+
index e5240776cc0d59656dad979d599333ff8998efa7..e28e4b13b48a259978240410066f416850a25a47 100644 (file)
@@ -1,15 +1,16 @@
 // Scintilla source code edit control
 /** @file LexClw.cxx
  ** Lexer for Clarion.
+ ** 2004/12/17 Updated Lexer
  **/
-// Copyright 2003 by Ron Schofield <ron@schofieldcomputer.com>
+// Copyright 2003-2004 by Ron Schofield <ron@schofieldcomputer.com>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
 #include <string.h>
-#include <ctype.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <ctype.h>
 
 #include "Platform.h"
 
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-static char MakeUpperCase(char ch) {
-       if (ch < 'a' || ch > 'z')
-               return ch;
-       else
-               return static_cast<char>(ch - 'a' + 'A');
+// Is an end of line character
+inline bool IsEOL(const int ch) {
+
+       return(ch == '\n');
+}
+
+// Convert character to uppercase
+static char CharacterUpper(char chChar) {
+
+       if (chChar < 'a' || chChar > 'z') {
+               return(chChar);
+       }
+       else {
+               return(static_cast<char>(chChar - 'a' + 'A'));
+       }
 }
 
-static void MakeUpperCaseString(char *s) {
-       while (*s) {
-               *s = MakeUpperCase(*s);
-               s++;
+// Convert string to uppercase
+static void StringUpper(char *szString) {
+
+       while (*szString) {
+               *szString = CharacterUpper(*szString);
+               szString++;
        }
 }
 
 // Is a label start character
 inline bool IsALabelStart(const int iChar) {
+
        return(isalpha(iChar) || iChar == '_');
 }
 
 // Is a label character
 inline bool IsALabelCharacter(const int iChar) {
-       return(isalnum(iChar) || iChar == '_' || iChar == ':');
+
+       return(isalnum(iChar) || iChar == '_' || iChar == ':'); 
 }
 
-// Is the character is a ! and the the next character is not a !
-inline bool IsACommentStart(StyleContext &scDoc) {
-       return(scDoc.ch == '!' && scDoc.chNext != '!');
+// Is the character is a ! and the the next character is not a ! 
+inline bool IsACommentStart(const int iChar) {
+
+       return(iChar == '!');
 }
 
 // Is the character a Clarion hex character (ABCDEF)
 inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
+
        // Case insensitive.
        if (!bCaseSensitive) {
                if (strchr("ABCDEFabcdef", iChar) != NULL) {
@@ -68,6 +85,7 @@ inline bool IsAHexCharacter(const int iChar, bool bCaseSensitive) {
 
 // Is the character a Clarion base character (B=Binary, O=Octal, H=Hex)
 inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {
+
        // Case insensitive.
        if (!bCaseSensitive) {
                // If character is a numeric base character
@@ -87,8 +105,9 @@ inline bool IsANumericBaseCharacter(const int iChar, bool bCaseSensitive) {
 
 // Set the correct numeric constant state
 inline bool SetNumericConstantState(StyleContext &scDoc) {
+
        int iPoints = 0;                        // Point counter
-       char cNumericString[100];       // Numeric string buffer
+       char cNumericString[512];       // Numeric string buffer
 
        // Buffer the current numberic string
        scDoc.GetCurrent(cNumericString, sizeof(cNumericString));
@@ -103,7 +122,7 @@ inline bool SetNumericConstantState(StyleContext &scDoc) {
                                break;
                        default :
                                break;
-               }
+               }       
        }
        // If points found (can be more than one for improper formatted number
        if (iPoints > 0) {
@@ -115,18 +134,68 @@ inline bool SetNumericConstantState(StyleContext &scDoc) {
        }
 }
 
+// Get the next word in uppercase from the current position (keyword lookahead)
+inline bool GetNextWordUpper(Accessor &styler, unsigned int uiStartPos, int iLength, char *cWord) {
+
+       unsigned int iIndex = 0;                // Buffer Index
+
+       // Loop through the remaining string from the current position
+       for (int iOffset = uiStartPos; iOffset < iLength; iOffset++) {
+               // Get the character from the buffer using the offset
+               char cCharacter = styler[iOffset];
+               if (IsEOL(cCharacter)) {
+                       break;
+               }
+               // If the character is alphabet character
+               if (isalpha(cCharacter)) {
+                       // Add UPPERCASE character to the word buffer
+                       cWord[iIndex++] = CharacterUpper(cCharacter);
+               }
+       }
+       // Add null termination
+       cWord[iIndex] = '\0';
+       // If no word was found
+       if (iIndex == 0) {
+               // Return failure
+               return(false);
+       }
+       // Else word was found
+       else {
+               // Return success
+               return(true);
+       }
+}
+
 // Clarion Language Colouring Procedure
-static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {
+static void ColouriseClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler, bool bCaseSensitive) {
+
+       int iParenthesesLevel = 0;              // Parenthese Level
+       int iColumn1Label = false;              // Label starts in Column 1
+
+       WordList &wlClarionKeywords = *wlKeywords[0];                   // Clarion Keywords
+       WordList &wlCompilerDirectives = *wlKeywords[1];                // Compiler Directives
+       WordList &wlRuntimeExpressions = *wlKeywords[2];                // Runtime Expressions
+       WordList &wlBuiltInProcsFuncs = *wlKeywords[3];                 // Builtin Procedures and Functions
+       WordList &wlStructsDataTypes = *wlKeywords[4];                  // Structures and Data Types
+       WordList &wlAttributes = *wlKeywords[5];                                // Procedure Attributes
+       WordList &wlStandardEquates = *wlKeywords[6];                   // Standard Equates
+       WordList &wlLabelReservedWords = *wlKeywords[7];                // Clarion Reserved Keywords (Labels)
+       WordList &wlProcLabelReservedWords = *wlKeywords[8];    // Clarion Reserved Keywords (Procedure Labels)
 
-       int iParenthesesLevel=0;                // Parenthese Level
+       const char wlProcReservedKeywordList[] = 
+       "PROCEDURE FUNCTION";
+       WordList wlProcReservedKeywords;
+       wlProcReservedKeywords.Set(wlProcReservedKeywordList);
 
-       WordList &wlClarionKeywords = *wlKeywords[0];           // Clarion Keywords
-       WordList &wlCompilerDirectives = *wlKeywords[1];        // Compiler Directives
-       WordList &wlBuiltInProcsFuncs = *wlKeywords[2];         // Builtin Procedures and Functions
-       WordList &wlStructsDataTypes = *wlKeywords[3];          // Structures and Data Types
-       WordList &wlAttributes = *wlKeywords[4];                        // Procedure Attributes
-       WordList &wlStandardEquates = *wlKeywords[5];           // Standard Equates
-       WordList &wlReservedWords = *wlKeywords[6];                     // Clarion Reserved Keywords
+       const char wlCompilerKeywordList[] = 
+       "COMPILE OMIT";
+       WordList wlCompilerKeywords;
+       wlCompilerKeywords.Set(wlCompilerKeywordList);
+
+       const char wlLegacyStatementsList[] =
+       "BOF EOF FUNCTION POINTER SHARE";
+       WordList wlLegacyStatements;
+       wlLegacyStatements.Set(wlLegacyStatementsList);
 
        StyleContext scDoc(uiStartPos, iLength, iInitStyle, accStyler);
 
@@ -143,26 +212,45 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                        if (!IsALabelCharacter(scDoc.ch)) {
                                // If the character is a . (dot syntax)
                                if (scDoc.ch == '.') {
+                                       // Turn off column 1 label flag as label now cannot be reserved work
+                                       iColumn1Label = false;
                                        // Uncolour the . (dot) to default state, move forward one character,
                                        // and change back to the label state.
                                        scDoc.SetState(SCE_CLW_DEFAULT);
                                        scDoc.Forward();
                                        scDoc.SetState(SCE_CLW_LABEL);
                                }
-                               // Else terminate the label state
+                               // Else check label
                                else {
-                                       char cLabel[100];               // Label buffer
+                                       char cLabel[512];               // Label buffer
                                        // Buffer the current label string
                                        scDoc.GetCurrent(cLabel,sizeof(cLabel));
                                        // If case insensitive, convert string to UPPERCASE to match passed keywords.
                                        if (!bCaseSensitive) {
-                                               MakeUpperCaseString(cLabel);
+                                               StringUpper(cLabel);
                                        }
-                                       // If label string is in the Clarion reserved keyword list
-                                       if (wlReservedWords.InList(cLabel)){
-                                               // change to error state
+                                       // Else if UPPERCASE label string is in the Clarion compiler keyword list
+                                       if (wlCompilerKeywords.InList(cLabel) && iColumn1Label){
+                                               // change the label to error state
+                                               scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
+                                       }
+                                       // Else if UPPERCASE label string is in the Clarion reserved keyword list
+                                       else if (wlLabelReservedWords.InList(cLabel) && iColumn1Label){
+                                               // change the label to error state
                                                scDoc.ChangeState(SCE_CLW_ERROR);
                                        }
+                                       // Else if UPPERCASE label string is 
+                                       else if (wlProcLabelReservedWords.InList(cLabel) && iColumn1Label) {
+                                               char cWord[512];        // Word buffer
+                                               // Get the next word from the current position
+                                               if (GetNextWordUpper(accStyler,scDoc.currentPos,uiStartPos+iLength,cWord)) {
+                                                       // If the next word is a procedure reserved word
+                                                       if (wlProcReservedKeywords.InList(cWord)) {
+                                                               // Change the label to error state
+                                                               scDoc.ChangeState(SCE_CLW_ERROR);
+                                                       }
+                                               }
+                                       }
                                        // Else if label string is in the compiler directive keyword list
                                        else if (wlCompilerDirectives.InList(cLabel)) {
                                                // change the state to compiler directive state
@@ -177,14 +265,14 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                else if (scDoc.state == SCE_CLW_KEYWORD) {
                        // If character is : (colon)
                        if (scDoc.ch == ':') {
-                               char cEquate[100];              // Equate buffer
+                               char cEquate[512];              // Equate buffer
                                // Move forward to include : (colon) in buffer
                                scDoc.Forward();
                                // Buffer the equate string
                                scDoc.GetCurrent(cEquate,sizeof(cEquate));
                                // If case insensitive, convert string to UPPERCASE to match passed keywords.
                                if (!bCaseSensitive) {
-                                       MakeUpperCaseString(cEquate);
+                                       StringUpper(cEquate);
                                }
                                // If statement string is in the equate list
                                if (wlStandardEquates.InList(cEquate)) {
@@ -194,43 +282,58 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                        }
                        // If the character is not a valid label character
                        else if (!IsALabelCharacter(scDoc.ch)) {
-                               char cStatement[100];           // Statement buffer
+                               char cStatement[512];           // Statement buffer
                                // Buffer the statement string
                                scDoc.GetCurrent(cStatement,sizeof(cStatement));
                                // If case insensitive, convert string to UPPERCASE to match passed keywords.
                                if (!bCaseSensitive) {
-                                       MakeUpperCaseString(cStatement);
+                                       StringUpper(cStatement);
                                }
                                // If statement string is in the Clarion keyword list
                                if (wlClarionKeywords.InList(cStatement)) {
-                                       // Set to the Clarion keyword state
+                                       // Change the statement string to the Clarion keyword state
                                        scDoc.ChangeState(SCE_CLW_KEYWORD);
                                }
                                // Else if statement string is in the compiler directive keyword list
                                else if (wlCompilerDirectives.InList(cStatement)) {
-                                       // Set to the compiler directive state
+                                       // Change the statement string to the compiler directive state
                                        scDoc.ChangeState(SCE_CLW_COMPILER_DIRECTIVE);
                                }
+                               // Else if statement string is in the runtime expressions keyword list
+                               else if (wlRuntimeExpressions.InList(cStatement)) {
+                                       // Change the statement string to the runtime expressions state
+                                       scDoc.ChangeState(SCE_CLW_RUNTIME_EXPRESSIONS);
+                               }
                                // Else if statement string is in the builtin procedures and functions keyword list
                                else if (wlBuiltInProcsFuncs.InList(cStatement)) {
-                                       // Set to the builtin procedures and functions state
+                                       // Change the statement string to the builtin procedures and functions state
                                        scDoc.ChangeState(SCE_CLW_BUILTIN_PROCEDURES_FUNCTION);
                                }
                                // Else if statement string is in the tructures and data types keyword list
                                else if (wlStructsDataTypes.InList(cStatement)) {
-                                       // Set to the structures and data types state
+                                       // Change the statement string to the structures and data types state
                                        scDoc.ChangeState(SCE_CLW_STRUCTURE_DATA_TYPE);
                                }
                                // Else if statement string is in the procedure attribute keyword list
                                else if (wlAttributes.InList(cStatement)) {
-                                       // Set to the procedure attribute state
+                                       // Change the statement string to the procedure attribute state
                                        scDoc.ChangeState(SCE_CLW_ATTRIBUTE);
                                }
                                // Else if statement string is in the standard equate keyword list
                                else if (wlStandardEquates.InList(cStatement)) {
-                                       // Set to the standard equate state
+                                       // Change the statement string to the standard equate state
                                        scDoc.ChangeState(SCE_CLW_STANDARD_EQUATE);
                                }
+                               // Else if statement string is in the deprecated or legacy keyword list
+                               else if (wlLegacyStatements.InList(cStatement)) {
+                                       // Change the statement string to the standard equate state
+                                       scDoc.ChangeState(SCE_CLW_DEPRECATED);
+                               }
+                               // Else the statement string doesn't match any work list
+                               else {
+                                       // Change the statement string to the default state
+                                       scDoc.ChangeState(SCE_CLW_DEFAULT);
+                               }
                                // Terminate the keyword state and set to default state
                                scDoc.SetState(SCE_CLW_DEFAULT);
                        }
@@ -261,13 +364,13 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                                // Increment the parenthese level
                                iParenthesesLevel++;
                        }
-                       // Else if the character is a ) (close parenthese)
+                       // Else if the character is a ) (close parenthese) 
                        else if (scDoc.ch == ')') {
                                // If the parenthese level is set to zero
                                // parentheses matched
                                if (!iParenthesesLevel) {
                                        scDoc.SetState(SCE_CLW_DEFAULT);
-                               }
+                               } 
                                // Else parenthese level is greater than zero
                                // still looking for matching parentheses
                                else {
@@ -292,7 +395,7 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                        || IsAHexCharacter(scDoc.ch, bCaseSensitive)
                        || scDoc.ch == '.'
                        || IsANumericBaseCharacter(scDoc.ch, bCaseSensitive))) {
-                               // If the number was a real
+                               // If the number was a real 
                                if (SetNumericConstantState(scDoc)) {
                                        // Colour the matched string to the real constant state
                                        scDoc.ChangeState(SCE_CLW_REAL_CONSTANT);
@@ -313,8 +416,13 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
 
                // Beginning of Line Handling
                if (scDoc.atLineStart) {
+                       // Reset the column 1 label flag
+                       iColumn1Label = false;
                        // If column 1 character is a label start character
                        if (IsALabelStart(scDoc.ch)) {
+                               // Label character is found in column 1
+                               // so set column 1 label flag and clear last column 1 label
+                               iColumn1Label = true;
                                // Set the state to label
                                scDoc.SetState(SCE_CLW_LABEL);
                        }
@@ -323,8 +431,8 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                                // Set to default state
                                scDoc.SetState(SCE_CLW_DEFAULT);
                        }
-                       // else if the start of a comment or is an * (asterisk)
-                       else if (IsACommentStart(scDoc) || scDoc.ch == '*' ) {
+                       // else if comment start (!) or is an * (asterisk)
+                       else if (IsACommentStart(scDoc.ch) || scDoc.ch == '*' ) {
                                // then set the state to comment.
                                scDoc.SetState(SCE_CLW_COMMENT);
                        }
@@ -349,7 +457,7 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                }
                // Default Handling
                else {
-                       // If in default state
+                       // If in default state 
                        if (scDoc.state == SCE_CLW_DEFAULT) {
                                // If is a letter could be a possible statement
                                if (isalpha(scDoc.ch)) {
@@ -362,13 +470,13 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                                        scDoc.SetState(SCE_CLW_INTEGER_CONSTANT);
                                }
                                // else if the start of a comment or a | (line continuation)
-                               else if (IsACommentStart(scDoc) || scDoc.ch == '|') {
+                               else if (IsACommentStart(scDoc.ch) || scDoc.ch == '|') {
                                        // then set the state to comment.
                                        scDoc.SetState(SCE_CLW_COMMENT);
-                               }
+                               }               
                                // else if the character is a ' (single quote)
                                else if (scDoc.ch == '\'') {
-                                       // If the character is also a ' (single quote)
+                                       // If the character is also a ' (single quote) 
                                        // Embedded Apostrophe
                                        if (scDoc.chNext == '\'') {
                                                // Move forward colouring it as default state
@@ -378,8 +486,8 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                                                // move to the next character and then set the state to comment.
                                                scDoc.ForwardSetState(SCE_CLW_STRING);
                                        }
-                               }
-                               // else the character is an @ (apersand)
+                               }               
+                               // else the character is an @ (ampersand)
                                else if (scDoc.ch == '@') {
                                        // Case insensitive.
                                        if (!bCaseSensitive) {
@@ -397,7 +505,7 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
                                                        scDoc.SetState(SCE_CLW_PICTURE_STRING);
                                                }
                                        }
-                               }
+                               }               
                        }
                }
        }
@@ -406,36 +514,162 @@ static void ColouriseClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle
 }
 
 // Clarion Language Case Sensitive Colouring Procedure
-static void ColouriseClwDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
-       ColouriseClwDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
+static void ColouriseClarionDocSensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
+
+       ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, true);
 }
 
 // Clarion Language Case Insensitive Colouring Procedure
-static void ColouriseClwDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
-       ColouriseClwDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
+static void ColouriseClarionDocInsensitive(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
+
+       ColouriseClarionDoc(uiStartPos, iLength, iInitStyle, wlKeywords, accStyler, false);
+}
+
+// Fill Buffer
+
+static void FillBuffer(unsigned int uiStart, unsigned int uiEnd, Accessor &accStyler, char *szBuffer, unsigned int uiLength) {
+
+       unsigned int uiPos = 0;
+
+       while ((uiPos < uiEnd - uiStart + 1) && (uiPos < uiLength-1)) {
+               szBuffer[uiPos] = static_cast<char>(toupper(accStyler[uiStart + uiPos]));
+               uiPos++;
+       }
+       szBuffer[uiPos] = '\0';
+}
+
+// Classify Clarion Fold Point
+
+static int ClassifyClarionFoldPoint(int iLevel, const char* szString) {
+
+       if (!(isdigit(szString[0]) || (szString[0] == '.'))) {
+               if (strcmp(szString, "PROCEDURE") == 0) {
+       //              iLevel = SC_FOLDLEVELBASE + 1;
+               }
+               else if (strcmp(szString, "MAP") == 0 ||
+                       strcmp(szString,"ACCEPT") == 0 ||
+                       strcmp(szString,"BEGIN") == 0 ||
+                       strcmp(szString,"CASE") == 0 ||
+                       strcmp(szString,"EXECUTE") == 0 ||
+                       strcmp(szString,"IF") == 0 ||
+                       strcmp(szString,"ITEMIZE") == 0 ||
+                       strcmp(szString,"INTERFACE") == 0 ||
+                       strcmp(szString,"JOIN") == 0 ||
+                       strcmp(szString,"LOOP") == 0 ||
+                       strcmp(szString,"MODULE") == 0 ||
+                       strcmp(szString,"RECORD") == 0) {
+                       iLevel++;
+               }
+               else if (strcmp(szString, "APPLICATION") == 0 ||
+                       strcmp(szString, "CLASS") == 0 ||
+                       strcmp(szString, "DETAIL") == 0 ||
+                       strcmp(szString, "FILE") == 0 ||
+                       strcmp(szString, "FOOTER") == 0 ||
+                       strcmp(szString, "FORM") == 0 ||
+                       strcmp(szString, "GROUP") == 0 ||
+                       strcmp(szString, "HEADER") == 0 ||
+                       strcmp(szString, "INTERFACE") == 0 ||
+                       strcmp(szString, "MENU") == 0 ||
+                       strcmp(szString, "MENUBAR") == 0 ||
+                       strcmp(szString, "OLE") == 0 ||
+                       strcmp(szString, "OPTION") == 0 ||
+                       strcmp(szString, "QUEUE") == 0 ||
+                       strcmp(szString, "REPORT") == 0 ||
+                       strcmp(szString, "SHEET") == 0 ||
+                       strcmp(szString, "TAB") == 0 ||
+                       strcmp(szString, "TOOLBAR") == 0 ||
+                       strcmp(szString, "VIEW") == 0 ||
+                       strcmp(szString, "WINDOW") == 0) {
+                       iLevel++;
+               }
+               else if (strcmp(szString, "END") == 0 ||
+                       strcmp(szString, "UNTIL") == 0 ||
+                       strcmp(szString, "WHILE") == 0) {
+                       iLevel--;
+               }
+       }
+       return(iLevel);
 }
 
 // Clarion Language Folding Procedure
-#ifdef FOLDING_IMPLEMENTED
-static void FoldClwDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *wlKeywords[], Accessor &accStyler) {
+static void FoldClarionDoc(unsigned int uiStartPos, int iLength, int iInitStyle, WordList *[], Accessor &accStyler) {
+
+       unsigned int uiEndPos = uiStartPos + iLength;
+       int iLineCurrent = accStyler.GetLine(uiStartPos);
+       int iLevelPrev = accStyler.LevelAt(iLineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int iLevelCurrent = iLevelPrev;
+       char chNext = accStyler[uiStartPos];
+       int iStyle = iInitStyle;
+       int iStyleNext = accStyler.StyleAt(uiStartPos);
+       int iVisibleChars = 0;
+       int iLastStart = 0;
+
+       for (unsigned int uiPos = uiStartPos; uiPos < uiEndPos; uiPos++) {
+
+               char chChar = chNext;
+               chNext = accStyler.SafeGetCharAt(uiPos + 1);
+               int iStylePrev = iStyle;
+               iStyle = iStyleNext;
+               iStyleNext = accStyler.StyleAt(uiPos + 1);
+               bool bEOL = (chChar == '\r' && chNext != '\n') || (chChar == '\n');
+       
+               if (iStylePrev == SCE_CLW_DEFAULT) {
+                       if (iStyle == SCE_CLW_KEYWORD || iStyle == SCE_CLW_STRUCTURE_DATA_TYPE) {
+                               // Store last word start point.
+                               iLastStart = uiPos;
+                       }
+               }
+
+               if (iStylePrev == SCE_CLW_KEYWORD || iStylePrev == SCE_CLW_STRUCTURE_DATA_TYPE) {
+                       if(iswordchar(chChar) && !iswordchar(chNext)) {
+                               char chBuffer[100];
+                               FillBuffer(iLastStart, uiPos, accStyler, chBuffer, sizeof(chBuffer));
+                               iLevelCurrent = ClassifyClarionFoldPoint(iLevelCurrent,chBuffer);
+                       //      if ((iLevelCurrent == SC_FOLDLEVELBASE + 1) && iLineCurrent > 1) {
+                       //              accStyler.SetLevel(iLineCurrent-1,SC_FOLDLEVELBASE);
+                       //              iLevelPrev = SC_FOLDLEVELBASE;
+                       //      }
+                       }
+               }
+
+               if (bEOL) {
+                       int iLevel = iLevelPrev;
+                       if ((iLevelCurrent > iLevelPrev) && (iVisibleChars > 0))
+                               iLevel |= SC_FOLDLEVELHEADERFLAG;
+                       if (iLevel != accStyler.LevelAt(iLineCurrent)) {
+                               accStyler.SetLevel(iLineCurrent,iLevel);
+                       }
+                       iLineCurrent++;
+                       iLevelPrev = iLevelCurrent;
+                       iVisibleChars = 0;
+               }
+               
+               if (!isspacechar(chChar))
+                       iVisibleChars++;
+       }
 
+       // Fill in the real level of the next line, keeping the current flags
+       // as they will be filled in later.
+       int iFlagsNext = accStyler.LevelAt(iLineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+       accStyler.SetLevel(iLineCurrent, iLevelPrev | iFlagsNext);
 }
-#endif
 
 // Word List Descriptions
 static const char * const rgWordListDescriptions[] = {
        "Clarion Keywords",
        "Compiler Directives",
        "Built-in Procedures and Functions",
+       "Runtime Expressions",
        "Structure and Data Types",
        "Attributes",
        "Standard Equates",
-       "Reserved Words",
+       "Reserved Words (Labels)",
+       "Reserved Words (Procedure Labels)",
        0,
 };
 
 // Case Sensitive Clarion Language Lexer
-LexerModule lmClw(SCLEX_CLW, ColouriseClwDocSensitive, "clw", NULL, rgWordListDescriptions);
+LexerModule lmClw(SCLEX_CLW, ColouriseClarionDocSensitive, "clarion", FoldClarionDoc, rgWordListDescriptions);
 
 // Case Insensitive Clarion Language Lexer
-LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClwDocInsensitive, "clwnocase", NULL, rgWordListDescriptions);
+LexerModule lmClwNoCase(SCLEX_CLWNOCASE, ColouriseClarionDocInsensitive, "clarionnocase", FoldClarionDoc, rgWordListDescriptions);
index c6ca0650585470cf431a24f9579f0f02c794b01a..40f3a60bd37a4f3451cd3211d8acff13dd8e2f3c 100644 (file)
@@ -1,8 +1,8 @@
 // Scintilla source code edit control
 /** @file LexCPP.cxx
- ** Lexer for C++, C, Java, and Javascript.
+ ** Lexer for C++, C, Java, and JavaScript.
  **/
-// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
 #define KEYWORD_BOXHEADER 1
 #define KEYWORD_FOLDCONTRACTED 2
 
-static bool IsOKBeforeRE(const int ch) {
+static bool IsOKBeforeRE(int ch) {
        return (ch == '(') || (ch == '=') || (ch == ',');
 }
 
-static inline bool IsAWordChar(const int ch) {
+static inline bool IsAWordChar(int ch) {
        return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
 }
 
-static inline bool IsAWordStart(const int ch) {
-       return (ch < 0x80) && (isalnum(ch) || ch == '_');
+static inline bool IsAWordStart(int ch) {
+       return (ch < 0x80) && (isalpha(ch) || ch == '_');
 }
 
-static inline bool IsADoxygenChar(const int ch) {
-       return (islower(ch) || ch == '$' || ch == '@' ||
-               ch == '\\' || ch == '&' || ch == '<' ||
-               ch == '>' || ch == '#' || ch == '{' ||
-               ch == '}' || ch == '[' || ch == ']');
+static inline bool IsADoxygenChar(int ch) {
+       return (ch < 0x80 && islower(ch)) || ch == '$' || ch == '@' ||
+               ch == '\\' || ch == '&' || ch == '<' ||
+               ch == '>' || ch == '#' || ch == '{' ||
+               ch == '}' || ch == '[' || ch == ']';
 }
 
-static inline bool IsStateComment(const int state) {
-       return ((state == SCE_C_COMMENT) ||
-               (state == SCE_C_COMMENTLINE) ||
-               (state == SCE_C_COMMENTDOC) ||
-               (state == SCE_C_COMMENTDOCKEYWORD) ||
-               (state == SCE_C_COMMENTDOCKEYWORDERROR));
-}
-
-static inline bool IsStateString(const int state) {
-       return ((state == SCE_C_STRING) || (state == SCE_C_VERBATIM));
+static bool IsSpaceEquiv(int state) {
+       return (state <= SCE_C_COMMENTDOC) ||
+               // including SCE_C_DEFAULT, SCE_C_COMMENT, SCE_C_COMMENTLINE
+               (state == SCE_C_COMMENTLINEDOC) || (state == SCE_C_COMMENTDOCKEYWORD) ||
+               (state == SCE_C_COMMENTDOCKEYWORDERROR);
 }
 
 static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
@@ -64,21 +59,52 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
 
        bool stylingWithinPreprocessor = styler.GetPropertyInt("styling.within.preprocessor") != 0;
 
-       // Do not leak onto next line
-       if (initStyle == SCE_C_STRINGEOL)
-               initStyle = SCE_C_DEFAULT;
-
        int chPrevNonWhite = ' ';
        int visibleChars = 0;
        bool lastWordWasUUID = false;
+       int styleBeforeDCKeyword = SCE_C_DEFAULT;
+       bool continuationLine = false;
+
+       if (initStyle == SCE_C_PREPROCESSOR) {
+               // Set continuationLine if last character of previous line is '\'
+               int lineCurrent = styler.GetLine(startPos);
+               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;
+                       }
+                       continuationLine = lineEndChar == '\\';
+               }
+       }
+
+       // look back to set chPrevNonWhite properly for better regex colouring
+       if (startPos > 0) {
+               int back = startPos;
+               while (--back && IsSpaceEquiv(styler.StyleAt(back)))
+                       ;
+               if (styler.StyleAt(back) == SCE_C_OPERATOR) {
+                       chPrevNonWhite = styler.SafeGetCharAt(back);
+               }
+       }
 
        StyleContext sc(startPos, length, initStyle, styler);
 
        for (; sc.More(); sc.Forward()) {
 
-               if (sc.atLineStart && (sc.state == SCE_C_STRING)) {
-                       // Prevent SCE_C_STRINGEOL from leaking back to previous line
-                       sc.SetState(SCE_C_STRING);
+               if (sc.atLineStart) {
+                       if (sc.state == SCE_C_STRING) {
+                               // Prevent SCE_C_STRINGEOL from leaking back to previous line which 
+                               // ends with a line continuation by locking in the state upto this position.
+                               sc.SetState(SCE_C_STRING);
+                       }
+                       // Reset states to begining of colourise so no surprises
+                       // if different sets of lines lexed.
+                       visibleChars = 0;
+                       lastWordWasUUID = false;
                }
 
                // Handle line continuation generically.
@@ -88,124 +114,161 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
                                if (sc.ch == '\r' && sc.chNext == '\n') {
                                        sc.Forward();
                                }
+                               continuationLine = true;
                                continue;
                        }
                }
 
                // Determine if the current state should terminate.
-               if (sc.state == SCE_C_OPERATOR) {
-                       sc.SetState(SCE_C_DEFAULT);
-               } else if (sc.state == SCE_C_NUMBER) {
-                       if (!IsAWordChar(sc.ch)) {
-                               sc.SetState(SCE_C_DEFAULT);
-                       }
-               } else if (sc.state == SCE_C_IDENTIFIER) {
-                       if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
-                               char s[100];
-                               if (caseSensitive) {
-                                       sc.GetCurrent(s, sizeof(s));
-                               } else {
-                                       sc.GetCurrentLowered(s, sizeof(s));
-                               }
-                               if (keywords.InList(s)) {
-                                       lastWordWasUUID = strcmp(s, "uuid") == 0;
-                                       sc.ChangeState(SCE_C_WORD);
-                               } else if (keywords2.InList(s)) {
-                                       sc.ChangeState(SCE_C_WORD2);
-                               } else if (keywords4.InList(s)) {
-                                       sc.ChangeState(SCE_C_GLOBALCLASS);
-                               }
+               switch (sc.state) {
+                       case SCE_C_OPERATOR:
                                sc.SetState(SCE_C_DEFAULT);
-                       }
-               } else if (sc.state == SCE_C_PREPROCESSOR) {
-                       if (stylingWithinPreprocessor) {
-                               if (IsASpace(sc.ch)) {
+                               break;
+                       case SCE_C_NUMBER:
+                               // We accept almost anything because of hex. and number suffixes
+                               if (!IsAWordChar(sc.ch)) {
                                        sc.SetState(SCE_C_DEFAULT);
                                }
-                       } else {
-                               if ((sc.ch == '\r') || (sc.ch == '\n') || (sc.Match('/', '*')) || (sc.Match('/', '/'))) {
+                               break;
+                       case SCE_C_IDENTIFIER:
+                               if (!IsAWordChar(sc.ch) || (sc.ch == '.')) {
+                                       char s[1000];
+                                       if (caseSensitive) {
+                                               sc.GetCurrent(s, sizeof(s));
+                                       } else {
+                                               sc.GetCurrentLowered(s, sizeof(s));
+                                       }
+                                       if (keywords.InList(s)) {
+                                               lastWordWasUUID = strcmp(s, "uuid") == 0;
+                                               sc.ChangeState(SCE_C_WORD);
+                                       } else if (keywords2.InList(s)) {
+                                               sc.ChangeState(SCE_C_WORD2);
+                                       } else if (keywords4.InList(s)) {
+                                               sc.ChangeState(SCE_C_GLOBALCLASS);
+                                       }
                                        sc.SetState(SCE_C_DEFAULT);
                                }
-                       }
-               } else if (sc.state == SCE_C_COMMENT) {
-                       if (sc.Match('*', '/')) {
-                               sc.Forward();
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       }
-               } else if (sc.state == SCE_C_COMMENTDOC) {
-                       if (sc.Match('*', '/')) {
-                               sc.Forward();
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       } else if (sc.ch == '@' || sc.ch == '\\') {
-                               sc.SetState(SCE_C_COMMENTDOCKEYWORD);
-                       }
-               } else if (sc.state == SCE_C_COMMENTLINE || sc.state == SCE_C_COMMENTLINEDOC) {
-                       if (sc.ch == '\r' || sc.ch == '\n') {
-                               sc.SetState(SCE_C_DEFAULT);
-                               visibleChars = 0;
-                       }
-               } else if (sc.state == SCE_C_COMMENTDOCKEYWORD) {
-                       if (sc.Match('*', '/')) {
-                               sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
-                               sc.Forward();
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       } else if (!IsADoxygenChar(sc.ch)) {
-                               char s[100];
-                               if (caseSensitive) {
-                                       sc.GetCurrent(s, sizeof(s));
+                               break;
+                       case SCE_C_PREPROCESSOR:
+                               if (sc.atLineStart && !continuationLine) {
+                                       sc.SetState(SCE_C_DEFAULT);
+                               } else if (stylingWithinPreprocessor) {
+                                       if (IsASpace(sc.ch)) {
+                                               sc.SetState(SCE_C_DEFAULT);
+                                       }
                                } else {
-                                       sc.GetCurrentLowered(s, sizeof(s));
-                               }
-                               if (!isspace(sc.ch) || !keywords3.InList(s + 1)) {
-                                       sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
+                                       if (sc.Match('/', '*') || sc.Match('/', '/')) {
+                                               sc.SetState(SCE_C_DEFAULT);
+                                       }
                                }
-                               sc.SetState(SCE_C_COMMENTDOC);
-                       }
-               } else if (sc.state == SCE_C_STRING) {
-                       if (sc.ch == '\\') {
-                               if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+                               break;
+                       case SCE_C_COMMENT:
+                               if (sc.Match('*', '/')) {
                                        sc.Forward();
+                                       sc.ForwardSetState(SCE_C_DEFAULT);
                                }
-                       } else if (sc.ch == '\"') {
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       } else if (sc.atLineEnd) {
-                               sc.ChangeState(SCE_C_STRINGEOL);
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                               visibleChars = 0;
-                       }
-               } else if (sc.state == SCE_C_CHARACTER) {
-                       if (sc.atLineEnd) {
-                               sc.ChangeState(SCE_C_STRINGEOL);
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                               visibleChars = 0;
-                       } else if (sc.ch == '\\') {
-                               if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+                               break;
+                       case SCE_C_COMMENTDOC:
+                               if (sc.Match('*', '/')) {
                                        sc.Forward();
+                                       sc.ForwardSetState(SCE_C_DEFAULT);
+                               } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
+                                       // Verify that we have the conditions to mark a comment-doc-keyword
+                                       if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
+                                               styleBeforeDCKeyword = SCE_C_COMMENTDOC;
+                                               sc.SetState(SCE_C_COMMENTDOCKEYWORD);
+                                       }
                                }
-                       } else if (sc.ch == '\'') {
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       }
-               } else if (sc.state == SCE_C_REGEX) {
-                       if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == '/') {
-                               sc.ForwardSetState(SCE_C_DEFAULT);
-                       } else if (sc.ch == '\\') {
-                               // Gobble up the quoted character
-                               if (sc.chNext == '\\' || sc.chNext == '/') {
-                                       sc.Forward();
+                               break;
+                       case SCE_C_COMMENTLINE:
+                               if (sc.atLineStart) {
+                                       sc.SetState(SCE_C_DEFAULT);
                                }
-                       }
-               } else if (sc.state == SCE_C_VERBATIM) {
-                       if (sc.ch == '\"') {
-                               if (sc.chNext == '\"') {
+                               break;
+                       case SCE_C_COMMENTLINEDOC:
+                               if (sc.atLineStart) {
+                                       sc.SetState(SCE_C_DEFAULT);
+                               } else if (sc.ch == '@' || sc.ch == '\\') { // JavaDoc and Doxygen support
+                                       // Verify that we have the conditions to mark a comment-doc-keyword
+                                       if ((IsASpace(sc.chPrev) || sc.chPrev == '/' || sc.chPrev == '!') && (!IsASpace(sc.chNext))) {
+                                               styleBeforeDCKeyword = SCE_C_COMMENTLINEDOC;
+                                               sc.SetState(SCE_C_COMMENTDOCKEYWORD);
+                                       }
+                               }
+                               break;
+                       case SCE_C_COMMENTDOCKEYWORD:
+                               if ((styleBeforeDCKeyword == SCE_C_COMMENTDOC) && sc.Match('*', '/')) {
+                                       sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
                                        sc.Forward();
-                               } else {
                                        sc.ForwardSetState(SCE_C_DEFAULT);
+                               } else if (!IsADoxygenChar(sc.ch)) {
+                                       char s[100];
+                                       if (caseSensitive) {
+                                               sc.GetCurrent(s, sizeof(s));
+                                       } else {
+                                               sc.GetCurrentLowered(s, sizeof(s));
+                                       }
+                                       if (!isspace(sc.ch) || !keywords3.InList(s + 1)) {
+                                               sc.ChangeState(SCE_C_COMMENTDOCKEYWORDERROR);
+                                       }
+                                       sc.SetState(styleBeforeDCKeyword);
+                               }
+                               break;
+                       case SCE_C_STRING:
+                               if (sc.atLineEnd) {
+                                       sc.ChangeState(SCE_C_STRINGEOL);
+                               } else if (sc.ch == '\\') {
+                                       if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+                                               sc.Forward();
+                                       }
+                               } else if (sc.ch == '\"') {
+                                       sc.ForwardSetState(SCE_C_DEFAULT);
+                               }
+                               break;
+                       case SCE_C_CHARACTER:
+                               if (sc.atLineEnd) {
+                                       sc.ChangeState(SCE_C_STRINGEOL);
+                               } else if (sc.ch == '\\') {
+                                       if (sc.chNext == '\"' || sc.chNext == '\'' || sc.chNext == '\\') {
+                                               sc.Forward();
+                                       }
+                               } else if (sc.ch == '\'') {
+                                       sc.ForwardSetState(SCE_C_DEFAULT);
+                               }
+                               break;
+                       case SCE_C_REGEX:
+                               if (sc.atLineStart) {
+                                       sc.SetState(SCE_C_DEFAULT);
+                               } else if (sc.ch == '/') {
+                                       sc.Forward();
+                                       while ((sc.ch < 0x80) && islower(sc.ch))
+                                               sc.Forward();    // gobble regex flags
+                                       sc.SetState(SCE_C_DEFAULT);
+                               } else if (sc.ch == '\\') {
+                                       // Gobble up the quoted character
+                                       if (sc.chNext == '\\' || sc.chNext == '/') {
+                                               sc.Forward();
+                                       }
+                               }
+                               break;
+                       case SCE_C_STRINGEOL:
+                               if (sc.atLineStart) {
+                                       sc.SetState(SCE_C_DEFAULT);
+                               }
+                               break;
+                       case SCE_C_VERBATIM:
+                               if (sc.ch == '\"') {
+                                       if (sc.chNext == '\"') {
+                                               sc.Forward();
+                                       } else {
+                                               sc.ForwardSetState(SCE_C_DEFAULT);
+                                       }
+                               }
+                               break;
+                       case SCE_C_UUID:
+                               if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
+                                       sc.SetState(SCE_C_DEFAULT);
                                }
-                       }
-               } else if (sc.state == SCE_C_UUID) {
-                       if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ')') {
-                               sc.SetState(SCE_C_DEFAULT);
-                       }
                }
 
                // Determine if a new state should be entered.
@@ -241,7 +304,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
                                else
                                        sc.SetState(SCE_C_COMMENTLINE);
                        } else if (sc.ch == '/' && IsOKBeforeRE(chPrevNonWhite)) {
-                               sc.SetState(SCE_C_REGEX);
+                               sc.SetState(SCE_C_REGEX);       // JavaScript's RegEx
                        } else if (sc.ch == '\"') {
                                sc.SetState(SCE_C_STRING);
                        } else if (sc.ch == '\'') {
@@ -253,7 +316,7 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
                                do {
                                        sc.Forward();
                                } while ((sc.ch == ' ' || sc.ch == '\t') && sc.More());
-                               if (sc.ch == '\r' || sc.ch == '\n') {
+                               if (sc.atLineEnd) {
                                        sc.SetState(SCE_C_DEFAULT);
                                }
                        } else if (isoperator(static_cast<char>(sc.ch))) {
@@ -261,26 +324,20 @@ static void ColouriseCppDoc(unsigned int startPos, int length, int initStyle, Wo
                        }
                }
 
-               if (sc.atLineEnd) {
-                       // Reset states to begining of colourise so no surprises
-                       // if different sets of lines lexed.
-                       chPrevNonWhite = ' ';
-                       visibleChars = 0;
-                       lastWordWasUUID = false;
-               }
-               if (!IsASpace(sc.ch)) {
+               if (!IsASpace(sc.ch) && !IsSpaceEquiv(sc.state)) {
                        chPrevNonWhite = sc.ch;
                        visibleChars++;
                }
+               continuationLine = false;
        }
        sc.Complete();
 }
 
 static bool IsStreamCommentStyle(int style) {
        return style == SCE_C_COMMENT ||
-              style == SCE_C_COMMENTDOC ||
-              style == SCE_C_COMMENTDOCKEYWORD ||
-              style == SCE_C_COMMENTDOCKEYWORDERROR;
+               style == SCE_C_COMMENTDOC ||
+               style == SCE_C_COMMENTDOCKEYWORD ||
+               style == SCE_C_COMMENTDOCKEYWORDERROR;
 }
 
 // Store both the current line's fold level and the next lines in the
index f45ce1cda4c656fedf11860b19e74be7b851765c..963a7b3ef77f10ac8a5e29075b7d7ec3151afab9 100644 (file)
@@ -107,6 +107,25 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo
                                if (lastState == SCE_CSS_DEFAULT)
                                        sc.SetState(SCE_CSS_DIRECTIVE);
                                break;
+                       case '*':
+                               if (lastState == SCE_CSS_DEFAULT)
+                                       sc.SetState(SCE_CSS_TAG);
+                               break;
+                       case '>':
+                       case '+':
+                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_CLASS
+                                       || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
+                                       sc.SetState(SCE_CSS_DEFAULT);
+                               break;
+                       case '[':
+                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
+                                       lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
+                                       sc.SetState(SCE_CSS_ATTRIBUTE);
+                               break;
+                       case ']':
+                               if (lastState == SCE_CSS_ATTRIBUTE)
+                                       sc.SetState(SCE_CSS_TAG);
+                               break;
                        case '{':
                                if (lastState == SCE_CSS_DIRECTIVE)
                                        sc.SetState(SCE_CSS_DEFAULT);
@@ -126,11 +145,13 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo
                                        sc.SetState(SCE_CSS_VALUE);
                                break;
                        case '.':
-                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT)
+                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
+                                       lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
                                        sc.SetState(SCE_CSS_CLASS);
                                break;
                        case '#':
-                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_DEFAULT)
+                               if (lastState == SCE_CSS_TAG || lastState == SCE_CSS_PSEUDOCLASS || lastState == SCE_CSS_DEFAULT ||
+                                       lastState == SCE_CSS_CLASS || lastState == SCE_CSS_ID || lastState == SCE_CSS_UNKNOWN_PSEUDOCLASS)
                                        sc.SetState(SCE_CSS_ID);
                                break;
                        case ',':
@@ -208,6 +229,7 @@ static void ColouriseCssDoc(unsigned int startPos, int length, int initStyle, Wo
                } else if (sc.state == SCE_CSS_VALUE && (sc.ch == '\"' || sc.ch == '\'')) {
                        sc.SetState((sc.ch == '\"' ? SCE_CSS_DOUBLESTRING : SCE_CSS_SINGLESTRING));
                } else if (IsCssOperator(static_cast<char>(sc.ch))
+                       && (sc.state != SCE_CSS_ATTRIBUTE || sc.ch == ']')
                        && (sc.state != SCE_CSS_VALUE || sc.ch == ';' || sc.ch == '}' || sc.ch == '!')
                        && (sc.state != SCE_CSS_DIRECTIVE || sc.ch == ';' || sc.ch == '{')
                ) {
diff --git a/src/stc/scintilla/src/LexCaml.cxx b/src/stc/scintilla/src/LexCaml.cxx
new file mode 100644 (file)
index 0000000..5f4fad5
--- /dev/null
@@ -0,0 +1,399 @@
+// Scintilla source code edit control
+/** @file LexCaml.cxx
+ ** Lexer for Objective Caml.
+ **/
+// Copyright 2005 by Robert Roessler <robertr@rftp.com>
+// The License.txt file describes the conditions under which this software may be distributed.
+/*     Release History
+       20050204 Initial release.
+       20050205 Quick compiler standards/"cleanliness" adjustment.
+       20050206 Added cast for IsLeadByte().
+       20050209 Changes to "external" build support.
+       20050306 Fix for 1st-char-in-doc "corner" case.
+       20050502 Fix for [harmless] one-past-the-end coloring.
+       20050515 Refined numeric token recognition logic.
+       20051125 Added 2nd "optional" keywords class.
+       20051129 Support "magic" (read-only) comments for RCaml.
+       20051204 Swtich to using StyleContext infrastructure.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+//     Since the Microsoft __iscsym[f] funcs are not ANSI...
+inline int  iscaml(int c) {return isalnum(c) || c == '_';}
+inline int iscamlf(int c) {return isalpha(c) || c == '_';}
+inline int iscamld(int c) {return isdigit(c) || c == '_';}
+
+static const int baseT[24] = {
+       0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,     /* A - L */
+       0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0,16      /* M - X */
+};
+
+#ifdef BUILD_AS_EXTERNAL_LEXER
+/*
+       (actually seems to work!)
+*/
+#include "WindowAccessor.h"
+#include "ExternalLexer.h"
+
+#if PLAT_WIN
+#include <windows.h>
+#endif
+
+static void ColouriseCamlDoc(
+       unsigned int startPos, int length,
+       int initStyle,
+       WordList *keywordlists[],
+       Accessor &styler);
+
+static void FoldCamlDoc(
+       unsigned int startPos, int length,
+       int initStyle,
+       WordList *keywordlists[],
+       Accessor &styler);
+
+static void InternalLexOrFold(int lexOrFold, unsigned int startPos, int length,
+       int initStyle, char *words[], WindowID window, char *props);
+
+static const char* LexerName = "caml";
+
+#ifdef TRACE
+void Platform::DebugPrintf(const char *format, ...) {
+       char buffer[2000];
+       va_list pArguments;
+       va_start(pArguments, format);
+       vsprintf(buffer,format,pArguments);
+       va_end(pArguments);
+       Platform::DebugDisplay(buffer);
+}
+#else
+void Platform::DebugPrintf(const char *, ...) {
+}
+#endif
+
+bool Platform::IsDBCSLeadByte(int codePage, char ch) {
+       return ::IsDBCSLeadByteEx(codePage, ch) != 0;
+}
+
+long Platform::SendScintilla(WindowID w, unsigned int msg, unsigned long wParam, long lParam) {
+       return ::SendMessage(reinterpret_cast<HWND>(w), msg, wParam, lParam);
+}
+
+long Platform::SendScintillaPointer(WindowID w, unsigned int msg, unsigned long wParam, void *lParam) {
+       return ::SendMessage(reinterpret_cast<HWND>(w), msg, wParam,
+               reinterpret_cast<LPARAM>(lParam));
+}
+
+void EXT_LEXER_DECL Fold(unsigned int lexer, unsigned int startPos, int length,
+       int initStyle, char *words[], WindowID window, char *props)
+{
+       // below useless evaluation(s) to supress "not used" warnings
+       lexer;
+       // build expected data structures and do the Fold
+       InternalLexOrFold(1, startPos, length, initStyle, words, window, props);
+
+}
+
+int EXT_LEXER_DECL GetLexerCount()
+{
+       return 1;       // just us [Objective] Caml lexers here!
+}
+
+void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)
+{
+       // below useless evaluation(s) to supress "not used" warnings
+       Index;
+       // return as much of our lexer name as will fit (what's up with Index?)
+       if (buflength > 0) {
+               buflength--;
+               int n = strlen(LexerName);
+               if (n > buflength)
+                       n = buflength;
+               memcpy(name, LexerName, n), name[n] = '\0';
+       }
+}
+
+void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length,
+       int initStyle, char *words[], WindowID window, char *props)
+{
+       // below useless evaluation(s) to supress "not used" warnings
+       lexer;
+       // build expected data structures and do the Lex
+       InternalLexOrFold(0, startPos, length, initStyle, words, window, props);
+}
+
+static void InternalLexOrFold(int foldOrLex, unsigned int startPos, int length,
+       int initStyle, char *words[], WindowID window, char *props)
+{
+       // create and initialize a WindowAccessor (including contained PropSet)
+       PropSet ps;
+       ps.SetMultiple(props);
+       WindowAccessor wa(window, ps);
+       // create and initialize WordList(s)
+       int nWL = 0;
+       for (; words[nWL]; nWL++) ;     // count # of WordList PTRs needed
+       WordList** wl = new WordList* [nWL + 1];// alloc WordList PTRs
+       int i = 0;
+       for (; i < nWL; i++) {
+               wl[i] = new WordList(); // (works or THROWS bad_alloc EXCEPTION)
+               wl[i]->Set(words[i]);
+       }
+       wl[i] = 0;
+       // call our "internal" folder/lexer (... then do Flush!)
+       if (foldOrLex)
+               FoldCamlDoc(startPos, length, initStyle, wl, wa);
+       else
+               ColouriseCamlDoc(startPos, length, initStyle, wl, wa);
+       wa.Flush();
+       // clean up before leaving
+       for (i = nWL - 1; i >= 0; i--)
+               delete wl[i];
+       delete [] wl;
+}
+
+static
+#endif /* BUILD_AS_EXTERNAL_LEXER */
+
+void ColouriseCamlDoc(
+       unsigned int startPos, int length,
+       int initStyle,
+       WordList *keywordlists[],
+       Accessor &styler)
+{
+       // initialize styler
+       StyleContext sc(startPos, length, initStyle, styler);
+       // set up [initial] state info (terminating states that shouldn't "bleed")
+       int nesting = 0;
+       if (sc.state < SCE_CAML_STRING)
+               sc.state = SCE_CAML_DEFAULT;
+       if (sc.state >= SCE_CAML_COMMENT)
+               nesting = (sc.state & 0x0f) - SCE_CAML_COMMENT;
+
+       int chBase = 0, chToken = 0, chLit = 0;
+       WordList& keywords  = *keywordlists[0];
+       WordList& keywords2 = *keywordlists[1];
+       WordList& keywords3 = *keywordlists[2];
+       const int useMagic = styler.GetPropertyInt("lexer.caml.magic", 0);
+
+       // foreach char in range...
+       while (sc.More()) {
+               // set up [per-char] state info
+               int state2 = -1;                // (ASSUME no state change)
+               int chColor = sc.currentPos - 1;// (ASSUME standard coloring range)
+               bool advance = true;    // (ASSUME scanner "eats" 1 char)
+
+               // step state machine
+               switch (sc.state & 0x0f) {
+               case SCE_CAML_DEFAULT:
+                       chToken = sc.currentPos;        // save [possible] token start (JIC)
+                       // it's wide open; what do we have?
+                       if (iscamlf(sc.ch))
+                               state2 = SCE_CAML_IDENTIFIER;
+                       else if (sc.Match('`') && iscamlf(sc.chNext))
+                               state2 = SCE_CAML_TAGNAME;
+                       else if (sc.Match('#') && isdigit(sc.chNext))
+                               state2 = SCE_CAML_LINENUM;
+                       else if (isdigit(sc.ch)) {
+                               state2 = SCE_CAML_NUMBER, chBase = 10;
+                               if (sc.Match('0') && strchr("bBoOxX", sc.chNext))
+                                       chBase = baseT[tolower(sc.chNext) - 'a'], sc.Forward();
+                       } else if (sc.Match('\''))      /* (char literal?) */
+                               state2 = SCE_CAML_CHAR, chLit = 0;
+                       else if (sc.Match('\"'))
+                               state2 = SCE_CAML_STRING;
+                       else if (sc.Match('(', '*'))
+                               state2 = SCE_CAML_COMMENT,
+                                       sc.ch = ' ',    // (make SURE "(*)" isn't seen as a closed comment)
+                                       sc.Forward();
+                       else if (strchr("!?~"           /* Caml "prefix-symbol" */
+                                       "=<>@^|&+-*/$%"         /* Caml "infix-symbol" */
+                                       "()[]{};,:.#", sc.ch))  /* Caml "bracket" or ;,:.# */
+                               state2 = SCE_CAML_OPERATOR;
+                       break;
+
+               case SCE_CAML_IDENTIFIER:
+                       // [try to] interpret as [additional] identifier char
+                       if (!(iscaml(sc.ch) || sc.Match('\''))) {
+                               const int n = sc.currentPos - chToken;
+                               if (n < 24) {
+                                       // length is believable as keyword, [re-]construct token
+                                       char t[24];
+                                       for (int i = -n; i < 0; i++)
+                                               t[n + i] = static_cast<char>(sc.GetRelative(i));
+                                       t[n] = '\0';
+                                       // special-case "_" token as KEYWORD
+                                       if ((n == 1 && sc.chPrev == '_') || keywords.InList(t))
+                                               sc.ChangeState(SCE_CAML_KEYWORD);
+                                       else if (keywords2.InList(t))
+                                               sc.ChangeState(SCE_CAML_KEYWORD2);
+                                       else if (keywords3.InList(t))
+                                               sc.ChangeState(SCE_CAML_KEYWORD3);
+                               }
+                               state2 = SCE_CAML_DEFAULT, advance = false;
+                       }
+                       break;
+
+               case SCE_CAML_TAGNAME:
+                       // [try to] interpret as [additional] tagname char
+                       if (!(iscaml(sc.ch) || sc.Match('\'')))
+                               state2 = SCE_CAML_DEFAULT, advance = false;
+                       break;
+
+               /*case SCE_CAML_KEYWORD:
+               case SCE_CAML_KEYWORD2:
+               case SCE_CAML_KEYWORD3:
+                       // [try to] interpret as [additional] keyword char
+                       if (!iscaml(ch))
+                               state2 = SCE_CAML_DEFAULT, advance = false;
+                       break;*/
+
+               case SCE_CAML_LINENUM:
+                       // [try to] interpret as [additional] linenum directive char
+                       if (!isdigit(sc.ch))
+                               state2 = SCE_CAML_DEFAULT, advance = false;
+                       break;
+
+               case SCE_CAML_OPERATOR: {
+                       // [try to] interpret as [additional] operator char
+                       const char* o = 0;
+                       if (iscaml(sc.ch) || isspace(sc.ch)                /* ident or whitespace */
+                               || (o = strchr(")]};,\'\"`#", sc.ch),o)/* "termination" chars */
+                               || !strchr("!$%&*+-./:<=>?@^|~", sc.ch)/* "operator" chars */) {
+                               // check for INCLUSIVE termination
+                               if (o && strchr(")]};,", sc.ch)) {
+                                       if ((sc.Match(')') && sc.chPrev == '(')
+                                               || (sc.Match(']') && sc.chPrev == '['))
+                                               // special-case "()" and "[]" tokens as KEYWORDS
+                                               sc.ChangeState(SCE_CAML_KEYWORD);
+                                       chColor++;
+                               } else
+                                       advance = false;
+                               state2 = SCE_CAML_DEFAULT;
+                       }
+                       break;
+               }
+
+               case SCE_CAML_NUMBER:
+                       // [try to] interpret as [additional] numeric literal char
+                       // N.B. - improperly accepts "extra" digits in base 2 or 8 literals
+                       if (iscamld(sc.ch) || IsADigit(sc.ch, chBase))
+                               break;
+                       // how about an integer suffix?
+                       if ((sc.Match('l') || sc.Match('L') || sc.Match('n'))
+                               && (iscamld(sc.chPrev) || IsADigit(sc.chPrev, chBase)))
+                               break;
+                       // or a floating-point literal?
+                       if (chBase == 10) {
+                               // with a decimal point?
+                               if (sc.Match('.') && iscamld(sc.chPrev))
+                                       break;
+                               // with an exponent? (I)
+                               if ((sc.Match('e') || sc.Match('E'))
+                                       && (iscamld(sc.chPrev) || sc.chPrev == '.'))
+                                       break;
+                               // with an exponent? (II)
+                               if ((sc.Match('+') || sc.Match('-'))
+                                       && (sc.chPrev == 'e' || sc.chPrev == 'E'))
+                                       break;
+                       }
+                       // it looks like we have run out of number
+                       state2 = SCE_CAML_DEFAULT, advance = false;
+                       break;
+
+               case SCE_CAML_CHAR:
+                       // [try to] interpret as [additional] char literal char
+                       if (sc.Match('\\')) {
+                               chLit = 1;      // (definitely IS a char literal)
+                               if (sc.chPrev == '\\')
+                                       sc.ch = ' ';    // (so termination test isn't fooled)
+                       // should we be terminating - one way or another?
+                       } else if ((sc.Match('\'') && sc.chPrev != '\\') || sc.atLineEnd) {
+                               state2 = SCE_CAML_DEFAULT;
+                               if (sc.Match('\''))
+                                       chColor++;
+                               else
+                                       sc.ChangeState(SCE_CAML_IDENTIFIER);
+                       // ... maybe a char literal, maybe not
+                       } else if (chLit < 1 && sc.currentPos - chToken >= 2)
+                               sc.ChangeState(SCE_CAML_IDENTIFIER), advance = false;
+                       break;
+
+               case SCE_CAML_STRING:
+                       // [try to] interpret as [additional] string literal char
+                       if (sc.Match('\\') && sc.chPrev == '\\')
+                               sc.ch = ' ';    // (so '\\' doesn't cause us trouble)
+                       else if (sc.Match('\"') && sc.chPrev != '\\')
+                               state2 = SCE_CAML_DEFAULT, chColor++;
+                       break;
+
+               case SCE_CAML_COMMENT:
+               case SCE_CAML_COMMENT1:
+               case SCE_CAML_COMMENT2:
+               case SCE_CAML_COMMENT3:
+                       // we're IN a comment - does this start a NESTED comment?
+                       if (sc.Match('(', '*'))
+                               state2 = sc.state + 1, chToken = sc.currentPos,
+                                       sc.ch = ' ',    // (make SURE "(*)" isn't seen as a closed comment)
+                                       sc.Forward(), nesting++;
+                       // [try to] interpret as [additional] comment char
+                       else if (sc.Match(')') && sc.chPrev == '*') {
+                               if (nesting)
+                                       state2 = (sc.state & 0x0f) - 1, chToken = 0, nesting--;
+                               else
+                                       state2 = SCE_CAML_DEFAULT;
+                               chColor++;
+                       // enable "magic" (read-only) comment AS REQUIRED
+                       } else if (useMagic && sc.currentPos - chToken == 4
+                               && sc.Match('c') && sc.chPrev == 'r' && sc.GetRelative(-2) == '@')
+                               sc.state |= 0x10;       // (switch to read-only comment style)
+                       break;
+               }
+
+               // handle state change and char coloring as required
+               if (state2 >= 0)
+                       styler.ColourTo(chColor, sc.state), sc.ChangeState(state2);
+               // move to next char UNLESS re-scanning current char
+               if (advance)
+                       sc.Forward();
+       }
+
+       // do any required terminal char coloring (JIC)
+       sc.Complete();
+}
+
+#ifdef BUILD_AS_EXTERNAL_LEXER
+static
+#endif /* BUILD_AS_EXTERNAL_LEXER */
+void FoldCamlDoc(
+       unsigned int startPos, int length,
+       int initStyle,
+       WordList *keywordlists[],
+       Accessor &styler)
+{
+       // below useless evaluation(s) to supress "not used" warnings
+       startPos || length || initStyle || keywordlists[0] || styler.Length();
+}
+
+static const char * const camlWordListDesc[] = {
+       "Keywords",             // primary Objective Caml keywords
+       "Keywords2",    // "optional" keywords (typically from Pervasives)
+       "Keywords3",    // "optional" keywords (typically typenames)
+       0
+};
+
+#ifndef BUILD_AS_EXTERNAL_LEXER
+LexerModule lmCaml(SCLEX_CAML, ColouriseCamlDoc, "caml", FoldCamlDoc, camlWordListDesc);
+#endif /* BUILD_AS_EXTERNAL_LEXER */
diff --git a/src/stc/scintilla/src/LexCsound.cxx b/src/stc/scintilla/src/LexCsound.cxx
new file mode 100644 (file)
index 0000000..27f7b99
--- /dev/null
@@ -0,0 +1,207 @@
+// Scintilla source code edit control
+/** @file LexCsound.cxx
+ ** Lexer for Csound (Orchestra & Score)
+ ** Written by Georg Ritter - <ritterfuture A T gmail D O T com>
+ **/
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+
+static inline bool IsAWordChar(const int ch) {
+       return (ch < 0x80) && (isalnum(ch) || ch == '.' ||
+               ch == '_' || ch == '?');
+}
+
+static inline bool IsAWordStart(const int ch) {
+       return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.' ||
+               ch == '%' || ch == '@' || ch == '$' || ch == '?');
+}
+
+static inline bool IsCsoundOperator(char ch) {
+       if (isalnum(ch))
+               return false;
+       // '.' left out as it is used to make up numbers
+       if (ch == '*' || ch == '/' || ch == '-' || ch == '+' ||
+               ch == '(' || ch == ')' || ch == '=' || ch == '^' ||
+               ch == '[' || ch == ']' || ch == '<' || ch == '&' ||
+               ch == '>' || ch == ',' || ch == '|' || ch == '~' ||
+               ch == '%' || ch == ':')
+               return true;
+       return false;
+}
+
+static void ColouriseCsoundDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+                               Accessor &styler) {
+
+       WordList &opcode = *keywordlists[0];
+       WordList &headerStmt = *keywordlists[1];
+       WordList &otherKeyword = *keywordlists[2];
+
+       // Do not leak onto next line
+       if (initStyle == SCE_CSOUND_STRINGEOL)
+               initStyle = SCE_CSOUND_DEFAULT;
+
+       StyleContext sc(startPos, length, initStyle, styler);
+
+       for (; sc.More(); sc.Forward())
+       {
+               // Handle line continuation generically.
+               if (sc.ch == '\\') {
+                       if (sc.chNext == '\n' || sc.chNext == '\r') {
+                               sc.Forward();
+                               if (sc.ch == '\r' && sc.chNext == '\n') {
+                                       sc.Forward();
+                               }
+                               continue;
+                       }
+               }
+              
+               // Determine if the current state should terminate.
+               if (sc.state == SCE_CSOUND_OPERATOR) {
+                       if (!IsCsoundOperator(static_cast<char>(sc.ch))) {
+                           sc.SetState(SCE_CSOUND_DEFAULT);
+                       }
+               }else if (sc.state == SCE_CSOUND_NUMBER) {
+                       if (!IsAWordChar(sc.ch)) {
+                               sc.SetState(SCE_CSOUND_DEFAULT);
+                       }
+               } else if (sc.state == SCE_CSOUND_IDENTIFIER) {
+                       if (!IsAWordChar(sc.ch) ) {
+                               char s[100];
+                               sc.GetCurrent(s, sizeof(s));
+
+                               if (opcode.InList(s)) {
+                                       sc.ChangeState(SCE_CSOUND_OPCODE);
+                               } else if (headerStmt.InList(s)) {
+                                       sc.ChangeState(SCE_CSOUND_HEADERSTMT);
+                               } else if (otherKeyword.InList(s)) {
+                                       sc.ChangeState(SCE_CSOUND_USERKEYWORD);
+                               } else if (s[0] == 'p') {
+                                       sc.ChangeState(SCE_CSOUND_PARAM);
+                               } else if (s[0] == 'a') {
+                                       sc.ChangeState(SCE_CSOUND_ARATE_VAR);
+                               } else if (s[0] == 'k') {
+                                       sc.ChangeState(SCE_CSOUND_KRATE_VAR);
+                               } else if (s[0] == 'i') { // covers both i-rate variables and i-statements
+                                       sc.ChangeState(SCE_CSOUND_IRATE_VAR);
+                               } else if (s[0] == 'g') {
+                                       sc.ChangeState(SCE_CSOUND_GLOBAL_VAR);
+                               }
+                               sc.SetState(SCE_CSOUND_DEFAULT);
+                       }
+               }
+               else if (sc.state == SCE_CSOUND_COMMENT ) {
+                       if (sc.atLineEnd) {
+                               sc.SetState(SCE_CSOUND_DEFAULT);
+                       }
+               }
+               else if ((sc.state == SCE_CSOUND_ARATE_VAR) ||
+                       (sc.state == SCE_CSOUND_KRATE_VAR) ||
+               (sc.state == SCE_CSOUND_IRATE_VAR)) {
+                       if (!IsAWordChar(sc.ch)) {
+                               sc.SetState(SCE_CSOUND_DEFAULT);
+                       }
+               }
+               
+               // Determine if a new state should be entered.
+               if (sc.state == SCE_CSOUND_DEFAULT) {
+                       if (sc.ch == ';'){
+                               sc.SetState(SCE_CSOUND_COMMENT);
+                       } else if (isdigit(sc.ch) || (sc.ch == '.' && isdigit(sc.chNext))) {
+                               sc.SetState(SCE_CSOUND_NUMBER);
+                       } else if (IsAWordStart(sc.ch)) {
+                               sc.SetState(SCE_CSOUND_IDENTIFIER);
+                       } else if (IsCsoundOperator(static_cast<char>(sc.ch))) {
+                               sc.SetState(SCE_CSOUND_OPERATOR);
+                       } else if (sc.ch == 'p') {
+                               sc.SetState(SCE_CSOUND_PARAM);
+                       } else if (sc.ch == 'a') {
+                               sc.SetState(SCE_CSOUND_ARATE_VAR);
+                       } else if (sc.ch == 'k') {
+                               sc.SetState(SCE_CSOUND_KRATE_VAR);
+                       } else if (sc.ch == 'i') { // covers both i-rate variables and i-statements
+                               sc.SetState(SCE_CSOUND_IRATE_VAR);
+                       } else if (sc.ch == 'g') {
+                               sc.SetState(SCE_CSOUND_GLOBAL_VAR);
+                       }
+               }
+       }
+       sc.Complete();
+}
+
+static void FoldCsoundInstruments(unsigned int startPos, int length, int /* initStyle */, WordList *[], 
+               Accessor &styler) {
+       unsigned int lengthDoc = startPos + length;
+       int visibleChars = 0;
+       int lineCurrent = styler.GetLine(startPos);
+       int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int levelCurrent = levelPrev;
+       char chNext = styler[startPos];
+       int stylePrev = 0;
+       int styleNext = styler.StyleAt(startPos);
+       for (unsigned int i = startPos; i < lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               int style = styleNext;
+               styleNext = styler.StyleAt(i + 1);
+               bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+               if ((stylePrev != SCE_CSOUND_OPCODE) && (style == SCE_CSOUND_OPCODE)) {
+                       char s[20];
+                       unsigned int j = 0;
+                       while ((j < (sizeof(s) - 1)) && (iswordchar(styler[i + j]))) {
+                               s[j] = styler[i + j];
+                               j++;
+                       }
+                       s[j] = '\0';
+
+                       if (strcmp(s, "instr") == 0)
+                               levelCurrent++;
+                       if (strcmp(s, "endin") == 0)
+                               levelCurrent--;
+               }
+
+               if (atEOL) {
+                       int lev = levelPrev;
+                       if (visibleChars == 0)
+                               lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visibleChars > 0))
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+                       if (lev != styler.LevelAt(lineCurrent)) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+                       lineCurrent++;
+                       levelPrev = levelCurrent;
+                       visibleChars = 0;
+               }
+               if (!isspacechar(ch))
+                       visibleChars++;
+               stylePrev = style;
+       }
+       // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+       int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+       styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+}
+
+
+static const char * const csoundWordListDesc[] = {
+       "Opcodes",
+       "Header Statements",
+       "User keywords",
+       0
+};
+
+LexerModule lmCsound(SCLEX_CSOUND, ColouriseCsoundDoc, "csound", FoldCsoundInstruments, csoundWordListDesc);
index 974efd9a72e1d9a3a5071fb4315b2c92e296ee68..e9e154cd5f64b8eb8051aa11c7ccbf8ad08a0cda 100644 (file)
@@ -10,7 +10,6 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <fcntl.h>
 
 #include "Platform.h"
 
diff --git a/src/stc/scintilla/src/LexFlagship.cxx b/src/stc/scintilla/src/LexFlagship.cxx
new file mode 100644 (file)
index 0000000..db0314e
--- /dev/null
@@ -0,0 +1,226 @@
+// Scintilla source code edit control
+/** @file LexFlagShip.cxx
+ ** Lexer for FlagShip 
+ ** (Syntactically compatible to other XBase dialects, like dBase, Clipper, Fox etc.)
+ **/
+// Copyright 2005 by Randy Butler
+// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+static bool IsFlagShipComment(Accessor &styler, int pos, int len) {
+       return len>0 && styler[pos]=='\'';
+}
+
+static inline bool IsTypeCharacter(int ch) {
+       return ch == '%' || ch == '&' || ch == '@' || ch == '!' || ch == '#' || ch == '$';
+}
+
+// Extended to accept accented characters
+static inline bool IsAWordChar(int ch) {
+       return ch >= 0x80 ||
+              (isalnum(ch) || ch == '.' || ch == '_');
+}
+
+static inline bool IsAWordStart(int ch) {
+       return ch >= 0x80 ||
+              (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsADateCharacter(const int ch) {
+       return (ch < 0x80) &&
+               (isalnum(ch) || ch == '|' || ch == '-' || ch == '/' || ch == ':' || ch == ' ' || ch == '\t');
+}
+
+
+static void ColouriseFlagShipDoc(unsigned int startPos, int length, int initStyle,
+                           WordList *keywordlists[], Accessor &styler) {
+
+       //bool FSScriptSyntax = true;
+       WordList &keywords = *keywordlists[0];
+       WordList &keywords2 = *keywordlists[1];
+       WordList &keywords3 = *keywordlists[2];
+       WordList &keywords4 = *keywordlists[3];
+
+       styler.StartAt(startPos);
+
+       int visibleChars = 0;
+
+       StyleContext sc(startPos, length, initStyle, styler);
+
+       for (; sc.More(); sc.Forward()) {
+
+               if (sc.state == SCE_FS_OPERATOR) {
+                       sc.SetState(SCE_FS_DEFAULT);
+               } else if (sc.state == SCE_FS_IDENTIFIER) {
+                       if (!IsAWordChar(sc.ch)) {
+                               char s[100];
+                               sc.GetCurrentLowered(s, sizeof(s));
+                               if (keywords.InList(s)) {
+                                       sc.ChangeState(SCE_FS_KEYWORD);
+                               } else if (keywords2.InList(s)) {
+                                       sc.ChangeState(SCE_FS_KEYWORD2);
+                               } else if (keywords3.InList(s)) {
+                                       sc.ChangeState(SCE_FS_KEYWORD3);
+                               } else if (keywords4.InList(s)) {
+                                       sc.ChangeState(SCE_FS_KEYWORD4);
+                               }// Else, it is really an identifier...
+                               sc.SetState(SCE_FS_DEFAULT);
+                       }
+               } else if (sc.state == SCE_FS_NUMBER) {
+                       if (!IsAWordChar(sc.ch)) {
+                               sc.SetState(SCE_FS_DEFAULT);
+                       }
+               } else if (sc.state == SCE_FS_STRING) {
+                       // VB doubles quotes to preserve them, so just end this string
+                       // state now as a following quote will start again
+                       if (sc.ch == '\"') {
+                               if (tolower(sc.chNext) == 'c') {
+                                       sc.Forward();
+                               }
+                               sc.ForwardSetState(SCE_FS_DEFAULT);
+                       } else if (sc.atLineEnd) {
+                               sc.ChangeState(SCE_FS_STRINGEOL);
+                               sc.ForwardSetState(SCE_FS_DEFAULT);
+                       }
+               } else if (sc.state == SCE_FS_COMMENT) {
+                       if (sc.Match('*', '/')) {   // new code
+                               sc.Forward();
+                               sc.ForwardSetState(SCE_FS_DEFAULT);
+                       //if (sc.atLineEnd) {       // old code
+                       //      sc.SetState(SCE_FS_DEFAULT);
+                       }
+               } else if (sc.state == SCE_FS_COMMENTLINE) {  //new code
+                       if (sc.ch == '\r' || sc.ch == '\n') {
+                               sc.SetState(SCE_FS_DEFAULT);
+                               visibleChars = 0;
+                       }
+               } else if (sc.state == SCE_FS_PREPROCESSOR) {
+                       if (sc.atLineEnd) {
+                               sc.SetState(SCE_FS_DEFAULT);
+                       }
+               } else if (sc.state == SCE_FS_DATE) {
+                       if (sc.ch == '#' || !IsADateCharacter(sc.chNext)) {
+                               sc.ForwardSetState(SCE_FS_DEFAULT);
+                       }
+               }
+
+               // Determine if a new state should be entered.
+               if (sc.state == SCE_FS_DEFAULT) {
+                       if (sc.Match('/', '*')) {  // New code
+                               sc.SetState(SCE_FS_COMMENT);
+                               sc.Forward();   // Eat the * so it isn't used for the end of the comment
+                       //if (sc.ch == '\'') {  // Old code
+                       //      sc.SetState(SCE_FS_COMMENT); // old code
+                       } else if (sc.Match('/', '/')) { // New code
+                               sc.SetState(SCE_FS_COMMENTLINE);
+                       } else if (sc.ch == '\"') {
+                               sc.SetState(SCE_FS_STRING);
+                       } else if (sc.ch == '#' && visibleChars == 0) {
+                               // Preprocessor commands are alone on their line
+                               sc.SetState(SCE_FS_PREPROCESSOR);
+                       } else if (sc.ch == '#') {
+                               int n = 1;
+                               int chSeek = ' ';
+                               while ((n < 100) && (chSeek == ' ' || chSeek == '\t')) {
+                                       chSeek = sc.GetRelative(n);
+                                       n++;
+                               }
+                               if (IsADigit(chSeek)) {
+                                       sc.SetState(SCE_FS_DATE);
+                               } else {
+                                       sc.SetState(SCE_FS_OPERATOR);
+                               }
+                       } else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {
+                               sc.SetState(SCE_FS_NUMBER);
+                       } else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {
+                               sc.SetState(SCE_FS_NUMBER);
+                       } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+                               sc.SetState(SCE_FS_NUMBER);
+                       } else if (IsAWordStart(sc.ch) || (sc.ch == '[')) {
+                               sc.SetState(SCE_FS_IDENTIFIER);
+                       } else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {
+                               sc.SetState(SCE_FS_OPERATOR);
+                       }
+               }
+
+               if (sc.atLineEnd) {
+                       visibleChars = 0;
+               }
+               if (!IsASpace(sc.ch)) {
+                       visibleChars++;
+               }
+       }
+       sc.Complete();
+}
+
+static void FoldFlagShipDoc(unsigned int startPos, int length, int,
+                                                  WordList *[], Accessor &styler) {
+
+       int endPos = startPos + length;
+
+       // Backtrack to previous line in case need to fix its fold status
+       int lineCurrent = styler.GetLine(startPos);
+       if (startPos > 0) {
+               if (lineCurrent > 0) {
+                       lineCurrent--;
+                       startPos = styler.LineStart(lineCurrent);
+               }
+       }
+       int spaceFlags = 0;
+       int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsFlagShipComment);
+       char chNext = styler[startPos];
+       for (int i = startPos; i < endPos; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+
+               if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == endPos)) {
+                       int lev = indentCurrent;
+                       int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsFlagShipComment);
+                       if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
+                               // Only non whitespace lines can be headers
+                               if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
+                                       lev |= SC_FOLDLEVELHEADERFLAG;
+                               } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
+                                       // Line after is blank so check the next - maybe should continue further?
+                                       int spaceFlags2 = 0;
+                                       int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsFlagShipComment);
+                                       if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
+                                               lev |= SC_FOLDLEVELHEADERFLAG;
+                                       }
+                               }
+                       }
+                       indentCurrent = indentNext;
+                       styler.SetLevel(lineCurrent, lev);
+                       lineCurrent++;
+               }
+       }
+}
+
+
+static const char * const FSWordListDesc[] = {
+       "Keywords",
+       "functions",
+       "user2",
+       "user3",
+       0
+};
+
+LexerModule lmFlagShip(SCLEX_FLAGSHIP, ColouriseFlagShipDoc, "flagship", FoldFlagShipDoc, FSWordListDesc);
+
+
+
index 0cc7342e69134535e4d329e3e4cd5449d77de823..3ab1116ea6ed2a889830452e32615f27cfc5f9f7 100644 (file)
@@ -273,9 +273,11 @@ static void FoldFortranDoc(unsigned int startPos, int length, int initStyle,
        int style = initStyle;
        /***************************************/
        int lastStart = 0;
-       char prevWord[32] = "", Label[6] = "";
+       char prevWord[32] = "";
+       char Label[6] = "";
        // Variables for do label folding.
-       static int doLabels[100], posLabel=-1;
+       static int doLabels[100];
+       static int posLabel=-1;
        /***************************************/
        for (unsigned int i = startPos; i < endPos; i++) {
                char ch = chNext;
index 2e3c02c1c927cd461ca1a599751f5b38fa234880..f76fff6cc4b86e5d665a1b12445d065e27723612 100644 (file)
@@ -236,7 +236,7 @@ ColouriseGui4CliDoc(unsigned int startPos, int length, int initStyle,
                if (!noforward) sc.Forward();
 
        }
-       styler.ColourTo(sc.currentPos, sc.state);
+       sc.Complete();
 }
 
 // Main folding function called by Scintilla - (based on props (.ini) files function)
index e3546b436fdb6b1674a29fef85e44e92a3cedd71..d830a46439e822b5a0704ccbd29d27152a618b81 100644 (file)
@@ -2,7 +2,7 @@
 /** @file LexHTML.cxx
  ** Lexer for HTML.
  **/
-// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
@@ -35,13 +35,24 @@ static inline bool IsAWordStart(const int ch) {
        return (ch < 0x80) && (isalnum(ch) || ch == '_');
 }
 
-static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) {
-       char s[30 + 1];
-       unsigned int i = 0;
-       for (; i < end - start + 1 && i < 30; i++) {
-               s[i] = static_cast<char>(tolower(styler[start + i]));
+static inline int MakeLowerCase(int ch) {
+       if (ch < 'A' || ch > 'Z')
+               return ch;
+       else
+               return ch - 'A' + 'a';
+}
+
+static void GetTextSegment(Accessor &styler, unsigned int start, unsigned int end, char *s, size_t len) {
+       size_t i = 0;
+       for (; (i < end - start + 1) && (i < len-1); i++) {
+               s[i] = static_cast<char>(MakeLowerCase(styler[start + i]));
        }
        s[i] = '\0';
+}
+
+static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start, unsigned int end, script_type prevValue) {
+       char s[100];
+       GetTextSegment(styler, start, end, s, sizeof(s));
        //Platform::DebugPrintf("Scripting indicator [%s]\n", s);
        if (strstr(s, "src"))   // External script
                return eScriptNone;
@@ -63,12 +74,8 @@ static script_type segIsScriptingIndicator(Accessor &styler, unsigned int start,
 
 static int PrintScriptingIndicatorOffset(Accessor &styler, unsigned int start, unsigned int end) {
        int iResult = 0;
-       char s[30 + 1];
-       unsigned int i = 0;
-       for (; i < end - start + 1 && i < 30; i++) {
-               s[i] = static_cast<char>(tolower(styler[start + i]));
-       }
-       s[i] = '\0';
+       char s[100];
+       GetTextSegment(styler, start, end, s, sizeof(s));
        if (0 == strncmp(s, "php", 3)) {
                iResult = 3;
        }
@@ -183,12 +190,8 @@ static void classifyAttribHTML(unsigned int start, unsigned int end, WordList &k
        if (wordIsNumber) {
                chAttr = SCE_H_NUMBER;
        } else {
-               char s[30 + 1];
-               unsigned int i = 0;
-               for (; i < end - start + 1 && i < 30; i++) {
-                       s[i] = static_cast<char>(tolower(styler[start + i]));
-               }
-               s[i] = '\0';
+               char s[100];
+               GetTextSegment(styler, start, end, s, sizeof(s));
                if (keywords.InList(s))
                        chAttr = SCE_H_ATTRIBUTE;
        }
@@ -207,7 +210,7 @@ static int classifyTagHTML(unsigned int start, unsigned int end,
        for (unsigned int cPos = start; cPos <= end && i < 30; cPos++) {
                char ch = styler[cPos];
                if ((ch != '<') && (ch != '/')) {
-                       s[i++] = caseSensitive ? ch : static_cast<char>(tolower(ch));
+                       s[i++] = caseSensitive ? ch : static_cast<char>(MakeLowerCase(ch));
                }
        }
 
@@ -270,12 +273,8 @@ static int classifyWordHTVB(unsigned int start, unsigned int end, WordList &keyw
        if (wordIsNumber)
                chAttr = SCE_HB_NUMBER;
        else {
-               char s[30 + 1];
-               unsigned int i = 0;
-               for (; i < end - start + 1 && i < 30; i++) {
-                       s[i] = static_cast<char>(tolower(styler[start + i]));
-               }
-               s[i] = '\0';
+               char s[100];
+               GetTextSegment(styler, start, end, s, sizeof(s));
                if (keywords.InList(s)) {
                        chAttr = SCE_HB_WORD;
                        if (strcmp(s, "rem") == 0)
@@ -318,12 +317,8 @@ static void classifyWordHTPHP(unsigned int start, unsigned int end, WordList &ke
        if (wordIsNumber)
                chAttr = SCE_HPHP_NUMBER;
        else {
-               char s[100 + 1];
-               unsigned int i = 0;
-               for (; i < end - start + 1 && i < 100; i++) {
-                       s[i] = static_cast<char>(tolower(styler[start + i]));
-               }
-               s[i] = '\0';
+               char s[100];
+               GetTextSegment(styler, start, end, s, sizeof(s));
                if (keywords.InList(s))
                        chAttr = SCE_HPHP_WORD;
        }
@@ -406,6 +401,11 @@ static bool IsCommentState(const int state) {
        return state == SCE_H_COMMENT || state == SCE_H_SGML_COMMENT;
 }
 
+static bool IsScriptCommentState(const int state) {
+       return state == SCE_HJ_COMMENT || state == SCE_HJ_COMMENTLINE || state == SCE_HJA_COMMENT ||
+                  state == SCE_HJA_COMMENTLINE || state == SCE_HB_COMMENTLINE || state == SCE_HBA_COMMENTLINE;
+}
+
 static bool isLineEnd(char ch) {
        return ch == '\r' || ch == '\n';
 }
@@ -424,6 +424,8 @@ static bool isPHPStringState(int state) {
 
 static int FindPhpStringDelimiter(char *phpStringDelimiter, const int phpStringDelimiterSize, int i, const int lengthDoc, Accessor &styler) {
        int j;
+       while (i < lengthDoc && (styler[i] == ' ' || styler[i] == '\t'))
+               i++;
        phpStringDelimiter[0] = '\n';
        for (j = i; j < lengthDoc && styler[j] != '\n' && styler[j] != '\r'; j++) {
                if (j - i < phpStringDelimiterSize - 2)
@@ -501,12 +503,28 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
        char chPrev = ' ';
        char ch = ' ';
        char chPrevNonWhite = ' ';
+       // look back to set chPrevNonWhite properly for better regex colouring
+       if (scriptLanguage == eScriptJS && startPos > 0) {
+               int back = startPos;
+               int style = 0;
+               while (--back) {
+                       style = styler.StyleAt(back);
+                       if (style < SCE_HJ_DEFAULT || style > SCE_HJ_COMMENTDOC)
+                               // includes SCE_HJ_COMMENT & SCE_HJ_COMMENTLINE
+                               break;
+               }
+               if (style == SCE_HJ_SYMBOLS) {
+                       chPrevNonWhite = styler.SafeGetCharAt(back);
+               }
+       }
+
        styler.StartSegment(startPos);
        const int lengthDoc = startPos + length;
        for (int i = startPos; i < lengthDoc; i++) {
                const char chPrev2 = chPrev;
                chPrev = ch;
-               if (ch != ' ' && ch != '\t')
+               if (!isspacechar(ch) && state != SCE_HJ_COMMENT &&
+                       state != SCE_HJ_COMMENTLINE && state != SCE_HJ_COMMENTDOC)
                        chPrevNonWhite = ch;
                ch = styler[i];
                char chNext = styler.SafeGetCharAt(i + 1);
@@ -605,9 +623,8 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                        case SCE_H_SINGLESTRING:
                        case SCE_HJ_COMMENT:
                        case SCE_HJ_COMMENTDOC:
-                               // SCE_HJ_COMMENTLINE removed as this is a common thing done to hide
-                               // the end of script marker from some JS interpreters.
-                               //case SCE_HJ_COMMENTLINE:
+                       //case SCE_HJ_COMMENTLINE: // removed as this is a common thing done to hide
+                       // the end of script marker from some JS interpreters.
                        case SCE_HJ_DOUBLESTRING:
                        case SCE_HJ_SINGLESTRING:
                        case SCE_HJ_REGEX:
@@ -617,6 +634,19 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                        case SCE_HP_TRIPLEDOUBLE:
                                break;
                        default :
+                               // check if the closing tag is a script tag
+                               if (state == SCE_HJ_COMMENTLINE) {
+                                       char tag[7]; // room for the <script> tag
+                                       char chr;       // current char
+                                       int j=0;
+                                       chr = styler.SafeGetCharAt(i+2);
+                                       while (j < 6 && !isspacechar(chr)) {
+                                               tag[j++] = static_cast<char>(MakeLowerCase(chr));
+                                               chr = styler.SafeGetCharAt(i+2+j);
+                                       }
+                                       tag[j] = '\0';
+                                       if (strcmp(tag, "script") != 0) break;
+                               }
                                // closing tag of the script (it's a closing HTML tag anyway)
                                styler.ColourTo(i - 1, StateToPrint);
                                state = SCE_H_TAGUNKNOWN;
@@ -636,7 +666,8 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                         !isPHPStringState(state) &&
                         (state != SCE_HPHP_COMMENT) &&
                         (ch == '<') &&
-                        (chNext == '?')) {
+                        (chNext == '?') &&
+                                !IsScriptCommentState(state) ) {
                        scriptLanguage = segIsScriptingIndicator(styler, styler.GetStartSegment() + 2, i + 10, eScriptPHP);
                        if (scriptLanguage != eScriptPHP && isStringState(state)) continue;
                        styler.ColourTo(i - 1, StateToPrint);
@@ -653,11 +684,9 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                                inScriptType = eNonHtmlScriptPreProc;
                        else
                                inScriptType = eNonHtmlPreProc;
-                       // fold whole script
-                       if (foldHTMLPreprocessor){
+                       // Fold whole script, but not if the XML first tag (all XML-like tags in this case)
+                       if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
                                levelCurrent++;
-                               if (scriptLanguage == eScriptXML)
-                                       levelCurrent--; // no folding of the XML first tag (all XML-like tags in this case)
                        }
                        // should be better
                        ch = styler.SafeGetCharAt(i);
@@ -665,7 +694,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                }
 
                // handle the start of ASP pre-processor = Non-HTML
-               else if (!isCommentASPState(state) && (ch == '<') && (chNext == '%')) {
+               else if (!isCommentASPState(state) && (ch == '<') && (chNext == '%') && !isPHPStringState(state)) {
                        styler.ColourTo(i - 1, StateToPrint);
                        beforePreProc = state;
                        if (inScriptType == eNonHtmlScript)
@@ -706,15 +735,18 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                /////////////////////////////////////
                // handle the start of SGML language (DTD)
                else if (((scriptLanguage == eScriptNone) || (scriptLanguage == eScriptXML)) &&
-                        (chPrev == '<') &&
-                        (ch == '!') &&
-                        (StateToPrint != SCE_H_CDATA) && (!IsCommentState(StateToPrint))) {
+                                (chPrev == '<') &&
+                                (ch == '!') &&
+                                (StateToPrint != SCE_H_CDATA) &&
+                                (!IsCommentState(StateToPrint)) &&
+                                (!IsScriptCommentState(StateToPrint)) ) {
                        beforePreProc = state;
                        styler.ColourTo(i - 2, StateToPrint);
                        if ((chNext == '-') && (chNext2 == '-')) {
                                state = SCE_H_COMMENT; // wait for a pending command
-                       }
-                       else if (isWordCdata(i + 1, i + 7, styler)) {
+                               styler.ColourTo(i + 2, SCE_H_COMMENT);
+                               i += 2; // follow styling after the --
+                       } else if (isWordCdata(i + 1, i + 7, styler)) {
                                state = SCE_H_CDATA;
                        } else {
                                styler.ColourTo(i, SCE_H_SGML_DEFAULT); // <! is default
@@ -733,7 +765,7 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                              || (inScriptType == eNonHtmlScriptPreProc)) && (
                                 ((scriptLanguage == eScriptPHP) && (ch == '?') && !isPHPStringState(state) && (state != SCE_HPHP_COMMENT)) ||
                                 ((scriptLanguage != eScriptNone) && !isStringState(state) &&
-                                 (ch == '%'))
+                                 ((ch == '%') || (ch == '?')))
                             ) && (chNext == '>')) ||
                         ((scriptLanguage == eScriptSGML) && (ch == '>') && (state != SCE_H_SGML_COMMENT))) {
                        if (state == SCE_H_ASPAT) {
@@ -778,10 +810,11 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                                inScriptType = eNonHtmlScript;
                        else
                                inScriptType = eHtml;
-                       scriptLanguage = eScriptNone;
-                       // unfold all scripting languages
-                       if (foldHTMLPreprocessor)
+                       // Unfold all scripting languages, except for XML tag
+                       if (foldHTMLPreprocessor && (scriptLanguage != eScriptXML)) {
                                levelCurrent--;
+                       }
+                       scriptLanguage = eScriptNone;
                        continue;
                }
                /////////////////////////////////////
@@ -1219,12 +1252,14 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                        if (ch == '/' && chPrev == '*') {
                                styler.ColourTo(i, StateToPrint);
                                state = SCE_HJ_DEFAULT;
+                               ch = ' ';
                        }
                        break;
                case SCE_HJ_COMMENTLINE:
                        if (ch == '\r' || ch == '\n') {
                                styler.ColourTo(i - 1, statePrintForState(SCE_HJ_COMMENTLINE, inScriptType));
                                state = SCE_HJ_DEFAULT;
+                               ch = ' ';
                        }
                        break;
                case SCE_HJ_DOUBLESTRING:
@@ -1272,6 +1307,13 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                        break;
                case SCE_HJ_REGEX:
                        if (ch == '\r' || ch == '\n' || ch == '/') {
+                               if (ch == '/') {
+                                       while (isascii(chNext) && islower(chNext)) {   // gobble regex flags
+                                               i++;
+                                               ch = chNext;
+                                               chNext = styler.SafeGetCharAt(i + 1);
+                                       }
+                               }
                                styler.ColourTo(i, StateToPrint);
                                state = SCE_HJ_DEFAULT;
                        } else if (ch == '\\') {
@@ -1496,7 +1538,10 @@ static void ColouriseHyperTextDoc(unsigned int startPos, int length, int initSty
                        }
                        break;
                case SCE_HPHP_NUMBER:
-                       if (!IsADigit(ch) && ch != '.' && ch != 'e' && ch != 'E' && (ch != '-' || (chPrev != 'e' && chPrev != 'E'))) {
+                       // recognize bases 8,10 or 16 integers OR floating-point numbers
+                       if (!IsADigit(ch)
+                               && strchr(".xXabcdefABCDEF", ch) == NULL
+                               && ((ch != '-' && ch != '+') || (chPrev != 'e' && chPrev != 'E'))) {
                                styler.ColourTo(i - 1, SCE_HPHP_NUMBER);
                                if (isoperator(ch))
                                        state = SCE_HPHP_OPERATOR;
@@ -1946,6 +1991,12 @@ static void ColourisePHPDoc(unsigned int startPos, int length, int initStyle, Wo
        sc.Complete();
 }
 
+static void ColourisePHPScriptDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+                                               Accessor &styler) {
+       if(startPos == 0) initStyle = SCE_HPHP_DEFAULT;
+               ColouriseHyperTextDoc(startPos,length,initStyle,keywordlists,styler);
+}
+
 static const char * const htmlWordListDesc[] = {
        "HTML elements and attributes",
        "JavaScript keywords",
@@ -1956,7 +2007,19 @@ static const char * const htmlWordListDesc[] = {
        0,
 };
 
-LexerModule lmHTML(SCLEX_HTML, ColouriseHyperTextDoc, "hypertext", 0, htmlWordListDesc);
-LexerModule lmXML(SCLEX_XML, ColouriseHyperTextDoc, "xml", 0, htmlWordListDesc);
-LexerModule lmASP(SCLEX_ASP, ColouriseASPDoc, "asp", 0, htmlWordListDesc);
-LexerModule lmPHP(SCLEX_PHP, ColourisePHPDoc, "php", 0, htmlWordListDesc);
+static const char * const phpscriptWordListDesc[] = {
+       "", //Unused
+       "", //Unused
+       "", //Unused
+       "", //Unused
+       "PHP keywords",
+       "", //Unused
+       0,
+};
+
+LexerModule lmHTML(SCLEX_HTML, ColouriseHyperTextDoc, "hypertext", 0, htmlWordListDesc, 7);
+LexerModule lmXML(SCLEX_XML, ColouriseHyperTextDoc, "xml", 0, htmlWordListDesc, 7);
+// SCLEX_ASP and SCLEX_PHP should not be used in new code: use SCLEX_HTML instead.
+LexerModule lmASP(SCLEX_ASP, ColouriseASPDoc, "asp", 0, htmlWordListDesc, 7);
+LexerModule lmPHP(SCLEX_PHP, ColourisePHPDoc, "php", 0, htmlWordListDesc, 7);
+LexerModule lmPHPSCRIPT(SCLEX_PHPSCRIPT, ColourisePHPScriptDoc, "phpscript", 0, phpscriptWordListDesc, 7);
diff --git a/src/stc/scintilla/src/LexHaskell.cxx b/src/stc/scintilla/src/LexHaskell.cxx
new file mode 100644 (file)
index 0000000..0e4be85
--- /dev/null
@@ -0,0 +1,263 @@
+/******************************************************************
+ *    LexHaskell.cxx
+ *
+ *    A haskell lexer for the scintilla code control.
+ *    Some stuff "lended" from LexPython.cxx and LexCPP.cxx.
+ *    External lexer stuff inspired from the caml external lexer.
+ *
+ *    Written by Tobias Engvall - tumm at dtek dot chalmers dot se
+ *
+ *
+ *    TODO:
+ *    * Implement a folder :)
+ *    * Nice Character-lexing (stuff inside '\''), LexPython has
+ *      this.
+ *
+ *
+ *****************************************************************/
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+#ifdef BUILD_AS_EXTERNAL_LEXER
+
+#include "ExternalLexer.h"
+#include "WindowAccessor.h"
+
+#define BUILD_EXTERNAL_LEXER 0
+
+#endif
+
+// Max level of nested comments
+#define SCE_HA_COMMENTMAX SCE_HA_COMMENTBLOCK3
+
+
+enum kwType { kwOther, kwClass, kwData, kwInstance, kwImport, kwModule, kwType};
+
+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 (ch < 0x80) && (isalnum(ch) || ch == '_');
+}
+
+static inline bool IsAWordChar(const int ch) {
+   return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_' || ch == '\'');
+}
+
+static void ColorizeHaskellDoc(unsigned int startPos, int length, int initStyle,
+                               WordList *keywordlists[], Accessor &styler) {
+
+   WordList &keywords = *keywordlists[0];
+
+   int kwLast = kwOther;
+
+   StyleContext sc(startPos, length, initStyle, styler);
+
+   for (; sc.More(); sc.Forward()) {
+
+      // Check for state end
+         // Operator
+      if (sc.state == SCE_HA_OPERATOR) {
+         kwLast = kwOther;
+         sc.SetState(SCE_HA_DEFAULT);
+      }
+         // String
+      else if (sc.state == SCE_HA_STRING) {
+         if (sc.ch == '\"') {
+            sc.ForwardSetState(SCE_HA_DEFAULT);
+         }
+      }
+         // Char
+      else if (sc.state == SCE_HA_CHARACTER) {
+         if (sc.ch == '\'') {
+            sc.ForwardSetState(SCE_HA_DEFAULT);
+         }
+      }
+         // Number
+      else if (sc.state == SCE_HA_NUMBER) {
+         if (!IsADigit(sc.ch)) {
+            sc.SetState(SCE_HA_DEFAULT);
+         }
+      }
+         // Types, constructors, etc.
+      else if (sc.state == SCE_HA_CAPITAL) {
+         if (!IsAWordChar(sc.ch) || sc.ch == '.') {
+            sc.SetState(SCE_HA_DEFAULT);
+         }
+      }
+         // Identifier
+      else if (sc.state == SCE_HA_IDENTIFIER) {
+         if (!IsAWordChar(sc.ch)) {
+            char s[100];
+            sc.GetCurrent(s, sizeof(s));
+            int style = SCE_HA_IDENTIFIER;
+            if ((kwLast == kwImport) || (strcmp(s,"qualified") == 0) || (strcmp(s,"as") == 0)) {
+               style = SCE_HA_IMPORT;
+            } else if (keywords.InList(s)) {
+               style = SCE_HA_KEYWORD;
+            } else if (kwLast == kwData) {
+               style = SCE_HA_DATA;
+            } else if (kwLast == kwClass) {
+               style = SCE_HA_CLASS;
+            } else if (kwLast == kwModule) {
+               style = SCE_HA_MODULE;
+            } else if (isupper(s[0])) {
+               style = SCE_HA_CAPITAL;
+            }
+            sc.ChangeState(style);
+            sc.SetState(SCE_HA_DEFAULT);
+            if (style == SCE_HA_KEYWORD) {
+               if (0 == strcmp(s, "class"))
+                  kwLast = kwClass;
+               else if (0 == strcmp(s, "data"))
+                  kwLast = kwData;
+               else if (0 == strcmp(s, "instance"))
+                  kwLast = kwInstance;
+               else if (0 == strcmp(s, "import"))
+                  kwLast = kwImport;
+               else if (0 == strcmp(s, "module"))
+                  kwLast = kwModule;
+               else
+                  kwLast = kwOther;
+            } else if (style == SCE_HA_CLASS || style == SCE_HA_IMPORT ||
+                       style == SCE_HA_MODULE || style == SCE_HA_CAPITAL ||
+                       style == SCE_HA_DATA || style == SCE_HA_INSTANCE) {
+               kwLast = kwOther;
+            }
+         }
+      }
+         // Comments
+            // Oneliner
+      else if (sc.state == SCE_HA_COMMENTLINE) {
+         if (IsNewline(sc.ch))
+            sc.SetState(SCE_HA_DEFAULT);
+      }
+            // Nested
+      else if (sc.state >= SCE_HA_COMMENTBLOCK) {
+         if (sc.Match("{-")) {
+            if (sc.state < SCE_HA_COMMENTMAX)
+               sc.SetState(sc.state + 1);
+         }
+         else if (sc.Match("-}")) {
+            sc.Forward();
+            if (sc.state == SCE_HA_COMMENTBLOCK)
+               sc.ForwardSetState(SCE_HA_DEFAULT);
+            else
+               sc.ForwardSetState(sc.state - 1);
+         }
+      }
+      // New state?
+      if (sc.state == SCE_HA_DEFAULT) {
+         // Digit
+         if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+            sc.SetState(SCE_HA_NUMBER);
+         }
+         // Comment line
+         else if (sc.Match("--")) {
+            sc.SetState(SCE_HA_COMMENTLINE);
+         // Comment block
+         }
+         else if (sc.Match("{-")) {
+            sc.SetState(SCE_HA_COMMENTBLOCK);
+         }
+         // String
+         else if (sc.Match('\"')) {
+            sc.SetState(SCE_HA_STRING);
+         }
+         // Character
+         else if (sc.Match('\'') && IsWhitespace(sc.GetRelative(-1)) ) {
+            sc.SetState(SCE_HA_CHARACTER);
+         }
+         // Stringstart
+         else if (sc.Match('\"')) {
+            sc.SetState(SCE_HA_STRING);
+         }
+         // Operator
+         else if (isascii(sc.ch) && isoperator(static_cast<char>(sc.ch))) {
+            sc.SetState(SCE_HA_OPERATOR);
+         }
+         // Keyword
+         else if (IsAWordStart(sc.ch)) {
+               sc.SetState(SCE_HA_IDENTIFIER);
+         }
+
+      }
+   }
+   sc.Complete();
+}
+
+// External stuff - used for dynamic-loading, not implemented in wxStyledTextCtrl yet.
+// Inspired by the caml external lexer - Credits to Robert Roessler - http://www.rftp.com
+#ifdef BUILD_EXTERNAL_LEXER
+static const char* LexerName = "haskell";
+
+void EXT_LEXER_DECL Lex(unsigned int lexer, unsigned int startPos, int length, int initStyle,
+                        char *words[], WindowID window, char *props)
+{
+   PropSet ps;
+   ps.SetMultiple(props);
+   WindowAccessor wa(window, ps);
+
+   int nWL = 0;
+   for (; words[nWL]; nWL++) ;
+   WordList** wl = new WordList* [nWL + 1];
+   int i = 0;
+   for (; i<nWL; i++)
+   {
+      wl[i] = new WordList();
+      wl[i]->Set(words[i]);
+   }
+   wl[i] = 0;
+
+   ColorizeHaskellDoc(startPos, length, initStyle, wl, wa);
+   wa.Flush();
+   for (i=nWL-1;i>=0;i--)
+      delete wl[i];
+   delete [] wl;
+}
+
+void EXT_LEXER_DECL Fold (unsigned int lexer, unsigned int startPos, int length, int initStyle,
+                        char *words[], WindowID window, char *props)
+{
+
+}
+
+int EXT_LEXER_DECL GetLexerCount()
+{
+   return 1;
+}
+
+void EXT_LEXER_DECL GetLexerName(unsigned int Index, char *name, int buflength)
+{
+   if (buflength > 0) {
+      buflength--;
+      int n = strlen(LexerName);
+      if (n > buflength)
+         n = buflength;
+      memcpy(name, LexerName, n), name[n] = '\0';
+   }
+}
+#endif
+
+LexerModule lmHaskell(SCLEX_HASKELL, ColorizeHaskellDoc, "haskell");
+
index 549b573e2ed3275a31d97e9a5d1dfdbdadd7d01a..91385f0fd4914efc1347e9039f1d35f5dcd4d7f6 100644 (file)
 #include "KeyWords.h"
 #include "Scintilla.h"
 #include "SciLexer.h"
+#include "StyleContext.h"
 
+#define SCE_LISP_CHARACTER 29
+#define SCE_LISP_MACRO 30
+#define SCE_LISP_MACRO_DISPATCH 31
 
 static inline bool isLispoperator(char ch) {
        if (isascii(ch) && isalnum(ch))
                return false;
-       if (ch == '\'' || ch == '(' || ch == ')' )
+       if (ch == '\'' || ch == '`' || ch == '(' || ch == ')' )
                return true;
        return false;
 }
@@ -35,7 +39,7 @@ static inline bool isLispwordstart(char ch) {
 }
 
 
-static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
+static void classifyWordLisp(unsigned int start, unsigned int end, WordList &keywords, WordList &keywords_kw, Accessor &styler) {
        PLATFORM_ASSERT(end >= start);
        char s[100];
        unsigned int i;
@@ -51,6 +55,11 @@ static void classifyWordLisp(unsigned int start, unsigned int end, WordList &key
        else {
                if (keywords.InList(s)) {
                        chAttr = SCE_LISP_KEYWORD;
+               } else if (keywords_kw.InList(s)) {
+                       chAttr = SCE_LISP_KEYWORD_KW;
+               } else if ((s[0] == '*' && s[i-1] == '*') ||
+                          (s[0] == '+' && s[i-1] == '+')) {
+                       chAttr = SCE_LISP_SPECIAL;
                }
        }
        styler.ColourTo(end, chAttr);
@@ -62,10 +71,11 @@ static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, W
                             Accessor &styler) {
 
        WordList &keywords = *keywordlists[0];
+       WordList &keywords_kw = *keywordlists[1];
 
        styler.StartAt(startPos);
 
-       int state = initStyle;
+       int state = initStyle, radix = -1;
        char chNext = styler[startPos];
        unsigned int lengthDoc = startPos + length;
        styler.StartSegment(startPos);
@@ -82,7 +92,11 @@ static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, W
                }
 
                if (state == SCE_LISP_DEFAULT) {
-                       if (isLispwordstart(ch)) {
+                       if (ch == '#') {
+                               styler.ColourTo(i - 1, state);
+                               radix = -1;
+                               state = SCE_LISP_MACRO_DISPATCH;
+                       } else if (isLispwordstart(ch)) {
                                styler.ColourTo(i - 1, state);
                                state = SCE_LISP_IDENTIFIER;
                        }
@@ -93,27 +107,105 @@ static void ColouriseLispDoc(unsigned int startPos, int length, int initStyle, W
                        else if (isLispoperator(ch) || ch=='\'') {
                                styler.ColourTo(i - 1, state);
                                styler.ColourTo(i, SCE_LISP_OPERATOR);
+                               if (ch=='\'' && isLispwordstart(chNext)) {
+                                       state = SCE_LISP_SYMBOL;
+                               }
                        }
                        else if (ch == '\"') {
                                styler.ColourTo(i - 1, state);
                                state = SCE_LISP_STRING;
                        }
-               } else if (state == SCE_LISP_IDENTIFIER) {
+               } else if (state == SCE_LISP_IDENTIFIER || state == SCE_LISP_SYMBOL) {
                        if (!isLispwordstart(ch)) {
-                               classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, styler);
+                               if (state == SCE_LISP_IDENTIFIER) {
+                                       classifyWordLisp(styler.GetStartSegment(), i - 1, keywords, keywords_kw, styler);
+                               } else {
+                                       styler.ColourTo(i - 1, state);
+                               }
                                state = SCE_LISP_DEFAULT;
                        } /*else*/
                        if (isLispoperator(ch) || ch=='\'') {
                                styler.ColourTo(i - 1, state);
                                styler.ColourTo(i, SCE_LISP_OPERATOR);
+                               if (ch=='\'' && isLispwordstart(chNext)) {
+                                       state = SCE_LISP_SYMBOL;
+                               }
+                       }
+               } else if (state == SCE_LISP_MACRO_DISPATCH) {
+                       if (!isdigit(ch)) {
+                               if (ch != 'r' && ch != 'R' && (i - styler.GetStartSegment()) > 1) {
+                                       state = SCE_LISP_DEFAULT;
+                               } else {
+                                       switch (ch) {
+                                               case '|': state = SCE_LISP_MULTI_COMMENT; break;
+                                               case 'o':
+                                               case 'O': radix = 8; state = SCE_LISP_MACRO; break;
+                                               case 'x':
+                                               case 'X': radix = 16; state = SCE_LISP_MACRO; break;
+                                               case 'b':
+                                               case 'B': radix = 2; state = SCE_LISP_MACRO; break;
+                                               case '\\': state = SCE_LISP_CHARACTER; break;
+                                               case ':':
+                                               case '-':
+                                               case '+': state = SCE_LISP_MACRO; break;
+                                               case '\'': if (isLispwordstart(chNext)) {
+                                                                  state = SCE_LISP_SPECIAL;
+                                                          } else {
+                                                                  styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
+                                                                  styler.ColourTo(i, SCE_LISP_OPERATOR);
+                                                                  state = SCE_LISP_DEFAULT;
+                                                          }
+                                                          break;
+                                               default: if (isLispoperator(ch)) {
+                                                                styler.ColourTo(i - 1, SCE_LISP_DEFAULT);
+                                                                styler.ColourTo(i, SCE_LISP_OPERATOR);
+                                                        }
+                                                        state = SCE_LISP_DEFAULT;
+                                                        break;
+                                       }
+                               }
+                       }
+               } else if (state == SCE_LISP_MACRO) {
+                       if (isLispwordstart(ch) && (radix == -1 || IsADigit(ch, radix))) {
+                               state = SCE_LISP_SPECIAL;
+                       } else {
+                               state = SCE_LISP_DEFAULT;
+                       }
+               } else if (state == SCE_LISP_CHARACTER) {
+                       if (isLispoperator(ch)) {
+                               styler.ColourTo(i, SCE_LISP_SPECIAL);
+                               state = SCE_LISP_DEFAULT;
+                       } else if (isLispwordstart(ch)) {
+                               styler.ColourTo(i, SCE_LISP_SPECIAL);
+                               state = SCE_LISP_SPECIAL;
+                       } else {
+                               state = SCE_LISP_DEFAULT;
+                       }
+               } else if (state == SCE_LISP_SPECIAL) {
+                       if (!isLispwordstart(ch) || (radix != -1 && !IsADigit(ch, radix))) {
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_LISP_DEFAULT;
+                       }
+                       if (isLispoperator(ch) || ch=='\'') {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_LISP_OPERATOR);
+                               if (ch=='\'' && isLispwordstart(chNext)) {
+                                       state = SCE_LISP_SYMBOL;
+                               }
                        }
-
                } else {
                        if (state == SCE_LISP_COMMENT) {
                                if (atEOL) {
                                        styler.ColourTo(i - 1, state);
                                        state = SCE_LISP_DEFAULT;
                                }
+                       } else if (state == SCE_LISP_MULTI_COMMENT) {
+                               if (ch == '|' && chNext == '#') {
+                                       i++;
+                                       chNext = styler.SafeGetCharAt(i + 1);
+                                       styler.ColourTo(i, state);
+                                       state = SCE_LISP_DEFAULT;
+                               }
                        } else if (state == SCE_LISP_STRING) {
                                if (ch == '\\') {
                                        if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
@@ -175,6 +267,7 @@ static void FoldLispDoc(unsigned int startPos, int length, int /* initStyle */,
 }
 
 static const char * const lispWordListDesc[] = {
+       "Functions and special operators",
        "Keywords",
        0
 };
index 3e4b25cb5e9acb3c600b0077ef09545673d0e900..7f6df070acb081cb97d95962d2df1d7f2defb54d 100644 (file)
@@ -12,7 +12,6 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <fcntl.h>
 
 #include "Platform.h"
 
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-static inline bool IsAWordChar(const int ch) {
-       return (ch < 0x80) && (isalnum(ch) || ch == '_' || ch == '.');
+// Extended to accept accented characters
+static inline bool IsAWordChar(int ch) {
+       return ch >= 0x80 ||
+              (isalnum(ch) || ch == '.' || ch == '_');
 }
 
-static inline bool IsAWordStart(const int ch) {
-       return (ch < 0x80) && (isalnum(ch) || ch == '_');
+static inline bool IsAWordStart(int ch) {
+       return ch >= 0x80 ||
+              (isalpha(ch) || ch == '_');
 }
 
-static inline bool IsANumberChar(const int ch) {
+static inline bool IsANumberChar(int ch) {
        // Not exactly following number definition (several dots are seen as OK, etc.)
        // but probably enough in most cases.
        return (ch < 0x80) &&
@@ -55,6 +57,18 @@ static inline bool IsLuaOperator(int ch) {
        return false;
 }
 
+// Test for [=[ ... ]=] delimiters, returns 0 if it's only a [ or ],
+// return 1 for [[ or ]], returns >=2 for [=[ or ]=] and so on.
+// The maximum number of '=' characters allowed is 254.
+static int LongDelimCheck(StyleContext &sc) {
+       int sep = 1;
+       while (sc.GetRelative(sep) == '=' && sep < 0xFF)
+               sep++;
+       if (sc.GetRelative(sep) == sc.ch)
+               return sep;
+       return 0;
+}
+
 static void ColouriseLuaDoc(
        unsigned int startPos,
        int length,
@@ -72,19 +86,19 @@ static void ColouriseLuaDoc(
        WordList &keywords8 = *keywordlists[7];
 
        int currentLine = styler.GetLine(startPos);
-       // Initialize the literal string [[ ... ]] nesting level, if we are inside such a string.
-       int literalStringLevel = 0;
-       if (initStyle == SCE_LUA_LITERALSTRING) {
-               literalStringLevel = styler.GetLineState(currentLine - 1);
-       }
-       // Initialize the block comment --[[ ... ]] nesting level, if we are inside such a comment
-       int blockCommentLevel = 0;
-       if (initStyle == SCE_LUA_COMMENT) {
-               blockCommentLevel = styler.GetLineState(currentLine - 1);
+       // Initialize long string [[ ... ]] or block comment --[[ ... ]] nesting level,
+       // if we are inside such a string. Block comment was introduced in Lua 5.0,
+       // blocks with separators [=[ ... ]=] in Lua 5.1.
+       int nestLevel = 0;
+       int sepCount = 0;
+       if (initStyle == SCE_LUA_LITERALSTRING || initStyle == SCE_LUA_COMMENT) {
+               int lineState = styler.GetLineState(currentLine - 1);
+               nestLevel = lineState >> 8;
+               sepCount = lineState & 0xFF;
        }
 
        // Do not leak onto next line
-       if (initStyle == SCE_LUA_STRINGEOL) {
+       if (initStyle == SCE_LUA_STRINGEOL || initStyle == SCE_LUA_COMMENTLINE || initStyle == SCE_LUA_PREPROCESSOR) {
                initStyle = SCE_LUA_DEFAULT;
        }
 
@@ -99,12 +113,9 @@ static void ColouriseLuaDoc(
                        currentLine = styler.GetLine(sc.currentPos);
                        switch (sc.state) {
                        case SCE_LUA_LITERALSTRING:
-                               // Inside a literal string, we set the line state
-                               styler.SetLineState(currentLine, literalStringLevel);
-                               break;
-                       case SCE_LUA_COMMENT:   // Block comment
-                               // Inside a block comment, we set the line state
-                               styler.SetLineState(currentLine, blockCommentLevel);
+                       case SCE_LUA_COMMENT:
+                               // Inside a literal string or block comment, we set the line state
+                               styler.SetLineState(currentLine, (nestLevel << 8) | sepCount);
                                break;
                        default:
                                // Reset the line state
@@ -162,13 +173,9 @@ static void ColouriseLuaDoc(
                                }
                                sc.SetState(SCE_LUA_DEFAULT);
                        }
-               } else if (sc.state == SCE_LUA_COMMENTLINE ) {
+               } else if (sc.state == SCE_LUA_COMMENTLINE || sc.state == SCE_LUA_PREPROCESSOR) {
                        if (sc.atLineEnd) {
-                               sc.SetState(SCE_LUA_DEFAULT);
-                       }
-               } else if (sc.state == SCE_LUA_PREPROCESSOR ) {
-                       if (sc.atLineEnd) {
-                               sc.SetState(SCE_LUA_DEFAULT);
+                               sc.ForwardSetState(SCE_LUA_DEFAULT);
                        }
                } else if (sc.state == SCE_LUA_STRING) {
                        if (sc.ch == '\\') {
@@ -192,26 +199,23 @@ static void ColouriseLuaDoc(
                                sc.ChangeState(SCE_LUA_STRINGEOL);
                                sc.ForwardSetState(SCE_LUA_DEFAULT);
                        }
-               } else if (sc.state == SCE_LUA_LITERALSTRING) {
-                       if (sc.Match('[', '[')) {
-                               literalStringLevel++;
-                               sc.Forward();
-                               sc.SetState(SCE_LUA_LITERALSTRING);
-                       } else if (sc.Match(']', ']') && literalStringLevel > 0) {
-                               literalStringLevel--;
-                               sc.Forward();
-                               if (literalStringLevel == 0) {
-                                       sc.ForwardSetState(SCE_LUA_DEFAULT);
+               } else if (sc.state == SCE_LUA_LITERALSTRING || sc.state == SCE_LUA_COMMENT) {
+                       if (sc.ch == '[') {
+                               int sep = LongDelimCheck(sc);
+                               if (sep == 1 && sepCount == 1) {    // [[-only allowed to nest
+                                       nestLevel++;
+                                       sc.Forward();
                                }
-                       }
-               } else if (sc.state == SCE_LUA_COMMENT) {       // Lua 5.0's block comment
-                       if (sc.Match('[', '[')) {
-                               blockCommentLevel++;
-                               sc.Forward();
-                       } else if (sc.Match(']', ']') && blockCommentLevel > 0) {
-                               blockCommentLevel--;
-                               sc.Forward();
-                               if (blockCommentLevel == 0) {
+                       } else if (sc.ch == ']') {
+                               int sep = LongDelimCheck(sc);
+                               if (sep == 1 && sepCount == 1) {    // un-nest with ]]-only
+                                       nestLevel--;
+                                       sc.Forward();
+                                       if (nestLevel == 0) {
+                                               sc.ForwardSetState(SCE_LUA_DEFAULT);
+                                       }
+                               } else if (sep > 1 && sep == sepCount) {   // ]=]-style delim
+                                       sc.Forward(sep);
                                        sc.ForwardSetState(SCE_LUA_DEFAULT);
                                }
                        }
@@ -223,21 +227,32 @@ static void ColouriseLuaDoc(
                                sc.SetState(SCE_LUA_NUMBER);
                        } else if (IsAWordStart(sc.ch)) {
                                sc.SetState(SCE_LUA_IDENTIFIER);
-                       } else if (sc.Match('\"')) {
+                       } else if (sc.ch == '\"') {
                                sc.SetState(SCE_LUA_STRING);
-                       } else if (sc.Match('\'')) {
+                       } else if (sc.ch == '\'') {
                                sc.SetState(SCE_LUA_CHARACTER);
-                       } else if (sc.Match('[', '[')) {
-                               literalStringLevel = 1;
-                               sc.SetState(SCE_LUA_LITERALSTRING);
-                               sc.Forward();
-                       } else if (sc.Match("--[[")) {  // Lua 5.0's block comment
-                               blockCommentLevel = 1;
-                               sc.SetState(SCE_LUA_COMMENT);
-                               sc.Forward(3);
+                       } else if (sc.ch == '[') {
+                               sepCount = LongDelimCheck(sc);
+                               if (sepCount == 0) {
+                                       sc.SetState(SCE_LUA_OPERATOR);
+                               } else {
+                                       nestLevel = 1;
+                                       sc.SetState(SCE_LUA_LITERALSTRING);
+                                       sc.Forward(sepCount);
+                               }
                        } else if (sc.Match('-', '-')) {
                                sc.SetState(SCE_LUA_COMMENTLINE);
-                               sc.Forward();
+                               if (sc.Match("--[")) {
+                                       sc.Forward(2);
+                                       sepCount = LongDelimCheck(sc);
+                                       if (sepCount > 0) {
+                                               nestLevel = 1;
+                                               sc.ChangeState(SCE_LUA_COMMENT);
+                                               sc.Forward(sepCount);
+                                       }
+                               } else {
+                                       sc.Forward();
+                               }
                        } else if (sc.atLineStart && sc.Match('$')) {
                                sc.SetState(SCE_LUA_PREPROCESSOR);      // Obsolete since Lua 4.0, but still in old code
                        } else if (IsLuaOperator(static_cast<char>(sc.ch))) {
@@ -267,7 +282,7 @@ static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, W
                styleNext = styler.StyleAt(i + 1);
                bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
                if (style == SCE_LUA_WORD) {
-                       if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e') {
+                       if (ch == 'i' || ch == 'd' || ch == 'f' || ch == 'e' || ch == 'r' || ch == 'u') {
                                for (unsigned int j = 0; j < 8; j++) {
                                        if (!iswordchar(styler[i + j])) {
                                                break;
@@ -276,10 +291,10 @@ static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, W
                                        s[j + 1] = '\0';
                                }
 
-                               if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0)) {
+                               if ((strcmp(s, "if") == 0) || (strcmp(s, "do") == 0) || (strcmp(s, "function") == 0) || (strcmp(s, "repeat") == 0)) {
                                        levelCurrent++;
                                }
-                               if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0)) {
+                               if ((strcmp(s, "end") == 0) || (strcmp(s, "elseif") == 0) || (strcmp(s, "until") == 0)) {
                                        levelCurrent--;
                                }
                        }
@@ -289,6 +304,12 @@ static void FoldLuaDoc(unsigned int startPos, int length, int /* initStyle */, W
                        } else if (ch == '}' || ch == ')') {
                                levelCurrent--;
                        }
+               } else if (style == SCE_LUA_LITERALSTRING || style == SCE_LUA_COMMENT) {
+                       if (ch == '[') {
+                               levelCurrent++;
+                       } else if (ch == ']') {
+                               levelCurrent--;
+                       }
                }
 
                if (atEOL) {
@@ -321,8 +342,10 @@ static const char * const luaWordListDesc[] = {
        "Basic functions",
        "String, (table) & math functions",
        "(coroutines), I/O & system facilities",
-       "XXX",
-       "XXX",
+       "user1",
+       "user2",
+       "user3",
+       "user4",
        0
 };
 
index 6019f24d39450ffebb81fa553ac91faeddcdad54..0c54ce670153033c7a6d3138a35d88207173b221 100644 (file)
@@ -2,7 +2,7 @@
 /** @file LexMSSQL.cxx
  ** Lexer for MSSQL.
  **/
-// Copyright 1998-2002 by Filip Yaghob <fy@eg.cz>
+// By Filip Yaghob <fyaghob@gmail.com>
 
 
 #include <stdlib.h>
 #define KW_MSSQL_STORED_PROCEDURES  5
 #define KW_MSSQL_OPERATORS          6
 
-//~ val SCE_MSSQL_DEFAULT=0
-//~ val SCE_MSSQL_COMMENT=1
-//~ val SCE_MSSQL_LINE_COMMENT=2
-//~ val SCE_MSSQL_NUMBER=3
-//~ val SCE_MSSQL_STRING=4
-//~ val SCE_MSSQL_OPERATOR=5
-//~ val SCE_MSSQL_IDENTIFIER=6
-//~ val SCE_MSSQL_VARIABLE=7
-//~ val SCE_MSSQL_COLUMN_NAME=8
-//~ val SCE_MSSQL_STATEMENT=9
-//~ val SCE_MSSQL_DATATYPE=10
-//~ val SCE_MSSQL_SYSTABLE=11
-//~ val SCE_MSSQL_GLOBAL_VARIABLE=12
-//~ val SCE_MSSQL_FUNCTION=13
-//~ val SCE_MSSQL_STORED_PROCEDURE=14
-//~ val SCE_MSSQL_DEFAULT_PREF_DATATYPE 15
-//~ val SCE_MSSQL_COLUMN_NAME_2 16
-
 static bool isMSSQLOperator(char ch) {
        if (isascii(ch) && isalnum(ch))
                return false;
@@ -133,22 +115,7 @@ static void ColouriseMSSQLDoc(unsigned int startPos, int length,
        bool fold = styler.GetPropertyInt("fold") != 0;
        int lineCurrent = styler.GetLine(startPos);
        int spaceFlags = 0;
-/*
-       WordList &kwStatements          = *keywordlists[KW_MSSQL_STATEMENTS];
-    WordList &kwDataTypes           = *keywordlists[KW_MSSQL_DATA_TYPES];
-    WordList &kwSystemTables        = *keywordlists[KW_MSSQL_SYSTEM_TABLES];
-    WordList &kwGlobalVariables     = *keywordlists[KW_MSSQL_GLOBAL_VARIABLES];
-    WordList &kwFunctions           = *keywordlists[KW_MSSQL_FUNCTIONS];
 
-       char s[100];
-       int iixx = 0;
-       s[0] = 's';     s[1] = 'e'; s[2] = 'l'; s[3] = 'e'; s[4] = 'c'; s[5] = 't'; s[6] = 0;
-       if (kwStatements.InList(s))
-               iixx = 1;
-       s[0] = 's';     s[1] = 'e'; s[2] = 'r'; s[3] = 'v'; s[4] = 'e'; s[5] = 'r'; s[6] = 'n'; s[7] = 'a'; s[8] = 'm'; s[9] = 'e'; s[10] = 0;
-       if (kwGlobalVariables.InList(s))
-               iixx += 2;
-*/
        int state = initStyle;
        int prevState = initStyle;
        char chPrev = ' ';
@@ -315,6 +282,69 @@ static void ColouriseMSSQLDoc(unsigned int startPos, int length,
        styler.ColourTo(lengthDoc - 1, state);
 }
 
+static void FoldMSSQLDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
+       bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+       bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+       unsigned int endPos = startPos + length;
+       int visibleChars = 0;
+       int lineCurrent = styler.GetLine(startPos);
+       int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int levelCurrent = levelPrev;
+       char chNext = styler[startPos];
+       bool inComment = (styler.StyleAt(startPos-1) == SCE_MSSQL_COMMENT);
+    char s[10];
+       for (unsigned int i = startPos; i < endPos; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               int style = styler.StyleAt(i);
+               bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+        // Comment folding
+               if (foldComment) {
+                       if (!inComment && (style == SCE_MSSQL_COMMENT))
+                               levelCurrent++;
+                       else if (inComment && (style != SCE_MSSQL_COMMENT))
+                               levelCurrent--;
+                       inComment = (style == SCE_MSSQL_COMMENT);
+               }
+        if (style == SCE_MSSQL_STATEMENT) {
+            // Folding between begin and end
+            if (ch == 'b' || ch == 'e') {
+                for (unsigned int j = 0; j < 5; j++) {
+                                       if (!iswordchar(styler[i + j])) {
+                                               break;
+                                       }
+                                       s[j] = styler[i + j];
+                                       s[j + 1] = '\0';
+                }
+                               if (strcmp(s, "begin") == 0) {
+                                       levelCurrent++;
+                               }
+                               if (strcmp(s, "end") == 0) {
+                                       levelCurrent--;
+                               }
+            }
+        }
+               if (atEOL) {
+                       int lev = levelPrev;
+                       if (visibleChars == 0 && foldCompact)
+                               lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visibleChars > 0))
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+                       if (lev != styler.LevelAt(lineCurrent)) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+                       lineCurrent++;
+                       levelPrev = levelCurrent;
+                       visibleChars = 0;
+               }
+               if (!isspacechar(ch))
+                       visibleChars++;
+       }
+       // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+       int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+       styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+}
+
 static const char * const sqlWordListDesc[] = {
        "Statements",
     "Data Types",
@@ -326,4 +356,4 @@ static const char * const sqlWordListDesc[] = {
        0,
 };
 
-LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", 0, sqlWordListDesc);
+LexerModule lmMSSQL(SCLEX_MSSQL, ColouriseMSSQLDoc, "mssql", FoldMSSQLDoc, sqlWordListDesc);
index 7152229d668dad9aaaa43615e2077bb53824702f..b7d482c0f1d9a74e10b0907cd94176b06095e293 100644 (file)
@@ -160,8 +160,8 @@ static void ColouriseMETAPOSTDoc(
        int currentInterface = CheckMETAPOSTInterface(startPos,length,styler,defaultInterface) ;
 
        // 0  no keyword highlighting
-       // 1  metapost keyword highlighting
-       // 2+ metafun keyword highlighting
+       // 1  metapost keyword hightlighting
+       // 2+ metafun keyword hightlighting
 
        int extraInterface = 0 ;
 
index 0f969bbfb8c4d3c9b711dd8cc0bd66cc4de36f9b..6a7274ef59b2b7a2ab9764a093ec11c93a867a47 100644 (file)
@@ -2,8 +2,8 @@
 /** @file LexNsis.cxx
  ** Lexer for NSIS
  **/
-// Copyright 2003, 2004 by Angelo Mandato <angelo [at] spaceblue [dot] com>
-// Last Updated: 02/22/2004
+// Copyright 2003 - 2005 by Angelo Mandato <angelo [at] spaceblue [dot] com>
+// Last Updated: 03/13/2005
 // The License.txt file describes the conditions under which this software may be distributed.
 #include <stdlib.h>
 #include <string.h>
 #define SCE_NSIS_MACRODEF 12
 #define SCE_NSIS_STRINGVAR 13
 #define SCE_NSIS_NUMBER 14
+// ADDED for Scintilla v1.63
+#define SCE_NSIS_SECTIONGROUP 15
+#define SCE_NSIS_PAGEEX 16
+#define SCE_NSIS_FUNCTIONDEF 17
+#define SCE_NSIS_COMMENTBOX 18
 */
 
 static bool isNsisNumber(char ch)
@@ -55,6 +60,40 @@ static bool isNsisLetter(char ch)
   return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
 }
 
+static bool NsisNextLineHasElse(unsigned int start, unsigned int end, Accessor &styler)
+{
+  int nNextLine = -1;
+  for( unsigned int i = start; i < end; i++ )
+  {
+    char cNext = styler.SafeGetCharAt( i );
+    if( cNext == '\n' )
+    {
+      nNextLine = i+1;
+      break;
+    }
+  }
+
+  if( nNextLine == -1 ) // We never foudn the next line...
+    return false;
+
+  for( unsigned int firstChar = nNextLine; firstChar < end; firstChar++ )
+  {
+    char cNext = styler.SafeGetCharAt( firstChar );
+    if( cNext == ' ' )
+      continue;
+    if( cNext == '\t' )
+      continue;
+    if( cNext == '!' )
+    {
+      if( styler.Match(firstChar, "!else") )
+        return true;
+    }
+    break;
+  }
+
+  return false;
+}
+
 static int NsisCmp( char *s1, char *s2, bool bIgnoreCase )
 {
   if( bIgnoreCase )
@@ -63,25 +102,38 @@ static int NsisCmp( char *s1, char *s2, bool bIgnoreCase )
   return strcmp( s1, s2 );
 }
 
-static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler )
+static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel, Accessor &styler, bool bElse, bool foldUtilityCmd )
 {
+  int style = styler.StyleAt(end);
+
   // If the word is too long, it is not what we are looking for
-  if( end - start > 13 )
+  if( end - start > 20 )
     return foldlevel;
 
-  // Check the style at this point, if it is not valid, then return zero
-  if( styler.StyleAt(end) != SCE_NSIS_FUNCTION && styler.StyleAt(end) != SCE_NSIS_SECTIONDEF &&
-      styler.StyleAt(end) != SCE_NSIS_SUBSECTIONDEF && styler.StyleAt(end) != SCE_NSIS_IFDEFINEDEF &&
-      styler.StyleAt(end) != SCE_NSIS_MACRODEF )
-        return foldlevel;
+  if( foldUtilityCmd )
+  {
+    // Check the style at this point, if it is not valid, then return zero
+    if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF &&
+        style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_IFDEFINEDEF &&
+        style != SCE_NSIS_MACRODEF && style != SCE_NSIS_SECTIONGROUP &&
+        style != SCE_NSIS_PAGEEX )
+          return foldlevel;
+  }
+  else
+  { 
+    if( style != SCE_NSIS_FUNCTIONDEF && style != SCE_NSIS_SECTIONDEF &&
+        style != SCE_NSIS_SUBSECTIONDEF && style != SCE_NSIS_SECTIONGROUP &&
+        style != SCE_NSIS_PAGEEX )
+          return foldlevel;
+  }
 
   int newFoldlevel = foldlevel;
   bool bIgnoreCase = false;
   if( styler.GetPropertyInt("nsis.ignorecase") == 1 )
     bIgnoreCase = true;
 
-  char s[15]; // The key word we are looking for has atmost 13 characters
-  for (unsigned int i = 0; i < end - start + 1 && i < 14; i++)
+  char s[20]; // The key word we are looking for has atmost 13 characters
+  for (unsigned int i = 0; i < end - start + 1 && i < 19; i++)
        {
                s[i] = static_cast<char>( styler[ start + i ] );
                s[i + 1] = '\0';
@@ -93,15 +145,17 @@ static int calculateFoldNsis(unsigned int start, unsigned int end, int foldlevel
       newFoldlevel++;
     else if( NsisCmp(s, "!endif", bIgnoreCase) == 0 || NsisCmp(s, "!macroend", bIgnoreCase ) == 0 )
       newFoldlevel--;
+    else if( bElse && NsisCmp(s, "!else", bIgnoreCase) == 0 )
+      newFoldlevel++;
   }
   else
   {
-    if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 )
+    if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionGroup", bIgnoreCase ) == 0 || NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "SubSection", bIgnoreCase ) == 0 || NsisCmp(s, "PageEx", bIgnoreCase ) == 0 )
       newFoldlevel++;
-    else if( NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 )
+    else if( NsisCmp(s, "SectionGroupEnd", bIgnoreCase ) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase ) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase ) == 0 )
       newFoldlevel--;
   }
-
+  
   return newFoldlevel;
 }
 
@@ -138,14 +192,23 @@ static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keyw
        if( NsisCmp(s, "!ifdef", bIgnoreCase ) == 0 ||  NsisCmp(s, "!ifndef", bIgnoreCase) == 0 ||  NsisCmp(s, "!endif", bIgnoreCase) == 0 )
                return SCE_NSIS_IFDEFINEDEF;
 
+  if( NsisCmp(s, "!else", bIgnoreCase ) == 0 ) // ||  NsisCmp(s, "!ifndef", bIgnoreCase) == 0 ||  NsisCmp(s, "!endif", bIgnoreCase) == 0 )
+               return SCE_NSIS_IFDEFINEDEF;
+
+  if( NsisCmp(s, "SectionGroup", bIgnoreCase) == 0 || NsisCmp(s, "SectionGroupEnd", bIgnoreCase) == 0 ) // Covers SectionGroup and SectionGroupEnd
+    return SCE_NSIS_SECTIONGROUP;
+
        if( NsisCmp(s, "Section", bIgnoreCase ) == 0 || NsisCmp(s, "SectionEnd", bIgnoreCase) == 0 ) // Covers Section and SectionEnd
                return SCE_NSIS_SECTIONDEF;
 
        if( NsisCmp(s, "SubSection", bIgnoreCase) == 0 || NsisCmp(s, "SubSectionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd
                return SCE_NSIS_SUBSECTIONDEF;
 
-       if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers SubSection and SubSectionEnd
-               return SCE_NSIS_FUNCTION;
+  if( NsisCmp(s, "PageEx", bIgnoreCase) == 0 || NsisCmp(s, "PageExEnd", bIgnoreCase) == 0 ) // Covers PageEx and PageExEnd
+    return SCE_NSIS_PAGEEX;
+
+       if( NsisCmp(s, "Function", bIgnoreCase) == 0 || NsisCmp(s, "FunctionEnd", bIgnoreCase) == 0 ) // Covers Function and FunctionEnd
+               return SCE_NSIS_FUNCTIONDEF;
 
        if ( Functions.InList(s) )
                return SCE_NSIS_FUNCTION;
@@ -188,9 +251,6 @@ static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keyw
     bool bHasSimpleNsisNumber = true;
     for (unsigned int j = 1; j < end - start + 1 && j < 99; j++)
          {
-      if( s[j] == '\0' || s[j] == '\r' || s[j] == '\n' )
-        break;
-
       if( !isNsisNumber( s[j] ) )
       {
         bHasSimpleNsisNumber = false;
@@ -208,6 +268,9 @@ static int classifyWordNsis(unsigned int start, unsigned int end, WordList *keyw
 static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *keywordLists[], Accessor &styler)
 {
        int state = SCE_NSIS_DEFAULT;
+  if( startPos > 0 )
+    state = styler.StyleAt(startPos-1); // Use the style from the previous line, usually default, but could be commentbox
+
        styler.StartAt( startPos );
        styler.GetLine( startPos );
 
@@ -270,35 +333,96 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k
 
                                        break;
                                }
+
+        if( cCurrChar == '/' && cNextChar == '*' )
+        {
+          styler.ColourTo(i-1,state);
+          state = SCE_NSIS_COMMENTBOX;
+          break;
+        }
+
                                break;
                        case SCE_NSIS_COMMENT:
                                if( cNextChar == '\n' || cNextChar == '\r' )
         {
-                                 styler.ColourTo(i,state);
-          state = SCE_NSIS_DEFAULT;
+          // Special case:
+          if( cCurrChar == '\\' )
+          {
+            styler.ColourTo(i-2,state);
+            styler.ColourTo(i,SCE_NSIS_DEFAULT);
+          }
+          else
+          {
+                                   styler.ColourTo(i,state);
+            state = SCE_NSIS_DEFAULT;
+          }
         }
                                break;
                        case SCE_NSIS_STRINGDQ:
-                               if( cCurrChar == '"' || cNextChar == '\r' || cNextChar == '\n' )
+      case SCE_NSIS_STRINGLQ:
+      case SCE_NSIS_STRINGRQ:
+
+        if( styler.SafeGetCharAt(i-1) == '\\' && styler.SafeGetCharAt(i-2) == '$' )
+          break; // Ignore the next character, even if it is a quote of some sort
+
+        if( cCurrChar == '"' && state == SCE_NSIS_STRINGDQ )
                                {
-                                       styler.ColourTo(i,SCE_NSIS_STRINGDQ);
+                                       styler.ColourTo(i,state);
                                  state = SCE_NSIS_DEFAULT;
+          break;
                                }
-                               break;
-                       case SCE_NSIS_STRINGLQ:
-                               if( cCurrChar == '`' || cNextChar == '\r' || cNextChar == '\n' )
-                               {
-                                       styler.ColourTo(i,SCE_NSIS_STRINGLQ);
+
+        if( cCurrChar == '`' && state == SCE_NSIS_STRINGLQ )
+        {
+                                       styler.ColourTo(i,state);
                                  state = SCE_NSIS_DEFAULT;
+          break;
                                }
-                               break;
-                       case SCE_NSIS_STRINGRQ:
-                               if( cCurrChar == '\'' || cNextChar == '\r' || cNextChar == '\n' )
+
+        if( cCurrChar == '\'' && state == SCE_NSIS_STRINGRQ )
                                {
-                                       styler.ColourTo(i,SCE_NSIS_STRINGRQ);
+                                       styler.ColourTo(i,state);
                                  state = SCE_NSIS_DEFAULT;
+          break;
                                }
+
+        if( cNextChar == '\r' || cNextChar == '\n' )
+        {
+          int nCurLine = styler.GetLine(i+1);
+          int nBack = i;
+          // We need to check if the previous line has a \ in it...
+          bool bNextLine = false;
+
+          while( nBack > 0 )
+          {
+            if( styler.GetLine(nBack) != nCurLine )
+              break;
+
+            char cTemp = styler.SafeGetCharAt(nBack, 'a'); // Letter 'a' is safe here
+
+            if( cTemp == '\\' )
+            {
+              bNextLine = true;
+              break;
+            }
+            if( cTemp != '\r' && cTemp != '\n' && cTemp != '\t' && cTemp != ' ' )
+              break;
+
+            nBack--;
+          }
+
+          if( bNextLine )
+          {
+            styler.ColourTo(i+1,state);
+          }
+          if( bNextLine == false )
+          {
+            styler.ColourTo(i,state);
+                                   state = SCE_NSIS_DEFAULT;
+          }
+        }
                                break;
+
                        case SCE_NSIS_FUNCTION:
 
                                // NSIS KeyWord:
@@ -308,7 +432,7 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k
           state = SCE_NSIS_DEFAULT;
                                else if( (isNsisChar(cCurrChar) && !isNsisChar( cNextChar) && cNextChar != '}') || cCurrChar == '}' )
                                {
-                                       state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler);
+                                       state = classifyWordNsis( styler.GetStartSegment(), i, keywordLists, styler );
                                        styler.ColourTo( i, state);
                                        state = SCE_NSIS_DEFAULT;
                                }
@@ -343,9 +467,17 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k
           }
                                }
                                break;
+      case SCE_NSIS_COMMENTBOX:
+
+        if( styler.SafeGetCharAt(i-1) == '*' && cCurrChar == '/' )
+        {
+          styler.ColourTo(i,state);
+          state = SCE_NSIS_DEFAULT;
+        }
+        break;
                }
 
-               if( state == SCE_NSIS_COMMENT )
+               if( state == SCE_NSIS_COMMENT || state == SCE_NSIS_COMMENTBOX )
                {
                        styler.ColourTo(i,state);
                }
@@ -361,10 +493,11 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k
         bVarInString = false;
         bIngoreNextDollarSign = true;
       }
-      else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' ) )
+      else if( bVarInString && cCurrChar == '\\' && (cNextChar == 'n' || cNextChar == 'r' || cNextChar == 't' || cNextChar == '"' || cNextChar == '`' || cNextChar == '\'' ) )
       {
+        styler.ColourTo( i+1, SCE_NSIS_STRINGVAR);
         bVarInString = false;
-        bIngoreNextDollarSign = true;
+        bIngoreNextDollarSign = false;
       }
 
       // Covers "$INSTDIR and user vars like $MYVAR"
@@ -401,19 +534,7 @@ static void ColouriseNsisDoc(unsigned int startPos, int length, int, WordList *k
        }
 
   // Colourise remaining document
-  switch( state )
-  {
-    case SCE_NSIS_COMMENT:
-    case SCE_NSIS_STRINGDQ:
-    case SCE_NSIS_STRINGLQ:
-    case SCE_NSIS_STRINGRQ:
-    case SCE_NSIS_VARIABLE:
-    case SCE_NSIS_STRINGVAR:
-      styler.ColourTo(nLengthDoc-1,state); break;
-
-    default:
-      styler.ColourTo(nLengthDoc-1,SCE_NSIS_DEFAULT); break;
-  }
+       styler.ColourTo(nLengthDoc-1,state);
 }
 
 static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler)
@@ -422,6 +543,10 @@ static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Ac
        if( styler.GetPropertyInt("fold") == 0 )
                return;
 
+  bool foldAtElse = styler.GetPropertyInt("fold.at.else", 0) == 1;
+  bool foldUtilityCmd = styler.GetPropertyInt("nsis.foldutilcmd", 1) == 1;
+  bool blockComment = false;
+
   int lineCurrent = styler.GetLine(startPos);
   unsigned int safeStartPos = styler.LineStart( lineCurrent );
 
@@ -432,19 +557,48 @@ static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Ac
        if (lineCurrent > 0)
                levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
        int levelNext = levelCurrent;
+  int style = styler.StyleAt(safeStartPos);
+  if( style == SCE_NSIS_COMMENTBOX )
+  {
+    if( styler.SafeGetCharAt(safeStartPos) == '/' && styler.SafeGetCharAt(safeStartPos+1) == '*' )
+      levelNext++;
+    blockComment = true;
+  }
 
   for (unsigned int i = safeStartPos; i < startPos + length; i++)
        {
     char chCurr = styler.SafeGetCharAt(i);
+    style = styler.StyleAt(i);
+    if( blockComment && style != SCE_NSIS_COMMENTBOX )
+    {
+      levelNext--;
+      blockComment = false;
+    }
+    else if( !blockComment && style == SCE_NSIS_COMMENTBOX )
+    {
+      levelNext++;
+      blockComment = true;
+    }
 
-    if( bArg1 ) //&& chCurr != '\n' )
+    if( bArg1 && !blockComment)
     {
       if( nWordStart == -1 && (isNsisLetter(chCurr) || chCurr == '!') )
+      {
         nWordStart = i;
-      else if( !isNsisLetter(chCurr) && nWordStart > -1 )
+      }
+      else if( isNsisLetter(chCurr) == false && nWordStart > -1 )
       {
-        int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler );
-        if( newLevel != levelNext )
+        int newLevel = calculateFoldNsis( nWordStart, i-1, levelNext, styler, foldAtElse, foldUtilityCmd );
+
+        if( newLevel == levelNext )
+        {
+          if( foldAtElse && foldUtilityCmd )
+          {
+            if( NsisNextLineHasElse(i, startPos + length, styler) )
+              levelNext--;
+          }
+        }
+        else
           levelNext = newLevel;
         bArg1 = false;
       }
@@ -452,10 +606,16 @@ static void FoldNsisDoc(unsigned int startPos, int length, int, WordList *[], Ac
 
     if( chCurr == '\n' )
     {
+      if( bArg1 && foldAtElse && foldUtilityCmd && !blockComment )
+      {
+        if( NsisNextLineHasElse(i, startPos + length, styler) )
+          levelNext--;
+      }
+
       // If we are on a new line...
       int levelUse = levelCurrent;
                        int lev = levelUse | levelNext << 16;
-                       if (levelUse < levelNext)
+      if (levelUse < levelNext )
                                lev |= SC_FOLDLEVELHEADERFLAG;
                        if (lev != styler.LevelAt(lineCurrent))
                                styler.SetLevel(lineCurrent, lev);
@@ -484,3 +644,4 @@ static const char * const nsisWordLists[] = {
 
 
 LexerModule lmNsis(SCLEX_NSIS, ColouriseNsisDoc, "nsis", FoldNsisDoc, nsisWordLists);
+
index f777e300fa24ec132a68137cc899bc81762a8a62..4f4c1e3258fcabf2c106f7813c12bb48d2c11511 100644 (file)
@@ -30,7 +30,19 @@ static bool Is1To9(char ch) {
 
 static inline bool AtEOL(Accessor &styler, unsigned int i) {
        return (styler[i] == '\n') ||
-               ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
+              ((styler[i] == '\r') && (styler.SafeGetCharAt(i + 1) != '\n'));
+}
+
+// Tests for BATCH Operators
+static bool IsBOperator(char ch) {
+       return (ch == '=') || (ch == '+') || (ch == '>') || (ch == '<') ||
+               (ch == '|') || (ch == '?') || (ch == '*');
+}
+
+// Tests for BATCH Separators
+static bool IsBSeparator(char ch) {
+       return (ch == ':') || (ch == '\\') || (ch == '.') || (ch == ';') ||
+               (ch == '\"') || (ch == '\'') || (ch == '/') || (ch == ')');
 }
 
 static void ColouriseBatchLine(
@@ -41,95 +53,391 @@ static void ColouriseBatchLine(
     WordList &keywords,
     Accessor &styler) {
 
-       unsigned int i = 0;
-       unsigned int state = SCE_BAT_DEFAULT;
+       unsigned int offset = 0;        // Line Buffer Offset
+       unsigned int enVarEnd;          // Environment Variable End point
+       unsigned int cmdLoc;            // External Command / Program Location
+       char wordBuffer[81];            // Word Buffer - large to catch long paths
+       unsigned int wbl;               // Word Buffer Length
+       unsigned int wbo;               // Word Buffer Offset - also Special Keyword Buffer Length
+       bool forFound = false;          // No Local Variable without FOR statement
+       // CHOICE, ECHO, GOTO, PROMPT and SET have Default Text that may contain Regular Keywords
+       //   Toggling Regular Keyword Checking off improves readability
+       // Other Regular Keywords and External Commands / Programs might also benefit from toggling
+       //   Need a more robust algorithm to properly toggle Regular Keyword Checking
+       bool continueProcessing = true; // Used to toggle Regular Keyword Checking
+       // Special Keywords are those that allow certain characters without whitespace after the command
+       // Examples are: cd. cd\ md. rd. dir| dir> echo: echo. path=
+       // Special Keyword Buffer used to determine if the first n characters is a Keyword
+       char sKeywordBuffer[10];        // Special Keyword Buffer
+       bool sKeywordFound;             // Exit Special Keyword for-loop if found
 
-       while ((i < lengthLine) && isspacechar(lineBuffer[i])) {        // Skip initial spaces
-               i++;
-       }
-       if (lineBuffer[i] == '@') {     // Hide command (ECHO OFF)
-               styler.ColourTo(startLine + i, SCE_BAT_HIDE);
-               i++;
-               while ((i < lengthLine) && isspacechar(lineBuffer[i])) {        // Skip next spaces
-                       i++;
-               }
+       // Skip initial spaces
+       while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
+               offset++;
        }
-       if (lineBuffer[i] == ':') {
-               // Label
-               if (lineBuffer[i + 1] == ':') {
-                       // :: is a fake label, similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
+       // Colorize Default Text
+       styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
+       // Set External Command / Program Location
+       cmdLoc = offset;
+
+       // Check for Fake Label (Comment) or Real Label - return if found
+       if (lineBuffer[offset] == ':') {
+               if (lineBuffer[offset + 1] == ':') {
+                       // Colorize Fake Label (Comment) - :: is similar to REM, see http://content.techweb.com/winmag/columns/explorer/2000/21.htm
                        styler.ColourTo(endPos, SCE_BAT_COMMENT);
-               } else {        // Real label
+               } else {
+                       // Colorize Real Label
                        styler.ColourTo(endPos, SCE_BAT_LABEL);
                }
-       } else {
-               // Check if initial word is a keyword
-               char wordBuffer[21];
-               unsigned int wbl = 0, offset = i;
-               // Copy word in buffer
-               for (; offset < lengthLine && wbl < 20 &&
+               return;
+       // Check for Drive Change (Drive Change is internal command) - return if found
+       } else if ((isalpha(lineBuffer[offset])) &&
+               (lineBuffer[offset + 1] == ':') &&
+               ((isspacechar(lineBuffer[offset + 2])) ||
+               (((lineBuffer[offset + 2] == '\\')) &&
+               (isspacechar(lineBuffer[offset + 3]))))) {
+               // Colorize Regular Keyword
+               styler.ColourTo(endPos, SCE_BAT_WORD);
+               return;
+       }
+
+       // Check for Hide Command (@ECHO OFF/ON)
+       if (lineBuffer[offset] == '@') {
+               styler.ColourTo(startLine + offset, SCE_BAT_HIDE);
+               offset++;
+       // Check for Argument (%n) or Environment Variable (%x...%)
+       } else if (lineBuffer[offset] == '%') {
+               enVarEnd = offset + 1;
+               // Search end of word for second % (can be a long path)
+               while ((enVarEnd < lengthLine) &&
+                       (!isspacechar(lineBuffer[enVarEnd])) &&
+                       (lineBuffer[enVarEnd] != '%') &&
+                       (!IsBOperator(lineBuffer[enVarEnd])) &&
+                       (!IsBSeparator(lineBuffer[enVarEnd]))) {
+                       enVarEnd++;
+               }
+               // Check for Argument (%n)
+               if ((Is0To9(lineBuffer[offset + 1])) &&
+                       (lineBuffer[enVarEnd] != '%')) {
+                       // Colorize Argument
+                       styler.ColourTo(startLine + offset + 1, SCE_BAT_IDENTIFIER);
+                       offset += 2;
+                       // Check for External Command / Program
+                       if (!isspacechar(lineBuffer[offset])) {
+                               cmdLoc = offset;
+                       }
+               // Check for Environment Variable (%x...%)
+               } else if ((lineBuffer[offset + 1] != '%') &&
+                       (lineBuffer[enVarEnd] == '%')) {
+                       offset = enVarEnd;
+                       // Colorize Environment Variable
+                       styler.ColourTo(startLine + offset, SCE_BAT_IDENTIFIER);
+                       offset++;
+                       // Check for External Command / Program
+                       if (!isspacechar(lineBuffer[offset])) {
+                               cmdLoc = offset;
+                       }
+               }
+       }
+       // Skip next spaces
+       while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
+               offset++;
+       }
+
+       // Read remainder of line word-at-a-time or remainder-of-word-at-a-time
+       while (offset < lengthLine) {
+               if (offset > startLine) {
+                       // Colorize Default Text
+                       styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
+               }
+               // Copy word from Line Buffer into Word Buffer
+               wbl = 0;
+               for (; offset < lengthLine && wbl < 80 &&
                        !isspacechar(lineBuffer[offset]); wbl++, offset++) {
                        wordBuffer[wbl] = static_cast<char>(tolower(lineBuffer[offset]));
                }
                wordBuffer[wbl] = '\0';
-               // Check if it is a comment
+               wbo = 0;
+
+               // Check for Comment - return if found
                if (CompareCaseInsensitive(wordBuffer, "rem") == 0) {
                        styler.ColourTo(endPos, SCE_BAT_COMMENT);
-                       return ;
+                       return;
                }
-               // Check if it is in the list
-               if (keywords.InList(wordBuffer)) {
-                       styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD);  // Regular keyword
-               } else {
-                       // Search end of word (can be a long path)
-                       while (offset < lengthLine &&
-                               !isspacechar(lineBuffer[offset])) {
-                               offset++;
+               // Check for Separator
+               if (IsBSeparator(wordBuffer[0])) {
+                       // Check for External Command / Program
+                       if ((cmdLoc == offset - wbl) &&
+                               ((wordBuffer[0] == ':') ||
+                               (wordBuffer[0] == '\\') ||
+                               (wordBuffer[0] == '.'))) {
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 1);
+                               // Colorize External Command / Program
+                               styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
+                               // Reset External Command / Program Location
+                               cmdLoc = offset;
+                       } else {
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 1);
+                               // Colorize Default Text
+                               styler.ColourTo(startLine + offset - 1, SCE_BAT_DEFAULT);
+                       }
+               // Check for Regular Keyword in list
+               } else if ((keywords.InList(wordBuffer)) &&
+                       (continueProcessing)) {
+                       // Local Variables do not exist if no FOR statement
+                       if (CompareCaseInsensitive(wordBuffer, "for") == 0) {
+                               forFound = true;
+                       }
+                       // ECHO, GOTO, PROMPT and SET require no further Regular Keyword Checking
+                       if ((CompareCaseInsensitive(wordBuffer, "echo") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "goto") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "prompt") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "set") == 0)) {
+                               continueProcessing = false;
+                       }
+                       // Identify External Command / Program Location for ERRORLEVEL, and EXIST
+                       if ((CompareCaseInsensitive(wordBuffer, "errorlevel") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "exist") == 0)) {
+                               // Reset External Command / Program Location
+                               cmdLoc = offset;
+                               // Skip next spaces
+                               while ((cmdLoc < lengthLine) &&
+                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
+                               }
+                               // Skip comparison
+                               while ((cmdLoc < lengthLine) &&
+                                       (!isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
+                               }
+                               // Skip next spaces
+                               while ((cmdLoc < lengthLine) &&
+                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
+                               }
+                       // Identify External Command / Program Location for CALL, DO, LOADHIGH and LH
+                       } else if ((CompareCaseInsensitive(wordBuffer, "call") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "do") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "loadhigh") == 0) ||
+                               (CompareCaseInsensitive(wordBuffer, "lh") == 0)) {
+                               // Reset External Command / Program Location
+                               cmdLoc = offset;
+                               // Skip next spaces
+                               while ((cmdLoc < lengthLine) &&
+                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
+                               }
+                       }
+                       // Colorize Regular keyword
+                       styler.ColourTo(startLine + offset - 1, SCE_BAT_WORD);
+                       // No need to Reset Offset
+               // Check for Special Keyword in list, External Command / Program, or Default Text
+               } else if ((wordBuffer[0] != '%') &&
+                       (!IsBOperator(wordBuffer[0])) &&
+                       (continueProcessing)) {
+                       // Check for Special Keyword
+                       //     Affected Commands are in Length range 2-6
+                       //     Good that ERRORLEVEL, EXIST, CALL, DO, LOADHIGH, and LH are unaffected
+                       sKeywordFound = false;
+                       for (unsigned int keywordLength = 2; keywordLength < wbl && keywordLength < 7 && !sKeywordFound; keywordLength++) {
+                               wbo = 0;
+                               // Copy Keyword Length from Word Buffer into Special Keyword Buffer
+                               for (; wbo < keywordLength; wbo++) {
+                                       sKeywordBuffer[wbo] = static_cast<char>(wordBuffer[wbo]);
+                               }
+                               sKeywordBuffer[wbo] = '\0';
+                               // Check for Special Keyword in list
+                               if ((keywords.InList(sKeywordBuffer)) &&
+                                       ((IsBOperator(wordBuffer[wbo])) ||
+                                       (IsBSeparator(wordBuffer[wbo])))) {
+                                       sKeywordFound = true;
+                                       // ECHO requires no further Regular Keyword Checking
+                                       if (CompareCaseInsensitive(sKeywordBuffer, "echo") == 0) {
+                                               continueProcessing = false;
+                                       }
+                                       // Colorize Special Keyword as Regular Keyword
+                                       styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_WORD);
+                                       // Reset Offset to re-process remainder of word
+                                       offset -= (wbl - wbo);
                        }
-                       styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);       // External command / program
                }
-               // Remainder of the line: colourise the variables.
-
-               while (offset < lengthLine) {
-                       if (state == SCE_BAT_DEFAULT && lineBuffer[offset] == '%') {
-                               styler.ColourTo(startLine + offset - 1, state);
-                               if (Is0To9(lineBuffer[offset + 1])) {
-                                       styler.ColourTo(startLine + offset + 1, SCE_BAT_IDENTIFIER);
-                                       offset += 2;
-                               } else if (lineBuffer[offset + 1] == '%' &&
-                                          !isspacechar(lineBuffer[offset + 2])) {
-                                       // Should be safe, as there is CRLF at the end of the line...
-                                       styler.ColourTo(startLine + offset + 2, SCE_BAT_IDENTIFIER);
-                                       offset += 3;
+                       // Check for External Command / Program or Default Text
+                       if (!sKeywordFound) {
+                               wbo = 0;
+                               // Check for External Command / Program
+                               if (cmdLoc == offset - wbl) {
+                                       // Read up to %, Operator or Separator
+                                       while ((wbo < wbl) &&
+                                               (wordBuffer[wbo] != '%') &&
+                                               (!IsBOperator(wordBuffer[wbo])) &&
+                                               (!IsBSeparator(wordBuffer[wbo]))) {
+                                               wbo++;
+                                       }
+                                       // Reset External Command / Program Location
+                                       cmdLoc = offset - (wbl - wbo);
+                                       // Reset Offset to re-process remainder of word
+                                       offset -= (wbl - wbo);
+                                       // CHOICE requires no further Regular Keyword Checking
+                                       if (CompareCaseInsensitive(wordBuffer, "choice") == 0) {
+                                               continueProcessing = false;
+                                       }
+                                       // Check for START (and its switches) - What follows is External Command \ Program
+                                       if (CompareCaseInsensitive(wordBuffer, "start") == 0) {
+                                               // Reset External Command / Program Location
+                                               cmdLoc = offset;
+                                               // Skip next spaces
+                                               while ((cmdLoc < lengthLine) &&
+                                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                                       cmdLoc++;
+                                               }
+                                               // Reset External Command / Program Location if command switch detected
+                                               if (lineBuffer[cmdLoc] == '/') {
+                                                       // Skip command switch
+                                                       while ((cmdLoc < lengthLine) &&
+                                                               (!isspacechar(lineBuffer[cmdLoc]))) {
+                                                               cmdLoc++;
+                                                       }
+                                                       // Skip next spaces
+                                                       while ((cmdLoc < lengthLine) &&
+                                                               (isspacechar(lineBuffer[cmdLoc]))) {
+                                                               cmdLoc++;
+                                                       }
+                                               }
+                                       }
+                                       // Colorize External command / program
+                                       styler.ColourTo(startLine + offset - 1, SCE_BAT_COMMAND);
+                                       // No need to Reset Offset
+                               // Check for Default Text
                                } else {
-                                       state = SCE_BAT_IDENTIFIER;
+                                       // Read up to %, Operator or Separator
+                                       while ((wbo < wbl) &&
+                                               (wordBuffer[wbo] != '%') &&
+                                               (!IsBOperator(wordBuffer[wbo])) &&
+                                               (!IsBSeparator(wordBuffer[wbo]))) {
+                                               wbo++;
+                                       }
+                                       // Colorize Default Text
+                                       styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
+                                       // Reset Offset to re-process remainder of word
+                                       offset -= (wbl - wbo);
+                               }
+                       }
+               // Check for Argument  (%n), Environment Variable (%x...%) or Local Variable (%%a)
+               } else if (wordBuffer[0] == '%') {
+                       // Colorize Default Text
+                       styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
+                       wbo++;
+                       // Search to end of word for second % (can be a long path)
+                       while ((wbo < wbl) &&
+                               (wordBuffer[wbo] != '%') &&
+                               (!IsBOperator(wordBuffer[wbo])) &&
+                               (!IsBSeparator(wordBuffer[wbo]))) {
+                               wbo++;
+                       }
+                       // Check for Argument (%n)
+                       if ((Is0To9(wordBuffer[1])) &&
+                               (wordBuffer[wbo] != '%')) {
+                               // Check for External Command / Program
+                               if (cmdLoc == offset - wbl) {
+                                       cmdLoc = offset - (wbl - 2);
+                               }
+                               // Colorize Argument
+                               styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_IDENTIFIER);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 2);
+                       // Check for Environment Variable (%x...%)
+                       } else if ((wordBuffer[1] != '%') &&
+                               (wordBuffer[wbo] == '%')) {
+                               wbo++;
+                               // Check for External Command / Program
+                               if (cmdLoc == offset - wbl) {
+                                       cmdLoc = offset - (wbl - wbo);
+                       }
+                               // Colorize Environment Variable
+                               styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_IDENTIFIER);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - wbo);
+                       // Check for Local Variable (%%a)
+                       } else if ((forFound) &&
+                               (wordBuffer[1] == '%') &&
+                               (wordBuffer[2] != '%') &&
+                               (!IsBOperator(wordBuffer[2])) &&
+                               (!IsBSeparator(wordBuffer[2]))) {
+                               // Check for External Command / Program
+                               if (cmdLoc == offset - wbl) {
+                                       cmdLoc = offset - (wbl - 3);
+                               }
+                               // Colorize Local Variable
+                               styler.ColourTo(startLine + offset - 1 - (wbl - 3), SCE_BAT_IDENTIFIER);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 3);
+                       }
+               // Check for Operator
+               } else if (IsBOperator(wordBuffer[0])) {
+                       // Colorize Default Text
+                       styler.ColourTo(startLine + offset - 1 - wbl, SCE_BAT_DEFAULT);
+                       // Check for Comparison Operator
+                       if ((wordBuffer[0] == '=') && (wordBuffer[1] == '=')) {
+                               // Identify External Command / Program Location for IF
+                               cmdLoc = offset;
+                               // Skip next spaces
+                               while ((cmdLoc < lengthLine) &&
+                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
+                               }
+                               // Colorize Comparison Operator
+                               styler.ColourTo(startLine + offset - 1 - (wbl - 2), SCE_BAT_OPERATOR);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 2);
+                       // Check for Pipe Operator
+                       } else if (wordBuffer[0] == '|') {
+                               // Reset External Command / Program Location
+                               cmdLoc = offset - wbl + 1;
+                               // Skip next spaces
+                               while ((cmdLoc < lengthLine) &&
+                                       (isspacechar(lineBuffer[cmdLoc]))) {
+                                       cmdLoc++;
                                }
-                       } else if (state == SCE_BAT_IDENTIFIER && lineBuffer[offset] == '%') {
-                               styler.ColourTo(startLine + offset, state);
-                               state = SCE_BAT_DEFAULT;
-                       } else if (state == SCE_BAT_DEFAULT &&
-                                  (lineBuffer[offset] == '*' ||
-                                   lineBuffer[offset] == '?' ||
-                                   lineBuffer[offset] == '=' ||
-                                   lineBuffer[offset] == '<' ||
-                                   lineBuffer[offset] == '>' ||
-                                   lineBuffer[offset] == '|')) {
-                               styler.ColourTo(startLine + offset - 1, state);
-                               styler.ColourTo(startLine + offset, SCE_BAT_OPERATOR);
+                               // Colorize Pipe Operator
+                               styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 1);
+                       // Check for Other Operator
+                       } else {
+                               // Check for > Operator
+                               if (wordBuffer[0] == '>') {
+                                       // Turn Keyword and External Command / Program checking back on
+                                       continueProcessing = true;
+                               }
+                               // Colorize Other Operator
+                               styler.ColourTo(startLine + offset - 1 - (wbl - 1), SCE_BAT_OPERATOR);
+                               // Reset Offset to re-process remainder of word
+                               offset -= (wbl - 1);
+                       }
+               // Check for Default Text
+               } else {
+                       // Read up to %, Operator or Separator
+                       while ((wbo < wbl) &&
+                               (wordBuffer[wbo] != '%') &&
+                               (!IsBOperator(wordBuffer[wbo])) &&
+                               (!IsBSeparator(wordBuffer[wbo]))) {
+                               wbo++;
                        }
+                       // Colorize Default Text
+                       styler.ColourTo(startLine + offset - 1 - (wbl - wbo), SCE_BAT_DEFAULT);
+                       // Reset Offset to re-process remainder of word
+                       offset -= (wbl - wbo);
+               }
+               // Skip next spaces - nothing happens if Offset was Reset
+               while ((offset < lengthLine) && (isspacechar(lineBuffer[offset]))) {
                        offset++;
                }
-               //              if (endPos > startLine + offset - 1) {
-               styler.ColourTo(endPos, SCE_BAT_DEFAULT);               // Remainder of line, currently not lexed
-               //              }
        }
-
+       // Colorize Default Text for remainder of line - currently not lexed
+       styler.ColourTo(endPos, SCE_BAT_DEFAULT);
 }
-// ToDo: (not necessarily at beginning of line) GOTO, [IF] NOT, ERRORLEVEL
-// IF [NO] (test) (command) -- test is EXIST (filename) | (string1)==(string2) | ERRORLEVEL (number)
-// FOR %%(variable) IN (set) DO (command) -- variable is [a-zA-Z] -- eg for %%X in (*.txt) do type %%X
-// ToDo: %n (parameters), %EnvironmentVariable% colourising
-// ToDo: Colourise = > >> < | "
 
 static void ColouriseBatchDoc(
     unsigned int startPos,
@@ -240,7 +548,7 @@ static void FoldDiffDoc(unsigned int startPos, int length, int, WordList*[], Acc
                int nextLevel = prevLevel;
                if (prevLevel & SC_FOLDLEVELHEADERFLAG)
                        nextLevel = (prevLevel & SC_FOLDLEVELNUMBERMASK) + 1;
-               
+
                int lineType = styler.StyleAt(curLineStart);
                if (lineType == SCE_DIFF_COMMAND)
                        nextLevel = (SC_FOLDLEVELBASE + 1) | SC_FOLDLEVELHEADERFLAG;
@@ -248,13 +556,13 @@ static void FoldDiffDoc(unsigned int startPos, int length, int, WordList*[], Acc
                        nextLevel = (SC_FOLDLEVELBASE + 2) | SC_FOLDLEVELHEADERFLAG;
                } else if (lineType == SCE_DIFF_POSITION)
                        nextLevel = (SC_FOLDLEVELBASE + 3) | SC_FOLDLEVELHEADERFLAG;
-               
+
                if ((nextLevel & SC_FOLDLEVELHEADERFLAG) && (nextLevel == prevLevel))
                        styler.SetLevel(curLine-1, prevLevel & ~SC_FOLDLEVELHEADERFLAG);
 
                styler.SetLevel(curLine, nextLevel);
                prevLevel = nextLevel;
-               
+
                curLineStart = styler.LineStart(++curLine);
        } while (static_cast<int>(startPos) + length > curLineStart);
 }
@@ -372,7 +680,7 @@ static void FoldPropsDoc(unsigned int startPos, int length, int, WordList *[], A
 
                        lineCurrent++;
                        visibleChars = 0;
-                       headerPoint=false;
+                       headerPoint = false;
                }
                if (!isspacechar(ch))
                        visibleChars++;
@@ -475,172 +783,207 @@ static void ColouriseMakeDoc(unsigned int startPos, int length, int, WordList *[
        }
 }
 
-static bool strstart(char *haystack, char *needle) {
+static bool strstart(const char *haystack, const char *needle) {
        return strncmp(haystack, needle, strlen(needle)) == 0;
 }
 
-static void ColouriseErrorListLine(
-    char *lineBuffer,
-    unsigned int lengthLine,
-    //         unsigned int startLine,
-    unsigned int endPos,
-    Accessor &styler) {
-       const int unRecognized = 99;
+static int RecogniseErrorListLine(const char *lineBuffer, unsigned int lengthLine) {
        if (lineBuffer[0] == '>') {
                // Command or return status
-               styler.ColourTo(endPos, SCE_ERR_CMD);
+               return SCE_ERR_CMD;
        } else if (lineBuffer[0] == '<') {
                // Diff removal, but not interested. Trapped to avoid hitting CTAG cases.
-               styler.ColourTo(endPos, SCE_ERR_DEFAULT);
+               return SCE_ERR_DEFAULT;
        } else if (lineBuffer[0] == '!') {
-               styler.ColourTo(endPos, SCE_ERR_DIFF_CHANGED);
+               return SCE_ERR_DIFF_CHANGED;
        } else if (lineBuffer[0] == '+') {
-               styler.ColourTo(endPos, SCE_ERR_DIFF_ADDITION);
-       } else if (lineBuffer[0] == '-' && lineBuffer[1] == '-' && lineBuffer[2] == '-') {
-               styler.ColourTo(endPos, SCE_ERR_DIFF_MESSAGE);
+               if (strstart(lineBuffer, "+++ ")) {
+                       return SCE_ERR_DIFF_MESSAGE;
+               } else {
+                       return SCE_ERR_DIFF_ADDITION;
+               }
        } else if (lineBuffer[0] == '-') {
-               styler.ColourTo(endPos, SCE_ERR_DIFF_DELETION);
+               if (strstart(lineBuffer, "--- ")) {
+                       return SCE_ERR_DIFF_MESSAGE;
+               } else {
+                       return SCE_ERR_DIFF_DELETION;
+               }
        } else if (strstart(lineBuffer, "cf90-")) {
                // Absoft Pro Fortran 90/95 v8.2 error and/or warning message
-               styler.ColourTo(endPos, SCE_ERR_ABSF);
+               return SCE_ERR_ABSF;
        } else if (strstart(lineBuffer, "fortcom:")) {
                // Intel Fortran Compiler v8.0 error/warning message
-               styler.ColourTo(endPos, SCE_ERR_IFORT);
+               return SCE_ERR_IFORT;
        } else if (strstr(lineBuffer, "File \"") && strstr(lineBuffer, ", line ")) {
-               styler.ColourTo(endPos, SCE_ERR_PYTHON);
+               return SCE_ERR_PYTHON;
        } else if (strstr(lineBuffer, " in ") && strstr(lineBuffer, " on line ")) {
-               styler.ColourTo(endPos, SCE_ERR_PHP);
+               return SCE_ERR_PHP;
        } else if ((strstart(lineBuffer, "Error ") ||
-               strstart(lineBuffer, "Warning ")) &&
-               strstr(lineBuffer, " at (") &&
-               strstr(lineBuffer, ") : ") &&
-               (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) {
+                   strstart(lineBuffer, "Warning ")) &&
+                  strstr(lineBuffer, " at (") &&
+                  strstr(lineBuffer, ") : ") &&
+                  (strstr(lineBuffer, " at (") < strstr(lineBuffer, ") : "))) {
                // Intel Fortran Compiler error/warning message
-               styler.ColourTo(endPos, SCE_ERR_IFC);
+               return SCE_ERR_IFC;
        } else if (strstart(lineBuffer, "Error ")) {
                // Borland error message
-               styler.ColourTo(endPos, SCE_ERR_BORLAND);
+               return SCE_ERR_BORLAND;
        } else if (strstart(lineBuffer, "Warning ")) {
                // Borland warning message
-               styler.ColourTo(endPos, SCE_ERR_BORLAND);
+               return SCE_ERR_BORLAND;
        } else if (strstr(lineBuffer, "at line " ) &&
                   (strstr(lineBuffer, "at line " ) < (lineBuffer + lengthLine)) &&
                   strstr(lineBuffer, "file ") &&
                   (strstr(lineBuffer, "file ") < (lineBuffer + lengthLine))) {
                // Lua 4 error message
-               styler.ColourTo(endPos, SCE_ERR_LUA);
+               return SCE_ERR_LUA;
        } else if (strstr(lineBuffer, " at " ) &&
                   (strstr(lineBuffer, " at " ) < (lineBuffer + lengthLine)) &&
                   strstr(lineBuffer, " line ") &&
                   (strstr(lineBuffer, " line ") < (lineBuffer + lengthLine)) &&
-                          (strstr(lineBuffer, " at " ) < (strstr(lineBuffer, " line ")))) {
+                  (strstr(lineBuffer, " at " ) < (strstr(lineBuffer, " line ")))) {
                // perl error message
-               styler.ColourTo(endPos, SCE_ERR_PERL);
+               return SCE_ERR_PERL;
        } else if ((memcmp(lineBuffer, "   at ", 6) == 0) &&
-               strstr(lineBuffer, ":line ")) {
+                  strstr(lineBuffer, ":line ")) {
                // A .NET traceback
-               styler.ColourTo(endPos, SCE_ERR_NET);
+               return SCE_ERR_NET;
        } else if (strstart(lineBuffer, "Line ") &&
-               strstr(lineBuffer, ", file ")) {
+                  strstr(lineBuffer, ", file ")) {
                // Essential Lahey Fortran error message
-               styler.ColourTo(endPos, SCE_ERR_ELF);
+               return SCE_ERR_ELF;
        } else if (strstart(lineBuffer, "line ") &&
-                      strstr(lineBuffer, " column ")) {
+                  strstr(lineBuffer, " column ")) {
                // HTML tidy style: line 42 column 1
-               styler.ColourTo(endPos, SCE_ERR_TIDY);
+               return SCE_ERR_TIDY;
        } else if (strstart(lineBuffer, "\tat ") &&
-               strstr(lineBuffer, "(") &&
-               strstr(lineBuffer, ".java:")) {
+                  strstr(lineBuffer, "(") &&
+                  strstr(lineBuffer, ".java:")) {
                // Java stack back trace
-               styler.ColourTo(endPos, SCE_ERR_JAVA_STACK);
+               return SCE_ERR_JAVA_STACK;
        } else {
-               // Look for GCC <filename>:<line>:message
-               // Look for Microsoft <filename>(line) :message
-               // Look for Microsoft <filename>(line,pos)message
-               // Look for CTags \tmessage
-               // Look for Lua 5 traceback \t<filename>:<line>:message
+               // Look for one of the following formats:
+               // GCC: <filename>:<line>:<message>
+               // Microsoft: <filename>(<line>) :<message>
+               // Common: <filename>(<line>): warning|error|note|remark|catastrophic|fatal
+               // Common: <filename>(<line>) warning|error|note|remark|catastrophic|fatal
+               // Microsoft: <filename>(<line>,<column>)<message>
+               // CTags: \t<message>
+               // Lua 5 traceback: \t<filename>:<line>:<message>
                bool initialTab = (lineBuffer[0] == '\t');
-               int state = 0;
+               enum { stInitial, 
+                       stGccStart, stGccDigit, stGcc,
+                       stMsStart, stMsDigit, stMsBracket, stMsVc, stMsDigitComma, stMsDotNet,
+                       stCtagsStart, stCtagsStartString, stCtagsStringDollar, stCtags,
+                       stUnrecognized
+               } state = stInitial;
                for (unsigned int i = 0; i < lengthLine; i++) {
                        char ch = lineBuffer[i];
                        char chNext = ' ';
-                       if ((i+1) < lengthLine)
-                               chNext = lineBuffer[i+1];
-                       if (state == 0) {
+                       if ((i + 1) < lengthLine)
+                               chNext = lineBuffer[i + 1];
+                       if (state == stInitial) {
                                if (ch == ':') {
                                        // May be GCC, or might be Lua 5 (Lua traceback same but with tab prefix)
                                        if ((chNext != '\\') && (chNext != '/')) {
                                                // This check is not completely accurate as may be on
                                                // GTK+ with a file name that includes ':'.
-                                               state = 1;
+                                               state = stGccStart;
                                        }
                                } else if ((ch == '(') && Is1To9(chNext) && (!initialTab)) {
                                        // May be Microsoft
                                        // Check against '0' often removes phone numbers
-                                       state = 10;
+                                       state = stMsStart;
                                } else if ((ch == '\t') && (!initialTab)) {
                                        // May be CTags
-                                       state = 20;
+                                       state = stCtagsStart;
                                }
-                       } else if (state == 1) {
-                               state = Is1To9(ch) ? 2 : unRecognized;
-                       } else if (state == 2) {
+                       } else if (state == stGccStart) {       // <filename>:
+                               state = Is1To9(ch) ? stGccDigit : stUnrecognized;
+                       } else if (state == stGccDigit) {       // <filename>:<line>
                                if (ch == ':') {
-                                       state = 3;      // :9.*: is GCC
+                                       state = stGcc;  // :9.*: is GCC
                                        break;
                                } else if (!Is0To9(ch)) {
-                                       state = unRecognized;
+                                       state = stUnrecognized;
                                }
-                       } else if (state == 10) {
-                               state = Is0To9(ch) ? 11 : unRecognized;
-                       } else if (state == 11) {
+                       } else if (state == stMsStart) {        // <filename>(
+                               state = Is0To9(ch) ? stMsDigit : stUnrecognized;
+                       } else if (state == stMsDigit) {        // <filename>(<line>
                                if (ch == ',') {
-                                       state = 14;
+                                       state = stMsDigitComma;
                                } else if (ch == ')') {
-                                       state = 12;
+                                       state = stMsBracket;
                                } else if ((ch != ' ') && !Is0To9(ch)) {
-                                       state = unRecognized;
+                                       state = stUnrecognized;
                                }
-                       } else if (state == 12) {
+                       } else if (state == stMsBracket) {      // <filename>(<line>)
                                if ((ch == ' ') && (chNext == ':')) {
-                                       state = 13;
+                                       state = stMsVc;
+                               } else if ((ch == ':' && chNext == ' ') || (ch == ' ')) {
+                                       // Possibly Delphi.. don't test against chNext as it's one of the strings below.
+                                       char word[512];
+                                       unsigned int j, chPos;
+                                       unsigned numstep;
+                                       chPos = 0;
+                                       if (ch == ' ')
+                                               numstep = 1; // ch was ' ', handle as if it's a delphi errorline, only add 1 to i.
+                                       else
+                                               numstep = 2; // otherwise add 2.
+                                       for (j = i + numstep; j < lengthLine && isalpha(lineBuffer[j]) && chPos < sizeof(word) - 1; j++)
+                                               word[chPos++] = lineBuffer[j];
+                                       word[chPos] = 0;
+                                       if (!CompareCaseInsensitive(word, "error") || !CompareCaseInsensitive(word, "warning") || 
+                                               !CompareCaseInsensitive(word, "fatal") || !CompareCaseInsensitive(word, "catastrophic") || 
+                                               !CompareCaseInsensitive(word, "note") || !CompareCaseInsensitive(word, "remark")) {
+                                               state = stMsVc;
+                                       } else
+                                               state = stUnrecognized;
                                } else {
-                                       state = unRecognized;
+                                       state = stUnrecognized;
                                }
-                       } else if (state == 14) {
+                       } else if (state == stMsDigitComma) {   // <filename>(<line>,
                                if (ch == ')') {
-                                       state = 15;
+                                       state = stMsDotNet;
                                        break;
                                } else if ((ch != ' ') && !Is0To9(ch)) {
-                                       state = unRecognized;
+                                       state = stUnrecognized;
                                }
-                       } else if (state == 20) {
-                               if ((lineBuffer[i-1] == '\t') &&
-                                       ((ch == '/' && lineBuffer[i+1] == '^') || Is0To9(ch))) {
-                                       state = 24;
+                       } else if (state == stCtagsStart) {
+                               if ((lineBuffer[i - 1] == '\t') &&
+                                       ((ch == '/' && lineBuffer[i + 1] == '^') || Is0To9(ch))) {
+                                       state = stCtags;
                                        break;
-                               } else if ((ch == '/') && (lineBuffer[i+1] == '^')) {
-                                       state = 21;
+                               } else if ((ch == '/') && (lineBuffer[i + 1] == '^')) {
+                                       state = stCtagsStartString;
                                }
-                       } else if ((state == 21) && ((lineBuffer[i] == '$') && (lineBuffer[i+1] == '/'))) {
-                               state = 22;
+                       } else if ((state == stCtagsStartString) && ((lineBuffer[i] == '$') && (lineBuffer[i + 1] == '/'))) {
+                               state = stCtagsStringDollar;
                                break;
                        }
                }
-               if (state == 3) {
-                       styler.ColourTo(endPos, SCE_ERR_GCC);
-               } else if ((state == 13) || (state == 14) || (state == 15)) {
-                       styler.ColourTo(endPos, SCE_ERR_MS);
-               } else if ((state == 22) || (state == 24)) {
-                       styler.ColourTo(endPos, SCE_ERR_CTAG);
+               if (state == stGcc) {
+                       return SCE_ERR_GCC;
+               } else if ((state == stMsVc) || (state == stMsDotNet)) {
+                       return SCE_ERR_MS;
+               } else if ((state == stCtagsStringDollar) || (state == stCtags)) {
+                       return SCE_ERR_CTAG;
                } else {
-                       styler.ColourTo(endPos, SCE_ERR_DEFAULT);
+                       return SCE_ERR_DEFAULT;
                }
        }
 }
 
+static void ColouriseErrorListLine(
+    char *lineBuffer,
+    unsigned int lengthLine,
+    unsigned int endPos,
+    Accessor &styler) {
+       styler.ColourTo(endPos, RecogniseErrorListLine(lineBuffer, lengthLine));
+}
+
 static void ColouriseErrorListDoc(unsigned int startPos, int length, int, WordList *[], Accessor &styler) {
-       char lineBuffer[1024];
+       char lineBuffer[10000];
        styler.StartAt(startPos);
        styler.StartSegment(startPos);
        unsigned int linePos = 0;
index 0c1a21ab48bdd7c8fdc8f1c8e76a9184a939759c..5cc05ce6ab70f3a764d8d1acfb38363cf360930f 100644 (file)
@@ -3,7 +3,7 @@
  ** Lexer for POV-Ray SDL (Persistance of Vision Raytracer, Scene Description Language).
  ** Written by Philippe Lhoste but this is mostly a derivative of LexCPP...
  **/
-// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 // Some points that distinguish from a simple C lexer:
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-static inline bool IsAWordChar(const int ch) {
+static inline bool IsAWordChar(int ch) {
        return ch < 0x80 && (isalnum(ch) || ch == '_');
 }
 
-static inline bool IsAWordStart(const int ch) {
+static inline bool IsAWordStart(int ch) {
        return ch < 0x80 && isalpha(ch);
 }
 
-static inline bool IsANumberChar(const int ch) {
+static inline bool IsANumberChar(int ch) {
        // Not exactly following number definition (several dots are seen as OK, etc.)
        // but probably enough in most cases.
        return (ch < 0x80) &&
@@ -69,13 +69,14 @@ static void ColourisePovDoc(
        }
 
        // Do not leak onto next line
-       if (initStyle == SCE_POV_STRINGEOL) {
+       if (initStyle == SCE_POV_STRINGEOL || initStyle == SCE_POV_COMMENTLINE) {
                initStyle = SCE_POV_DEFAULT;
        }
 
-       StyleContext sc(startPos, length, initStyle, styler);
        short stringLen = 0;
 
+       StyleContext sc(startPos, length, initStyle, styler);
+
        for (; sc.More(); sc.Forward()) {
                if (sc.atLineEnd) {
                        // Update the line state, so it can be seen by next line
@@ -125,7 +126,8 @@ static void ColourisePovDoc(
                        }
                } else if (sc.state == SCE_POV_DIRECTIVE) {
                        if (!IsAWordChar(sc.ch)) {
-                               char s[100], *p;
+                               char s[100];
+                               char *p;
                                sc.GetCurrent(s, sizeof(s));
                                p = s;
                                // Skip # and whitespace between # and directive word
@@ -150,7 +152,7 @@ static void ColourisePovDoc(
                        }
                } else if (sc.state == SCE_POV_COMMENTLINE) {
                        if (sc.atLineEnd) {
-                               sc.SetState(SCE_POV_DEFAULT);
+                               sc.ForwardSetState(SCE_POV_DEFAULT);
                        }
                } else if (sc.state == SCE_POV_STRING) {
                        if (sc.ch == '\\') {
index a44f3cefcca362af5f0a2daa672a3fb448a7874a..3c75ae554d65bf05d28cecf9f4b197ac8b52a7e3 100644 (file)
@@ -11,7 +11,6 @@
 #include <ctype.h>
 #include <stdarg.h>
 #include <stdio.h>
-#include <fcntl.h>
 
 #include "Platform.h"
 
index 67d60fc1ae8f5a290718a732147f04c950f0d706..cb9152ecaf2fd2b2301c199b514700d86196fc8a 100644 (file)
@@ -2,8 +2,8 @@
 /** @file LexPerl.cxx
  ** Lexer for subset of Perl.
  **/
-// Lexical analysis fixes by Kein-Hong Man <mkh@pl.jaring.my> 2003-2004
-// Copyright 1998-2004 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
+// Lexical analysis fixes by Kein-Hong Man <mkh@pl.jaring.my>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-#define PERLNUM_DECIMAL 1
-#define PERLNUM_NON_DEC 2
-#define PERLNUM_FLOAT 3
-#define PERLNUM_VECTOR 4
-#define PERLNUM_V_VECTOR 5
+#define PERLNUM_BINARY 1    // order is significant: 1-4 cannot have a dot
+#define PERLNUM_HEX 2
+#define PERLNUM_OCTAL 3
+#define PERLNUM_FLOAT 4     // actually exponent part
+#define PERLNUM_DECIMAL 5   // 1-5 are numbers; 6-7 are strings
+#define PERLNUM_VECTOR 6
+#define PERLNUM_V_VECTOR 7
+#define PERLNUM_BAD 8
+
+#define BACK_NONE 0         // lookback state for bareword disambiguation:
+#define BACK_OPERATOR 1     // whitespace/comments are insignificant
+#define BACK_KEYWORD 2      // operators/keywords are needed for disambiguation
 
 #define HERE_DELIM_MAX 256
 
@@ -44,7 +51,7 @@ static inline bool isPerlOperator(char ch) {
                ch == '(' || ch == ')' || ch == '-' || ch == '+' ||
                ch == '=' || ch == '|' || ch == '{' || ch == '}' ||
                ch == '[' || ch == ']' || ch == ':' || ch == ';' ||
-               ch == '>' || ch == ',' || 
+               ch == '>' || ch == ',' ||
                ch == '?' || ch == '!' || ch == '.' || ch == '~')
                return true;
        // these chars are already tested before this call
@@ -52,17 +59,13 @@ static inline bool isPerlOperator(char ch) {
        return false;
 }
 
-static int classifyWordPerl(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
+static bool isPerlKeyword(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
        char s[100];
-       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
-               s[i] = styler[start + i];
-               s[i + 1] = '\0';
-       }
-       char chAttr = SCE_PL_IDENTIFIER;
-       if (keywords.InList(s))
-               chAttr = SCE_PL_WORD;
-       styler.ColourTo(end, chAttr);
-       return chAttr;
+    unsigned int i, len = end - start;
+    if (len > 30) { len = 30; }
+       for (i = 0; i < len; i++, start++) s[i] = styler[start];
+    s[i] = '\0';
+       return keywords.InList(s);
 }
 
 static inline bool isEndVar(char ch) {
@@ -76,16 +79,12 @@ static inline bool isNonQuote(char ch) {
 }
 
 static inline char actualNumStyle(int numberStyle) {
-       switch (numberStyle) {
-       case PERLNUM_VECTOR:
-       case PERLNUM_V_VECTOR:
-               return SCE_PL_STRING;
-       case PERLNUM_DECIMAL:
-       case PERLNUM_NON_DEC:
-       case PERLNUM_FLOAT:
-       default:
-               return SCE_PL_NUMBER;
-       }
+    if (numberStyle == PERLNUM_VECTOR || numberStyle == PERLNUM_V_VECTOR) {
+        return SCE_PL_STRING;
+    } else if (numberStyle == PERLNUM_BAD) {
+        return SCE_PL_ERROR;
+    }
+    return SCE_PL_NUMBER;
 }
 
 static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) {
@@ -133,6 +132,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                char *Delimiter;        // the Delimiter, 256: sizeof PL_tokenbuf
                HereDocCls() {
                        State = 0;
+            Quote = 0;
+            Quoted = false;
                        DelimiterLength = 0;
                        Delimiter = new char[HERE_DELIM_MAX];
                        Delimiter[0] = '\0';
@@ -196,6 +197,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
        || state == SCE_PL_CHARACTER
        || state == SCE_PL_NUMBER
        || state == SCE_PL_IDENTIFIER
+    || state == SCE_PL_ERROR
        ) {
                while ((startPos > 1) && (styler.StyleAt(startPos - 1) == state)) {
                        startPos--;
@@ -203,6 +205,22 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                state = SCE_PL_DEFAULT;
        }
 
+    // lookback at start of lexing to set proper state for backflag
+    // after this, they are updated when elements are lexed
+    int backflag = BACK_NONE;
+    unsigned int backPos = startPos;
+    if (backPos > 0) {
+        backPos--;
+        int sty = SCE_PL_DEFAULT;
+        while ((backPos > 0) && (sty = styler.StyleAt(backPos),
+               sty == SCE_PL_DEFAULT || sty == SCE_PL_COMMENTLINE))
+            backPos--;
+        if (sty == SCE_PL_OPERATOR)
+            backflag = BACK_OPERATOR;
+        else if (sty == SCE_PL_WORD)
+            backflag = BACK_KEYWORD;
+    }
+
        styler.StartAt(startPos);
        char chPrev = styler.SafeGetCharAt(startPos - 1);
        if (startPos == 0)
@@ -269,25 +287,34 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                        if (isdigit(ch) || (isdigit(chNext) &&
                                (ch == '.' || ch == 'v'))) {
                                state = SCE_PL_NUMBER;
+                backflag = BACK_NONE;
                                numState = PERLNUM_DECIMAL;
                                dotCount = 0;
                                if (ch == '0') {        // hex,bin,octal
-                                       if (chNext == 'x' || chNext == 'b' || isdigit(chNext)) {
-                                               numState = PERLNUM_NON_DEC;
-                                       }
+                                       if (chNext == 'x') {
+                                               numState = PERLNUM_HEX;
+                                       } else if (chNext == 'b') {
+                        numState = PERLNUM_BINARY;
+                    } else if (isdigit(chNext)) {
+                        numState = PERLNUM_OCTAL;
+                    }
+                    if (numState != PERLNUM_DECIMAL) {
+                                               i++;
+                                               ch = chNext;
+                                               chNext = chNext2;
+                    }
                                } else if (ch == 'v') { // vector
                                        numState = PERLNUM_V_VECTOR;
                                }
                        } else if (iswordstart(ch)) {
-                               if (chPrev == '>' && styler.SafeGetCharAt(i - 2) == '-') {
-                                       state = SCE_PL_IDENTIFIER;      // part of "->" expr
-                                       if ((!iswordchar(chNext) && chNext != '\'')
-                                               || (chNext == '.' && chNext2 == '.')) {
-                                               // We need that if length of word == 1!
-                                               styler.ColourTo(i, SCE_PL_IDENTIFIER);
-                                               state = SCE_PL_DEFAULT;
-                                       }
-                               } else if (ch == 's' && !isNonQuote(chNext)) {
+                // if immediately prefixed by '::', always a bareword
+                state = SCE_PL_WORD;
+                if (chPrev == ':' && styler.SafeGetCharAt(i - 2) == ':') {
+                    state = SCE_PL_IDENTIFIER;
+                }
+                unsigned int kw = i + 1;
+                // first check for possible quote-like delimiter
+                               if (ch == 's' && !isNonQuote(chNext)) {
                                        state = SCE_PL_REGSUBST;
                                        Quote.New(2);
                                } else if (ch == 'm' && !isNonQuote(chNext)) {
@@ -302,36 +329,119 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                } else if (ch == 't' && chNext == 'r' && !isNonQuote(chNext2)) {
                                        state = SCE_PL_REGSUBST;
                                        Quote.New(2);
-                                       i++;
-                                       chNext = chNext2;
+                    kw++;
                                } else if (ch == 'q' && (chNext == 'q' || chNext == 'r' || chNext == 'w' || chNext == 'x') && !isNonQuote(chNext2)) {
                                        if      (chNext == 'q') state = SCE_PL_STRING_QQ;
                                        else if (chNext == 'x') state = SCE_PL_STRING_QX;
                                        else if (chNext == 'r') state = SCE_PL_STRING_QR;
                                        else if (chNext == 'w') state = SCE_PL_STRING_QW;
-                                       i++;
-                                       chNext = chNext2;
                                        Quote.New(1);
+                    kw++;
                                } else if (ch == 'x' && (chNext == '=' ||       // repetition
-                                          (chNext != '_' && !isalnum(chNext)) ||
-                                          (isdigit(chPrev) && isdigit(chNext)))) {
-                                       styler.ColourTo(i, SCE_PL_OPERATOR);
-                               } else {
-                                       state = SCE_PL_WORD;
-                                       if ((!iswordchar(chNext) && chNext != '\'')
-                                               || (chNext == '.' && chNext2 == '.')) {
-                                               // We need that if length of word == 1!
-                                               // This test is copied from the SCE_PL_WORD handler.
-                                               classifyWordPerl(styler.GetStartSegment(), i, keywords, styler);
-                                               state = SCE_PL_DEFAULT;
-                                       }
-                               }
+                           (chNext != '_' && !isalnum(chNext)) ||
+                           (isdigit(chPrev) && isdigit(chNext)))) {
+                    state = SCE_PL_OPERATOR;
+                }
+                // if potentially a keyword, scan forward and grab word, then check
+                // if it's really one; if yes, disambiguation test is performed
+                // otherwise it is always a bareword and we skip a lot of scanning
+                // note: keywords assumed to be limited to [_a-zA-Z] only
+                if (state == SCE_PL_WORD) {
+                    while (iswordstart(styler.SafeGetCharAt(kw))) kw++;
+                    if (!isPerlKeyword(styler.GetStartSegment(), kw, keywords, styler)) {
+                        state = SCE_PL_IDENTIFIER;
+                    }
+                }
+                // if already SCE_PL_IDENTIFIER, then no ambiguity, skip this
+                // for quote-like delimiters/keywords, attempt to disambiguate
+                // to select for bareword, change state -> SCE_PL_IDENTIFIER
+                if (state != SCE_PL_IDENTIFIER && i > 0) {
+                    unsigned int j = i;
+                    bool moreback = false;      // true if passed newline/comments
+                    bool brace = false;         // true if opening brace found
+                    char ch2;
+                    // first look backwards past whitespace/comments for EOLs
+                    // if BACK_NONE, neither operator nor keyword, so skip test
+                    if (backflag != BACK_NONE) {
+                        while (--j > backPos) {
+                            if (isEOLChar(styler.SafeGetCharAt(j)))
+                                moreback = true;
+                        }
+                        ch2 = styler.SafeGetCharAt(j);
+                        if (ch2 == '{' && !moreback) {
+                            // {bareword: possible variable spec
+                            brace = true;
+                        } else if ((ch2 == '&')
+                                // &bareword: subroutine call
+                                || (ch2 == '>' && styler.SafeGetCharAt(j - 1) == '-')
+                                // ->bareword: part of variable spec
+                                || (ch2 == 'b' && styler.Match(j - 2, "su"))) {
+                                // sub bareword: subroutine declaration
+                                // (implied BACK_KEYWORD, no keywords end in 'sub'!)
+                            state = SCE_PL_IDENTIFIER;
+                        }
+                        // if status still ambiguous, look forward after word past
+                        // tabs/spaces only; if ch2 isn't one of '[{(,' it can never
+                        // match anything, so skip the whole thing
+                        j = kw;
+                        if (state != SCE_PL_IDENTIFIER
+                            && (ch2 == '{' || ch2 == '(' || ch2 == '['|| ch2 == ',')
+                            && kw < lengthDoc) {
+                            while (ch2 = styler.SafeGetCharAt(j),
+                                   (ch2 == ' ' || ch2 == '\t') && j < lengthDoc) {
+                                j++;
+                            }
+                            if ((ch2 == '}' && brace)
+                             // {bareword}: variable spec
+                             || (ch2 == '=' && styler.SafeGetCharAt(j + 1) == '>')) {
+                             // [{(, bareword=>: hash literal
+                                state = SCE_PL_IDENTIFIER;
+                            }
+                        }
+                    }
+                }
+                backflag = BACK_NONE;
+                // an identifier or bareword
+                if (state == SCE_PL_IDENTIFIER) {
+                    if ((!iswordchar(chNext) && chNext != '\'')
+                        || (chNext == '.' && chNext2 == '.')) {
+                        // We need that if length of word == 1!
+                        // This test is copied from the SCE_PL_WORD handler.
+                        styler.ColourTo(i, SCE_PL_IDENTIFIER);
+                        state = SCE_PL_DEFAULT;
+                    }
+                // a keyword
+                } else if (state == SCE_PL_WORD) {
+                    i = kw - 1;
+                    if (ch == '_' && chNext == '_' &&
+                        (isMatch(styler, lengthDoc, styler.GetStartSegment(), "__DATA__")
+                      || isMatch(styler, lengthDoc, styler.GetStartSegment(), "__END__"))) {
+                        styler.ColourTo(i, SCE_PL_DATASECTION);
+                        state = SCE_PL_DATASECTION;
+                    } else {
+                        styler.ColourTo(i, SCE_PL_WORD);
+                        state = SCE_PL_DEFAULT;
+                        backflag = BACK_KEYWORD;
+                        backPos = i;
+                    }
+                    ch = styler.SafeGetCharAt(i);
+                    chNext = styler.SafeGetCharAt(i + 1);
+                // a repetition operator 'x'
+                } else if (state == SCE_PL_OPERATOR) {
+                    styler.ColourTo(i, SCE_PL_OPERATOR);
+                    state = SCE_PL_DEFAULT;
+                // quote-like delimiter, skip one char if double-char delimiter
+                } else {
+                    i = kw - 1;
+                    chNext = styler.SafeGetCharAt(i + 1);
+                }
                        } else if (ch == '#') {
                                state = SCE_PL_COMMENTLINE;
                        } else if (ch == '\"') {
                                state = SCE_PL_STRING;
                                Quote.New(1);
                                Quote.Open(ch);
+                backflag = BACK_NONE;
                        } else if (ch == '\'') {
                                if (chPrev == '&') {
                                        // Archaic call
@@ -341,10 +451,12 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        Quote.New(1);
                                        Quote.Open(ch);
                                }
+                backflag = BACK_NONE;
                        } else if (ch == '`') {
                                state = SCE_PL_BACKTICKS;
                                Quote.New(1);
                                Quote.Open(ch);
+                backflag = BACK_NONE;
                        } else if (ch == '$') {
                                if ((chNext == '{') || isspacechar(chNext)) {
                                        styler.ColourTo(i, SCE_PL_SCALAR);
@@ -360,28 +472,42 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                                chNext = chNext2;
                                        }
                                }
+                backflag = BACK_NONE;
                        } else if (ch == '@') {
                                if (isalpha(chNext) || chNext == '#' || chNext == '$'
-                                                   || chNext == '_' || chNext == '+') {
+                                       || chNext == '_' || chNext == '+' || chNext == '-') {
                                        state = SCE_PL_ARRAY;
                                } else if (chNext != '{' && chNext != '[') {
                                        styler.ColourTo(i, SCE_PL_ARRAY);
-                                       i++;
-                                       ch = ' ';
                                } else {
                                        styler.ColourTo(i, SCE_PL_ARRAY);
                                }
+                backflag = BACK_NONE;
                        } else if (ch == '%') {
-                               if (isalpha(chNext) || chNext == '#' || chNext == '$' || chNext == '_') {
+                               if (isalpha(chNext) || chNext == '#' || chNext == '$'
+                    || chNext == '_' || chNext == '!' || chNext == '^') {
                                        state = SCE_PL_HASH;
+                    i++;
+                    ch = chNext;
+                    chNext = chNext2;
                                } else if (chNext == '{') {
                                        styler.ColourTo(i, SCE_PL_HASH);
                                } else {
                                        styler.ColourTo(i, SCE_PL_OPERATOR);
                                }
+                backflag = BACK_NONE;
                        } else if (ch == '*') {
-                               if (isalpha(chNext) || chNext == '_' || chNext == '{') {
+                char strch[2];
+                strch[0] = chNext;
+                strch[1] = '\0';
+                               if (isalpha(chNext) || chNext == '_' ||
+                    NULL != strstr("^/|,\\\";#%^:?<>)[]", strch)) {
                                        state = SCE_PL_SYMBOLTABLE;
+                    i++;
+                    ch = chNext;
+                    chNext = chNext2;
+                               } else if (chNext == '{') {
+                                       styler.ColourTo(i, SCE_PL_SYMBOLTABLE);
                                } else {
                                        if (chNext == '*') {    // exponentiation
                                                i++;
@@ -390,14 +516,22 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        }
                                        styler.ColourTo(i, SCE_PL_OPERATOR);
                                }
-                       } else if (ch == '/') {
+                backflag = BACK_NONE;
+                       } else if (ch == '/' || (ch == '<' && chNext == '<')) {
                                // Explicit backward peeking to set a consistent preferRE for
                                // any slash found, so no longer need to track preferRE state.
                                // Find first previous significant lexed element and interpret.
+                // Test for HERE doc start '<<' shares this code, helps to
+                // determine if it should be an operator.
                                bool preferRE = false;
+                bool isHereDoc = (ch == '<');
+                bool hereDocSpace = false;      // these are for corner case:
+                bool hereDocScalar = false;     // SCALAR [whitespace] '<<'
                                unsigned int bk = (i > 0)? i - 1: 0;
                                char bkch;
                                styler.Flush();
+                if (styler.StyleAt(bk) == SCE_PL_DEFAULT)
+                    hereDocSpace = true;
                                while ((bk > 0) && (styler.StyleAt(bk) == SCE_PL_DEFAULT ||
                                        styler.StyleAt(bk) == SCE_PL_COMMENTLINE)) {
                                        bk--;
@@ -494,9 +628,13 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                                        bk--;
                                                }
                                                break;
+                    case SCE_PL_SCALAR:     // for $var<< case
+                        hereDocScalar = true;
+                        break;
                                        // other styles uses the default, preferRE=false
                                        case SCE_PL_WORD:
                                        case SCE_PL_POD:
+                                       case SCE_PL_POD_VERB:
                                        case SCE_PL_HERE_Q:
                                        case SCE_PL_HERE_QQ:
                                        case SCE_PL_HERE_QX:
@@ -504,24 +642,39 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                                break;
                                        }
                                }
-                               if (preferRE) {
-                                       state = SCE_PL_REGEX;
-                                       Quote.New(1);
-                                       Quote.Open(ch);
-                               } else {
-                                       styler.ColourTo(i, SCE_PL_OPERATOR);
-                               }
-                       } else if (ch == '<' && chNext == '<') {
-                               state = SCE_PL_HERE_DELIM;
-                               HereDoc.State = 0;
+                if (isHereDoc) {    // handle HERE doc
+                    // if SCALAR whitespace '<<', *always* a HERE doc
+                    if (preferRE || (hereDocSpace && hereDocScalar)) {
+                        state = SCE_PL_HERE_DELIM;
+                        HereDoc.State = 0;
+                    } else {        // << operator
+                                               i++;
+                                               ch = chNext;
+                                               chNext = chNext2;
+                        styler.ColourTo(i, SCE_PL_OPERATOR);
+                    }
+                } else {            // handle regexp
+                    if (preferRE) {
+                        state = SCE_PL_REGEX;
+                        Quote.New(1);
+                        Quote.Open(ch);
+                    } else {        // / operator
+                        styler.ColourTo(i, SCE_PL_OPERATOR);
+                    }
+                }
+                backflag = BACK_NONE;
                        } else if (ch == '<') {
                                // looks forward for matching > on same line
                                unsigned int fw = i + 1;
                                while (fw < lengthDoc) {
                                        char fwch = styler.SafeGetCharAt(fw);
-                                       if (isEOLChar(fwch) || isspacechar(fwch))
+                                       if (fwch == ' ') {
+                                               if (styler.SafeGetCharAt(fw-1) != '\\' ||
+                                                   styler.SafeGetCharAt(fw-2) != '\\')
+                                               break;
+                                       } else if (isEOLChar(fwch) || isspacechar(fwch)) {
                                                break;
-                                       else if (fwch == '>') {
+                                       else if (fwch == '>') {
                                                if ((fw - i) == 2 &&    // '<=>' case
                                                    styler.SafeGetCharAt(fw-1) == '=') {
                                                        styler.ColourTo(fw, SCE_PL_OPERATOR);
@@ -535,10 +688,12 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        fw++;
                                }
                                styler.ColourTo(i, SCE_PL_OPERATOR);
+                backflag = BACK_NONE;
                        } else if (ch == '='    // POD
                                   && isalpha(chNext)
                                   && (isEOLChar(chPrev))) {
                                state = SCE_PL_POD;
+                backflag = BACK_NONE;
                                //sookedpos = 0;
                                //sooked[sookedpos] = '\0';
                        } else if (ch == '-'    // file test operators
@@ -549,6 +704,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                i++;
                                ch = chNext;
                                chNext = chNext2;
+                backflag = BACK_NONE;
                        } else if (isPerlOperator(ch)) {
                                if (ch == '.' && chNext == '.') { // .. and ...
                                        i++;
@@ -558,6 +714,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        chNext = styler.SafeGetCharAt(i + 1);
                                }
                                styler.ColourTo(i, SCE_PL_OPERATOR);
+                backflag = BACK_OPERATOR;
+                backPos = i;
                        } else {
                                // keep colouring defaults to make restart easier
                                styler.ColourTo(i, SCE_PL_DEFAULT);
@@ -567,7 +725,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                if (chNext == '.') {
                                        // double dot is always an operator
                                        goto numAtEnd;
-                               } else if (numState == PERLNUM_NON_DEC || numState == PERLNUM_FLOAT) {
+                               } else if (numState <= PERLNUM_FLOAT) {
                                        // non-decimal number or float exponent, consume next dot
                                        styler.ColourTo(i - 1, SCE_PL_NUMBER);
                                        styler.ColourTo(i, SCE_PL_OPERATOR);
@@ -594,7 +752,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                if (numState == PERLNUM_VECTOR || numState == PERLNUM_V_VECTOR) {
                                        if (isalpha(ch)) {
                                                if (dotCount == 0) { // change to word
-                                                       state = SCE_PL_WORD;
+                                                       state = SCE_PL_IDENTIFIER;
                                                } else { // vector then word
                                                        goto numAtEnd;
                                                }
@@ -614,9 +772,24 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        if (!isdigit(ch)) { // float then word
                                                goto numAtEnd;
                                        }
-                               } else {// (numState == PERLNUM_NON_DEC)
-                                       // allow alphanum for bin,hex,oct for now
-                               }
+                               } else if (numState == PERLNUM_OCTAL) {
+                    if (!isdigit(ch))
+                        goto numAtEnd;
+                    else if (ch > '7')
+                        numState = PERLNUM_BAD;
+                } else if (numState == PERLNUM_BINARY) {
+                    if (!isdigit(ch))
+                        goto numAtEnd;
+                    else if (ch > '1')
+                        numState = PERLNUM_BAD;
+                } else if (numState == PERLNUM_HEX) {
+                    int ch2 = toupper(ch);
+                    if (!isdigit(ch) && !(ch2 >= 'A' && ch2 <= 'F'))
+                        goto numAtEnd;
+                               } else {//(numState == PERLNUM_BAD) {
+                    if (!isdigit(ch))
+                        goto numAtEnd;
+                }
                        } else {
                                // complete current number or vector
                        numAtEnd:
@@ -624,25 +797,8 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                state = SCE_PL_DEFAULT;
                                goto restartLexer;
                        }
-               } else if (state == SCE_PL_WORD) {
-                       if ((!iswordchar(chNext) && chNext != '\'')
-                               || chNext == '.') {
-                               // ".." is always an operator if preceded by a SCE_PL_WORD.
-                               // "." never used in Perl variable names
-                               // Archaic Perl has quotes inside names
-                               if (isMatch(styler, lengthDoc, styler.GetStartSegment(), "__DATA__")
-                                || isMatch(styler, lengthDoc, styler.GetStartSegment(), "__END__")) {
-                                       styler.ColourTo(i, SCE_PL_DATASECTION);
-                                       state = SCE_PL_DATASECTION;
-                               } else {
-                                       classifyWordPerl(styler.GetStartSegment(), i, keywords, styler);
-                                       state = SCE_PL_DEFAULT;
-                                       ch = ' ';
-                               }
-                       }
                } else if (state == SCE_PL_IDENTIFIER) {
-                       if ((!iswordchar(chNext) && chNext != '\'')
-                               || chNext == '.') {
+                       if (!iswordstart(chNext) && chNext != '\'') {
                                styler.ColourTo(i, SCE_PL_IDENTIFIER);
                                state = SCE_PL_DEFAULT;
                                ch = ' ';
@@ -685,29 +841,46 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                // Whitespace acceptable after <<[-] operator.
                                //
                                if (HereDoc.State == 0) { // '<<' encountered
+                    bool gotspace = false;
+                    unsigned int oldi = i;
+                    if (chNext == ' ' || chNext == '\t') {
+                        // skip whitespace; legal for quoted delimiters
+                        gotspace = true;
+                        do {
+                            i++;
+                            chNext = styler.SafeGetCharAt(i + 1);
+                        } while ((i + 1 < lengthDoc) && (chNext == ' ' || chNext == '\t'));
+                        chNext2 = styler.SafeGetCharAt(i + 2);
+                    }
                                        HereDoc.State = 1;
                                        HereDoc.Quote = chNext;
                                        HereDoc.Quoted = false;
                                        HereDoc.DelimiterLength = 0;
                                        HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
-                                       if (chNext == '\'' || chNext == '"' || chNext == '`') { // a quoted here-doc delimiter
+                                       if (chNext == '\'' || chNext == '"' || chNext == '`') {
+                        // a quoted here-doc delimiter
                                                i++;
                                                ch = chNext;
                                                chNext = chNext2;
                                                HereDoc.Quoted = true;
-                                       } else if (isalpha(chNext) || chNext == '_') {
-                                               // an unquoted here-doc delimiter, no special handling
                                        } else if (isspacechar(chNext) || isdigit(chNext) || chNext == '\\'
-                                               || chNext == '=' || chNext == '$' || chNext == '@') {
+                                               || chNext == '=' || chNext == '$' || chNext == '@'
+                        || ((isalpha(chNext) || chNext == '_') && gotspace)) {
                                                // left shift << or <<= operator cases
+                        // restore position if operator
+                        i = oldi;
                                                styler.ColourTo(i, SCE_PL_OPERATOR);
                                                state = SCE_PL_DEFAULT;
                                                HereDoc.State = 0;
+                        goto restartLexer;
                                        } else {
+                                               // an unquoted here-doc delimiter, no special handling
+                        // (cannot be prefixed by spaces/tabs), or
                                                // symbols terminates; deprecated zero-length delimiter
                                        }
 
                                } else if (HereDoc.State == 1) { // collect the delimiter
+                    backflag = BACK_NONE;
                                        if (HereDoc.Quoted) { // a quoted here-doc delimiter
                                                if (ch == HereDoc.Quote) { // closing quote => end of delimiter
                                                        styler.ColourTo(i, state);
@@ -746,20 +919,31 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        if (isEOLChar(ch)) {
                                                styler.ColourTo(i - 1, state);
                                                state = SCE_PL_DEFAULT;
+                        backflag = BACK_NONE;
                                                HereDoc.State = 0;
                                                goto restartLexer;
                                        }
                                        chNext = styler.SafeGetCharAt(i + 1);
                                }
-                       } else if (state == SCE_PL_POD) {
-                               if (ch == '=' && isEOLChar(chPrev)) {
-                                       if (isMatch(styler, lengthDoc, i, "=cut")) {
-                                               styler.ColourTo(i - 1 + 4, state);
-                                               i += 4;
-                                               state = SCE_PL_DEFAULT;
-                                               ch = styler.SafeGetCharAt(i);
-                                               //chNext = styler.SafeGetCharAt(i + 1);
-                                               goto restartLexer;
+                       } else if (state == SCE_PL_POD
+                               || state == SCE_PL_POD_VERB) {
+                               if (isEOLChar(chPrev)) {
+                                       if (ch == ' ' || ch == '\t') {
+                                               styler.ColourTo(i - 1, state);
+                                               state = SCE_PL_POD_VERB;
+                                       } else {
+                                               styler.ColourTo(i - 1, state);
+                                               state = SCE_PL_POD;
+                                               if (ch == '=') {
+                                                       if (isMatch(styler, lengthDoc, i, "=cut")) {
+                                                               styler.ColourTo(i - 1 + 4, state);
+                                                               i += 4;
+                                                               state = SCE_PL_DEFAULT;
+                                                               ch = styler.SafeGetCharAt(i);
+                                                               //chNext = styler.SafeGetCharAt(i + 1);
+                                                               goto restartLexer;
+                                                       }
+                                               }
                                        }
                                }
                        } else if (state == SCE_PL_SCALAR       // variable names
@@ -772,8 +956,7 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
                                        chNext = chNext2;
                                }
                                else if (isEndVar(ch)) {
-                                       if ((state == SCE_PL_SCALAR || state == SCE_PL_ARRAY)
-                                           && i == (styler.GetStartSegment() + 1)) {
+                                       if (i == (styler.GetStartSegment() + 1)) {
                                                // Special variable: $(, $_ etc.
                                                styler.ColourTo(i, state);
                                                state = SCE_PL_DEFAULT;
@@ -917,33 +1100,57 @@ static void ColourisePerlDoc(unsigned int startPos, int length, int initStyle,
        styler.ColourTo(lengthDoc - 1, state);
 }
 
+static bool IsCommentLine(int line, Accessor &styler) {
+       int pos = styler.LineStart(line);
+       int eol_pos = styler.LineStart(line + 1) - 1;
+       for (int i = pos; i < eol_pos; i++) {
+               char ch = styler[i];
+        int style = styler.StyleAt(i);
+               if (ch == '#' && style == SCE_PL_COMMENTLINE)
+                       return true;
+               else if (ch != ' ' && ch != '\t')
+                       return false;
+       }
+       return false;
+}
+
 static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[],
                             Accessor &styler) {
        bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
        bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+       // Custom folding of POD and packages
+       bool foldPOD = styler.GetPropertyInt("fold.perl.pod", 1) != 0;
+       bool foldPackage = styler.GetPropertyInt("fold.perl.package", 1) != 0;
        unsigned int endPos = startPos + length;
        int visibleChars = 0;
        int lineCurrent = styler.GetLine(startPos);
-       int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int levelPrev = SC_FOLDLEVELBASE;
+       if (lineCurrent > 0)
+               levelPrev = styler.LevelAt(lineCurrent - 1) >> 16;
        int levelCurrent = levelPrev;
        char chNext = styler[startPos];
+       char chPrev = styler.SafeGetCharAt(startPos - 1);
        int styleNext = styler.StyleAt(startPos);
+       // Used at end of line to determine if the line was a package definition
+       bool isPackageLine = false;
+       bool isPodHeading = false;
        for (unsigned int i = startPos; i < endPos; i++) {
                char ch = chNext;
                chNext = styler.SafeGetCharAt(i + 1);
                int style = styleNext;
                styleNext = styler.StyleAt(i + 1);
                bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
-               if (foldComment && (style == SCE_PL_COMMENTLINE)) {
-                       if ((ch == '/') && (chNext == '/')) {
-                               char chNext2 = styler.SafeGetCharAt(i + 2);
-                               if (chNext2 == '{') {
-                                       levelCurrent++;
-                               } else if (chNext2 == '}') {
-                                       levelCurrent--;
-                               }
-                       }
-               }
+               bool atLineStart = isEOLChar(chPrev) || i == 0;
+        // Comment folding
+               if (foldComment && atEOL && IsCommentLine(lineCurrent, styler))
+        {
+            if (!IsCommentLine(lineCurrent - 1, styler)
+                && IsCommentLine(lineCurrent + 1, styler))
+                levelCurrent++;
+            else if (IsCommentLine(lineCurrent - 1, styler)
+                     && !IsCommentLine(lineCurrent+1, styler))
+                levelCurrent--;
+        }
                if (style == SCE_C_OPERATOR) {
                        if (ch == '{') {
                                levelCurrent++;
@@ -951,8 +1158,51 @@ static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[],
                                levelCurrent--;
                        }
                }
+               // Custom POD folding
+               if (foldPOD && atLineStart) {
+                       int stylePrevCh = (i) ? styler.StyleAt(i - 1):SCE_PL_DEFAULT;
+                       if (style == SCE_PL_POD) {
+                               if (stylePrevCh != SCE_PL_POD && stylePrevCh != SCE_PL_POD_VERB)
+                                       levelCurrent++;
+                               else if (styler.Match(i, "=cut"))
+                                       levelCurrent--;
+                               else if (styler.Match(i, "=head"))
+                                       isPodHeading = true;
+                       } else if (style == SCE_PL_DATASECTION) {
+                if (ch == '=' && isalpha(chNext) && levelCurrent == SC_FOLDLEVELBASE)
+                    levelCurrent++;
+                else if (styler.Match(i, "=cut") && levelCurrent > SC_FOLDLEVELBASE)
+                    levelCurrent--;
+                else if (styler.Match(i, "=head"))
+                                       isPodHeading = true;
+                // if package used or unclosed brace, level > SC_FOLDLEVELBASE!
+                // reset needed as level test is vs. SC_FOLDLEVELBASE
+                else if (styler.Match(i, "__END__"))
+                    levelCurrent = SC_FOLDLEVELBASE;
+            }
+               }
+               // Custom package folding
+               if (foldPackage && atLineStart) {
+                       if (style == SCE_PL_WORD && styler.Match(i, "package")) {
+                               isPackageLine = true;
+                       }
+               }
+
                if (atEOL) {
                        int lev = levelPrev;
+                       if (isPodHeading) {
+                lev = levelPrev - 1;
+                lev |= SC_FOLDLEVELHEADERFLAG;
+                isPodHeading = false;
+                       }
+                       // Check if line was a package declaration
+                       // because packages need "special" treatment
+                       if (isPackageLine) {
+                               lev = SC_FOLDLEVELBASE | SC_FOLDLEVELHEADERFLAG;
+                               levelCurrent = SC_FOLDLEVELBASE + 1;
+                               isPackageLine = false;
+                       }
+            lev |= levelCurrent << 16;
                        if (visibleChars == 0 && foldCompact)
                                lev |= SC_FOLDLEVELWHITEFLAG;
                        if ((levelCurrent > levelPrev) && (visibleChars > 0))
@@ -966,6 +1216,7 @@ static void FoldPerlDoc(unsigned int startPos, int length, int, WordList *[],
                }
                if (!isspacechar(ch))
                        visibleChars++;
+               chPrev = ch;
        }
        // Fill in the real level of the next line, keeping the current flags as they will be filled in later
        int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
index e13c6220d9c40be7efed0ef868639367a557ea5d..c1397b79130979b6390e9bb49357f2a66d1df17e 100644 (file)
@@ -109,6 +109,7 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
        }
 
        WordList &keywords = *keywordlists[0];
+       WordList &keywords2 = *keywordlists[1];
 
        const int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
 
@@ -186,6 +187,8 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
                                        style = SCE_P_CLASSNAME;
                                } else if (kwLast == kwDef) {
                                        style = SCE_P_DEFNAME;
+                               } else if (keywords2.InList(s)) {
+                                       style = SCE_P_WORD2;
                                }
                                sc.ChangeState(style);
                                sc.SetState(SCE_P_DEFAULT);
@@ -198,9 +201,7 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
                                                kwLast = kwImport;
                                        else
                                                kwLast = kwOther;
-                               } else if (style == SCE_P_CLASSNAME) {
-                                       kwLast = kwOther;
-                               } else if (style == SCE_P_DEFNAME) {
+                               } else {
                                        kwLast = kwOther;
                                }
                        }
@@ -208,6 +209,10 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
                        if (sc.ch == '\r' || sc.ch == '\n') {
                                sc.SetState(SCE_P_DEFAULT);
                        }
+               } else if (sc.state == SCE_P_DECORATOR) {
+                       if (sc.ch == '\r' || sc.ch == '\n') {
+                               sc.SetState(SCE_P_DEFAULT);
+                       }
                } else if ((sc.state == SCE_P_STRING) || (sc.state == SCE_P_CHARACTER)) {
                        if (sc.ch == '\\') {
                                if ((sc.chNext == '\r') && (sc.GetRelative(2) == '\n')) {
@@ -262,6 +267,8 @@ static void ColourisePyDoc(unsigned int startPos, int length, int initStyle,
                                sc.SetState(SCE_P_OPERATOR);
                        } else if (sc.ch == '#') {
                                sc.SetState(sc.chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE);
+                       } else if (sc.ch == '@') {
+                               sc.SetState(SCE_P_DECORATOR);
                        } else if (IsPyStringStart(sc.ch, sc.chNext, sc.GetRelative(2))) {
                                unsigned int nextIndex = 0;
                                sc.SetState(GetPyStringState(styler, sc.currentPos, &nextIndex));
@@ -432,6 +439,7 @@ static void FoldPyDoc(unsigned int startPos, int length, int /*initStyle - unuse
 
 static const char * const pythonWordListDesc[] = {
        "Keywords",
+       "Highlighted identifiers",
        0
 };
 
diff --git a/src/stc/scintilla/src/LexRebol.cxx b/src/stc/scintilla/src/LexRebol.cxx
new file mode 100644 (file)
index 0000000..f829c1e
--- /dev/null
@@ -0,0 +1,319 @@
+// Scintilla source code edit control
+/** @file LexRebol.cxx
+ ** Lexer for REBOL.
+ ** Written by Pascal Hurni, inspired from LexLua by Paul Winwood & Marcos E. Wurzius & Philippe Lhoste
+ **
+ ** History:
+ **            2005-04-07      First release.
+ **            2005-04-10      Closing parens and brackets go now in default style
+ **                                    String and comment nesting should be more safe
+ **/
+// Copyright 2005 by Pascal Hurni <pascal_hurni@fastmail.fm>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+#include "StyleContext.h"
+
+
+static inline bool IsAWordChar(const int ch) {
+       return (isalnum(ch) || ch == '?' || ch == '!' || ch == '.' || ch == '\'' || ch == '+' || ch == '-' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~');
+}
+
+static inline bool IsAWordStart(const int ch, const int ch2) {
+       return ((ch == '+' || ch == '-' || ch == '.') && !isdigit(ch2)) ||
+               (isalpha(ch) || ch == '?' || ch == '!' || ch == '\'' || ch == '*' || ch == '&' || ch == '|' || ch == '=' || ch == '_' || ch == '~');
+}
+
+static inline bool IsAnOperator(const int ch, const int ch2, const int ch3) {
+       // One char operators
+       if (IsASpaceOrTab(ch2)) {
+               return ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '<' || ch == '>' || ch == '=' || ch == '?';
+       }
+
+       // Two char operators
+       if (IsASpaceOrTab(ch3)) {
+               return (ch == '*' && ch2 == '*') ||
+                          (ch == '/' && ch2 == '/') ||
+                          (ch == '<' && (ch2 == '=' || ch2 == '>')) ||
+                          (ch == '>' && ch2 == '=') ||
+                          (ch == '=' && (ch2 == '=' || ch2 == '?')) ||
+                          (ch == '?' && ch2 == '?');
+       }
+
+       return false;
+}
+
+static inline bool IsBinaryStart(const int ch, const int ch2, const int ch3, const int ch4) {
+       return (ch == '#' && ch2 == '{') ||
+                  (IsADigit(ch) && ch2 == '#' && ch3 == '{' ) ||
+                  (IsADigit(ch) && IsADigit(ch2) && ch3 == '#' && ch4 == '{' );
+}
+
+
+static void ColouriseRebolDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[], Accessor &styler) {
+
+       WordList &keywords = *keywordlists[0];
+       WordList &keywords2 = *keywordlists[1];
+       WordList &keywords3 = *keywordlists[2];
+       WordList &keywords4 = *keywordlists[3];
+       WordList &keywords5 = *keywordlists[4];
+       WordList &keywords6 = *keywordlists[5];
+       WordList &keywords7 = *keywordlists[6];
+       WordList &keywords8 = *keywordlists[7];
+
+       int currentLine = styler.GetLine(startPos);
+       // Initialize the braced string {.. { ... } ..} nesting level, if we are inside such a string.
+       int stringLevel = 0;
+       if (initStyle == SCE_REBOL_BRACEDSTRING || initStyle == SCE_REBOL_COMMENTBLOCK) {
+               stringLevel = styler.GetLineState(currentLine - 1);
+       }
+
+       bool blockComment = initStyle == SCE_REBOL_COMMENTBLOCK;
+       int dotCount = 0;
+
+       // Do not leak onto next line
+       if (initStyle == SCE_REBOL_COMMENTLINE) {
+               initStyle = SCE_REBOL_DEFAULT;
+       }
+
+       StyleContext sc(startPos, length, initStyle, styler);
+       if (startPos == 0) {
+               sc.SetState(SCE_REBOL_PREFACE);
+       }
+       for (; sc.More(); sc.Forward()) {
+
+               //--- What to do at line end ?
+               if (sc.atLineEnd) {
+                       // Can be either inside a {} string or simply at eol
+                       if (sc.state != SCE_REBOL_BRACEDSTRING && sc.state != SCE_REBOL_COMMENTBLOCK &&
+                               sc.state != SCE_REBOL_BINARY && sc.state != SCE_REBOL_PREFACE)
+                               sc.SetState(SCE_REBOL_DEFAULT);
+
+                       // Update the line state, so it can be seen by next line
+                       currentLine = styler.GetLine(sc.currentPos);
+                       switch (sc.state) {
+                       case SCE_REBOL_BRACEDSTRING:
+                       case SCE_REBOL_COMMENTBLOCK:
+                               // Inside a braced string, we set the line state
+                               styler.SetLineState(currentLine, stringLevel);
+                               break;
+                       default:
+                               // Reset the line state
+                               styler.SetLineState(currentLine, 0);
+                               break;
+                       }
+
+                       // continue with next char
+                       continue;
+               }
+
+               //--- What to do on white-space ?
+               if (IsASpaceOrTab(sc.ch))
+               {
+                       // Return to default if any of these states
+                       if (sc.state == SCE_REBOL_OPERATOR || sc.state == SCE_REBOL_CHARACTER ||
+                               sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR ||
+                               sc.state == SCE_REBOL_TUPLE || sc.state == SCE_REBOL_FILE ||
+                               sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME ||
+                               sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE ||
+                               sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_EMAIL) {
+                               sc.SetState(SCE_REBOL_DEFAULT);
+                       }
+               }
+
+               //--- Specialize state ?
+               // URL, Email look like identifier
+               if (sc.state == SCE_REBOL_IDENTIFIER)
+               {
+                       if (sc.ch == ':' && !IsASpace(sc.chNext)) {
+                               sc.ChangeState(SCE_REBOL_URL);
+                       } else if (sc.ch == '@') {
+                               sc.ChangeState(SCE_REBOL_EMAIL);
+                       } else if (sc.ch == '$') {
+                               sc.ChangeState(SCE_REBOL_MONEY);
+                       }
+               }
+               // Words look like identifiers
+               if (sc.state == SCE_REBOL_IDENTIFIER || (sc.state >= SCE_REBOL_WORD && sc.state <= SCE_REBOL_WORD8)) {
+                       // Keywords ?
+                       if (!IsAWordChar(sc.ch) || sc.Match('/')) {
+                               char s[100];
+                               sc.GetCurrentLowered(s, sizeof(s));
+                               blockComment = strcmp(s, "comment") == 0;
+                               if (keywords8.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD8);
+                               } else if (keywords7.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD7);
+                               } else if (keywords6.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD6);
+                               } else if (keywords5.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD5);
+                               } else if (keywords4.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD4);
+                               } else if (keywords3.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD3);
+                               } else if (keywords2.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD2);
+                               } else if (keywords.InList(s)) {
+                                       sc.ChangeState(SCE_REBOL_WORD);
+                               }
+                               // Keep same style if there are refinements
+                               if (!sc.Match('/')) {
+                                       sc.SetState(SCE_REBOL_DEFAULT);
+                               }
+                       }
+               // special numbers
+               } else if (sc.state == SCE_REBOL_NUMBER) {
+                       switch (sc.ch) {
+                       case 'x':       sc.ChangeState(SCE_REBOL_PAIR);
+                                               break;
+                       case ':':       sc.ChangeState(SCE_REBOL_TIME);
+                                               break;
+                       case '-':
+                       case '/':       sc.ChangeState(SCE_REBOL_DATE);
+                                               break;
+                       case '.':       if (++dotCount >= 2) sc.ChangeState(SCE_REBOL_TUPLE);
+                                               break;
+                       }
+               }
+
+               //--- Determine if the current state should terminate
+               if (sc.state == SCE_REBOL_QUOTEDSTRING || sc.state == SCE_REBOL_CHARACTER) {
+                       if (sc.ch == '^' && sc.chNext == '\"') {
+                               sc.Forward();
+                       } else if (sc.ch == '\"') {
+                               sc.ForwardSetState(SCE_REBOL_DEFAULT);
+                       }
+               } else if (sc.state == SCE_REBOL_BRACEDSTRING || sc.state == SCE_REBOL_COMMENTBLOCK) {
+                       if (sc.ch == '}') {
+                               if (--stringLevel == 0) {
+                                       sc.ForwardSetState(SCE_REBOL_DEFAULT);
+                               }
+                       } else if (sc.ch == '{') {
+                               stringLevel++;
+                       }
+               } else if (sc.state == SCE_REBOL_BINARY) {
+                       if (sc.ch == '}') {
+                               sc.ForwardSetState(SCE_REBOL_DEFAULT);
+                       }
+               } else if (sc.state == SCE_REBOL_TAG) {
+                       if (sc.ch == '>') {
+                               sc.ForwardSetState(SCE_REBOL_DEFAULT);
+                       }
+               } else if (sc.state == SCE_REBOL_PREFACE) {
+                       if (sc.MatchIgnoreCase("rebol"))
+                       {
+                               int i;
+                               for (i=5; IsASpaceOrTab(styler.SafeGetCharAt(sc.currentPos+i, 0)); i++);
+                               if (sc.GetRelative(i) == '[')
+                                       sc.SetState(SCE_REBOL_DEFAULT);
+                       }
+               }
+
+               //--- Parens and bracket changes to default style when the current is a number
+               if (sc.state == SCE_REBOL_NUMBER || sc.state == SCE_REBOL_PAIR || sc.state == SCE_REBOL_TUPLE ||
+                       sc.state == SCE_REBOL_MONEY || sc.state == SCE_REBOL_ISSUE || sc.state == SCE_REBOL_EMAIL ||
+                       sc.state == SCE_REBOL_URL || sc.state == SCE_REBOL_DATE || sc.state == SCE_REBOL_TIME) {
+                       if (sc.ch == '(' || sc.ch == '[' || sc.ch == ')' || sc.ch == ']') {
+                               sc.SetState(SCE_REBOL_DEFAULT);
+                       }
+               }
+
+               //--- Determine if a new state should be entered.
+               if (sc.state == SCE_REBOL_DEFAULT) {
+                       if (IsAnOperator(sc.ch, sc.chNext, sc.GetRelative(2))) {
+                               sc.SetState(SCE_REBOL_OPERATOR);
+                       } else if (IsBinaryStart(sc.ch, sc.chNext, sc.GetRelative(2), sc.GetRelative(3))) {
+                               sc.SetState(SCE_REBOL_BINARY);
+                       } else if (IsAWordStart(sc.ch, sc.chNext)) {
+                               sc.SetState(SCE_REBOL_IDENTIFIER);
+                       } else if (IsADigit(sc.ch) || sc.ch == '+' || sc.ch == '-' || /*Decimal*/ sc.ch == '.' || sc.ch == ',') {
+                               dotCount = 0;
+                               sc.SetState(SCE_REBOL_NUMBER);
+                       } else if (sc.ch == '\"') {
+                               sc.SetState(SCE_REBOL_QUOTEDSTRING);
+                       } else if (sc.ch == '{') {
+                               sc.SetState(blockComment ? SCE_REBOL_COMMENTBLOCK : SCE_REBOL_BRACEDSTRING);
+                               ++stringLevel;
+                       } else if (sc.ch == ';') {
+                               sc.SetState(SCE_REBOL_COMMENTLINE);
+                       } else if (sc.ch == '$') {
+                               sc.SetState(SCE_REBOL_MONEY);
+                       } else if (sc.ch == '%') {
+                               sc.SetState(SCE_REBOL_FILE);
+                       } else if (sc.ch == '<') {
+                               sc.SetState(SCE_REBOL_TAG);
+                       } else if (sc.ch == '#' && sc.chNext == '"') {
+                               sc.SetState(SCE_REBOL_CHARACTER);
+                               sc.Forward();
+                       } else if (sc.ch == '#' && sc.chNext != '"' && sc.chNext != '{' ) {
+                               sc.SetState(SCE_REBOL_ISSUE);
+                       }
+               }
+       }
+       sc.Complete();
+}
+
+
+static void FoldRebolDoc(unsigned int startPos, int length, int /* initStyle */, WordList *[],
+                            Accessor &styler) {
+       unsigned int lengthDoc = startPos + length;
+       int visibleChars = 0;
+       int lineCurrent = styler.GetLine(startPos);
+       int levelPrev = styler.LevelAt(lineCurrent) & SC_FOLDLEVELNUMBERMASK;
+       int levelCurrent = levelPrev;
+       char chNext = styler[startPos];
+       int styleNext = styler.StyleAt(startPos);
+       for (unsigned int i = startPos; i < lengthDoc; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               int style = styleNext;
+               styleNext = styler.StyleAt(i + 1);
+               bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+               if (style == SCE_REBOL_DEFAULT) {
+                       if (ch == '[') {
+                               levelCurrent++;
+                       } else if (ch == ']') {
+                               levelCurrent--;
+                       }
+               }
+               if (atEOL) {
+                       int lev = levelPrev;
+                       if (visibleChars == 0)
+                               lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visibleChars > 0))
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+                       if (lev != styler.LevelAt(lineCurrent)) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+                       lineCurrent++;
+                       levelPrev = levelCurrent;
+                       visibleChars = 0;
+               }
+               if (!isspacechar(ch))
+                       visibleChars++;
+       }
+       // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+       int flagsNext = styler.LevelAt(lineCurrent) & ~SC_FOLDLEVELNUMBERMASK;
+       styler.SetLevel(lineCurrent, levelPrev | flagsNext);
+}
+
+static const char * const rebolWordListDesc[] = {
+       "Keywords",
+       0
+};
+
+LexerModule lmREBOL(SCLEX_REBOL, ColouriseRebolDoc, "rebol", FoldRebolDoc, rebolWordListDesc);
+
index 692a47adefe6c02def9653cb8944c5e0f49d2bc7..f5ad020f404e31eae5127a05cda5f3dc597da048 100644 (file)
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-static void ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) {
+#ifdef SCI_NAMESPACE
+using namespace Scintilla;
+#endif
+
+//XXX Identical to Perl, put in common area
+static inline bool isEOLChar(char ch) {
+       return (ch == '\r') || (ch == '\n');
+}
+
+#define isSafeASCII(ch) ((unsigned int)(ch) <= 127)
+// This one's redundant, but makes for more readable code
+#define isHighBitChar(ch) ((unsigned int)(ch) > 127)
+
+static inline bool isSafeAlpha(char ch) {
+    return (isSafeASCII(ch) && isalpha(ch)) || ch == '_';
+}
+
+static inline bool isSafeAlnum(char ch) {
+    return (isSafeASCII(ch) && isalnum(ch)) || ch == '_';
+}
+
+static inline bool isSafeAlnumOrHigh(char ch) {
+    return isHighBitChar(ch) || isalnum(ch) || ch == '_';
+}
+
+static inline bool isSafeDigit(char ch) {
+    return isSafeASCII(ch) && isdigit(ch);
+}
+
+static inline bool isSafeWordcharOrHigh(char ch) {
+    return isHighBitChar(ch) || iswordchar(ch);
+}
+
+static bool inline iswhitespace(char ch) {
+       return ch == ' ' || ch == '\t';
+}
+
+#define MAX_KEYWORD_LENGTH 200
+
+#define STYLE_MASK 63
+#define actual_style(style) (style & STYLE_MASK)
+
+static bool followsDot(unsigned int pos, Accessor &styler) {
+    styler.Flush();
+    for (; pos >= 1; --pos) {
+        int style = actual_style(styler.StyleAt(pos));
+        char ch;
+        switch (style) {
+            case SCE_RB_DEFAULT:
+                ch = styler[pos];
+                if (ch == ' ' || ch == '\t') {
+                    //continue
+                } else {
+                    return false;
+                }
+                break;
+                
+            case SCE_RB_OPERATOR:
+                return styler[pos] == '.';
+
+            default:
+                return false;
+        }
+    }
+    return false;
+}
+
+// Forward declarations
+static bool keywordIsAmbiguous(const char *prevWord);
+static bool keywordDoStartsLoop(int pos,
+                                Accessor &styler);
+static bool keywordIsModifier(const char *word,
+                              int pos,
+                              Accessor &styler);
+
+static int ClassifyWordRb(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler, char *prevWord) {
        char s[100];
-       bool wordIsNumber = isdigit(styler[start]) != 0;
-       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
-               s[i] = styler[start + i];
-               s[i + 1] = '\0';
+    unsigned int i, j;
+       unsigned int lim = end - start + 1; // num chars to copy
+       if (lim >= MAX_KEYWORD_LENGTH) {
+               lim = MAX_KEYWORD_LENGTH - 1;
+       }
+       for (i = start, j = 0; j < lim; i++, j++) {
+               s[j] = styler[i];
        }
-       char chAttr = SCE_P_IDENTIFIER;
+    s[j] = '\0';
+       int chAttr;
        if (0 == strcmp(prevWord, "class"))
-               chAttr = SCE_P_CLASSNAME;
+               chAttr = SCE_RB_CLASSNAME;
        else if (0 == strcmp(prevWord, "module"))
-               chAttr = SCE_P_CLASSNAME;
+               chAttr = SCE_RB_MODULE_NAME;
        else if (0 == strcmp(prevWord, "def"))
-               chAttr = SCE_P_DEFNAME;
-       else if (wordIsNumber)
-               chAttr = SCE_P_NUMBER;
-       else if (keywords.InList(s))
-               chAttr = SCE_P_WORD;
-       // make sure that dot-qualifiers inside the word are lexed correct
-       else for (unsigned int i = 0; i < end - start + 1; i++) {
-               if (styler[start + i] == '.') {
-                       styler.ColourTo(start + i - 1, chAttr);
-                       styler.ColourTo(start + i, SCE_P_OPERATOR);
+               chAttr = SCE_RB_DEFNAME;
+    else if (keywords.InList(s) && !followsDot(start - 1, styler)) {
+        if (keywordIsAmbiguous(s)
+            && keywordIsModifier(s, start, styler)) {
+            
+            // Demoted keywords are colored as keywords,
+            // but do not affect changes in indentation.
+            //
+            // Consider the word 'if':
+            // 1. <<if test ...>> : normal
+            // 2. <<stmt if test>> : demoted
+            // 3. <<lhs = if ...>> : normal: start a new indent level
+            // 4. <<obj.if = 10>> : color as identifer, since it follows '.'
+            
+            chAttr = SCE_RB_WORD_DEMOTED;
+        } else {
+            chAttr = SCE_RB_WORD;
+        }
+       } else
+        chAttr = SCE_RB_IDENTIFIER;
+       styler.ColourTo(end, chAttr);
+       if (chAttr == SCE_RB_WORD) {
+               strcpy(prevWord, s);
+       } else {
+               prevWord[0] = 0;
+       }
+    return chAttr;
+}
+
+
+//XXX Identical to Perl, put in common area
+static bool isMatch(Accessor &styler, int lengthDoc, int pos, const char *val) {
+       if ((pos + static_cast<int>(strlen(val))) >= lengthDoc) {
+               return false;
+       }
+       while (*val) {
+               if (*val != styler[pos++]) {
+                       return false;
                }
+               val++;
        }
-       styler.ColourTo(end, chAttr);
-       strcpy(prevWord, s);
+       return true;
 }
 
-static bool IsRbComment(Accessor &styler, int pos, int len) {
-       return len>0 && styler[pos]=='#';
+// Do Ruby better -- find the end of the line, work back,
+// and then check for leading white space
+
+// Precondition: the here-doc target can be indented
+static bool lookingAtHereDocDelim(Accessor        &styler,
+                                  int                  pos,
+                                  int                  lengthDoc,
+                                  const char   *HereDocDelim)
+{
+    if (!isMatch(styler, lengthDoc, pos, HereDocDelim)) {
+        return false;
+    }
+    while (--pos > 0) {
+        char ch = styler[pos];
+        if (isEOLChar(ch)) {
+            return true;
+        } else if (ch != ' ' && ch != '\t') {
+            return false;
+        }
+    }
+    return false;
 }
 
-static bool IsRbStringStart(char ch, char chNext, char chNext2) {
-       if (ch == '\'' || ch == '"')
-               return true;
-       if (ch == 'u' || ch == 'U') {
-               if (chNext == '"' || chNext == '\'')
-                       return true;
-               if ((chNext == 'r' || chNext == 'R') && (chNext2 == '"' || chNext2 == '\''))
-                       return true;
-       }
-       if ((ch == 'r' || ch == 'R') && (chNext == '"' || chNext == '\''))
-               return true;
+//XXX Identical to Perl, put in common area
+static char opposite(char ch) {
+       if (ch == '(')
+               return ')';
+       if (ch == '[')
+               return ']';
+       if (ch == '{')
+               return '}';
+       if (ch == '<')
+               return '>';
+       return ch;
+}
+
+// Null transitions when we see we've reached the end
+// and need to relex the curr char.
 
-       return false;
+static void redo_char(int &i, char &ch, char &chNext, char &chNext2,
+                      int &state) {
+    i--;
+    chNext2 = chNext;
+    chNext = ch;
+    state = SCE_RB_DEFAULT;
 }
 
-static bool IsRbWordStart(char ch, char chNext, char chNext2) {
-       return (iswordchar(ch) && !IsRbStringStart(ch, chNext, chNext2));
+static void advance_char(int &i, char &ch, char &chNext, char &chNext2) {
+    i++;
+    ch = chNext;
+    chNext = chNext2;
 }
 
-/* Return the state to use for the string starting at i; *nextIndex will be set to the first index following the quote(s) */
-static int GetRbStringState(Accessor &styler, int i, int *nextIndex) {
-       char ch = styler.SafeGetCharAt(i);
-       char chNext = styler.SafeGetCharAt(i + 1);
+// precondition: startPos points to one after the EOL char
+static bool currLineContainsHereDelims(int& startPos,
+                                       Accessor &styler) {
+    if (startPos <= 1)
+        return false;
 
-       // Advance beyond r, u, or ur prefix, but bail if there are any unexpected chars
-       if (ch == 'r' || ch == 'R') {
-               i++;
-               ch = styler.SafeGetCharAt(i);
-               chNext = styler.SafeGetCharAt(i + 1);
-       }
-       else if (ch == 'u' || ch == 'U') {
-               if (chNext == 'r' || chNext == 'R')
-                       i += 2;
-               else
-                       i += 1;
-               ch = styler.SafeGetCharAt(i);
-               chNext = styler.SafeGetCharAt(i + 1);
-       }
+    int pos;
+    for (pos = startPos - 1; pos > 0; pos--) {
+        char ch = styler.SafeGetCharAt(pos);
+        if (isEOLChar(ch)) {
+            // Leave the pointers where they are -- there are no
+            // here doc delims on the current line, even if
+            // the EOL isn't default style
+            
+            return false;
+        } else {
+            styler.Flush();
+            if (actual_style(styler.StyleAt(pos)) == SCE_RB_HERE_DELIM) {
+                break;
+            }
+        }
+    }
+    if (pos == 0) {
+        return false;
+    }
+    // Update the pointers so we don't have to re-analyze the string
+    startPos = pos;
+    return true;
+}
 
-       if (ch != '"' && ch != '\'') {
-               *nextIndex = i + 1;
-               return SCE_P_DEFAULT;
-       }
 
-       if (i>0 && styler.SafeGetCharAt(i-1) == '$') {
-               *nextIndex = i + 1;
-               return SCE_P_DEFAULT;
-       }
+static bool isEmptyLine(int pos,
+                        Accessor &styler) {
+       int spaceFlags = 0;
+       int lineCurrent = styler.GetLine(pos);
+       int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, NULL);
+    return (indentCurrent & SC_FOLDLEVELWHITEFLAG) != 0;
+}
 
-       if (ch == chNext && ch == styler.SafeGetCharAt(i + 2)) {
-               *nextIndex = i + 3;
+static bool RE_CanFollowKeyword(const char *keyword) {
+    if (!strcmp(keyword, "and")
+        || !strcmp(keyword, "begin")
+        || !strcmp(keyword, "break")
+        || !strcmp(keyword, "case")
+        || !strcmp(keyword, "do")
+        || !strcmp(keyword, "else")
+        || !strcmp(keyword, "elsif")
+        || !strcmp(keyword, "if")
+        || !strcmp(keyword, "next")
+        || !strcmp(keyword, "return")
+        || !strcmp(keyword, "when")
+        || !strcmp(keyword, "unless")
+        || !strcmp(keyword, "until")
+        || !strcmp(keyword, "not")
+        || !strcmp(keyword, "or")) {
+        return true;
+    }
+    return false;
+}
 
-               if (ch == '"')
-                       return SCE_P_TRIPLEDOUBLE;
-               else
-                       return SCE_P_TRIPLE;
-       } else {
-               *nextIndex = i + 1;
+// Look at chars up to but not including endPos
+// Don't look at styles in case we're looking forward
 
-               if (ch == '"')
-                       return SCE_P_STRING;
-               else
-                       return SCE_P_CHARACTER;
-       }
+static int skipWhitespace(int startPos,
+                           int endPos,
+                           Accessor &styler) {
+    for (int i = startPos; i < endPos; i++) {
+        if (!iswhitespace(styler[i])) {
+            return i;
+        }
+    }
+    return endPos;
+}
+    
+// This routine looks for false positives like
+// undef foo, <<
+// There aren't too many.
+//
+// iPrev points to the start of <<
+
+static bool sureThisIsHeredoc(int iPrev, 
+                              Accessor &styler,
+                              char *prevWord) {
+                    
+    // Not so fast, since Ruby's so dynamic.  Check the context
+    // to make sure we're OK.
+    int prevStyle;
+    int lineStart = styler.GetLine(iPrev);
+    int lineStartPosn = styler.LineStart(lineStart);
+    styler.Flush();
+
+    // Find the first word after some whitespace
+    int firstWordPosn = skipWhitespace(lineStartPosn, iPrev, styler);
+    if (firstWordPosn >= iPrev) {
+        // Have something like {^     <<}
+               //XXX Look at the first previous non-comment non-white line
+               // to establish the context.  Not too likely though.
+        return true;
+    } else {
+        switch (prevStyle = styler.StyleAt(firstWordPosn)) {
+        case SCE_RB_WORD:
+        case SCE_RB_WORD_DEMOTED:
+        case SCE_RB_IDENTIFIER:
+            break;
+        default:
+            return true;
+        }
+    }
+    int firstWordEndPosn = firstWordPosn;
+    char *dst = prevWord;
+    for (;;) {
+        if (firstWordEndPosn >= iPrev ||
+            styler.StyleAt(firstWordEndPosn) != prevStyle) {
+            *dst = 0;
+            break;
+        }
+        *dst++ = styler[firstWordEndPosn];
+        firstWordEndPosn += 1;
+    }
+    //XXX Write a style-aware thing to regex scintilla buffer objects
+    if (!strcmp(prevWord, "undef")
+        || !strcmp(prevWord, "def")
+        || !strcmp(prevWord, "alias")) {
+        // These keywords are what we were looking for
+        return false;
+    }
+    return true;
+}
+
+// Routine that saves us from allocating a buffer for the here-doc target
+// targetEndPos points one past the end of the current target
+static bool haveTargetMatch(int currPos,
+                            int lengthDoc,
+                            int targetStartPos,
+                            int targetEndPos,
+                            Accessor &styler) {
+    if (lengthDoc - currPos < targetEndPos - targetStartPos) {
+        return false;
+    }
+    int i, j;
+    for (i = targetStartPos, j = currPos;
+         i < targetEndPos && j < lengthDoc;
+         i++, j++) {
+        if (styler[i] != styler[j]) {
+            return false;
+        }
+    }
+    return true;
+}
+
+// We need a check because the form
+// [identifier] <<[target]
+// is ambiguous.  The Ruby lexer/parser resolves it by
+// looking to see if [identifier] names a variable or a
+// function.  If it's the first, it's the start of a here-doc.
+// If it's a var, it's an operator.  This lexer doesn't
+// maintain a symbol table, so it looks ahead to see what's
+// going on, in cases where we have
+// ^[white-space]*[identifier([.|::]identifier)*][white-space]*<<[target]
+//
+// If there's no occurrence of [target] on a line, assume we don't.
+
+// return true == yes, we have no heredocs
+
+static bool sureThisIsNotHeredoc(int lt2StartPos,
+                                 Accessor &styler) {
+    int prevStyle;
+     // Use full document, not just part we're styling
+    int lengthDoc = styler.Length();
+    int lineStart = styler.GetLine(lt2StartPos);
+    int lineStartPosn = styler.LineStart(lineStart);
+    styler.Flush();
+    const bool definitely_not_a_here_doc = true;
+    const bool looks_like_a_here_doc = false;
+    
+    // Find the first word after some whitespace
+    int firstWordPosn = skipWhitespace(lineStartPosn, lt2StartPos, styler);
+    if (firstWordPosn >= lt2StartPos) {
+        return definitely_not_a_here_doc;
+    }
+    prevStyle = styler.StyleAt(firstWordPosn);
+    // If we have '<<' following a keyword, it's not a heredoc
+    if (prevStyle != SCE_RB_IDENTIFIER) {
+        return definitely_not_a_here_doc;
+    }
+    int newStyle = prevStyle;
+    // Some compilers incorrectly warn about uninit newStyle
+    for (firstWordPosn += 1; firstWordPosn <= lt2StartPos; firstWordPosn += 1) {
+        // Inner loop looks at the name
+        for (; firstWordPosn <= lt2StartPos; firstWordPosn += 1) {
+            newStyle = styler.StyleAt(firstWordPosn);
+            if (newStyle != prevStyle) {
+                break;
+            }
+        }
+        // Do we have '::' or '.'?
+        if (firstWordPosn < lt2StartPos && newStyle == SCE_RB_OPERATOR) {
+            char ch = styler[firstWordPosn];
+            if (ch == '.') {
+                // yes
+            } else if (ch == ':') {
+                if (styler.StyleAt(++firstWordPosn) != SCE_RB_OPERATOR) {
+                    return definitely_not_a_here_doc;
+                } else if (styler[firstWordPosn] != ':') {
+                    return definitely_not_a_here_doc;
+                }
+            } else {
+                break;
+            }
+        } else {
+            break;
+        }
+    }
+    // Skip next batch of white-space
+    firstWordPosn = skipWhitespace(firstWordPosn, lt2StartPos, styler);
+    if (firstWordPosn != lt2StartPos) {
+        // Have [[^ws[identifier]ws[*something_else*]ws<<
+        return definitely_not_a_here_doc;
+    }
+    // OK, now 'j' will point to the current spot moving ahead
+       int j = firstWordPosn + 1;
+    if (styler.StyleAt(j) != SCE_RB_OPERATOR || styler[j] != '<') {
+        // This shouldn't happen
+        return definitely_not_a_here_doc;
+    }
+    int nextLineStartPosn = styler.LineStart(lineStart + 1);
+    if (nextLineStartPosn >= lengthDoc) {
+        return definitely_not_a_here_doc;
+    }
+    j = skipWhitespace(j + 1, nextLineStartPosn, styler);
+    if (j >= lengthDoc) {
+        return definitely_not_a_here_doc;
+    }
+    bool allow_indent;
+    int target_start, target_end;
+    // From this point on no more styling, since we're looking ahead
+    if (styler[j] == '-') {
+        allow_indent = true;
+        j++;
+    } else {
+        allow_indent = false;
+    }
+
+    // Allow for quoted targets.
+    char target_quote = 0;
+    switch (styler[j]) {
+    case '\'':
+    case '"':
+    case '`':
+        target_quote = styler[j];
+        j += 1;
+    }
+    
+    if (isSafeAlnum(styler[j])) {
+        // Init target_end because some compilers think it won't
+        // be initialized by the time it's used
+        target_start = target_end = j;
+        j++;
+    } else {
+        return definitely_not_a_here_doc;
+    }
+    for (; j < lengthDoc; j++) {
+        if (!isSafeAlnum(styler[j])) {
+            if (target_quote && styler[j] != target_quote) {
+                // unquoted end
+                return definitely_not_a_here_doc;
+            }
+
+            // And for now make sure that it's a newline
+            // don't handle arbitrary expressions yet
+            
+            target_end = j;
+                       if (target_quote) {
+                               // Now we can move to the character after the string delimiter.
+                               j += 1;
+                       }
+            j = skipWhitespace(j, lengthDoc, styler);
+            if (j >= lengthDoc) {
+                return definitely_not_a_here_doc;
+            } else {
+                char ch = styler[j];
+                if (ch == '#' || isEOLChar(ch)) {
+                    // This is OK, so break and continue;
+                    break;
+                } else {
+                    return definitely_not_a_here_doc;
+                }
+            }
+        }
+    }
+
+    // Just look at the start of each line
+    int last_line = styler.GetLine(lengthDoc - 1);
+    // But don't go too far
+    if (last_line > lineStart + 50) {
+        last_line = lineStart + 50;
+    }
+    for (int line_num = lineStart + 1; line_num <= last_line; line_num++) {
+        if (allow_indent) {
+            j = skipWhitespace(styler.LineStart(line_num), lengthDoc, styler);
+        } else {
+            j = styler.LineStart(line_num);
+        }
+        // target_end is one past the end
+        if (haveTargetMatch(j, lengthDoc, target_start, target_end, styler)) {
+            // We got it
+            return looks_like_a_here_doc;
+        }
+    }
+    return definitely_not_a_here_doc;
+}
+
+//todo: if we aren't looking at a stdio character,
+// move to the start of the first line that is not in a 
+// multi-line construct
+
+static void synchronizeDocStart(unsigned int& startPos,
+                                int &length,
+                                int &initStyle,
+                                Accessor &styler,
+                                bool skipWhiteSpace=false) {
+
+    styler.Flush();
+    int style = actual_style(styler.StyleAt(startPos));
+    switch (style) {
+        case SCE_RB_STDIN:
+        case SCE_RB_STDOUT:
+        case SCE_RB_STDERR:
+            // Don't do anything else with these.
+            return;
+    }
+    
+    int pos = startPos;
+    // Quick way to characterize each line
+    int lineStart;
+    for (lineStart = styler.GetLine(pos); lineStart > 0; lineStart--) {
+        // Now look at the style before the previous line's EOL
+        pos = styler.LineStart(lineStart) - 1;
+        if (pos <= 10) {
+            lineStart = 0;
+            break;
+        }
+        char ch = styler.SafeGetCharAt(pos);
+        char chPrev = styler.SafeGetCharAt(pos - 1);
+        if (ch == '\n' && chPrev == '\r') {
+            pos--;
+        }
+        if (styler.SafeGetCharAt(pos - 1) == '\\') {
+            // Continuation line -- keep going
+        } else if (actual_style(styler.StyleAt(pos)) != SCE_RB_DEFAULT) {
+            // Part of multi-line construct -- keep going
+        } else if (currLineContainsHereDelims(pos, styler)) {
+            // Keep going, with pos and length now pointing
+            // at the end of the here-doc delimiter
+        } else if (skipWhiteSpace && isEmptyLine(pos, styler)) {
+            // Keep going
+        } else {
+            break;
+        }
+    }
+    pos = styler.LineStart(lineStart);
+    length += (startPos - pos);
+    startPos = pos;
+    initStyle = SCE_RB_DEFAULT;
 }
 
 static void ColouriseRbDoc(unsigned int startPos, int length, int initStyle,
                                                   WordList *keywordlists[], Accessor &styler) {
 
-       int lengthDoc = startPos + length;
+       // Lexer for Ruby often has to backtrack to start of current style to determine
+       // which characters are being used as quotes, how deeply nested is the
+       // start position and what the termination string is for here documents
+    
+       WordList &keywords = *keywordlists[0];
 
-       // Backtrack to previous line in case need to fix its tab whinging
-       if (startPos > 0) {
-               int lineCurrent = styler.GetLine(startPos);
-               if (lineCurrent > 0) {
-                       startPos = styler.LineStart(lineCurrent-1);
-                       if (startPos == 0)
-                               initStyle = SCE_P_DEFAULT;
-                       else
-                               initStyle = styler.StyleAt(startPos-1);
+       class HereDocCls {
+       public:
+               int State;
+        // States
+        // 0: '<<' encountered
+               // 1: collect the delimiter
+        // 1b: text between the end of the delimiter and the EOL
+               // 2: here doc text (lines after the delimiter)
+               char Quote;             // the char after '<<'
+               bool Quoted;            // true if Quote in ('\'','"','`')
+               int DelimiterLength;    // strlen(Delimiter)
+               char Delimiter[256];    // the Delimiter, limit of 256: from Perl
+        bool CanBeIndented;
+               HereDocCls() {
+                       State = 0;
+                       DelimiterLength = 0;
+                       Delimiter[0] = '\0';
+            CanBeIndented = false;
                }
-       }
+       };
+       HereDocCls HereDoc;     
 
-       // Ruby uses a different mask because bad indentation is marked by oring with 32
-       styler.StartAt(startPos, 127);
+       class QuoteCls {
+               public:
+               int  Count;
+               char Up;
+               char Down;
+               QuoteCls() {
+                       this->New();
+               }
+               void New() {
+                       Count = 0;
+                       Up    = '\0';
+                       Down  = '\0';
+               }
+               void Open(char u) {
+                       Count++;
+                       Up    = u;
+                       Down  = opposite(Up);
+               }
+       };
+       QuoteCls Quote;
 
-       WordList &keywords = *keywordlists[0];
+    int numDots = 0;  // For numbers --
+                      // Don't start lexing in the middle of a num
+
+    synchronizeDocStart(startPos, length, initStyle, styler, // ref args
+                        false);
 
-       int whingeLevel = styler.GetPropertyInt("tab.timmy.whinge.level");
-       char prevWord[200];
+       bool preferRE = true;
+    int state = initStyle;
+       int lengthDoc = startPos + length;
+
+       char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
        prevWord[0] = '\0';
        if (length == 0)
-               return ;
+               return;
 
-       int state = initStyle & 31;
-
-       int nextIndex = 0;
-       char chPrev = ' ';
-       char chPrev2 = ' ';
-       char chNext = styler[startPos];
+       char chPrev = styler.SafeGetCharAt(startPos - 1);
+       char chNext = styler.SafeGetCharAt(startPos);
+       // Ruby uses a different mask because bad indentation is marked by oring with 32
+       styler.StartAt(startPos, 127);
        styler.StartSegment(startPos);
-       bool atStartLine = true;
-       int spaceFlags = 0;
-       for (int i = startPos; i < lengthDoc; i++) {
-
-               if (atStartLine) {
-                       char chBad = static_cast<char>(64);
-                       char chGood = static_cast<char>(0);
-                       char chFlags = chGood;
-                       if (whingeLevel == 1) {
-                               chFlags = (spaceFlags & wsInconsistent) ? chBad : chGood;
-                       } else if (whingeLevel == 2) {
-                               chFlags = (spaceFlags & wsSpaceTab) ? chBad : chGood;
-                       } else if (whingeLevel == 3) {
-                               chFlags = (spaceFlags & wsSpace) ? chBad : chGood;
-                       } else if (whingeLevel == 4) {
-                               chFlags = (spaceFlags & wsTab) ? chBad : chGood;
-                       }
-                       styler.SetFlags(chFlags, static_cast<char>(state));
-                       atStartLine = false;
-               }
 
+    static int q_states[] = {SCE_RB_STRING_Q,
+                             SCE_RB_STRING_QQ,
+                             SCE_RB_STRING_QR,
+                             SCE_RB_STRING_QW,
+                             SCE_RB_STRING_QW,
+                             SCE_RB_STRING_QX};
+    static const char* q_chars = "qQrwWx";
+    
+       for (int i = startPos; i < lengthDoc; i++) {
                char ch = chNext;
                chNext = styler.SafeGetCharAt(i + 1);
                char chNext2 = styler.SafeGetCharAt(i + 2);
 
-               if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {
-                       if ((state == SCE_P_DEFAULT) || (state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE)) {
-                               // Perform colourisation of white space and triple quoted strings at end of each line to allow
-                               // tab marking to work inside white space and triple quoted strings
-                               styler.ColourTo(i, state);
-                       }
-                       atStartLine = true;
-               }
-
-               if (styler.IsLeadByte(ch)) {
-                       chNext = styler.SafeGetCharAt(i + 2);
+        if (styler.IsLeadByte(ch)) {
+                       chNext = chNext2;
                        chPrev = ' ';
-                       chPrev2 = ' ';
                        i += 1;
                        continue;
                }
+               
+        // skip on DOS/Windows
+        //No, don't, because some things will get tagged on,
+        // so we won't recognize keywords, for example
+#if 0
+               if (ch == '\r' && chNext == '\n') {
+               continue;
+        }
+#endif
+            
+        if (HereDoc.State == 1 && isEOLChar(ch)) {
+                       // Begin of here-doc (the line after the here-doc delimiter):
+                       HereDoc.State = 2;
+                       styler.ColourTo(i-1, state);
+            // Don't check for a missing quote, just jump into
+            // the here-doc state
+            state = SCE_RB_HERE_Q;
+        }
 
-               if (state == SCE_P_STRINGEOL) {
-                       if (ch != '\r' && ch != '\n') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_P_DEFAULT;
-                       }
-               }
-               if (state == SCE_P_DEFAULT) {
-                       if (IsRbWordStart(ch, chNext, chNext2)) {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_P_WORD;
+        // Regular transitions
+               if (state == SCE_RB_DEFAULT) {
+            if (isSafeDigit(ch)) {
+               styler.ColourTo(i - 1, state);
+                               state = SCE_RB_NUMBER;
+                numDots = 0;
+            } else if (isHighBitChar(ch) || iswordstart(ch)) {
+               styler.ColourTo(i - 1, state);
+                               state = SCE_RB_WORD;
                        } else if (ch == '#') {
                                styler.ColourTo(i - 1, state);
-                               state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
-                       } else if (ch == '=' && chNext == 'b') {
+                               state = SCE_RB_COMMENTLINE;
+                       } else if (ch == '=') {
                                // =begin indicates the start of a comment (doc) block
-                               if(styler.SafeGetCharAt(i + 2) == 'e' && styler.SafeGetCharAt(i + 3) == 'g' && styler.SafeGetCharAt(i + 4) == 'i' && styler.SafeGetCharAt(i + 5) == 'n') {
+                if (i == 0 || isEOLChar(chPrev)
+                    && chNext == 'b'
+                    && styler.SafeGetCharAt(i + 2) == 'e'
+                    && styler.SafeGetCharAt(i + 3) == 'g'
+                    && styler.SafeGetCharAt(i + 4) == 'i'
+                    && styler.SafeGetCharAt(i + 5) == 'n'
+                    && !isSafeWordcharOrHigh(styler.SafeGetCharAt(i + 6))) {
+                    styler.ColourTo(i - 1, state);
+                    state = SCE_RB_POD;
+                               } else {
                                        styler.ColourTo(i - 1, state);
-                                       state = SCE_P_TRIPLEDOUBLE; //SCE_C_COMMENT;
+                                       styler.ColourTo(i, SCE_RB_OPERATOR);
+                                       preferRE = true;
                                }
-                       }  else if (IsRbStringStart(ch, chNext, chNext2)) {
+                       } else if (ch == '"') {
                                styler.ColourTo(i - 1, state);
-                               state = GetRbStringState(styler, i, &nextIndex);
-                               if (nextIndex != i + 1) {
-                                       i = nextIndex - 1;
-                                       ch = ' ';
-                                       chPrev = ' ';
-                                       chNext = styler.SafeGetCharAt(i + 1);
-                               }
-                       } else if (isoperator(ch)) {
+                               state = SCE_RB_STRING;
+                               Quote.New();
+                               Quote.Open(ch);
+                       } else if (ch == '\'') {
+                styler.ColourTo(i - 1, state);
+                state = SCE_RB_CHARACTER;
+                Quote.New();
+                Quote.Open(ch);
+                       } else if (ch == '`') {
                                styler.ColourTo(i - 1, state);
-                               styler.ColourTo(i, SCE_P_OPERATOR);
-                       }
-                       } else if (state == SCE_P_WORD) {
-                       if (!iswordchar(ch)) {
-                               ClassifyWordRb(styler.GetStartSegment(), i - 1, keywords, styler, prevWord);
-                               state = SCE_P_DEFAULT;
-                               if (ch == '#') {
-                                       state = chNext == '#' ? SCE_P_COMMENTBLOCK : SCE_P_COMMENTLINE;
-                               } else if (IsRbStringStart(ch, chNext, chNext2)) {
-                                       styler.ColourTo(i - 1, state);
-                                       state = GetRbStringState(styler, i, &nextIndex);
-                                       if (nextIndex != i + 1) {
-                                               i = nextIndex - 1;
-                                               ch = ' ';
-                                               chPrev = ' ';
+                               state = SCE_RB_BACKTICKS;
+                               Quote.New();
+                               Quote.Open(ch);
+                       } else if (ch == '@') {
+                // Instance or class var
+                               styler.ColourTo(i - 1, state);
+                if (chNext == '@') {
+                    state = SCE_RB_CLASS_VAR;
+                    advance_char(i, ch, chNext, chNext2); // pass by ref
+                } else {
+                    state = SCE_RB_INSTANCE_VAR;
+                }
+                       } else if (ch == '$') {
+                // Check for a builtin global
+                               styler.ColourTo(i - 1, state);
+                // Recognize it bit by bit
+                state = SCE_RB_GLOBAL;
+            } else if (ch == '/' && preferRE) {
+                // Ambigous operator
+                               styler.ColourTo(i - 1, state);
+                               state = SCE_RB_REGEX;
+                Quote.New();
+                Quote.Open(ch);
+                       } else if (ch == '<' && chNext == '<' && chNext2 != '=') {
+
+                // Recognise the '<<' symbol - either a here document or a binary op
+                               styler.ColourTo(i - 1, state);
+                i++;
+                chNext = chNext2;
+                               styler.ColourTo(i, SCE_RB_OPERATOR);
+
+                if (! (strchr("\"\'`_-", chNext2) || isSafeAlpha(chNext2))) {
+                    // It's definitely not a here-doc,
+                    // based on Ruby's lexer/parser in the
+                    // heredoc_identifier routine.
+                    // Nothing else to do.
+                } else if (preferRE) {
+                    if (sureThisIsHeredoc(i - 1, styler, prevWord)) {
+                        state = SCE_RB_HERE_DELIM;
+                        HereDoc.State = 0;
+                    }
+                    // else leave it in default state
+                } else {
+                    if (sureThisIsNotHeredoc(i - 1, styler)) {
+                        // leave state as default
+                        // We don't have all the heuristics Perl has for indications
+                        // of a here-doc, because '<<' is overloadable and used
+                        // for so many other classes.
+                    } else {
+                        state = SCE_RB_HERE_DELIM;
+                        HereDoc.State = 0;
+                    }
+                }
+                preferRE = (state != SCE_RB_HERE_DELIM);
+            } else if (ch == ':') {
+                               styler.ColourTo(i - 1, state);
+                if (chNext == ':') {
+                    // Mark "::" as an operator, not symbol start
+                    styler.ColourTo(i + 1, SCE_RB_OPERATOR);
+                    advance_char(i, ch, chNext, chNext2); // pass by ref
+                    state = SCE_RB_DEFAULT;
+                                       preferRE = false;
+                } else if (isSafeWordcharOrHigh(chNext)) {
+                                       state = SCE_RB_SYMBOL;
+                } else if (strchr("[*!~+-*/%=<>&^|", chNext)) {
+                    // Do the operator analysis in-line, looking ahead
+                    // Based on the table in pickaxe 2nd ed., page 339
+                    bool doColoring = true;
+                    switch (chNext) {
+                    case '[':
+                        if (chNext2 == ']' ) {
+                            char ch_tmp = styler.SafeGetCharAt(i + 3);
+                            if (ch_tmp == '=') {
+                                i += 3;
+                                ch = ch_tmp;
+                                chNext = styler.SafeGetCharAt(i + 1);
+                            } else {
+                                i += 2;
+                                ch = chNext2;
+                                chNext = ch_tmp;
+                            }
+                        } else {
+                            doColoring = false;
+                        }
+                        break;
+
+                    case '*':
+                        if (chNext2 == '*') {
+                            i += 2;
+                            ch = chNext2;
+                            chNext = styler.SafeGetCharAt(i + 1);
+                        } else {
+                            advance_char(i, ch, chNext, chNext2);
+                        }
+                        break;
+
+                    case '!':
+                        if (chNext2 == '=' || chNext2 == '~') {
+                            i += 2;
+                            ch = chNext2;
+                            chNext = styler.SafeGetCharAt(i + 1);
+                        } else {
+                            advance_char(i, ch, chNext, chNext2);
+                        }
+                        break;
+
+                    case '<':
+                        if (chNext2 == '<') {
+                            i += 2;
+                            ch = chNext2;
+                            chNext = styler.SafeGetCharAt(i + 1);
+                        } else if (chNext2 == '=') {
+                            char ch_tmp = styler.SafeGetCharAt(i + 3);
+                            if (ch_tmp == '>') {  // <=> operator
+                                i += 3;
+                                ch = ch_tmp;
+                                chNext = styler.SafeGetCharAt(i + 1);
+                            } else {
+                                i += 2;
+                                ch = chNext2;
+                                chNext = ch_tmp;
+                            }
+                        } else {
+                            advance_char(i, ch, chNext, chNext2);
+                        }
+                        break;
+
+                    default:
+                        // Simple one-character operators
+                        advance_char(i, ch, chNext, chNext2);
+                        break;
+                    }
+                    if (doColoring) {
+                        styler.ColourTo(i, SCE_RB_SYMBOL);
+                        state = SCE_RB_DEFAULT;
+                    }
+                               } else if (!preferRE) {
+                                       // Don't color symbol strings (yet)
+                                       // Just color the ":" and color rest as string
+                                       styler.ColourTo(i, SCE_RB_SYMBOL);
+                                       state = SCE_RB_DEFAULT;
+                } else {
+                    styler.ColourTo(i, SCE_RB_OPERATOR);
+                    state = SCE_RB_DEFAULT;
+                    preferRE = true;
+                }
+            } else if (ch == '%') {
+                styler.ColourTo(i - 1, state);
+                bool have_string = false;
+                if (strchr(q_chars, chNext) && !isSafeWordcharOrHigh(chNext2)) {
+                    Quote.New();
+                    const char *hit = strchr(q_chars, chNext);
+                    if (hit != NULL) {
+                        state = q_states[hit - q_chars];
+                        Quote.Open(chNext2);
+                        i += 2;
+                        ch = chNext2;
                                                chNext = styler.SafeGetCharAt(i + 1);
+                        have_string = true;
+                    }
+                } else if (!isSafeWordcharOrHigh(chNext)) {
+                    // Ruby doesn't allow high bit chars here,
+                    // but the editor host might
+                    state = SCE_RB_STRING_QQ;
+                    Quote.Open(chNext);
+                    advance_char(i, ch, chNext, chNext2); // pass by ref
+                    have_string = true;
+                }
+                if (!have_string) {
+                    styler.ColourTo(i, SCE_RB_OPERATOR);
+                    // stay in default
+                    preferRE = true;
+                }
+            } else if (isoperator(ch) || ch == '.') {
+                               styler.ColourTo(i - 1, state);
+                               styler.ColourTo(i, SCE_RB_OPERATOR);
+                // If we're ending an expression or block,
+                // assume it ends an object, and the ambivalent
+                // constructs are binary operators
+                //
+                // So if we don't have one of these chars,
+                // we aren't ending an object exp'n, and ops
+                // like : << / are unary operators.
+                
+                preferRE = (strchr(")}].", ch) == NULL);
+                // Stay in default state
+            } else if (isEOLChar(ch)) {
+                // Make sure it's a true line-end, with no backslash
+                if ((ch == '\r' || (ch == '\n' && chPrev != '\r'))
+                    && chPrev != '\\') {
+                    // Assume we've hit the end of the statement.
+                    preferRE = true;
+                }
+            }
+        } else if (state == SCE_RB_WORD) {
+            if (ch == '.' || !isSafeWordcharOrHigh(ch)) {
+                // Words include x? in all contexts,
+                // and <letters>= after either 'def' or a dot
+                // Move along until a complete word is on our left
+
+                // Default accessor treats '.' as word-chars,
+                // but we don't for now.
+                
+                if (ch == '='
+                    && isSafeWordcharOrHigh(chPrev)
+                    && (chNext == '('
+                        || strchr(" \t\n\r", chNext) != NULL)
+                    && (!strcmp(prevWord, "def")
+                        || followsDot(styler.GetStartSegment(), styler))) {
+                    // <name>= is a name only when being def'd -- Get it the next time
+                    // This means that <name>=<name> is always lexed as
+                    // <name>, (op, =), <name>
+                } else if ((ch == '?' || ch == '!')
+                           && isSafeWordcharOrHigh(chPrev)
+                           && !isSafeWordcharOrHigh(chNext)) {
+                    // <name>? is a name -- Get it the next time
+                    // But <name>?<name> is always lexed as
+                    // <name>, (op, ?), <name>
+                    // Same with <name>! to indicate a method that
+                    // modifies its target
+                } else if (isEOLChar(ch)
+                           && isMatch(styler, lengthDoc, i - 7, "__END__")) {
+                    styler.ColourTo(i, SCE_RB_DATASECTION);
+                    state = SCE_RB_DATASECTION;
+                    // No need to handle this state -- we'll just move to the end
+                    preferRE = false;
+                } else {
+                                       int wordStartPos = styler.GetStartSegment();
+                    int word_style = ClassifyWordRb(wordStartPos, i - 1, keywords, styler, prevWord);
+                    switch (word_style) {
+                        case SCE_RB_WORD:
+                            preferRE = RE_CanFollowKeyword(prevWord);
+                                                       break;
+                            
+                        case SCE_RB_WORD_DEMOTED:
+                            preferRE = true;
+                                                       break;
+                            
+                        case SCE_RB_IDENTIFIER:
+                            if (isMatch(styler, lengthDoc, wordStartPos, "print")) {
+                                preferRE = true;
+                            } else if (isEOLChar(ch)) {
+                                preferRE = true;
+                            } else {
+                                preferRE = false;
+                            }
+                                                       break;
+                        default:
+                            preferRE = false;
+                    }
+                    if (ch == '.') {
+                        // We might be redefining an operator-method
+                        preferRE = false;
+                    }
+                    // And if it's the first 
+                    redo_char(i, ch, chNext, chNext2, state); // pass by ref
+                }
+            }
+        } else if (state == SCE_RB_NUMBER) {
+            if (isSafeAlnumOrHigh(ch) || ch == '_') {
+                // Keep going
+            } else if (ch == '.' && ++numDots == 1) {
+                // Keep going
+            } else {
+                styler.ColourTo(i - 1, state);
+                redo_char(i, ch, chNext, chNext2, state); // pass by ref
+                preferRE = false;
+            }
+        } else if (state == SCE_RB_COMMENTLINE) {
+                       if (isEOLChar(ch)) {
+                styler.ColourTo(i - 1, state);
+                state = SCE_RB_DEFAULT;
+                // Use whatever setting we had going into the comment
+            }
+        } else if (state == SCE_RB_HERE_DELIM) {
+            // See the comment for SCE_RB_HERE_DELIM in LexPerl.cxx
+            // Slightly different: if we find an immediate '-',
+            // the target can appear indented.
+            
+                       if (HereDoc.State == 0) { // '<<' encountered
+                               HereDoc.State = 1;
+                HereDoc.DelimiterLength = 0;
+                if (ch == '-') {
+                    HereDoc.CanBeIndented = true;
+                    advance_char(i, ch, chNext, chNext2); // pass by ref
+                } else {
+                    HereDoc.CanBeIndented = false;
+                }
+                if (isEOLChar(ch)) {
+                    // Bail out of doing a here doc if there's no target
+                    state = SCE_RB_DEFAULT;
+                    preferRE = false;
+                } else {
+                    HereDoc.Quote = ch;
+                
+                    if (ch == '\'' || ch == '"' || ch == '`') {
+                        HereDoc.Quoted = true;
+                        HereDoc.Delimiter[0] = '\0';
+                    } else {
+                        HereDoc.Quoted = false;
+                        HereDoc.Delimiter[0] = ch;
+                        HereDoc.Delimiter[1] = '\0';
+                        HereDoc.DelimiterLength = 1;
+                    }
+                }
+                       } else if (HereDoc.State == 1) { // collect the delimiter
+                if (isEOLChar(ch)) {
+                    // End the quote now, and go back for more
+                    styler.ColourTo(i - 1, state);
+                    state = SCE_RB_DEFAULT;
+                    i--;
+                    chNext = ch;
+                    chNext2 = chNext;
+                    preferRE = false;
+                } else if (HereDoc.Quoted) {
+                                       if (ch == HereDoc.Quote) { // closing quote => end of delimiter
+                                               styler.ColourTo(i, state);
+                                               state = SCE_RB_DEFAULT;
+                        preferRE = false;
+                    } else {
+                                               if (ch == '\\' && !isEOLChar(chNext)) {
+                            advance_char(i, ch, chNext, chNext2);
+                                               }
+                                               HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
+                                               HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
+                    }
+                } else { // an unquoted here-doc delimiter
+                                       if (isSafeAlnumOrHigh(ch) || ch == '_') {
+                                               HereDoc.Delimiter[HereDoc.DelimiterLength++] = ch;
+                                               HereDoc.Delimiter[HereDoc.DelimiterLength] = '\0';
+                                       } else {
+                                               styler.ColourTo(i - 1, state);
+                        redo_char(i, ch, chNext, chNext2, state);
+                        preferRE = false;
                                        }
-                               } else if (isoperator(ch)) {
-                                       styler.ColourTo(i, SCE_P_OPERATOR);
-                               }
-                       }
-               } else {
-                       if (state == SCE_P_COMMENTLINE || state == SCE_P_COMMENTBLOCK) {
-                               if (ch == '\r' || ch == '\n') {
+                }
+                               if (HereDoc.DelimiterLength >= static_cast<int>(sizeof(HereDoc.Delimiter)) - 1) {
                                        styler.ColourTo(i - 1, state);
-                                       state = SCE_P_DEFAULT;
-                               }
-                       } else if (state == SCE_P_STRING) {
-                               if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
-                                       styler.ColourTo(i - 1, state);
-                                       state = SCE_P_STRINGEOL;
-                               } else if (ch == '\\') {
-                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
-                                               i++;
-                                               ch = chNext;
-                                               chNext = styler.SafeGetCharAt(i + 1);
-                                       }
-                               } else if (ch == '\"') {
-                                       styler.ColourTo(i, state);
-                                       state = SCE_P_DEFAULT;
+                                       state = SCE_RB_ERROR;
+                    preferRE = false;
                                }
-                       } else if (state == SCE_P_CHARACTER) {
-                               if ((ch == '\r' || ch == '\n') && (chPrev != '\\')) {
-                                       styler.ColourTo(i - 1, state);
-                                       state = SCE_P_STRINGEOL;
-                               } else if (ch == '\\') {
-                                       if (chNext == '\"' || chNext == '\'' || chNext == '\\') {
-                                               i++;
+            }
+        } else if (state == SCE_RB_HERE_Q) {
+            // Not needed: HereDoc.State == 2
+            // Indentable here docs: look backwards
+            // Non-indentable: look forwards, like in Perl
+            //
+            // Why: so we can quickly resolve things like <<-" abc"
+
+            if (!HereDoc.CanBeIndented) {
+                if (isEOLChar(chPrev)
+                    && isMatch(styler, lengthDoc, i, HereDoc.Delimiter)) {
+                    styler.ColourTo(i - 1, state);
+                    i += HereDoc.DelimiterLength - 1;
+                    chNext = styler.SafeGetCharAt(i + 1);
+                    if (isEOLChar(chNext)) {
+                        styler.ColourTo(i, SCE_RB_HERE_DELIM);
+                        state = SCE_RB_DEFAULT;
+                        HereDoc.State = 0;
+                        preferRE = false;
+                    }
+                    // Otherwise we skipped through the here doc faster.
+                }
+            } else if (isEOLChar(chNext)
+                       && lookingAtHereDocDelim(styler,
+                                                i - HereDoc.DelimiterLength + 1,
+                                                lengthDoc,
+                                                HereDoc.Delimiter)) {
+                styler.ColourTo(i - 1 - HereDoc.DelimiterLength, state);
+                styler.ColourTo(i, SCE_RB_HERE_DELIM);
+                state = SCE_RB_DEFAULT;
+                preferRE = false;
+                HereDoc.State = 0;
+            }
+        } else if (state == SCE_RB_CLASS_VAR
+                   || state == SCE_RB_INSTANCE_VAR
+                   || state == SCE_RB_SYMBOL) {
+            if (!isSafeWordcharOrHigh(ch)) {
+                styler.ColourTo(i - 1, state);
+                redo_char(i, ch, chNext, chNext2, state); // pass by ref
+                preferRE = false;
+            }
+        } else if (state == SCE_RB_GLOBAL) {
+            if (!isSafeWordcharOrHigh(ch)) {
+                // handle special globals here as well
+                if (chPrev == '$') {
+                    if (ch == '-') {
+                        // Include the next char, like $-a
+                        advance_char(i, ch, chNext, chNext2);
+                    }
+                    styler.ColourTo(i, state);
+                    state = SCE_RB_DEFAULT;
+                } else {
+                    styler.ColourTo(i - 1, state);
+                    redo_char(i, ch, chNext, chNext2, state); // pass by ref
+                }
+                preferRE = false;
+            }
+        } else if (state == SCE_RB_POD) {
+            // PODs end with ^=end\s, -- any whitespace can follow =end
+            if (strchr(" \t\n\r", ch) != NULL
+                && i > 5
+                && isEOLChar(styler[i - 5])
+                && isMatch(styler, lengthDoc, i - 4, "=end")) {
+                styler.ColourTo(i - 1, state);
+                state = SCE_RB_DEFAULT;
+                preferRE = false;
+            }
+        } else if (state == SCE_RB_REGEX || state == SCE_RB_STRING_QR) {
+            if (ch == '\\' && Quote.Up != '\\') {
+                // Skip one
+                advance_char(i, ch, chNext, chNext2);
+            } else if (ch == Quote.Down) {
+                Quote.Count--;
+                if (Quote.Count == 0) {
+                    // Include the options
+                    while (isSafeAlpha(chNext)) {
+                        i++;
                                                ch = chNext;
-                                               chNext = styler.SafeGetCharAt(i + 1);
-                                       }
-                               } else if (ch == '\'') {
-                                       styler.ColourTo(i, state);
-                                       state = SCE_P_DEFAULT;
-                               }
-                       } else if (state == SCE_P_TRIPLE) {
-                               if (ch == '\'' && chPrev == '\'' && chPrev2 == '\'') {
-                                       styler.ColourTo(i, state);
-                                       state = SCE_P_DEFAULT;
-                               }
-                       } else if (state == SCE_P_TRIPLEDOUBLE) {
-                               // =end terminates the comment block
-                               if (ch == 'd' && chPrev == 'n' && chPrev2 == 'e') {
-                                       if  (styler.SafeGetCharAt(i - 3) == '=') {
-                                               styler.ColourTo(i, state);
-                                               state = SCE_P_DEFAULT;
-                                       }
-                               }
+                        chNext = styler.SafeGetCharAt(i + 1);
+                    }
+                    styler.ColourTo(i, state);
+                    state = SCE_RB_DEFAULT;
+                    preferRE = false;
+                }
+            } else if (ch == Quote.Up) {
+                // Only if close quoter != open quoter
+                Quote.Count++;
+                
+            } else if (ch == '#' ) {
+                //todo: distinguish comments from pound chars
+                // for now, handle as comment
+                styler.ColourTo(i - 1, state);
+                bool inEscape = false;
+                while (++i < lengthDoc) {
+                    ch = styler.SafeGetCharAt(i);
+                    if (ch == '\\') {
+                        inEscape = true;
+                    } else if (isEOLChar(ch)) {
+                        // Comment inside a regex
+                        styler.ColourTo(i - 1, SCE_RB_COMMENTLINE);
+                        break;
+                    } else if (inEscape) {
+                        inEscape = false;  // don't look at char
+                    } else if (ch == Quote.Down) {
+                        // Have the regular handler deal with this
+                        // to get trailing modifiers.
+                        i--;
+                        ch = styler[i];
+                                               break;
+                    }
+                }
+                chNext = styler.SafeGetCharAt(i + 1);
+                chNext2 = styler.SafeGetCharAt(i + 2);
+            }
+        // Quotes of all kinds...
+        } else if (state == SCE_RB_STRING_Q || state == SCE_RB_STRING_QQ || 
+                   state == SCE_RB_STRING_QX || state == SCE_RB_STRING_QW ||
+                   state == SCE_RB_STRING || state == SCE_RB_CHARACTER ||
+                   state == SCE_RB_BACKTICKS) {
+            if (!Quote.Down && !isspacechar(ch)) {
+                Quote.Open(ch);
+            } else if (ch == '\\' && Quote.Up != '\\') {
+                //Riddle me this: Is it safe to skip *every* escaped char?
+                advance_char(i, ch, chNext, chNext2);
+            } else if (ch == Quote.Down) {
+                Quote.Count--;
+                if (Quote.Count == 0) {
+                    styler.ColourTo(i, state);
+                    state = SCE_RB_DEFAULT;
+                    preferRE = false;
+                }
+            } else if (ch == Quote.Up) {
+                Quote.Count++;
+            }
+        }
+            
+        if (state == SCE_RB_ERROR) {
+            break;
+        }
+        chPrev = ch;
+    }
+    if (state == SCE_RB_WORD) {
+        // We've ended on a word, possibly at EOF, and need to
+        // classify it.
+        (void) ClassifyWordRb(styler.GetStartSegment(), lengthDoc - 1, keywords, styler, prevWord);
+    } else {
+        styler.ColourTo(lengthDoc - 1, state);
+    }
+}
+
+// Helper functions for folding, disambiguation keywords
+// Assert that there are no high-bit chars 
+
+static void getPrevWord(int pos,
+                        char *prevWord,
+                        Accessor &styler,
+                        int word_state)
+{
+    int i;
+    styler.Flush();
+    for (i = pos - 1; i > 0; i--) {
+        if (actual_style(styler.StyleAt(i)) != word_state) {
+            i++;
+            break;
+        }
+    }
+    if (i < pos - MAX_KEYWORD_LENGTH) // overflow
+        i = pos - MAX_KEYWORD_LENGTH;
+    char *dst = prevWord;
+    for (; i <= pos; i++) {
+        *dst++ = styler[i];
+    }
+       *dst = 0;
+}
+
+static bool keywordIsAmbiguous(const char *prevWord)
+{
+    // Order from most likely used to least likely
+    // Lots of ways to do a loop in Ruby besides 'while/until'
+    if (!strcmp(prevWord, "if")
+        || !strcmp(prevWord, "do")
+        || !strcmp(prevWord, "while")
+        || !strcmp(prevWord, "unless")
+        || !strcmp(prevWord, "until")) {
+        return true;
+    } else {
+        return false;
+    }
+}
+
+// Demote keywords in the following conditions:
+// if, while, unless, until modify a statement
+// do after a while or until, as a noise word (like then after if) 
+
+static bool keywordIsModifier(const char *word,
+                              int pos,
+                              Accessor &styler)
+{
+    if (word[0] == 'd' && word[1] == 'o' && !word[2]) {
+        return keywordDoStartsLoop(pos, styler);
+    }
+    char ch;
+    int style = SCE_RB_DEFAULT;
+       int lineStart = styler.GetLine(pos);
+    int lineStartPosn = styler.LineStart(lineStart);
+    styler.Flush();
+    while (--pos >= lineStartPosn) {
+        style = actual_style(styler.StyleAt(pos));
+               if (style == SCE_RB_DEFAULT) {
+                       if (iswhitespace(ch = styler[pos])) {
+                               //continue
+                       } else if (ch == '\r' || ch == '\n') {
+                               // Scintilla's LineStart() and GetLine() routines aren't
+                               // platform-independent, so if we have text prepared with
+                               // a different system we can't rely on it.
+                               return false;
                        }
+               } else {
+            break;
                }
-               chPrev2 = chPrev;
-               chPrev = ch;
-       }
-       if (state == SCE_P_WORD) {
-               ClassifyWordRb(styler.GetStartSegment(), lengthDoc-1, keywords, styler, prevWord);
-       } else {
-               styler.ColourTo(lengthDoc-1, state);
-       }
+    }
+    if (pos < lineStartPosn) {
+        return false; //XXX not quite right if the prev line is a continuation
+    }
+    // First things where the action is unambiguous
+    switch (style) {
+        case SCE_RB_DEFAULT:
+        case SCE_RB_COMMENTLINE:
+        case SCE_RB_POD:
+        case SCE_RB_CLASSNAME:
+        case SCE_RB_DEFNAME:
+        case SCE_RB_MODULE_NAME:
+            return false;
+        case SCE_RB_OPERATOR:
+            break;
+        case SCE_RB_WORD:
+            // Watch out for uses of 'else if'
+            //XXX: Make a list of other keywords where 'if' isn't a modifier
+            //     and can appear legitimately
+            // Formulate this to avoid warnings from most compilers
+            if (strcmp(word, "if") == 0) {
+                char prevWord[MAX_KEYWORD_LENGTH + 1];
+                getPrevWord(pos, prevWord, styler, SCE_RB_WORD);
+                return strcmp(prevWord, "else") != 0;
+            }
+            return true;
+        default:
+            return true;
+    }
+    // Assume that if the keyword follows an operator,
+    // usually it's a block assignment, like
+    // a << if x then y else z
+    
+    ch = styler[pos];
+    switch (ch) {
+        case ')':
+        case ']':
+        case '}':
+            return true;
+        default:
+            return false;
+    }
 }
 
-static void FoldRbDoc(unsigned int startPos, int length, int initStyle,
-                                                  WordList *[], Accessor &styler) {
-       int lengthDoc = startPos + length;
+#define WHILE_BACKWARDS "elihw"
+#define UNTIL_BACKWARDS "litnu"
+
+// Nothing fancy -- look to see if we follow a while/until somewhere
+// on the current line
+
+static bool keywordDoStartsLoop(int pos,
+                                Accessor &styler)
+{
+    char ch;
+    int style;
+       int lineStart = styler.GetLine(pos);
+    int lineStartPosn = styler.LineStart(lineStart);
+    styler.Flush();
+    while (--pos >= lineStartPosn) {
+        style = actual_style(styler.StyleAt(pos));
+               if (style == SCE_RB_DEFAULT) {
+                       if ((ch = styler[pos]) == '\r' || ch == '\n') {
+                               // Scintilla's LineStart() and GetLine() routines aren't
+                               // platform-independent, so if we have text prepared with
+                               // a different system we can't rely on it.
+                               return false;
+                       }
+               } else if (style == SCE_RB_WORD) {
+            // Check for while or until, but write the word in backwards
+            char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
+            char *dst = prevWord;
+            int wordLen = 0;
+            int start_word;
+            for (start_word = pos;
+                 start_word >= lineStartPosn && actual_style(styler.StyleAt(start_word)) == SCE_RB_WORD;
+                 start_word--) {
+                if (++wordLen < MAX_KEYWORD_LENGTH) {
+                    *dst++ = styler[start_word];
+                }
+            }
+            *dst = 0;
+            // Did we see our keyword?
+            if (!strcmp(prevWord, WHILE_BACKWARDS)
+                || !strcmp(prevWord, UNTIL_BACKWARDS)) {
+                return true;
+            }
+            // We can move pos to the beginning of the keyword, and then
+            // accept another decrement, as we can never have two contiguous
+            // keywords:
+            // word1 word2
+            //           ^
+            //        <-  move to start_word
+            //      ^
+            //      <- loop decrement
+            //     ^  # pointing to end of word1 is fine
+            pos = start_word;
+        }
+    }
+    return false;
+}
+
+/*
+ *  Folding Ruby
+ * 
+ *  The language is quite complex to analyze without a full parse.
+ *  For example, this line shouldn't affect fold level:
+ * 
+ *   print "hello" if feeling_friendly?
+ * 
+ *  Neither should this:
+ * 
+ *   print "hello" \
+ *      if feeling_friendly?
+ * 
+ * 
+ *  But this should:
+ * 
+ *   if feeling_friendly?  #++
+ *     print "hello" \
+ *     print "goodbye"
+ *   end                   #--
+ * 
+ *  So we cheat, by actually looking at the existing indentation
+ *  levels for each line, and just echoing it back.  Like Python.
+ *  Then if we get better at it, we'll take braces into consideration,
+ *  which always affect folding levels.
+
+ *  How the keywords should work:
+ *  No effect:
+ *  __FILE__ __LINE__ BEGIN END alias and 
+ *  defined? false in nil not or self super then
+ *  true undef
+
+ *  Always increment:
+ *  begin  class def do for module when {
+ * 
+ *  Always decrement:
+ *  end }
+ * 
+ *  Increment if these start a statement
+ *  if unless until while -- do nothing if they're modifiers
 
-       // Backtrack to previous line in case need to fix its fold status
+ *  These end a block if there's no modifier, but don't bother
+ *  break next redo retry return yield
+ * 
+ *  These temporarily de-indent, but re-indent
+ *  case else elsif ensure rescue
+ * 
+ *  This means that the folder reflects indentation rather
+ *  than setting it.  The language-service updates indentation
+ *  when users type return and finishes entering de-denters.
+ * 
+ *  Later offer to fold POD, here-docs, strings, and blocks of comments
+ */
+
+static void FoldRbDoc(unsigned int startPos, int length, int initStyle,
+                      WordList *[], Accessor &styler) {
+       const bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+       bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+    
+    synchronizeDocStart(startPos, length, initStyle, styler, // ref args
+                        false);
+       unsigned int endPos = startPos + length;
+       int visibleChars = 0;
        int lineCurrent = styler.GetLine(startPos);
-       if (startPos > 0) {
-               if (lineCurrent > 0) {
-                       lineCurrent--;
-                       startPos = styler.LineStart(lineCurrent);
-                       if (startPos == 0)
-                               initStyle = SCE_P_DEFAULT;
-                       else
-                               initStyle = styler.StyleAt(startPos-1);
-               }
-       }
-       int state = initStyle & 31;
-       int spaceFlags = 0;
-       int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags, IsRbComment);
-       if ((state == SCE_P_TRIPLE) || (state == SCE_P_TRIPLEDOUBLE))
-               indentCurrent |= SC_FOLDLEVELWHITEFLAG;
+       int levelPrev = startPos == 0 ? 0 : (styler.LevelAt(lineCurrent)
+                                         & SC_FOLDLEVELNUMBERMASK
+                                         & ~SC_FOLDLEVELBASE);
+       int levelCurrent = levelPrev;
        char chNext = styler[startPos];
-       for (int i = startPos; i < lengthDoc; i++) {
+       int styleNext = styler.StyleAt(startPos);
+       int stylePrev = startPos <= 1 ? SCE_RB_DEFAULT : styler.StyleAt(startPos - 1);
+    bool buffer_ends_with_eol = false;
+       for (unsigned int i = startPos; i < endPos; i++) {
                char ch = chNext;
                chNext = styler.SafeGetCharAt(i + 1);
-               int style = styler.StyleAt(i) & 31;
-
-               if ((ch == '\r' && chNext != '\n') || (ch == '\n') || (i == lengthDoc)) {
-                       int lev = indentCurrent;
-                       int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags, IsRbComment);
-                       if ((style == SCE_P_TRIPLE) || (style== SCE_P_TRIPLEDOUBLE))
-                               indentNext |= SC_FOLDLEVELWHITEFLAG;
-                       if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
-                               // Only non whitespace lines can be headers
-                               if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext & SC_FOLDLEVELNUMBERMASK)) {
-                                       lev |= SC_FOLDLEVELHEADERFLAG;
-                               } else if (indentNext & SC_FOLDLEVELWHITEFLAG) {
-                                       // Line after is blank so check the next - maybe should continue further?
-                                       int spaceFlags2 = 0;
-                                       int indentNext2 = styler.IndentAmount(lineCurrent + 2, &spaceFlags2, IsRbComment);
-                                       if ((indentCurrent & SC_FOLDLEVELNUMBERMASK) < (indentNext2 & SC_FOLDLEVELNUMBERMASK)) {
-                                               lev |= SC_FOLDLEVELHEADERFLAG;
-                                       }
+               int style = styleNext;
+               styleNext = styler.StyleAt(i + 1);
+               bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+        if (style == SCE_RB_COMMENTLINE) {
+            if (foldComment && stylePrev != SCE_RB_COMMENTLINE) {
+                if (chNext == '{') {
+                                       levelCurrent++;
+                               } else if (chNext == '}') {
+                                       levelCurrent--;
                                }
+            }
+        } else if (style == SCE_RB_OPERATOR) {
+                       if (strchr("[{(", ch)) {
+                               levelCurrent++;
+                       } else if (strchr(")}]", ch)) {
+                // Don't decrement below 0
+                if (levelCurrent > 0)
+                    levelCurrent--;
                        }
-                       indentCurrent = indentNext;
-                       styler.SetLevel(lineCurrent, lev);
+        } else if (style == SCE_RB_WORD && styleNext != SCE_RB_WORD) {
+            // Look at the keyword on the left and decide what to do
+            char prevWord[MAX_KEYWORD_LENGTH + 1]; // 1 byte for zero
+            prevWord[0] = 0;
+            getPrevWord(i, prevWord, styler, SCE_RB_WORD);
+            if (!strcmp(prevWord, "end")) {
+                // Don't decrement below 0
+                if (levelCurrent > 0)
+                    levelCurrent--;
+            } else if (   !strcmp(prevWord, "if")
+                       || !strcmp(prevWord, "def")
+                       || !strcmp(prevWord, "class")
+                       || !strcmp(prevWord, "module")
+                       || !strcmp(prevWord, "begin")
+                       || !strcmp(prevWord, "case")
+                       || !strcmp(prevWord, "do")
+                       || !strcmp(prevWord, "while")
+                       || !strcmp(prevWord, "unless")
+                       || !strcmp(prevWord, "until")
+                       || !strcmp(prevWord, "for")
+                          ) {
+                               levelCurrent++;
+            }
+        }
+               if (atEOL) {
+                       int lev = levelPrev;
+                       if (visibleChars == 0 && foldCompact)
+                               lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visibleChars > 0))
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+            styler.SetLevel(lineCurrent, lev|SC_FOLDLEVELBASE);
                        lineCurrent++;
-               }
-       }
+                       levelPrev = levelCurrent;
+                       visibleChars = 0;
+            buffer_ends_with_eol = true;
+               } else if (!isspacechar(ch)) {
+                       visibleChars++;
+            buffer_ends_with_eol = false;
+        }
+    }
+       // Fill in the real level of the next line, keeping the current flags as they will be filled in later
+    if (!buffer_ends_with_eol) {
+        lineCurrent++;
+        int new_lev = levelCurrent;
+        if (visibleChars == 0 && foldCompact)
+            new_lev |= SC_FOLDLEVELWHITEFLAG;
+                       if ((levelCurrent > levelPrev) && (visibleChars > 0))
+                               new_lev |= SC_FOLDLEVELHEADERFLAG;
+            levelCurrent = new_lev;
+    }
+       styler.SetLevel(lineCurrent, levelCurrent|SC_FOLDLEVELBASE);
 }
 
 static const char * const rubyWordListDesc[] = {
index 8383eefb02efc556081b55b734ab2e521ad6aece..75a958cb60009664592d9871cd57feb311d59e24 100644 (file)
@@ -1,8 +1,8 @@
 // Scintilla source code edit control
 /** @file LexSQL.cxx
- ** Lexer for SQL.
+ ** Lexer for SQL, including PL/SQL and SQL*Plus.
  **/
-// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
 
 #include "PropSet.h"
 #include "Accessor.h"
+#include "StyleContext.h"
 #include "KeyWords.h"
 #include "Scintilla.h"
 #include "SciLexer.h"
 
-static void classifyWordSQL(unsigned int start, unsigned int end, WordList &keywords, Accessor &styler) {
-       char s[100];
-       bool wordIsNumber = isdigit(styler[start]) || (styler[start] == '.');
-       for (unsigned int i = 0; i < end - start + 1 && i < 30; i++) {
-               s[i] = static_cast<char>(tolower(styler[start + i]));
-               s[i + 1] = '\0';
-       }
-       char chAttr = SCE_C_IDENTIFIER;
-       if (wordIsNumber)
-               chAttr = SCE_C_NUMBER;
-       else {
-               if (keywords.InList(s))
-                       chAttr = SCE_C_WORD;
-       }
-       styler.ColourTo(end, chAttr);
+static inline bool IsAWordChar(int ch) {
+       return (ch < 0x80) && (isalnum(ch) || ch == '.' || ch == '_');
+}
+
+static inline bool IsAWordStart(int ch) {
+       return (ch < 0x80) && (isalpha(ch) || ch == '_');
 }
 
-static void ColouriseSQLDoc(unsigned int startPos, int length,
-                            int initStyle, WordList *keywordlists[], Accessor &styler) {
+static inline bool IsADoxygenChar(int ch) {
+       return (islower(ch) || ch == '$' || ch == '@' ||
+               ch == '\\' || ch == '&' || ch == '<' ||
+               ch == '>' || ch == '#' || ch == '{' ||
+               ch == '}' || ch == '[' || ch == ']');
+}
+
+static inline bool IsANumberChar(int ch) {
+       // Not exactly following number definition (several dots are seen as OK, etc.)
+       // but probably enough in most cases.
+       return (ch < 0x80) &&
+               (isdigit(ch) || toupper(ch) == 'E' ||
+             ch == '.' || ch == '-' || ch == '+');
+}
 
-       WordList &keywords = *keywordlists[0];
 
-       styler.StartAt(startPos);
+static void ColouriseSQLDoc(unsigned int startPos, int length, int initStyle, WordList *keywordlists[],
+                            Accessor &styler) {
+
+       WordList &keywords1 = *keywordlists[0];
+       WordList &keywords2 = *keywordlists[1];
+       WordList &kw_pldoc = *keywordlists[2];
+       WordList &kw_sqlplus = *keywordlists[3];
+       WordList &kw_user1 = *keywordlists[4];
+       WordList &kw_user2 = *keywordlists[5];
+       WordList &kw_user3 = *keywordlists[6];
+       WordList &kw_user4 = *keywordlists[7];
+
+       StyleContext sc(startPos, length, initStyle, styler);
 
-       bool fold = styler.GetPropertyInt("fold") != 0;
        bool sqlBackslashEscapes = styler.GetPropertyInt("sql.backslash.escapes", 0) != 0;
+       bool sqlBackticksIdentifier = styler.GetPropertyInt("lexer.sql.backticks.identifier", 0) != 0;
+       int styleBeforeDCKeyword = SCE_C_DEFAULT;
+       bool fold = styler.GetPropertyInt("fold") != 0;
        int lineCurrent = styler.GetLine(startPos);
-       int spaceFlags = 0;
-
-       int state = initStyle;
-       char chPrev = ' ';
-       char chNext = styler[startPos];
-       styler.StartSegment(startPos);
-       unsigned int lengthDoc = startPos + length;
-       for (unsigned int i = startPos; i < lengthDoc; i++) {
-               char ch = chNext;
-               chNext = styler.SafeGetCharAt(i + 1);
 
-               if ((ch == '\r' && chNext != '\n') || (ch == '\n')) {
+       for (; sc.More(); sc.Forward()) {
+               // Fold based on indentation
+               if (sc.atLineStart) {
+                       int spaceFlags = 0;
                        int indentCurrent = styler.IndentAmount(lineCurrent, &spaceFlags);
-                       int lev = indentCurrent;
+                       int level = indentCurrent;
                        if (!(indentCurrent & SC_FOLDLEVELWHITEFLAG)) {
                                // Only non whitespace lines can be headers
                                int indentNext = styler.IndentAmount(lineCurrent + 1, &spaceFlags);
                                if (indentCurrent < (indentNext & ~SC_FOLDLEVELWHITEFLAG)) {
-                                       lev |= SC_FOLDLEVELHEADERFLAG;
+                                       level |= SC_FOLDLEVELHEADERFLAG;
                                }
                        }
                        if (fold) {
-                               styler.SetLevel(lineCurrent, lev);
+                               styler.SetLevel(lineCurrent, level);
                        }
                }
 
-               if (styler.IsLeadByte(ch)) {
-                       chNext = styler.SafeGetCharAt(i + 2);
-                       chPrev = ' ';
-                       i += 1;
-                       continue;
+               // Determine if the current state should terminate.
+               switch (sc.state) {
+               case SCE_SQL_OPERATOR:
+                       sc.SetState(SCE_SQL_DEFAULT);
+                       break;
+               case SCE_SQL_NUMBER:
+                       // We stop the number definition on non-numerical non-dot non-eE non-sign char
+                       if (!IsANumberChar(sc.ch)) {
+                               sc.SetState(SCE_SQL_DEFAULT);
+                       }
+                       break;
+               case SCE_SQL_IDENTIFIER:
+                       if (!IsAWordChar(sc.ch)) {
+                               int nextState = SCE_SQL_DEFAULT;
+                               char s[1000];
+                               sc.GetCurrentLowered(s, sizeof(s));
+                               if (keywords1.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_WORD);
+                               } else if (keywords2.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_WORD2);
+                               } else if (kw_sqlplus.InListAbbreviated(s, '~')) {
+                                       sc.ChangeState(SCE_SQL_SQLPLUS);
+                                       if (strncmp(s, "rem", 3) == 0) {
+                                               nextState = SCE_SQL_SQLPLUS_COMMENT;
+                                       } else if (strncmp(s, "pro", 3) == 0) {
+                                               nextState = SCE_SQL_SQLPLUS_PROMPT;
+                                       }
+                               } else if (kw_user1.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_USER1);
+                               } else if (kw_user2.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_USER2);
+                               } else if (kw_user3.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_USER3);
+                               } else if (kw_user4.InList(s)) {
+                                       sc.ChangeState(SCE_SQL_USER4);
+                               }
+                               sc.SetState(nextState);
+                       }
+                       break;
+               case SCE_SQL_QUOTEDIDENTIFIER:
+                       if (sc.ch == 0x60) {
+                               if (sc.chNext == 0x60) {
+                                       sc.Forward();   // Ignore it
+                               } else {
+                                       sc.ForwardSetState(SCE_SQL_DEFAULT);
+                               }
+                       }
+                       break;
+               case SCE_SQL_COMMENT:
+                       if (sc.Match('*', '/')) {
+                               sc.Forward();
+                               sc.ForwardSetState(SCE_SQL_DEFAULT);
+                       }
+                       break;
+               case SCE_SQL_COMMENTDOC:
+                       if (sc.Match('*', '/')) {
+                               sc.Forward();
+                               sc.ForwardSetState(SCE_SQL_DEFAULT);
+                       } else if (sc.ch == '@' || sc.ch == '\\') { // Doxygen support
+                               // Verify that we have the conditions to mark a comment-doc-keyword
+                               if ((IsASpace(sc.chPrev) || sc.chPrev == '*') && (!IsASpace(sc.chNext))) {
+                                       styleBeforeDCKeyword = SCE_SQL_COMMENTDOC;
+                                       sc.SetState(SCE_SQL_COMMENTDOCKEYWORD);
+                               }
+                       }
+                       break;
+               case SCE_SQL_COMMENTLINE:
+               case SCE_SQL_COMMENTLINEDOC:
+               case SCE_SQL_SQLPLUS_COMMENT:
+               case SCE_SQL_SQLPLUS_PROMPT:
+                       if (sc.atLineStart) {
+                               sc.SetState(SCE_SQL_DEFAULT);
+                       }
+                       break;
+               case SCE_SQL_COMMENTDOCKEYWORD:
+                       if ((styleBeforeDCKeyword == SCE_SQL_COMMENTDOC) && sc.Match('*', '/')) {
+                               sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR);
+                               sc.Forward();
+                               sc.ForwardSetState(SCE_SQL_DEFAULT);
+                       } else if (!IsADoxygenChar(sc.ch)) {
+                               char s[100];
+                               sc.GetCurrentLowered(s, sizeof(s));
+                               if (!isspace(sc.ch) || !kw_pldoc.InList(s + 1)) {
+                                       sc.ChangeState(SCE_SQL_COMMENTDOCKEYWORDERROR);
+                               }
+                               sc.SetState(styleBeforeDCKeyword);
+                       }
+                       break;
+               case SCE_SQL_CHARACTER:
+                       if (sqlBackslashEscapes && sc.ch == '\\') {
+                               sc.Forward();
+                       } else if (sc.ch == '\'') {
+                               if (sc.chNext == '\"') {
+                                       sc.Forward();
+                               } else {
+                                       sc.ForwardSetState(SCE_SQL_DEFAULT);
+                               }
+                       }
+                       break;
+               case SCE_SQL_STRING:
+                       if (sc.ch == '\\') {
+                               // Escape sequence
+                               sc.Forward();
+                       } else if (sc.ch == '\"') {
+                               if (sc.chNext == '\"') {
+                                       sc.Forward();
+                               } else {
+                                       sc.ForwardSetState(SCE_SQL_DEFAULT);
+                               }
+                       }
+                       break;
                }
 
-               if (state == SCE_C_DEFAULT) {
-                       if (iswordstart(ch)) {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_WORD;
-                       } else if (ch == '/' && chNext == '*') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_COMMENT;
-                       } else if (ch == '-' && chNext == '-') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_COMMENTLINE;
-                       } else if (ch == '#') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_COMMENTLINEDOC;
-                       } else if (ch == '\'') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_CHARACTER;
-                       } else if (ch == '"') {
-                               styler.ColourTo(i - 1, state);
-                               state = SCE_C_STRING;
-                       } else if (isoperator(ch)) {
-                               styler.ColourTo(i - 1, state);
-                               styler.ColourTo(i, SCE_C_OPERATOR);
-                       }
-               } else if (state == SCE_C_WORD) {
-                       if (!iswordchar(ch)) {
-                               classifyWordSQL(styler.GetStartSegment(), i - 1, keywords, styler);
-                               state = SCE_C_DEFAULT;
-                               if (ch == '/' && chNext == '*') {
-                                       state = SCE_C_COMMENT;
-                               } else if (ch == '-' && chNext == '-') {
-                                       state = SCE_C_COMMENTLINE;
-                               } else if (ch == '#') {
-                                       state = SCE_C_COMMENTLINEDOC;
-                               } else if (ch == '\'') {
-                                       state = SCE_C_CHARACTER;
-                               } else if (ch == '"') {
-                                       state = SCE_C_STRING;
-                               } else if (isoperator(ch)) {
-                                       styler.ColourTo(i, SCE_C_OPERATOR);
+               // Determine if a new state should be entered.
+               if (sc.state == SCE_SQL_DEFAULT) {
+                       if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
+                               sc.SetState(SCE_SQL_NUMBER);
+                       } else if (IsAWordStart(sc.ch)) {
+                               sc.SetState(SCE_SQL_IDENTIFIER);
+                       } else if (sc.ch == 0x60 && sqlBackticksIdentifier) {
+                               sc.SetState(SCE_SQL_QUOTEDIDENTIFIER);
+                       } else if (sc.Match('/', '*')) {
+                               if (sc.Match("/**") || sc.Match("/*!")) {       // Support of Doxygen doc. style
+                                       sc.SetState(SCE_SQL_COMMENTDOC);
+                               } else {
+                                       sc.SetState(SCE_SQL_COMMENT);
                                }
+                               sc.Forward();   // Eat the * so it isn't used for the end of the comment
+                       } else if (sc.Match('-', '-')) {
+                               // MySQL requires a space or control char after --
+                               // http://dev.mysql.com/doc/mysql/en/ansi-diff-comments.html
+                               // Perhaps we should enforce that with proper property:
+//~                    } else if (sc.Match("-- ")) {
+                               sc.SetState(SCE_SQL_COMMENTLINE);
+                       } else if (sc.ch == '#') {
+                               sc.SetState(SCE_SQL_COMMENTLINEDOC);
+                       } else if (sc.ch == '\'') {
+                               sc.SetState(SCE_SQL_CHARACTER);
+                       } else if (sc.ch == '\"') {
+                               sc.SetState(SCE_SQL_STRING);
+                       } else if (isoperator(static_cast<char>(sc.ch))) {
+                               sc.SetState(SCE_SQL_OPERATOR);
                        }
-               } else {
-                       if (state == SCE_C_COMMENT) {
-                               if (ch == '/' && chPrev == '*') {
-                                       if (((i > (styler.GetStartSegment() + 2)) || ((initStyle == SCE_C_COMMENT) &&
-                                           (styler.GetStartSegment() == startPos)))) {
-                                               styler.ColourTo(i, state);
-                                               state = SCE_C_DEFAULT;
-                                       }
+               }
+       }
+       sc.Complete();
+}
+
+static bool IsStreamCommentStyle(int style) {
+       return style == SCE_SQL_COMMENT ||
+              style == SCE_SQL_COMMENTDOC ||
+              style == SCE_SQL_COMMENTDOCKEYWORD ||
+              style == SCE_SQL_COMMENTDOCKEYWORDERROR;
+}
+
+// Store both the current line's fold level and the next lines in the
+// level store to make it easy to pick up with each increment.
+static void FoldSQLDoc(unsigned int startPos, int length, int initStyle,
+                            WordList *[], Accessor &styler) {
+       bool foldComment = styler.GetPropertyInt("fold.comment") != 0;
+       bool foldCompact = styler.GetPropertyInt("fold.compact", 1) != 0;
+       unsigned int endPos = startPos + length;
+       int visibleChars = 0;
+       int lineCurrent = styler.GetLine(startPos);
+       int levelCurrent = SC_FOLDLEVELBASE;
+       if (lineCurrent > 0) {
+               levelCurrent = styler.LevelAt(lineCurrent - 1) & SC_FOLDLEVELNUMBERMASK;
+       }
+       int levelNext = levelCurrent;
+       char chNext = styler[startPos];
+       int styleNext = styler.StyleAt(startPos);
+       int style = initStyle;
+       bool endFound = false;
+       for (unsigned int i = startPos; i < endPos; i++) {
+               char ch = chNext;
+               chNext = styler.SafeGetCharAt(i + 1);
+               int stylePrev = style;
+               style = styleNext;
+               styleNext = styler.StyleAt(i + 1);
+               bool atEOL = (ch == '\r' && chNext != '\n') || (ch == '\n');
+               if (foldComment && IsStreamCommentStyle(style)) {
+                       if (!IsStreamCommentStyle(stylePrev)) {
+                               levelNext++;
+                       } else if (!IsStreamCommentStyle(styleNext) && !atEOL) {
+                               // Comments don't end at end of line and the next character may be unstyled.
+                               levelNext--;
+                       }
+               }
+               if (foldComment && (style == SCE_SQL_COMMENTLINE)) {
+                       // MySQL needs -- comments to be followed by space or control char
+                       if ((ch == '-') && (chNext == '-')) {
+                               char chNext2 = styler.SafeGetCharAt(i + 2);
+                               char chNext3 = styler.SafeGetCharAt(i + 3);
+                               if (chNext2 == '{' || chNext3 == '{') {
+                                       levelNext++;
+                               } else if (chNext2 == '}' || chNext3 == '}') {
+                                       levelNext--;
                                }
-                       } else if (state == SCE_C_COMMENTLINE || state == SCE_C_COMMENTLINEDOC) {
-                               if (ch == '\r' || ch == '\n') {
-                                       styler.ColourTo(i - 1, state);
-                                       state = SCE_C_DEFAULT;
+                       }
+               }
+               if (style == SCE_SQL_OPERATOR) {
+                       if (ch == '(') {
+                               levelNext++;
+                       } else if (ch == ')') {
+                               levelNext--;
+                       }
+               }
+               // If new keyword (cannot trigger on elseif or nullif, does less tests)
+               if (style == SCE_SQL_WORD && stylePrev != SCE_SQL_WORD) {
+                       const int MAX_KW_LEN = 6;       // Maximum length of folding keywords
+                       char s[MAX_KW_LEN + 2];
+                       unsigned int j = 0;
+                       for (; j < MAX_KW_LEN + 1; j++) {
+                               if (!iswordchar(styler[i + j])) {
+                                       break;
                                }
-                       } else if (state == SCE_C_CHARACTER) {
-                               if (sqlBackslashEscapes && ch == '\\') {
-                                       i++;
-                                       ch = chNext;
-                                       chNext = styler.SafeGetCharAt(i + 1);
-                               } else if (ch == '\'') {
-                                       if (chNext == '\'') {
-                                               i++;
-                                       } else {
-                                               styler.ColourTo(i, state);
-                                               state = SCE_C_DEFAULT;
-                                               i++;
-                                       }
-                                       ch = chNext;
-                                       chNext = styler.SafeGetCharAt(i + 1);
+                               s[j] = static_cast<char>(tolower(styler[i + j]));
+                       }
+                       if (j == MAX_KW_LEN + 1) {
+                               // Keyword too long, don't test it
+                               s[0] = '\0';
+                       } else {
+                               s[j] = '\0';
+                       }
+                       if (strcmp(s, "if") == 0 || strcmp(s, "loop") == 0) {
+                               if (endFound) {
+                                       // ignore
+                                       endFound = false;
+                               } else {
+                                       levelNext++;
                                }
-                       } else if (state == SCE_C_STRING) {
-                               if (ch == '"') {
-                                       if (chNext == '"') {
-                                               i++;
-                                       } else {
-                                               styler.ColourTo(i, state);
-                                               state = SCE_C_DEFAULT;
-                                               i++;
-                                       }
-                                       ch = chNext;
-                                       chNext = styler.SafeGetCharAt(i + 1);
+                       } else if (strcmp(s, "begin") == 0) {
+                               levelNext++;
+                       } else if (strcmp(s, "end") == 0 ||
+                                               // DROP TABLE IF EXISTS or CREATE TABLE IF NOT EXISTS
+                                               strcmp(s, "exists") == 0) {
+                               endFound = true;
+                               levelNext--;
+                               if (levelNext < SC_FOLDLEVELBASE) {
+                                       levelNext = SC_FOLDLEVELBASE;
                                }
                        }
-                       if (state == SCE_C_DEFAULT) {    // One of the above succeeded
-                               if (ch == '/' && chNext == '*') {
-                                       state = SCE_C_COMMENT;
-                               } else if (ch == '-' && chNext == '-') {
-                                       state = SCE_C_COMMENTLINE;
-                               } else if (ch == '#') {
-                                       state = SCE_C_COMMENTLINEDOC;
-                               } else if (ch == '\'') {
-                                       state = SCE_C_CHARACTER;
-                               } else if (ch == '"') {
-                                       state = SCE_C_STRING;
-                               } else if (iswordstart(ch)) {
-                                       state = SCE_C_WORD;
-                               } else if (isoperator(ch)) {
-                                       styler.ColourTo(i, SCE_C_OPERATOR);
-                               }
+               }
+               if (atEOL) {
+                       int level = levelCurrent;
+                       if (visibleChars == 0 && foldCompact) {
+                               // Empty line
+                               level |= SC_FOLDLEVELWHITEFLAG;
                        }
+                       if (visibleChars > 0 && levelNext > levelCurrent) {
+                               level |= SC_FOLDLEVELHEADERFLAG;
+                       }
+                       if (level != styler.LevelAt(lineCurrent)) {
+                               styler.SetLevel(lineCurrent, level);
+                       }
+                       lineCurrent++;
+                       levelCurrent = levelNext;
+                       visibleChars = 0;
+                       endFound = false;
+               }
+               if (!isspacechar(ch)) {
+                       visibleChars++;
                }
-               chPrev = ch;
        }
-       styler.ColourTo(lengthDoc - 1, state);
 }
 
 static const char * const sqlWordListDesc[] = {
        "Keywords",
+       "Database Objects",
+       "PLDoc",
+       "SQL*Plus",
+       "User Keywords 1",
+       "User Keywords 2",
+       "User Keywords 3",
+       "User Keywords 4",
        0
 };
 
-LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", 0, sqlWordListDesc);
+LexerModule lmSQL(SCLEX_SQL, ColouriseSQLDoc, "sql", FoldSQLDoc, sqlWordListDesc);
diff --git a/src/stc/scintilla/src/LexSmalltalk.cxx b/src/stc/scintilla/src/LexSmalltalk.cxx
new file mode 100644 (file)
index 0000000..6f43ec3
--- /dev/null
@@ -0,0 +1,317 @@
+// Scintilla source code edit control
+/** @file LexSmalltalk.cxx
+ ** Lexer for Smalltalk language.
+ ** Written by Sergey Philippov, sphilippov-at-gmail-dot-com
+ **/
+// Copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+// The License.txt file describes the conditions under which this software may be distributed.
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+/*
+| lexTable classificationBlock charClasses |
+charClasses := #(#DecDigit #Letter #Special #Upper #BinSel).
+lexTable := ByteArray new: 128.
+classificationBlock := [ :charClass :chars |
+    | flag |
+    flag := 1 bitShift: (charClasses indexOf: charClass) - 1.
+    chars do: [ :char | lexTable at: char codePoint + 1 put: ((lexTable at: char codePoint + 1) bitOr: flag)]].
+
+classificationBlock
+    value: #DecDigit value: '0123456789';
+    value: #Letter value: '_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    value: #Special value: '()[]{};.^:';
+    value: #BinSel value: '~@%&*-+=|\/,<>?!';
+    value: #Upper value: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.
+
+((String new: 500) streamContents: [ :stream |            
+    stream crLf; nextPutAll: 'static int ClassificationTable[256] = {'.
+    lexTable keysAndValuesDo: [ :index :value |
+        ((index - 1) rem: 16) == 0 ifTrue: [
+            stream crLf; tab]
+        ifFalse: [
+            stream space].
+        stream print: value.
+        index ~= 256 ifTrue: [
+            stream nextPut: $,]].
+    stream crLf; nextPutAll: '};'; crLf.
+    
+    charClasses keysAndValuesDo: [ :index :name |
+        stream
+            crLf;
+            nextPutAll: (
+                ('static inline bool is<1s>(int ch) {return (ch > 0) && (ch %< 0x80) && ((ClassificationTable[ch] & <2p>) != 0);}')
+                    expandMacrosWith: name with: (1 bitShift: (index - 1)))
+    ]]) edit
+*/
+
+// autogenerated {{{{
+
+static int ClassificationTable[256] = {
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+    0, 16, 0, 0, 0, 16, 16, 0, 4, 4, 16, 16, 16, 16, 4, 16,
+    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4, 4, 16, 16, 16, 16,
+    16, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10,
+    10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 4, 16, 4, 4, 2,
+    0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+    2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 4, 16, 4, 16, 0,
+};
+
+static inline bool isDecDigit(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 1) != 0);}
+static inline bool isLetter(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 2) != 0);}
+static inline bool isSpecial(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 4) != 0);}
+static inline bool isUpper(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 8) != 0);}
+static inline bool isBinSel(int ch) {return (ch > 0) && (ch < 0x80) && ((ClassificationTable[ch] & 16) != 0);}
+// autogenerated }}}}
+
+static inline bool isAlphaNumeric(int ch) {
+    return isDecDigit(ch) || isLetter(ch);
+}
+
+static inline bool isDigitOfRadix(int ch, int radix)
+{
+    if (isDecDigit(ch))
+        return (ch - '0') < radix;
+    else if (!isUpper(ch))
+        return false;
+    else
+        return (ch - 'A' + 10) < radix;
+}
+
+static inline void skipComment(StyleContext& sc)
+{    
+    while (sc.More() && sc.ch != '\"')
+        sc.Forward();
+}
+
+static inline void skipString(StyleContext& sc)
+{
+    while (sc.More()) {
+        if (sc.ch == '\'') {
+            if (sc.chNext != '\'')
+                return;
+            sc.Forward();
+        }
+        sc.Forward();
+    }
+}
+
+static void handleHash(StyleContext& sc)
+{
+    if (isSpecial(sc.chNext)) {
+        sc.SetState(SCE_ST_SPECIAL);
+        return;
+    }
+    
+    sc.SetState(SCE_ST_SYMBOL);
+    sc.Forward();
+    if (sc.ch == '\'') {
+        sc.Forward();
+        skipString(sc);
+    }
+    else {
+        if (isLetter(sc.ch)) {
+            while (isAlphaNumeric(sc.chNext) || sc.chNext == ':')
+                sc.Forward();
+        }
+        else if (isBinSel(sc.ch)) {
+            while (isBinSel(sc.chNext))
+                sc.Forward();
+        }
+    }
+}
+
+static inline void handleSpecial(StyleContext& sc)
+{
+    if (sc.ch == ':' && sc.chNext == '=') {
+        sc.SetState(SCE_ST_ASSIGN);
+        sc.Forward();
+    }
+    else {
+        if (sc.ch == '^')
+            sc.SetState(SCE_ST_RETURN);
+        else
+            sc.SetState(SCE_ST_SPECIAL);
+    }
+}
+
+static inline void skipInt(StyleContext& sc, int radix)
+{
+    while (isDigitOfRadix(sc.chNext, radix))
+        sc.Forward();
+}
+
+static void handleNumeric(StyleContext& sc)
+{
+    char num[256];
+    int nl;
+    int radix;
+    
+    sc.SetState(SCE_ST_NUMBER);
+    num[0] = static_cast<char>(sc.ch);
+    nl = 1;
+    while (isDecDigit(sc.chNext)) {
+        num[nl++] = static_cast<char>(sc.chNext);
+        sc.Forward();
+        if (nl+1 == sizeof(num)/sizeof(num[0])) // overrun check
+            break;
+    }
+    if (sc.chNext == 'r') {
+        num[nl] = 0;
+        if (num[0] == '-')
+            radix = atoi(num + 1);
+        else
+            radix = atoi(num);
+        sc.Forward();
+        if (sc.chNext == '-')
+            sc.Forward();
+        skipInt(sc, radix);
+    }
+    else
+        radix = 10;
+    if (sc.chNext != '.' || !isDigitOfRadix(sc.GetRelative(2), radix))
+        return;
+    sc.Forward();
+    skipInt(sc, radix);
+    if (sc.chNext == 's') {
+        // ScaledDecimal
+        sc.Forward();
+        while (isDecDigit(sc.chNext))
+            sc.Forward();
+        return;
+    }
+    else if (sc.chNext != 'e' && sc.chNext != 'd' && sc.chNext != 'q')
+        return;
+    sc.Forward();
+    if (sc.chNext == '+' || sc.chNext == '-')
+        sc.Forward();
+    skipInt(sc, radix);
+}
+
+static inline void handleBinSel(StyleContext& sc)
+{
+    sc.SetState(SCE_ST_BINARY);
+    while (isBinSel(sc.chNext))
+        sc.Forward();
+}
+
+static void handleLetter(StyleContext& sc, WordList* specialSelectorList)
+{
+    char ident[256];
+    int il;
+    int state;
+    bool doubleColonPresent;
+    
+    sc.SetState(SCE_ST_DEFAULT);
+
+    ident[0] = static_cast<char>(sc.ch);
+    il = 1;
+    while (isAlphaNumeric(sc.chNext)) {
+        ident[il++] = static_cast<char>(sc.chNext);
+        sc.Forward();
+        if (il+2 == sizeof(ident)/sizeof(ident[0])) // overrun check
+            break;
+    }
+
+    if (sc.chNext == ':') {
+        doubleColonPresent = true;
+        ident[il++] = ':';
+        sc.Forward();
+    }
+    else
+        doubleColonPresent = false;
+    ident[il] = 0;
+    
+    if (specialSelectorList->InList(ident))
+            state = SCE_ST_SPEC_SEL;
+    else if (doubleColonPresent)
+            state = SCE_ST_KWSEND;
+    else if (isUpper(ident[0]))
+        state = SCE_ST_GLOBAL;
+    else {
+        if (!strcmp(ident, "self"))
+            state = SCE_ST_SELF;
+        else if (!strcmp(ident, "super"))
+            state = SCE_ST_SUPER;
+        else if (!strcmp(ident, "nil"))
+            state = SCE_ST_NIL;
+        else if (!strcmp(ident, "true") || !strcmp(ident, "false"))
+            state = SCE_ST_BOOL;
+        else
+            state = SCE_ST_DEFAULT;
+    }
+    
+    sc.ChangeState(state);
+}
+
+static void colorizeSmalltalkDoc(unsigned int startPos, int length, int initStyle, WordList *wordLists[], Accessor &styler)
+{
+    StyleContext sc(startPos, length, initStyle, styler);
+
+    if (initStyle == SCE_ST_COMMENT) {
+        skipComment(sc);
+        if (sc.More())
+            sc.Forward();
+    }
+    else if (initStyle == SCE_ST_STRING) {
+        skipString(sc);
+        if (sc.More())
+            sc.Forward();
+    }
+
+    for (; sc.More(); sc.Forward()) {
+        int ch;
+        
+        ch = sc.ch;
+        if (ch == '\"') {
+            sc.SetState(SCE_ST_COMMENT);
+            sc.Forward();
+            skipComment(sc);
+        }
+        else if (ch == '\'') {
+            sc.SetState(SCE_ST_STRING);
+            sc.Forward();
+            skipString(sc);
+        }
+        else if (ch == '#')
+            handleHash(sc);
+        else if (ch == '$') {
+            sc.SetState(SCE_ST_CHARACTER);
+            sc.Forward();
+        }
+        else if (isSpecial(ch))
+            handleSpecial(sc);
+        else if (isDecDigit(ch))
+            handleNumeric(sc);
+        else if (isLetter(ch))
+            handleLetter(sc, wordLists[0]);
+        else if (isBinSel(ch)) {
+            if (ch == '-' && isDecDigit(sc.chNext))
+                handleNumeric(sc);
+            else
+                handleBinSel(sc);
+        }
+        else
+            sc.SetState(SCE_ST_DEFAULT);
+    }
+    sc.Complete();
+}
+
+static const char* const smalltalkWordListDesc[] = {
+    "Special selectors",
+    0
+};
+
+LexerModule lmSmalltalk(SCLEX_SMALLTALK, colorizeSmalltalkDoc, "smalltalk", NULL, smalltalkWordListDesc);
diff --git a/src/stc/scintilla/src/LexTADS3.cxx b/src/stc/scintilla/src/LexTADS3.cxx
new file mode 100644 (file)
index 0000000..9938f63
--- /dev/null
@@ -0,0 +1,837 @@
+// Scintilla source code edit control
+/** @file LexTADS3.cxx
+ ** Lexer for TADS3.
+ **/
+/* Copyright 2005 by Michael Cartmell
+ * Parts copyright 1998-2002 by Neil Hodgson <neilh@scintilla.org>
+ * In particular FoldTADS3Doc is derived from FoldCppDoc
+ * The License.txt file describes the conditions under which this software may
+ * be distributed.
+ */
+
+/*
+ * TADS3 is a language designed by Michael J. Roberts for the writing of text
+ * based games.  TADS comes from Text Adventure Development System.  It has good
+ * support for the processing and outputting of formatted text and much of a
+ * TADS program listing consists of strings.
+ *
+ * TADS has two types of strings, those enclosed in single quotes (') and those
+ * enclosed in double quotes (").  These strings have different symantics and
+ * can be given different highlighting if desired.
+ *
+ * There can be embedded within both types of strings html tags
+ * ( <tag key=value> ), library directives ( <.directive> ), and message
+ * parameters ( {The doctor's/his} ).
+ *
+ * Double quoted strings can also contain interpolated expressions
+ * ( << rug.moved ? ' and a hole in the floor. ' : nil >> ).  These expressions
+ * may themselves contain single or double quoted strings, although the double
+ * quoted strings may not contain interpolated expressions.
+ *
+ * These embedded constructs influence the output and formatting and are an
+ * important part of a program and require highlighting.
+ *
+ * LINKS
+ * http://www.tads.org/
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#include "Platform.h"
+
+#include "PropSet.h"
+#include "Accessor.h"
+#include "StyleContext.h"
+#include "KeyWords.h"
+#include "Scintilla.h"
+#include "SciLexer.h"
+
+static const int T3_SINGLE_QUOTE = 1;
+static const int T3_INT_EXPRESSION = 2;
+
+static inline bool IsEOL(const int ch, const int chNext) {
+       return (ch == '\r' && chNext != '\n') || (ch == '\n');
+}
+
+static inline bool IsASpaceOrTab(const int ch) {
+       return ch == ' ' || ch == '\t';
+}
+
+static inline bool IsATADS3Operator(const int ch) {
+       return ch == '=' || ch == '{' || ch == '}' || ch == '(' || ch == ')'
+               || ch == '[' || ch == ']' || ch == ',' || ch == ':' || ch == ';'
+               || ch == '+' || ch == '-' || ch == '*' || ch == '/' || ch == '%'
+               || ch == '?' || ch == '!' || ch == '<' || ch == '>' || ch == '|'
+               || ch == '@' || ch == '&' || ch == '~';
+}
+
+static inline bool IsAWordChar(const int ch) {
+       return isalnum(ch) || ch == '_' || ch == '.';
+}
+
+static inline bool IsAWordStart(const int ch) {
+       return isalpha(ch) || ch == '_';
+}
+
+static inline bool IsAHexDigit(const int ch) {
+       int lch = tolower(ch);
+       return isdigit(lch) || lch == 'a' || lch == 'b' || lch == 'c'
+               || lch == 'd' || lch == 'e' || lch == 'f';
+}
+
+static inline bool IsAnHTMLChar(int ch) {
+       return isalnum(ch) || ch == '-' || ch == '_' || ch == '.';
+}
+
+static inline bool IsADirectiveChar(int ch) {
+       return isalnum(ch) || isspace(ch) || ch == '-' || ch == '/';
+}
+
+static inline bool IsANumberStart(StyleContext &sc) {
+       return isdigit(sc.ch)
+               || (!isdigit(sc.chPrev) && sc.ch == '.' && isdigit(sc.chNext));
+}
+
+inline static void ColouriseTADS3Operator(StyleContext &sc) {
+       int initState = sc.state;
+       sc.SetState(SCE_T3_OPERATOR);
+       sc.ForwardSetState(initState);
+}
+
+static void ColouriseTADSHTMLString(StyleContext &sc, int &lineState) {
+       int endState = sc.state;
+       int chQuote = sc.ch;
+       if (endState == SCE_T3_HTML_STRING) {
+               if (lineState&T3_SINGLE_QUOTE) {
+                       endState = SCE_T3_S_STRING;
+                       chQuote = '"';
+               } else if (lineState&T3_INT_EXPRESSION) {
+                       endState = SCE_T3_X_STRING;
+                       chQuote = '\'';
+               } else {
+                       endState = SCE_T3_D_STRING;
+                       chQuote = '\'';
+               }
+       } else {
+               sc.SetState(SCE_T3_HTML_STRING);
+               sc.Forward();
+       }
+       int chString = chQuote == '"'? '\'': '"';
+
+       while (sc.More()) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               if (sc.ch == chQuote) {
+                       sc.ForwardSetState(endState);
+                       return;
+               }
+               if (sc.ch == chString) {
+                       sc.SetState(endState);
+                       return;
+               }
+               if (sc.Match('\\', static_cast<char>(chQuote))
+                       || sc.Match('\\', static_cast<char>(chString))) {
+                       sc.Forward(2);
+               } else {
+                       sc.Forward();
+               }
+       }
+}
+
+static void ColouriseTADS3HTMLTagStart(StyleContext &sc) {
+       sc.SetState(SCE_T3_HTML_TAG);
+       sc.Forward();
+       if (sc.ch == '/') {
+               sc.Forward();
+       }
+       while (IsAnHTMLChar(sc.ch)) {
+               sc.Forward();
+       }
+}
+
+static void ColouriseTADS3HTMLTag(StyleContext &sc, int &lineState) {
+       int endState = sc.state;
+       int chQuote = '"';
+       int chString = '\'';
+       switch (endState) {
+               case SCE_T3_S_STRING:
+                       ColouriseTADS3HTMLTagStart(sc);
+                       sc.SetState(SCE_T3_HTML_DEFAULT);
+                       chQuote = '\'';
+                       chString = '"';
+                       break;
+               case SCE_T3_D_STRING:
+               case SCE_T3_X_STRING:
+                       ColouriseTADS3HTMLTagStart(sc);
+                       sc.SetState(SCE_T3_HTML_DEFAULT);
+                       break;
+               case SCE_T3_HTML_DEFAULT:
+                       if (lineState&T3_SINGLE_QUOTE) {
+                               endState = SCE_T3_S_STRING;
+                               chQuote = '\'';
+                               chString = '"';
+                       } else if (lineState&T3_INT_EXPRESSION) {
+                               endState = SCE_T3_X_STRING;
+                       } else {
+                               endState = SCE_T3_D_STRING;
+                       }
+                       break;
+       }
+
+       while (sc.More()) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               if (sc.Match('/', '>')) {
+                       sc.SetState(SCE_T3_HTML_TAG);
+                       sc.Forward(2);
+                       sc.SetState(endState);
+                       return;
+               }
+               if (sc.ch == '>') {
+                       sc.SetState(SCE_T3_HTML_TAG);
+                       sc.ForwardSetState(endState);
+                       return;
+               }
+               if (sc.ch == chQuote) {
+                       sc.SetState(endState);
+                       return;
+               }
+               if (sc.ch == chString) {
+                       ColouriseTADSHTMLString(sc, lineState);
+               } else if (sc.ch == '=') {
+                       ColouriseTADS3Operator(sc);
+               } else {
+                       sc.Forward();
+               }
+       }
+}
+
+static void ColouriseTADS3Keyword(StyleContext &sc,
+                                                       WordList *keywordlists[],       unsigned int endPos) {
+       char s[250];
+       WordList &keywords = *keywordlists[0];
+       WordList &userwords1 = *keywordlists[1];
+       WordList &userwords2 = *keywordlists[2];
+       WordList &userwords3 = *keywordlists[3];
+       int initState = sc.state;
+       sc.SetState(SCE_T3_IDENTIFIER);
+       while (sc.More() && (IsAWordChar(sc.ch))) {
+               sc.Forward();
+       }
+       sc.GetCurrent(s, sizeof(s));
+       if ( strcmp(s, "is") == 0 || strcmp(s, "not") == 0) {
+               // have to find if "in" is next
+               int n = 1;
+               while (n + sc.currentPos < endPos && IsASpaceOrTab(sc.GetRelative(n)))
+                       n++;
+               if (sc.GetRelative(n) == 'i' && sc.GetRelative(n+1) == 'n') {
+                       sc.Forward(n+2);
+                       sc.ChangeState(SCE_T3_KEYWORD);
+               }
+       } else if (keywords.InList(s)) {
+               sc.ChangeState(SCE_T3_KEYWORD);
+       } else if (userwords3.InList(s)) {
+               sc.ChangeState(SCE_T3_USER3);
+       } else if (userwords2.InList(s)) {
+               sc.ChangeState(SCE_T3_USER2);
+       } else if (userwords1.InList(s)) {
+               sc.ChangeState(SCE_T3_USER1);
+       }
+       sc.SetState(initState);
+}
+
+static void ColouriseTADS3MsgParam(StyleContext &sc, int &lineState) {
+       int endState = sc.state;
+       int chQuote = '"';
+       switch (endState) {
+               case SCE_T3_S_STRING:
+                       sc.SetState(SCE_T3_MSG_PARAM);
+                       sc.Forward();
+                       chQuote = '\'';
+                       break;
+               case SCE_T3_D_STRING:
+               case SCE_T3_X_STRING:
+                       sc.SetState(SCE_T3_MSG_PARAM);
+                       sc.Forward();
+                       break;
+               case SCE_T3_MSG_PARAM:
+                       if (lineState&T3_SINGLE_QUOTE) {
+                               endState = SCE_T3_S_STRING;
+                               chQuote = '\'';
+                       } else if (lineState&T3_INT_EXPRESSION) {
+                               endState = SCE_T3_X_STRING;
+                       } else {
+                               endState = SCE_T3_D_STRING;
+                       }
+                       break;
+       }
+       while (sc.More() && sc.ch != '}' && sc.ch != chQuote) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               if (sc.ch == '\\') {
+                       sc.Forward();
+               }
+               sc.Forward();
+       }
+       if (sc.ch == chQuote) {
+               sc.SetState(endState);
+       } else {
+               sc.ForwardSetState(endState);
+       }
+}
+
+static void ColouriseTADS3LibDirective(StyleContext &sc, int &lineState) {
+       int initState = sc.state;
+       int chQuote = '"';
+       switch (initState) {
+               case SCE_T3_S_STRING:
+                       sc.SetState(SCE_T3_LIB_DIRECTIVE);
+                       sc.Forward(2);
+                       chQuote = '\'';
+                       break;
+               case SCE_T3_D_STRING:
+                       sc.SetState(SCE_T3_LIB_DIRECTIVE);
+                       sc.Forward(2);
+                       break;
+               case SCE_T3_LIB_DIRECTIVE:
+                       if (lineState&T3_SINGLE_QUOTE) {
+                               initState = SCE_T3_S_STRING;
+                               chQuote = '\'';
+                       } else {
+                               initState = SCE_T3_D_STRING;
+                       }
+                       break;
+       }
+       while (sc.More() && IsADirectiveChar(sc.ch)) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               sc.Forward();
+       };
+       if (sc.ch == '>' || !sc.More()) {
+               sc.ForwardSetState(initState);
+       } else if (sc.ch == chQuote) {
+               sc.SetState(initState);
+       } else {
+               sc.ChangeState(initState);
+               sc.Forward();
+       }
+}
+
+static void ColouriseTADS3String(StyleContext &sc, int &lineState) {
+       int chQuote = sc.ch;
+       int endState = sc.state;
+       switch (sc.state) {
+               case SCE_T3_DEFAULT:
+               case SCE_T3_X_DEFAULT:
+                       if (chQuote == '"') {
+                               if (sc.state == SCE_T3_DEFAULT) {
+                                       sc.SetState(SCE_T3_D_STRING);
+                               } else {
+                                       sc.SetState(SCE_T3_X_STRING);
+                               }
+                               lineState &= ~T3_SINGLE_QUOTE;
+                       } else {
+                               sc.SetState(SCE_T3_S_STRING);
+                               lineState |= T3_SINGLE_QUOTE;
+                       }
+                       sc.Forward();
+                       break;
+               case SCE_T3_S_STRING:
+                       chQuote = '\'';
+                       endState = lineState&T3_INT_EXPRESSION ?
+                               SCE_T3_X_DEFAULT : SCE_T3_DEFAULT;
+                       break;
+               case SCE_T3_D_STRING:
+                       chQuote = '"';
+                       endState = SCE_T3_DEFAULT;
+                       break;
+               case SCE_T3_X_STRING:
+                       chQuote = '"';
+                       endState = SCE_T3_X_DEFAULT;
+                       break;
+       }
+       while (sc.More()) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               if (sc.ch == chQuote) {
+                       sc.ForwardSetState(endState);
+                       return;
+               }
+               if (sc.state == SCE_T3_D_STRING && sc.Match('<', '<')) {
+                       lineState |= T3_INT_EXPRESSION;
+                       sc.SetState(SCE_T3_X_DEFAULT);
+                       sc.Forward(2);
+                       return;
+               }
+               if (sc.Match('\\', static_cast<char>(chQuote))) {
+                       sc.Forward(2);
+               } else if (sc.ch == '{') {
+                       ColouriseTADS3MsgParam(sc, lineState);
+               } else if (sc.Match('<', '.')) {
+                       ColouriseTADS3LibDirective(sc, lineState);
+               } else if (sc.ch == '<') {
+                       ColouriseTADS3HTMLTag(sc, lineState);
+               } else {
+                       sc.Forward();
+               }
+       }
+}
+
+static void ColouriseTADS3Comment(StyleContext &sc, int endState) {
+       sc.SetState(SCE_T3_BLOCK_COMMENT);
+       while (sc.More()) {
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       return;
+               }
+               if (sc.Match('*', '/')) {
+                       sc.Forward(2);
+                       sc.SetState(endState);
+                       return;
+               }
+               sc.Forward();
+       }
+}
+
+static void ColouriseToEndOfLine(StyleContext &sc, int initState, int endState) {
+       sc.SetState(initState);
+       while (sc.More()) {
+               if (sc.ch == '\\') {
+                       sc.Forward();
+                       if (IsEOL(sc.ch, sc.chNext)) {
+                                       return;
+                       }
+               }
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       sc.SetState(endState);
+                       return;
+               }
+               sc.Forward();
+       }
+}
+
+static void ColouriseTADS3Number(StyleContext &sc) {
+       int endState = sc.state;
+       bool inHexNumber = false;
+       bool seenE = false;
+       bool seenDot = sc.ch == '.';
+       sc.SetState(SCE_T3_NUMBER);
+       if (sc.More()) {
+               sc.Forward();
+       }
+       if (sc.chPrev == '0' && tolower(sc.ch) == 'x') {
+               inHexNumber = true;
+               sc.Forward();
+       }
+       while (sc.More()) {
+               if (inHexNumber) {
+                       if (!IsAHexDigit(sc.ch)) {
+                               break;
+                       }
+               } else if (!isdigit(sc.ch)) {
+                       if (!seenE && tolower(sc.ch) == 'e') {
+                               seenE = true;
+                               seenDot = true;
+                               if (sc.chNext == '+' || sc.chNext == '-') {
+                                       sc.Forward();
+                               }
+                       } else if (!seenDot && sc.ch == '.') {
+                               seenDot = true;
+                       } else {
+                               break;
+                       }
+               }
+               sc.Forward();
+       }
+       sc.SetState(endState);
+}
+
+static void ColouriseTADS3Doc(unsigned int startPos, int length, int initStyle,
+                                                          WordList *keywordlists[], Accessor &styler) {
+       int visibleChars = 0;
+       int bracketLevel = 0;
+       int lineState = 0;
+       unsigned int endPos = startPos + length;
+       int lineCurrent = styler.GetLine(startPos);
+       if (lineCurrent > 0) {
+               lineState = styler.GetLineState(lineCurrent-1);
+       }
+       StyleContext sc(startPos, length, initStyle, styler);
+
+       while (sc.More()) {
+
+               if (IsEOL(sc.ch, sc.chNext)) {
+                       styler.SetLineState(lineCurrent, lineState);
+                       lineCurrent++;
+                       visibleChars = 0;
+                       sc.Forward();
+                       if (sc.ch == '\n') {
+                               sc.Forward();
+                       }
+               }
+
+               switch(sc.state) {
+                       case SCE_T3_PREPROCESSOR:
+                       case SCE_T3_LINE_COMMENT:
+                               ColouriseToEndOfLine(sc, sc.state, lineState&T3_INT_EXPRESSION ?
+                                       SCE_T3_X_DEFAULT : SCE_T3_DEFAULT);
+                               break;
+                       case SCE_T3_S_STRING:
+                       case SCE_T3_D_STRING:
+                       case SCE_T3_X_STRING:
+                               ColouriseTADS3String(sc, lineState);
+                               visibleChars++;
+                               break;
+                       case SCE_T3_MSG_PARAM:
+                               ColouriseTADS3MsgParam(sc, lineState);
+                               break;
+                       case SCE_T3_LIB_DIRECTIVE:
+                               ColouriseTADS3LibDirective(sc, lineState);
+                               break;
+                       case SCE_T3_HTML_DEFAULT:
+                               ColouriseTADS3HTMLTag(sc, lineState);
+                               break;
+                       case SCE_T3_HTML_STRING:
+                               ColouriseTADSHTMLString(sc, lineState);
+                               break;
+                       case SCE_T3_BLOCK_COMMENT:
+                               ColouriseTADS3Comment(sc, lineState&T3_INT_EXPRESSION ?
+                                       SCE_T3_X_DEFAULT : SCE_T3_DEFAULT);
+                               break;
+                       case SCE_T3_DEFAULT:
+                       case SCE_T3_X_DEFAULT:
+                               if (IsASpaceOrTab(sc.ch)) {
+                                       sc.Forward();
+                               } else if (sc.ch == '#' && visibleChars == 0) {
+                                       ColouriseToEndOfLine(sc, SCE_T3_PREPROCESSOR, sc.state);
+                               } else if (sc.Match('/', '*')) {
+                                       ColouriseTADS3Comment(sc, sc.state);
+                                       visibleChars++;
+                               } else if (sc.Match('/', '/')) {
+                                       ColouriseToEndOfLine(sc, SCE_T3_LINE_COMMENT, sc.state);
+                               } else if (sc.ch == '"') {
+                                       bracketLevel = 0;
+                                       ColouriseTADS3String(sc, lineState);
+                                       visibleChars++;
+                               } else if (sc.ch == '\'') {
+                                       ColouriseTADS3String(sc, lineState);
+                                       visibleChars++;
+                               } else if (sc.state == SCE_T3_X_DEFAULT && bracketLevel == 0
+                                                  && sc.Match('>', '>')) {
+                                       sc.Forward(2);
+                                       sc.SetState(SCE_T3_D_STRING);
+                                       lineState &= ~(T3_SINGLE_QUOTE|T3_INT_EXPRESSION);
+                               } else if (IsATADS3Operator(sc.ch)) {
+                                       if (sc.state == SCE_T3_X_DEFAULT) {
+                                               if (sc.ch == '(') {
+                                                       bracketLevel++;
+                                               } else if (sc.ch == ')') {
+                                                       bracketLevel--;
+                                               }
+                                       }
+                                       ColouriseTADS3Operator(sc);
+                                       visibleChars++;
+                               } else if (IsANumberStart(sc)) {
+                                       ColouriseTADS3Number(sc);
+                                       visibleChars++;
+                               } else if (IsAWordStart(sc.ch)) {
+                                       ColouriseTADS3Keyword(sc, keywordlists, endPos);
+                                       visibleChars++;
+                               } else if (sc.Match("...")) {
+                                       sc.SetState(SCE_T3_IDENTIFIER);
+                                       sc.Forward(3);
+                                       sc.SetState(SCE_T3_DEFAULT);
+                               } else {
+                                       sc.Forward();
+                                       visibleChars++;
+                               }
+                               break;
+                       default:
+                               sc.SetState(SCE_T3_DEFAULT);
+                               sc.Forward();
+               }
+       }
+       sc.Complete();
+}
+
+/*
+ TADS3 has two styles of top level block (TLB). Eg
+
+ // default style
+ silverKey : Key 'small silver key' 'small silver key'
+       "A small key glints in the sunlight. "
+ ;
+
+ and
+
+ silverKey : Key {
+       'small silver key'
+       'small silver key'
+       "A small key glints in the sunlight. "
+ }
+
+ Some constructs mandate one or the other, but usually the author has may choose
+ either.
+
+ T3_SEENSTART is used to indicate that a braceless TLB has been (potentially)
+ seen and is also used to match the closing ';' of the default style.
+
+ T3_EXPECTINGIDENTIFIER and T3_EXPECTINGPUNCTUATION are used to keep track of
+ what characters may be seen without incrementing the block level.  The general
+ pattern is identifier <punc> identifier, acceptable punctuation characters
+ are ':', ',', '(' and ')'.  No attempt is made to ensure that punctuation
+ characters are syntactically correct, eg parentheses match. A ')' always
+ signifies the start of a block.  We just need to check if it is followed by a
+ '{', in which case we let the brace handling code handle the folding level.
+
+ expectingIdentifier == false && expectingIdentifier == false
+ Before the start of a TLB.
+
+ expectingIdentifier == true && expectingIdentifier == true
+ Currently in an identifier.  Will accept identifier or punctuation.
+
+ expectingIdentifier == true && expectingIdentifier == false
+ Just seen a punctuation character & now waiting for an identifier to start.
+
+ expectingIdentifier == false && expectingIdentifier == truee
+ We were in an identifier and have seen space.  Now waiting to see a punctuation
+ character
+
+ Space, comments & preprocessor directives are always acceptable and are
+ equivalent.
+*/
+
+static const int T3_SEENSTART = 1 << 12;
+static const int T3_EXPECTINGIDENTIFIER = 1 << 13;
+static const int T3_EXPECTINGPUNCTUATION = 1 << 14;
+
+static inline bool IsStringTransition(int s1, int s2) {
+       return s1 != s2
+               && (s1 == SCE_T3_S_STRING || s1 == SCE_T3_X_STRING
+                       || s1 == SCE_T3_D_STRING && s2 != SCE_T3_X_DEFAULT)
+               && s2 != SCE_T3_LIB_DIRECTIVE
+               && s2 != SCE_T3_MSG_PARAM
+               && s2 != SCE_T3_HTML_TAG
+               && s2 != SCE_T3_HTML_STRING;
+}
+
+static inline bool IsATADS3Punctuation(const int ch) {
+       return ch == ':' || ch == ',' || ch == '(' || ch == ')';
+}
+
+static inline bool IsAnIdentifier(const int style) {
+       return style == SCE_T3_IDENTIFIER
+               || style == SCE_T3_USER1
+               || style == SCE_T3_USER2
+               || style == SCE_T3_USER3;
+}
+
+static inline bool IsSpaceEquivalent(const int ch, const int style) {
+       return isspace(ch)
+               || style == SCE_T3_BLOCK_COMMENT
+               || style == SCE_T3_LINE_COMMENT
+               || style == SCE_T3_PREPROCESSOR;
+}
+
+static char peekAhead(unsigned int startPos, unsigned int endPos,
+                                         Accessor &styler) {
+       for (unsigned int i = startPos; i < endPos; i++) {
+               int style = styler.StyleAt(i);
+               char ch = styler[i];
+               if (!IsSpaceEquivalent(ch, style)) {
+                       if (IsAnIdentifier(style)) {
+                               return 'a';
+                       }
+                       if (IsATADS3Punctuation(ch)) {
+                               return ':';
+                       }
+                       if (ch == '{') {
+                               return '{';
+                       }
+                       return '*';
+               }
+       }
+       return ' ';
+}
+
+static void FoldTADS3Doc(unsigned int startPos, int length, int initStyle,
+                            WordList *[], Accessor &styler) {
+       unsigned int endPos = startPos + length;
+       int lineCurrent = styler.GetLine(startPos);
+       int levelCurrent = SC_FOLDLEVELBASE;
+       if (lineCurrent > 0)
+               levelCurrent = styler.LevelAt(lineCurrent-1) >> 16;
+       int seenStart = levelCurrent & T3_SEENSTART;
+       int expectingIdentifier = levelCurrent & T3_EXPECTINGIDENTIFIER;
+       int expectingPunctuation = levelCurrent & T3_EXPECTINGPUNCTUATION;
+       levelCurrent &= SC_FOLDLEVELNUMBERMASK;
+       int levelMinCurrent = levelCurrent;
+       int levelNext = levelCurrent;
+       char chNext = styler[startPos];
+       int styleNext = styler.StyleAt(startPos);
+       int style = initStyle;
+       char ch = chNext;
+       int stylePrev = style;
+       bool redo = false;
+       for (unsigned int i = startPos; i < endPos; i++) {
+               if (redo) {
+                       redo = false;
+                       i--;
+               } else {
+                       ch = chNext;
+                       chNext = styler.SafeGetCharAt(i + 1);
+                       stylePrev = style;
+                       style = styleNext;
+                       styleNext = styler.StyleAt(i + 1);
+               }
+               bool atEOL = IsEOL(ch, chNext);
+
+               if (levelNext == SC_FOLDLEVELBASE) {
+                       if (IsSpaceEquivalent(ch, style)) {
+                               if (expectingPunctuation) {
+                                       expectingIdentifier = 0;
+                               }
+                               if (style == SCE_T3_BLOCK_COMMENT) {
+                                       levelNext++;
+                               }
+                       } else if (ch == '{') {
+                               levelNext++;
+                               seenStart = 0;
+                       } else if (ch == '\'' || ch == '"' || ch == '[') {
+                               levelNext++;
+                               if (seenStart) {
+                                       redo = true;
+                               }
+                       } else if (ch == ';') {
+                               seenStart = 0;
+                               expectingIdentifier = 0;
+                               expectingPunctuation = 0;
+                       } else if (expectingIdentifier && expectingPunctuation) {
+                               if (IsATADS3Punctuation(ch)) {
+                                       if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') {
+                                               levelNext++;
+                                       } else {
+                                               expectingPunctuation = 0;
+                                       }
+                               } else if (!IsAnIdentifier(style)) {
+                                       levelNext++;
+                               }
+                       } else if (expectingIdentifier && !expectingPunctuation) {
+                               if (!IsAnIdentifier(style)) {
+                                       levelNext++;
+                               } else {
+                                       expectingPunctuation = T3_EXPECTINGPUNCTUATION;
+                               }
+                       } else if (!expectingIdentifier && expectingPunctuation) {
+                               if (!IsATADS3Punctuation(ch)) {
+                                       levelNext++;
+                               } else {
+                                       if (ch == ')' && peekAhead(i+1, endPos, styler) != '{') {
+                                               levelNext++;
+                                       } else {
+                                               expectingIdentifier = T3_EXPECTINGIDENTIFIER;
+                                               expectingPunctuation = 0;
+                                       }
+                               }
+                       } else if (!expectingIdentifier && !expectingPunctuation) {
+                               if (IsAnIdentifier(style)) {
+                                       seenStart = T3_SEENSTART;
+                                       expectingIdentifier = T3_EXPECTINGIDENTIFIER;
+                                       expectingPunctuation = T3_EXPECTINGPUNCTUATION;
+                               }
+                       }
+
+                       if (levelNext != SC_FOLDLEVELBASE && style != SCE_T3_BLOCK_COMMENT) {
+                               expectingIdentifier = 0;
+                               expectingPunctuation = 0;
+                       }
+
+               } else if (levelNext == SC_FOLDLEVELBASE+1 && seenStart
+                                  && ch == ';' && style == SCE_T3_OPERATOR ) {
+                       levelNext--;
+                       seenStart = 0;
+               } else if (style == SCE_T3_BLOCK_COMMENT) {
+                       if (stylePrev != SCE_T3_BLOCK_COMMENT) {
+                               levelNext++;
+                       } else if (styleNext != SCE_T3_BLOCK_COMMENT && !atEOL) {
+                               // Comments don't end at end of line and the next character may be unstyled.
+                               levelNext--;
+                       }
+               } else if (ch == '\'' || ch == '"') {
+                       if (IsStringTransition(style, stylePrev)) {
+                               if (levelMinCurrent > levelNext) {
+                                       levelMinCurrent = levelNext;
+                               }
+                               levelNext++;
+                       } else if (IsStringTransition(style, styleNext)) {
+                               levelNext--;
+                       }
+               } else if (style == SCE_T3_OPERATOR) {
+                       if (ch == '{' || ch == '[') {
+                               // Measure the minimum before a '{' to allow
+                               // folding on "} else {"
+                               if (levelMinCurrent > levelNext) {
+                                       levelMinCurrent = levelNext;
+                               }
+                               levelNext++;
+                       } else if (ch == '}' || ch == ']') {
+                               levelNext--;
+                       }
+               }
+
+               if (atEOL) {
+                       if (seenStart && levelNext == SC_FOLDLEVELBASE) {
+                               switch (peekAhead(i+1, endPos, styler)) {
+                                       case ' ':
+                                       case '{':
+                                               break;
+                                       case '*':
+                                               levelNext++;
+                                               break;
+                                       case 'a':
+                                               if (expectingPunctuation) {
+                                                       levelNext++;
+                                               }
+                                               break;
+                                       case ':':
+                                               if (expectingIdentifier) {
+                                                       levelNext++;
+                                               }
+                                               break;
+                               }
+                               if (levelNext != SC_FOLDLEVELBASE) {
+                                       expectingIdentifier = 0;
+                                       expectingPunctuation = 0;
+                               }
+                       }
+                       int lev = levelMinCurrent | (levelNext | expectingIdentifier
+                               | expectingPunctuation | seenStart) << 16;
+                       if (levelMinCurrent < levelNext)
+                               lev |= SC_FOLDLEVELHEADERFLAG;
+                       if (lev != styler.LevelAt(lineCurrent)) {
+                               styler.SetLevel(lineCurrent, lev);
+                       }
+                       lineCurrent++;
+                       levelCurrent = levelNext;
+                       levelMinCurrent = levelCurrent;
+               }
+       }
+}
+
+static const char * const tads3WordList[] = {
+       "TADS3 Keywords",
+       "User defined 1",
+       "User defined 2",
+       "User defined 3",
+       0
+};
+
+LexerModule lmTADS3(SCLEX_TADS3, ColouriseTADS3Doc, "tads3", FoldTADS3Doc, tads3WordList);
index a5b09467019282f8f7036a94ce7d09bae9aedc73..65e530adb8b443a4faed89106d508ad5c5ea82d1 100644 (file)
@@ -275,7 +275,7 @@ static void ColouriseTeXDoc(
 // Hooks into the system:
 
 static const char * const texWordListDesc[] = {
-    "TeX, eTeX, pdfTeX, Omega"
+    "TeX, eTeX, pdfTeX, Omega",
     "ConTeXt Dutch",
     "ConTeXt English",
     "ConTeXt German",
index 93bdedbd897b77c946d6527e972dd266e9ca50fe..d9f02862913e405ad46234b2ab54557d57477381 100644 (file)
@@ -2,7 +2,7 @@
 /** @file LexVB.cxx
  ** Lexer for Visual Basic and VBScript.
  **/
-// Copyright 1998-2003 by Neil Hodgson <neilh@scintilla.org>
+// Copyright 1998-2005 by Neil Hodgson <neilh@scintilla.org>
 // The License.txt file describes the conditions under which this software may be distributed.
 
 #include <stdlib.h>
 #include "Scintilla.h"
 #include "SciLexer.h"
 
+// Internal state, highlighted as number
+#define SCE_B_FILENUMBER SCE_B_DEFAULT+100
+
+
 static bool IsVBComment(Accessor &styler, int pos, int len) {
-       return len>0 && styler[pos]=='\'';
+       return len > 0 && styler[pos] == '\'';
 }
 
 static inline bool IsTypeCharacter(int ch) {
@@ -36,12 +40,15 @@ static inline bool IsAWordChar(int ch) {
 
 static inline bool IsAWordStart(int ch) {
        return ch >= 0x80 ||
-              (isalnum(ch) || ch == '_');
+              (isalpha(ch) || ch == '_');
 }
 
-static inline bool IsADateCharacter(const int ch) {
+static inline bool IsANumberChar(int ch) {
+       // Not exactly following number definition (several dots are seen as OK, etc.)
+       // but probably enough in most cases.
        return (ch < 0x80) &&
-               (isalnum(ch) || ch == '|' || ch == '-' || ch == '/' || ch == ':' || ch == ' ' || ch == '\t');
+               (isdigit(ch) || toupper(ch) == 'E' ||
+             ch == '.' || ch == '-' || ch == '+');
 }
 
 static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
@@ -55,6 +62,12 @@ static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
        styler.StartAt(startPos);
 
        int visibleChars = 0;
+       int fileNbDigits = 0;
+
+       // Do not leak onto next line
+       if (initStyle == SCE_B_STRINGEOL || initStyle == SCE_B_COMMENT || initStyle == SCE_B_PREPROCESSOR) {
+               initStyle = SCE_B_DEFAULT;
+       }
 
        StyleContext sc(startPos, length, initStyle, styler);
 
@@ -96,7 +109,9 @@ static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
                                }
                        }
                } else if (sc.state == SCE_B_NUMBER) {
-                       if (!IsAWordChar(sc.ch)) {
+                       // We stop the number definition on non-numerical non-dot non-eE non-sign char
+                       // Also accepts A-F for hex. numbers
+                       if (!IsANumberChar(sc.ch) && !(tolower(sc.ch) >= 'a' && tolower(sc.ch) <= 'f')) {
                                sc.SetState(SCE_B_DEFAULT);
                        }
                } else if (sc.state == SCE_B_STRING) {
@@ -113,14 +128,38 @@ static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
                        }
                } else if (sc.state == SCE_B_COMMENT) {
                        if (sc.atLineEnd) {
-                               sc.SetState(SCE_B_DEFAULT);
+                               sc.ForwardSetState(SCE_B_DEFAULT);
                        }
                } else if (sc.state == SCE_B_PREPROCESSOR) {
                        if (sc.atLineEnd) {
+                               sc.ForwardSetState(SCE_B_DEFAULT);
+                       }
+               } else if (sc.state == SCE_B_FILENUMBER) {
+                       if (IsADigit(sc.ch)) {
+                               fileNbDigits++;
+                               if (fileNbDigits > 3) {
+                                       sc.ChangeState(SCE_B_DATE);
+                               }
+                       } else if (sc.ch == '\r' || sc.ch == '\n' || sc.ch == ',') {
+                               // Regular uses: Close #1; Put #1, ...; Get #1, ... etc.
+                               // Too bad if date is format #27, Oct, 2003# or something like that...
+                               // Use regular number state
+                               sc.ChangeState(SCE_B_NUMBER);
                                sc.SetState(SCE_B_DEFAULT);
+                       } else if (sc.ch == '#') {
+                               sc.ChangeState(SCE_B_DATE);
+                               sc.ForwardSetState(SCE_B_DEFAULT);
+                       } else {
+                               sc.ChangeState(SCE_B_DATE);
+                       }
+                       if (sc.state != SCE_B_FILENUMBER) {
+                               fileNbDigits = 0;
                        }
                } else if (sc.state == SCE_B_DATE) {
-                       if (sc.ch == '#' || !IsADateCharacter(sc.chNext)) {
+                       if (sc.atLineEnd) {
+                               sc.ChangeState(SCE_B_STRINGEOL);
+                               sc.ForwardSetState(SCE_B_DEFAULT);
+                       } else if (sc.ch == '#') {
                                sc.ForwardSetState(SCE_B_DEFAULT);
                        }
                }
@@ -134,26 +173,24 @@ static void ColouriseVBDoc(unsigned int startPos, int length, int initStyle,
                                // Preprocessor commands are alone on their line
                                sc.SetState(SCE_B_PREPROCESSOR);
                        } else if (sc.ch == '#') {
-                               int n = 1;
-                               int chSeek = ' ';
-                               while ((n < 100) && (chSeek == ' ' || chSeek == '\t')) {
-                                       chSeek = sc.GetRelative(n);
-                                       n++;
-                               }
-                               if (IsADigit(chSeek)) {
-                                       sc.SetState(SCE_B_DATE);
-                               } else {
-                                       sc.SetState(SCE_B_OPERATOR);
-                               }
+                               // It can be a date literal, ending with #, or a file number, from 1 to 511
+                               // The date literal depends on the locale, so anything can go between #'s.
+                               // Can be #January 1, 1993# or #1 Jan 93# or #05/11/2003#, etc.
+                               // So we set the FILENUMBER state, and switch to DATE if it isn't a file number
+                               sc.SetState(SCE_B_FILENUMBER);
                        } else if (sc.ch == '&' && tolower(sc.chNext) == 'h') {
+                               // Hexadecimal number
                                sc.SetState(SCE_B_NUMBER);
+                               sc.Forward();
                        } else if (sc.ch == '&' && tolower(sc.chNext) == 'o') {
+                               // Octal number
                                sc.SetState(SCE_B_NUMBER);
+                               sc.Forward();
                        } else if (IsADigit(sc.ch) || (sc.ch == '.' && IsADigit(sc.chNext))) {
                                sc.SetState(SCE_B_NUMBER);
                        } else if (IsAWordStart(sc.ch) || (sc.ch == '[')) {
                                sc.SetState(SCE_B_IDENTIFIER);
-                       } else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {
+                       } else if (isoperator(static_cast<char>(sc.ch)) || (sc.ch == '\\')) {   // Integer division
                                sc.SetState(SCE_B_OPERATOR);
                        }
                }
index ec9c86f74f2f8c208fc03dd86b79895a2a8446b1..6ded13c73ac32b23e2a45265b0b2cf3815f4cb5f 100644 (file)
@@ -282,7 +282,7 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac
                        surface->LineTo(right - 5, centreY + 5);
                        right += 4;
                }
-       } else { // SC_MARK_SHORTARROW
+       } else if (markType == SC_MARK_SHORTARROW) {
                Point pts[] = {
                        Point(centreX, centreY + dimOn2),
                        Point(centreX + dimOn2, centreY),
@@ -295,5 +295,7 @@ void LineMarker::Draw(Surface *surface, PRectangle &rcWhole, Font &fontForCharac
                };
                surface->Polygon(pts, sizeof(pts) / sizeof(pts[0]),
                                fore.allocated, back.allocated);
+       } else { // SC_MARK_FULLRECT
+               surface->FillRectangle(rcWhole, back.allocated);
        }
 }
index 1e9920d79c5a0400ef2f71d65f2c5acd99dcd182..b4011a04c7e3ba7079571318326316445a17a153 100644 (file)
@@ -329,6 +329,8 @@ char *SContainer::StringAllocate(const char *s, lenpos_t len) {
 
 // End SString functions
 
+bool PropSet::caseSensitiveFilenames = false;
+
 PropSet::PropSet() {
        superPS = 0;
        for (int root = 0; root < hashRoots; root++)
@@ -459,7 +461,7 @@ struct VarChain {
        VarChain(const char*var_=NULL, const VarChain *link_=NULL): var(var_), link(link_) {}
 
        bool contains(const char *testVar) const {
-               return (var && (0 == strcmp(var, testVar))) 
+               return (var && (0 == strcmp(var, testVar)))
                        || (link && link->contains(testVar));
        }
 
@@ -536,16 +538,23 @@ bool isprefix(const char *target, const char *prefix) {
                return true;
 }
 
-static bool IsSuffixCaseInsensitive(const char *target, const char *suffix) {
+static bool IsSuffix(const char *target, const char *suffix, bool caseSensitive) {
        size_t lentarget = strlen(target);
        size_t lensuffix = strlen(suffix);
        if (lensuffix > lentarget)
                return false;
+       if (caseSensitive) {
+               for (int i = static_cast<int>(lensuffix) - 1; i >= 0; i--) {
+                       if (target[i + lentarget - lensuffix] != suffix[i])
+                               return false;
+               }
+       } else {
        for (int i = static_cast<int>(lensuffix) - 1; i >= 0; i--) {
                if (MakeUpperCase(target[i + lentarget - lensuffix]) !=
                        MakeUpperCase(suffix[i]))
                        return false;
        }
+       }
        return true;
 }
 
@@ -577,7 +586,7 @@ SString PropSet::GetWild(const char *keybase, const char *filename) {
                                        char delchr = *del;
                                        *del = '\0';
                                        if (*keyfile == '*') {
-                                               if (IsSuffixCaseInsensitive(filename, keyfile + 1)) {
+                                               if (IsSuffix(filename, keyfile + 1, caseSensitiveFilenames)) {
                                                        *del = delchr;
                                                        delete []keyptr;
                                                        return p->val;
@@ -790,11 +799,13 @@ void WordList::Clear() {
        list = 0;
        len = 0;
        sorted = false;
+       sortedNoCase = false;
 }
 
 void WordList::Set(const char *s) {
        list = StringDup(s);
        sorted = false;
+       sortedNoCase = false;
        words = ArrayFromWordList(list, &len, onlyLineEnds);
        wordsNoCase = new char * [len + 1];
        memcpy(wordsNoCase, words, (len + 1) * sizeof (*words));
@@ -808,6 +819,7 @@ char *WordList::Allocate(int size) {
 
 void WordList::SetFromAllocated() {
        sorted = false;
+       sortedNoCase = false;
        words = ArrayFromWordList(list, &len, onlyLineEnds);
        wordsNoCase = new char * [len + 1];
        memcpy(wordsNoCase, words, (len + 1) * sizeof (*words));
@@ -823,9 +835,12 @@ int cmpStringNoCase(const void *a1, const void *a2) {
        return CompareCaseInsensitive(*(char**)(a1), *(char**)(a2));
 }
 
-static void SortWordList(char **words, char **wordsNoCase, unsigned int len) {
+static void SortWordList(char **words, unsigned int len) {
        qsort(reinterpret_cast<void*>(words), len, sizeof(*words),
              cmpString);
+}
+
+static void SortWordListNoCase(char **wordsNoCase, unsigned int len) {
        qsort(reinterpret_cast<void*>(wordsNoCase), len, sizeof(*wordsNoCase),
              cmpStringNoCase);
 }
@@ -835,7 +850,7 @@ bool WordList::InList(const char *s) {
                return false;
        if (!sorted) {
                sorted = true;
-               SortWordList(words, wordsNoCase, len);
+               SortWordList(words, len);
                for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
                        starts[k] = -1;
                for (int l = len - 1; l >= 0; l--) {
@@ -877,6 +892,68 @@ bool WordList::InList(const char *s) {
        return false;
 }
 
+/** similar to InList, but word s can be a substring of keyword.
+ * eg. the keyword define is defined as def~ine. This means the word must start
+ * with def to be a keyword, but also defi, defin and define are valid.
+ * The marker is ~ in this case.
+ */
+bool WordList::InListAbbreviated(const char *s, const char marker) {
+       if (0 == words)
+               return false;
+       if (!sorted) {
+               sorted = true;
+               SortWordList(words, len);
+               for (unsigned int k = 0; k < (sizeof(starts) / sizeof(starts[0])); k++)
+                       starts[k] = -1;
+               for (int l = len - 1; l >= 0; l--) {
+                       unsigned char indexChar = words[l][0];
+                       starts[indexChar] = l;
+               }
+       }
+       unsigned char firstChar = s[0];
+       int j = starts[firstChar];
+       if (j >= 0) {
+               while (words[j][0] == firstChar) {
+                       bool isSubword = false;
+                       int start = 1;
+                       if (words[j][1] == marker) {
+                               isSubword = true;
+                               start++;
+                       }
+                       if (s[1] == words[j][start]) {
+                               const char *a = words[j] + start;
+                               const char *b = s + 1;
+                               while (*a && *a == *b) {
+                                       a++;
+                                       if (*a == marker) {
+                                               isSubword = true;
+                                               a++;
+                                       }
+                                       b++;
+                               }
+                               if ((!*a || isSubword) && !*b)
+                                       return true;
+                       }
+                       j++;
+               }
+       }
+       j = starts['^'];
+       if (j >= 0) {
+               while (words[j][0] == '^') {
+                       const char *a = words[j] + 1;
+                       const char *b = s;
+                       while (*a && *a == *b) {
+                               a++;
+                               b++;
+                       }
+                       if (!*a)
+                               return true;
+                       j++;
+               }
+       }
+       return false;
+}
+
 /**
  * Returns an element (complete) of the wordlist array which has
  * the same beginning as the passed string.
@@ -892,11 +969,11 @@ const char *WordList::GetNearestWord(const char *wordStart, int searchLen, bool
 
        if (0 == words)
                return NULL;
-       if (!sorted) {
-               sorted = true;
-               SortWordList(words, wordsNoCase, len);
-       }
        if (ignoreCase) {
+               if (!sortedNoCase) {
+                       sortedNoCase = true;
+                       SortWordListNoCase(wordsNoCase, len);
+               }
                while (start <= end) { // binary searching loop
                        pivot = (start + end) >> 1;
                        word = wordsNoCase[pivot];
@@ -912,7 +989,7 @@ const char *WordList::GetNearestWord(const char *wordStart, int searchLen, bool
                                while (end < len-1 && !CompareNCaseInsensitive(wordStart, wordsNoCase[end+1], searchLen)) {
                                        end++;
                                }
-                               
+
                                // Finds first word in a series of equal words
                                for (pivot = start; pivot <= end; pivot++) {
                                        word = wordsNoCase[pivot];
@@ -930,6 +1007,10 @@ const char *WordList::GetNearestWord(const char *wordStart, int searchLen, bool
                                end = pivot - 1;
                }
        } else { // preserve the letter case
+               if (!sorted) {
+                       sorted = true;
+                       SortWordList(words, len);
+               }
                while (start <= end) { // binary searching loop
                        pivot = (start + end) >> 1;
                        word = words[pivot];
@@ -945,7 +1026,7 @@ const char *WordList::GetNearestWord(const char *wordStart, int searchLen, bool
                                while (end < len-1 && !strncmp(wordStart, words[end+1], searchLen)) {
                                        end++;
                                }
-                               
+
                                // Finds first word in a series of equal words
                                pivot = start;
                                while (pivot <= end) {
@@ -1020,11 +1101,11 @@ char *WordList::GetNearestWords(
 
        if (0 == words)
                return NULL;
-       if (!sorted) {
-               sorted = true;
-               SortWordList(words, wordsNoCase, len);
-       }
        if (ignoreCase) {
+               if (!sortedNoCase) {
+                       sortedNoCase = true;
+                       SortWordListNoCase(wordsNoCase, len);
+               }
                while (start <= end) { // Binary searching loop
                        pivot = (start + end) / 2;
                        cond = CompareNCaseInsensitive(wordStart, wordsNoCase[pivot], searchLen);
@@ -1053,6 +1134,10 @@ char *WordList::GetNearestWords(
                        }
                }
        } else {        // Preserve the letter case
+               if (!sorted) {
+                       sorted = true;
+                       SortWordList(words, len);
+               }
                while (start <= end) { // Binary searching loop
                        pivot = (start + end) / 2;
                        cond = strncmp(wordStart, words[pivot], searchLen);
index 8ca9cd0b825608ebd24729430cdde3dbd3f471dc..a558b371d2542ad64f2f9abf840a5af43721d1cb 100644 (file)
@@ -20,6 +20,8 @@
 class CharacterIndexer {
 public: 
        virtual char CharAt(int index)=0;
+       virtual ~CharacterIndexer() {
+       }
 };
 
 class RESearch {
index 1d3867b7fe1510660dbfd4fa9a985f7ffc0202fa..6be8b74b533134932031686896dfc313572d4710 100644 (file)
 ScintillaBase::ScintillaBase() {
        displayPopupMenu = true;
        listType = 0;
+       maxListWidth = 0;
 #ifdef SCI_LEXER
        lexLanguage = SCLEX_CONTAINER;
+       performingStyle = false;
        lexCurrent = 0;
        for (int wl = 0;wl < numWordLists;wl++)
                keyWordLists[wl] = new WordList;
@@ -214,7 +216,8 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
                        return;
                }
        }
-       ac.Start(wMain, idAutoComplete, currentPos, lenEntered, vs.lineHeight, IsUnicodeMode());
+       ac.Start(wMain, idAutoComplete, currentPos, LocationFromPosition(currentPos),
+                               lenEntered, vs.lineHeight, IsUnicodeMode());
 
        PRectangle rcClient = GetClientRectangle();
        Point pt = LocationFromPosition(currentPos - lenEntered);
@@ -242,7 +245,8 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
        rcac.bottom = Platform::Minimum(rcac.top + heightLB, rcClient.bottom);
        ac.lb->SetPositionRelative(rcac, wMain);
        ac.lb->SetFont(vs.styles[STYLE_DEFAULT].font);
-       ac.lb->SetAverageCharWidth(vs.styles[STYLE_DEFAULT].aveCharWidth);
+       unsigned int aveCharWidth = vs.styles[STYLE_DEFAULT].aveCharWidth;
+       ac.lb->SetAverageCharWidth(aveCharWidth);
        ac.lb->SetDoubleClickAction(AutoCompleteDoubleClick, this);
 
        ac.SetList(list);
@@ -251,6 +255,8 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
        PRectangle rcList = ac.lb->GetDesiredRect();
        int heightAlloced = rcList.bottom - rcList.top;
        widthLB = Platform::Maximum(widthLB, rcList.right - rcList.left);
+       if (maxListWidth != 0)
+               widthLB = Platform::Minimum(widthLB, aveCharWidth*maxListWidth);
        // Make an allowance for large strings in list
        rcList.left = pt.x - ac.lb->CaretFromEdge();
        rcList.right = rcList.left + widthLB;
@@ -262,7 +268,7 @@ void ScintillaBase::AutoCompleteStart(int lenEntered, const char *list) {
        }
        rcList.bottom = rcList.top + heightAlloced;
        ac.lb->SetPositionRelative(rcList, wMain);
-       ac.Show();
+       ac.Show(true);
        if (lenEntered != 0) {
                AutoCompleteMoveToCurrentWord();
        }
@@ -312,25 +318,31 @@ void ScintillaBase::AutoCompleteCompleted() {
        selected[0] = '\0';
        if (item != -1) {
                ac.lb->GetValue(item, selected, sizeof(selected));
+       } else {
+               ac.Cancel();
+               return;
        }
-       ac.Cancel();
-       if (item == -1)
+
+       ac.Show(false);
+
+       listSelected = selected;
+       SCNotification scn = {0};
+       scn.nmhdr.code = listType > 0 ? SCN_USERLISTSELECTION : SCN_AUTOCSELECTION;
+       scn.message = 0;
+       scn.wParam = listType;
+       scn.listType = listType;
+       Position firstPos = ac.posStart - ac.startLen;
+       scn.lParam = firstPos;
+       scn.text = listSelected.c_str();
+       NotifyParent(scn);
+
+       if (!ac.Active())
                return;
+       ac.Cancel();
 
-       if (listType > 0) {
-               userListSelected = selected;
-               SCNotification scn;
-               scn.nmhdr.code = SCN_USERLISTSELECTION;
-               scn.message = 0;
-               scn.wParam = listType;
-               scn.listType = listType;
-               scn.lParam = 0;
-               scn.text = userListSelected.c_str();
-               NotifyParent(scn);
+       if (listType > 0)
                return;
-       }
 
-       Position firstPos = ac.posStart - ac.startLen;
        Position endPos = currentPos;
        if (ac.dropRestOfWord)
                endPos = pdoc->ExtendWordSelect(endPos, 1, true);
@@ -378,7 +390,7 @@ void ScintillaBase::CallTipShow(Point pt, const char *defn) {
 }
 
 void ScintillaBase::CallTipClick() {
-       SCNotification scn;
+       SCNotification scn = {0};
        scn.nmhdr.code = SCN_CALLTIPCLICK;
        scn.position = ct.clickPlace;
        NotifyParent(scn);
@@ -430,29 +442,38 @@ void ScintillaBase::SetLexerLanguage(const char *languageName) {
 }
 
 void ScintillaBase::Colourise(int start, int end) {
-       int lengthDoc = pdoc->Length();
-       if (end == -1)
-               end = lengthDoc;
-       int len = end - start;
-
-       PLATFORM_ASSERT(len >= 0);
-       PLATFORM_ASSERT(start + len <= lengthDoc);
-
-       //WindowAccessor styler(wMain.GetID(), props);
-       DocumentAccessor styler(pdoc, props, wMain.GetID());
-
-       int styleStart = 0;
-       if (start > 0)
-               styleStart = styler.StyleAt(start - 1);
-       styler.SetCodePage(pdoc->dbcsCodePage);
-
-       if (lexCurrent && (len > 0)) {  // Should always succeed as null lexer should always be available
-               lexCurrent->Lex(start, len, styleStart, keyWordLists, styler);
-               styler.Flush();
-               if (styler.GetPropertyInt("fold")) {
-                       lexCurrent->Fold(start, len, styleStart, keyWordLists, styler);
+       if (!performingStyle) {
+               // Protect against reentrance, which may occur, for example, when
+               // fold points are discovered while performing styling and the folding
+               // code looks for child lines which may trigger styling.
+               performingStyle = true;
+
+               int lengthDoc = pdoc->Length();
+               if (end == -1)
+                       end = lengthDoc;
+               int len = end - start;
+
+               PLATFORM_ASSERT(len >= 0);
+               PLATFORM_ASSERT(start + len <= lengthDoc);
+
+               //WindowAccessor styler(wMain.GetID(), props);
+               DocumentAccessor styler(pdoc, props, wMain.GetID());
+
+               int styleStart = 0;
+               if (start > 0)
+                       styleStart = styler.StyleAt(start - 1);
+               styler.SetCodePage(pdoc->dbcsCodePage);
+
+               if (lexCurrent && (len > 0)) {  // Should always succeed as null lexer should always be available
+                       lexCurrent->Lex(start, len, styleStart, keyWordLists, styler);
                        styler.Flush();
+                       if (styler.GetPropertyInt("fold")) {
+                               lexCurrent->Fold(start, len, styleStart, keyWordLists, styler);
+                               styler.Flush();
+                       }
                }
+
+               performingStyle = false;
        }
 }
 #endif
@@ -553,6 +574,20 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
        case SCI_AUTOCGETDROPRESTOFWORD:
                return ac.dropRestOfWord;
 
+       case SCI_AUTOCSETMAXHEIGHT:
+               ac.lb->SetVisibleRows(wParam);
+               break;
+
+       case SCI_AUTOCGETMAXHEIGHT:
+               return ac.lb->GetVisibleRows();
+
+       case SCI_AUTOCSETMAXWIDTH:
+               maxListWidth = wParam;
+               break;
+
+       case SCI_AUTOCGETMAXWIDTH:
+               return maxListWidth;
+
        case SCI_REGISTERIMAGE:
                ac.lb->RegisterImage(wParam, reinterpret_cast<const char *>(lParam));
                break;
@@ -616,7 +651,12 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
                return lexLanguage;
 
        case SCI_COLOURISE:
-               Colourise(wParam, lParam);
+               if (lexLanguage == SCLEX_CONTAINER) {
+                       pdoc->ModifiedAt(wParam);
+                       NotifyStyleToNeeded((lParam == -1) ? pdoc->Length() : lParam);
+               } else {
+                       Colourise(wParam, lParam);
+               }
                Redraw();
                break;
 
@@ -625,6 +665,31 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
                          reinterpret_cast<const char *>(lParam));
                break;
 
+       case SCI_GETPROPERTY: {
+                       SString val = props.Get(reinterpret_cast<const char *>(wParam));
+                       const int n = val.length();
+                       if (lParam != 0) {
+                               char *ptr = reinterpret_cast<char *>(lParam);
+                               memcpy(ptr, val.c_str(), n);
+                               ptr[n] = '\0';  // terminate
+                       }
+                       return n;       // Not including NUL
+               }
+
+       case SCI_GETPROPERTYEXPANDED: {
+                       SString val = props.GetExpanded(reinterpret_cast<const char *>(wParam));
+                       const int n = val.length();
+                       if (lParam != 0) {
+                               char *ptr = reinterpret_cast<char *>(lParam);
+                               memcpy(ptr, val.c_str(), n);
+                               ptr[n] = '\0';  // terminate
+                       }
+                       return n;       // Not including NUL
+               }
+
+       case SCI_GETPROPERTYINT:
+               return props.GetInt(reinterpret_cast<const char *>(wParam), lParam);
+
        case SCI_SETKEYWORDS:
                if (wParam < numWordLists) {
                        keyWordLists[wParam]->Clear();
@@ -636,6 +701,8 @@ sptr_t ScintillaBase::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lPara
                SetLexerLanguage(reinterpret_cast<const char *>(lParam));
                break;
 
+       case SCI_GETSTYLEBITSNEEDED:
+               return lexCurrent ? lexCurrent->GetStyleBitsNeeded() : 5;
 #endif
 
        default:
index 6ea23ab5a3718bb1632182d5e0a4f96233c679f8..cb85b55b511e40163693709f944f7b3cae3cea87 100644 (file)
@@ -37,7 +37,10 @@ protected:
        CallTip ct;
 
        int listType;                   ///< 0 is an autocomplete list
-       SString userListSelected;       ///< Receives listbox selected string
+       SString listSelected;   ///< Receives listbox selected string
+       int maxListWidth;               /// Maximum width of list, in average character widths
+
+       bool performingStyle;   ///< Prevent reentrance
 
 #ifdef SCI_LEXER
        int lexLanguage;
index aedebbc012cba8ecb134fb735d37aa87dd333e35..36b50f9142f309d6d9ae1feaa95a715354df96d9 100644 (file)
@@ -45,7 +45,7 @@ public:
                currentPos(startPos),
                atLineStart(true),
                atLineEnd(false),
-               state(initStyle),
+               state(initStyle & chMask), // Mask off all bits which aren't in the chMask.
                chPrev(0),
                ch(0),
                chNext(0) {
@@ -104,7 +104,7 @@ public:
                return currentPos - styler.GetStartSegment();
        }
        int GetRelative(int n) {
-               return styler.SafeGetCharAt(currentPos+n);
+               return static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n));
        }
        bool Match(char ch0) {
                return ch == ch0;
@@ -134,7 +134,8 @@ public:
                        return false;
                s++;
                for (int n=2; *s; n++) {
-                       if (*s != tolower((styler.SafeGetCharAt(currentPos+n))))
+                       if (*s !=
+                               tolower(static_cast<unsigned char>(styler.SafeGetCharAt(currentPos+n))))
                                return false;
                        s++;
                }
index d3bbb4dcc12176b8a797a424cb8674f7ddfafb6d..36e7994f46c4dd9b562523c48df0db82de9f5363 100644 (file)
@@ -103,6 +103,11 @@ void XPM::Init(const char * const *linesForm) {
        height = atoi(line0);
        line0 = NextField(line0);
        nColours = atoi(line0);
+       line0 = NextField(line0);
+       if (atoi(line0) != 1) {
+               // Only one char per pixel is supported
+               return;
+       }
        codes = new char[nColours];
        colours = new ColourPair[nColours];
 
@@ -261,6 +266,7 @@ void XPMSet::Add(int id, const char *textForm) {
        for (int i = 0; i < len; i++) {
                if (set[i]->GetId() == id) {
                        set[i]->Init(textForm);
+                       set[i]->CopyDesiredColours();
                        return;
                }
        }
index ccf561d44cc63944bb3a8ace4ef82a049392e48a..1085b5346d12baefad173f006b5e54d91e0c9c32 100644 (file)
@@ -96,6 +96,7 @@ DEFINE_EVENT_TYPE( wxEVT_STC_ZOOM )
 DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_CLICK )
 DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_DCLICK )
 DEFINE_EVENT_TYPE( wxEVT_STC_CALLTIP_CLICK )
+DEFINE_EVENT_TYPE( wxEVT_STC_AUTOCOMP_SELECTION )    
 
 
 
@@ -529,6 +530,11 @@ void wxStyledTextCtrl::MarkerDefineBitmap(int markerNumber, const wxBitmap& bmp)
         
 }
 
+// Add a set of markers to a line.
+void wxStyledTextCtrl::MarkerAddSet(int line, int set) {
+    SendMsg(2466, line, set);
+}
+
 // Set a margin to be either numeric or symbolic.
 void wxStyledTextCtrl::SetMarginType(int margin, int marginType) {
     SendMsg(2240, margin, marginType);
@@ -926,6 +932,28 @@ void wxStyledTextCtrl::AutoCompSetTypeSeparator(int separatorCharacter) {
     SendMsg(2286, separatorCharacter, 0);
 }
 
+// Set the maximum width, in characters, of auto-completion and user lists.
+// Set to 0 to autosize to fit longest item, which is the default.
+void wxStyledTextCtrl::AutoCompSetMaxWidth(int characterCount) {
+    SendMsg(2208, characterCount, 0);
+}
+
+// Get the maximum width, in characters, of auto-completion and user lists.
+int wxStyledTextCtrl::AutoCompGetMaxWidth() {
+    return SendMsg(2209, 0, 0);
+}
+
+// Set the maximum height, in rows, of auto-completion and user lists.
+// The default is 5 rows.
+void wxStyledTextCtrl::AutoCompSetMaxHeight(int rowCount) {
+    SendMsg(2210, rowCount, 0);
+}
+
+// Set the maximum height, in rows, of auto-completion and user lists.
+int wxStyledTextCtrl::AutoCompGetMaxHeight() {
+    return SendMsg(2211, 0, 0);
+}
+
 // Set the number of spaces used for one level of indentation.
 void wxStyledTextCtrl::SetIndent(int indentSize) {
     SendMsg(2122, indentSize, 0);
@@ -1427,6 +1455,11 @@ int wxStyledTextCtrl::DocLineFromVisible(int lineDisplay) {
     return SendMsg(2221, lineDisplay, 0);
 }
 
+// The number of display lines needed to wrap a document line
+int wxStyledTextCtrl::WrapCount(int line) {
+    return SendMsg(2235, line, 0);
+}
+
 // Set the fold level of a line.
 // This encodes an integer level along with flags indicating whether the
 // line is a header and whether it is effectively white space.
@@ -1611,8 +1644,8 @@ void wxStyledTextCtrl::SetEndAtLastLine(bool endAtLastLine) {
 
 // Retrieve whether the maximum scroll position has the last
 // line at the bottom of the view.
-int wxStyledTextCtrl::GetEndAtLastLine() {
-    return SendMsg(2278, 0, 0);
+bool wxStyledTextCtrl::GetEndAtLastLine() {
+    return SendMsg(2278, 0, 0) != 0;
 }
 
 // Retrieve the height of a particular line of text in pixels.
@@ -2412,12 +2445,42 @@ void wxStyledTextCtrl::Allocate(int bytes) {
     SendMsg(2446, bytes, 0);
 }
 
-// Find the position of a column on a line taking into account tabs and 
+// Find the position of a column on a line taking into account tabs and
 // multi-byte characters. If beyond end of line, return line end position.
 int wxStyledTextCtrl::FindColumn(int line, int column) {
     return SendMsg(2456, line, column);
 }
 
+// Can the caret preferred x position only be changed by explicit movement commands?
+bool wxStyledTextCtrl::GetCaretSticky() {
+    return SendMsg(2457, 0, 0) != 0;
+}
+
+// Stop the caret preferred x position changing when the user types.
+void wxStyledTextCtrl::SetCaretSticky(bool useCaretStickyBehaviour) {
+    SendMsg(2458, useCaretStickyBehaviour, 0);
+}
+
+// Switch between sticky and non-sticky: meant to be bound to a key.
+void wxStyledTextCtrl::ToggleCaretSticky() {
+    SendMsg(2459, 0, 0);
+}
+
+// Enable/Disable convert-on-paste for line endings
+void wxStyledTextCtrl::SetPasteConvertEndings(bool convert) {
+    SendMsg(2467, convert, 0);
+}
+
+// Get convert-on-paste setting
+bool wxStyledTextCtrl::GetPasteConvertEndings() {
+    return SendMsg(2468, 0, 0) != 0;
+}
+
+// Duplicate the selection. If selection empty duplicate the line containing the caret.
+void wxStyledTextCtrl::SelectionDuplicate() {
+    SendMsg(2469, 0, 0);
+}
+
 // Start notifying the container of all key presses and commands.
 void wxStyledTextCtrl::StartRecord() {
     SendMsg(3001, 0, 0);
@@ -2458,6 +2521,44 @@ void wxStyledTextCtrl::SetLexerLanguage(const wxString& language) {
     SendMsg(4006, 0, (long)(const char*)wx2stc(language));
 }
 
+// Retrieve a 'property' value previously set with SetProperty.
+wxString wxStyledTextCtrl::GetProperty(const wxString& key) {
+         int len = SendMsg(SCI_GETPROPERTY, (long)(const char*)wx2stc(key), NULL);
+         if (!len) return wxEmptyString;
+
+         wxMemoryBuffer mbuf(len+1);
+         char* buf = (char*)mbuf.GetWriteBuf(len+1);
+         SendMsg(4008, (long)(const char*)wx2stc(key), (long)buf);
+         mbuf.UngetWriteBuf(len);
+         mbuf.AppendByte(0);
+         return stc2wx(buf);
+}
+
+// Retrieve a 'property' value previously set with SetProperty,
+// with '$()' variable replacement on returned buffer.
+wxString wxStyledTextCtrl::GetPropertyExpanded(const wxString& key) {
+         int len = SendMsg(SCI_GETPROPERTYEXPANDED, (long)(const char*)wx2stc(key), NULL);
+         if (!len) return wxEmptyString;
+
+         wxMemoryBuffer mbuf(len+1);
+         char* buf = (char*)mbuf.GetWriteBuf(len+1);
+         SendMsg(4009, (long)(const char*)wx2stc(key), (long)buf);
+         mbuf.UngetWriteBuf(len);
+         mbuf.AppendByte(0);
+         return stc2wx(buf);
+}
+
+// Retrieve a 'property' value previously set with SetProperty,
+// interpreted as an int AFTER any '$()' variable replacement.
+int wxStyledTextCtrl::GetPropertyInt(const wxString& key) {
+    return SendMsg(4010, (long)(const char*)wx2stc(key), 0);
+}
+
+// Retrieve the number of bits the current lexer needs for styling.
+int wxStyledTextCtrl::GetStyleBitsNeeded() {
+    return SendMsg(4011, 0, 0);
+}
+
 // END of generated section
 //----------------------------------------------------------------------
 
@@ -2634,6 +2735,14 @@ void wxStyledTextCtrl::StyleSetCharacterSet(int style, int characterSet)
         case wxSTC_CHARSET_THAI:
             encoding = wxFONTENCODING_ISO8859_11;
             break;
+
+        case wxSTC_CHARSET_CYRILLIC:
+            encoding = wxFONTENCODING_ISO8859_5;
+            break;
+                
+        case wxSTC_CHARSET_8859_15:
+            encoding = wxFONTENCODING_ISO8859_15;;
+            break;
     }
 
     // We just have Scintilla track the wxFontEncoding for us.  It gets used
@@ -3199,6 +3308,10 @@ void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
         evt.SetEventType(wxEVT_STC_CALLTIP_CLICK);
         break;
 
+    case SCN_AUTOCSELECTION:
+        evt.SetEventType(wxEVT_STC_AUTOCOMP_SELECTION);
+        break;
+        
     default:
         return;
     }
index b36707101257b8170a938fe101976187febac68e..b99563feded2b5962193e8d9c7be766baeb3cfb9 100644 (file)
@@ -96,6 +96,7 @@ DEFINE_EVENT_TYPE( wxEVT_STC_ZOOM )
 DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_CLICK )
 DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_DCLICK )
 DEFINE_EVENT_TYPE( wxEVT_STC_CALLTIP_CLICK )
+DEFINE_EVENT_TYPE( wxEVT_STC_AUTOCOMP_SELECTION )    
 
 
 
@@ -402,6 +403,14 @@ void wxStyledTextCtrl::StyleSetCharacterSet(int style, int characterSet)
         case wxSTC_CHARSET_THAI:
             encoding = wxFONTENCODING_ISO8859_11;
             break;
+
+        case wxSTC_CHARSET_CYRILLIC:
+            encoding = wxFONTENCODING_ISO8859_5;
+            break;
+                
+        case wxSTC_CHARSET_8859_15:
+            encoding = wxFONTENCODING_ISO8859_15;;
+            break;
     }
 
     // We just have Scintilla track the wxFontEncoding for us.  It gets used
@@ -967,6 +976,10 @@ void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
         evt.SetEventType(wxEVT_STC_CALLTIP_CLICK);
         break;
 
+    case SCN_AUTOCSELECTION:
+        evt.SetEventType(wxEVT_STC_AUTOCOMP_SELECTION);
+        break;
+        
     default:
         return;
     }
index ad50ff81bdd7b27b900dcb751a3aab79e3a69add..9dd1d5dfbdd2187d3ff12bbbc27245fb342bea8c 100644 (file)
@@ -445,6 +445,7 @@ BEGIN_DECLARE_EVENT_TYPES()
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_HOTSPOT_CLICK,      1673)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_HOTSPOT_DCLICK,     1674)
     DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_CALLTIP_CLICK,      1675)
+    DECLARE_EXPORTED_EVENT_TYPE(WXDLLIMPEXP_STC, wxEVT_STC_AUTOCOMP_SELECTION, 1676)
 END_DECLARE_EVENT_TYPES()
 #else
     enum {
@@ -472,7 +473,8 @@ END_DECLARE_EVENT_TYPES()
         wxEVT_STC_ZOOM,
         wxEVT_STC_HOTSPOT_CLICK,
         wxEVT_STC_HOTSPOT_DCLICK,
-        wxEVT_STC_CALLTIP_CLICK
+        wxEVT_STC_CALLTIP_CLICK,
+        wxEVT_STC_AUTOCOMP_SELECTION
     };
 #endif
 
@@ -506,7 +508,7 @@ typedef void (wxEvtHandler::*wxStyledTextEventFunction)(wxStyledTextEvent&);
 #define EVT_STC_HOTSPOT_CLICK(id, fn)      DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_HOTSPOT_CLICK,         id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #define EVT_STC_HOTSPOT_DCLICK(id, fn)     DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_HOTSPOT_DCLICK,        id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #define EVT_STC_CALLTIP_CLICK(id, fn))     DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_CALLTIP_CLICK          id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
-
+#define EVT_STC_AUTOCOMP_SELECTION(id, fn) DECLARE_EVENT_TABLE_ENTRY( wxEVT_STC_AUTOCOMP_SELECTION     id, wxID_ANY, (wxObjectEventFunction) (wxEventFunction)  wxStaticCastEvent( wxStyledTextEventFunction, & fn ), (wxObject *) NULL ),
 #endif
 
 //----------------------------------------------------------------------
@@ -515,9 +517,9 @@ typedef void (wxEvtHandler::*wxStyledTextEventFunction)(wxStyledTextEvent&);
 #ifndef SWIG
 #if wxUSE_UNICODE
 
-wxString stc2wx(const char* str);
-wxString stc2wx(const char* str, size_t len);
-const wxWX2MBbuf wx2stc(const wxString& str);
+WXDLLIMPEXP_STC wxString stc2wx(const char* str);
+WXDLLIMPEXP_STC wxString stc2wx(const char* str, size_t len);
+WXDLLIMPEXP_STC const wxWX2MBbuf wx2stc(const wxString& str);
 
 #else // not UNICODE
 
index 6cc097871c57082750015d42836220a896dfd19c..99bcff3e64474192f3b144bd085099f58f4ab2bd 100644 (file)
@@ -152,6 +152,9 @@ DocStr(wxStyledTextCtrl::MarkerPrevious,
 DocStr(wxStyledTextCtrl::MarkerDefineBitmap,
 "Define a marker from a bitmap", "");
 
+DocStr(wxStyledTextCtrl::MarkerAddSet,
+"Add a set of markers to a line.", "");
+
 DocStr(wxStyledTextCtrl::SetMarginType,
 "Set a margin to be either numeric or symbolic.", "");
 
@@ -387,6 +390,20 @@ DocStr(wxStyledTextCtrl::AutoCompSetTypeSeparator,
 "Change the type-separator character in the string setting up an auto-completion list.
 Default is '?' but can be changed if items contain '?'.", "");
 
+DocStr(wxStyledTextCtrl::AutoCompSetMaxWidth,
+"Set the maximum width, in characters, of auto-completion and user lists.
+Set to 0 to autosize to fit longest item, which is the default.", "");
+
+DocStr(wxStyledTextCtrl::AutoCompGetMaxWidth,
+"Get the maximum width, in characters, of auto-completion and user lists.", "");
+
+DocStr(wxStyledTextCtrl::AutoCompSetMaxHeight,
+"Set the maximum height, in rows, of auto-completion and user lists.
+The default is 5 rows.", "");
+
+DocStr(wxStyledTextCtrl::AutoCompGetMaxHeight,
+"Set the maximum height, in rows, of auto-completion and user lists.", "");
+
 DocStr(wxStyledTextCtrl::SetIndent,
 "Set the number of spaces used for one level of indentation.", "");
 
@@ -643,6 +660,9 @@ DocStr(wxStyledTextCtrl::VisibleFromDocLine,
 DocStr(wxStyledTextCtrl::DocLineFromVisible,
 "Find the document line of a display line taking hidden lines into account.", "");
 
+DocStr(wxStyledTextCtrl::WrapCount,
+"The number of display lines needed to wrap a document line", "");
+
 DocStr(wxStyledTextCtrl::SetFoldLevel,
 "Set the fold level of a line.
 This encodes an integer level along with flags indicating whether the
@@ -1261,9 +1281,27 @@ DocStr(wxStyledTextCtrl::Allocate,
 "Enlarge the document to a particular size of text bytes.", "");
 
 DocStr(wxStyledTextCtrl::FindColumn,
-"Find the position of a column on a line taking into account tabs and 
+"Find the position of a column on a line taking into account tabs and
 multi-byte characters. If beyond end of line, return line end position.", "");
 
+DocStr(wxStyledTextCtrl::GetCaretSticky,
+"Can the caret preferred x position only be changed by explicit movement commands?", "");
+
+DocStr(wxStyledTextCtrl::SetCaretSticky,
+"Stop the caret preferred x position changing when the user types.", "");
+
+DocStr(wxStyledTextCtrl::ToggleCaretSticky,
+"Switch between sticky and non-sticky: meant to be bound to a key.", "");
+
+DocStr(wxStyledTextCtrl::SetPasteConvertEndings,
+"Enable/Disable convert-on-paste for line endings", "");
+
+DocStr(wxStyledTextCtrl::GetPasteConvertEndings,
+"Get convert-on-paste setting", "");
+
+DocStr(wxStyledTextCtrl::SelectionDuplicate,
+"Duplicate the selection. If selection empty duplicate the line containing the caret.", "");
+
 DocStr(wxStyledTextCtrl::StartRecord,
 "Start notifying the container of all key presses and commands.", "");
 
@@ -1287,3 +1325,17 @@ DocStr(wxStyledTextCtrl::SetKeyWords,
 
 DocStr(wxStyledTextCtrl::SetLexerLanguage,
 "Set the lexing language of the document based on string name.", "");
+
+DocStr(wxStyledTextCtrl::GetProperty,
+"Retrieve a 'property' value previously set with SetProperty.", "");
+
+DocStr(wxStyledTextCtrl::GetPropertyExpanded,
+"Retrieve a 'property' value previously set with SetProperty,
+with '$()' variable replacement on returned buffer.", "");
+
+DocStr(wxStyledTextCtrl::GetPropertyInt,
+"Retrieve a 'property' value previously set with SetProperty,
+interpreted as an int AFTER any '$()' variable replacement.", "");
+
+DocStr(wxStyledTextCtrl::GetStyleBitsNeeded,
+"Retrieve the number of bits the current lexer needs for styling.", "");
index 82b6a2fbb5dc422698b1c3980f0ec782f7382614..eb7e3b0350339e9eb5a7dd7fa0abcace68d38ab1 100644 (file)
@@ -43,6 +43,7 @@
 %rename(STC_MARK_DOTDOTDOT)                 wxSTC_MARK_DOTDOTDOT;
 %rename(STC_MARK_ARROWS)                    wxSTC_MARK_ARROWS;
 %rename(STC_MARK_PIXMAP)                    wxSTC_MARK_PIXMAP;
+%rename(STC_MARK_FULLRECT)                  wxSTC_MARK_FULLRECT;
 %rename(STC_MARK_CHARACTER)                 wxSTC_MARK_CHARACTER;
 %rename(STC_MARKNUM_FOLDEREND)              wxSTC_MARKNUM_FOLDEREND;
 %rename(STC_MARKNUM_FOLDEROPENMID)          wxSTC_MARKNUM_FOLDEROPENMID;
@@ -73,6 +74,7 @@
 %rename(STC_CHARSET_MAC)                    wxSTC_CHARSET_MAC;
 %rename(STC_CHARSET_OEM)                    wxSTC_CHARSET_OEM;
 %rename(STC_CHARSET_RUSSIAN)                wxSTC_CHARSET_RUSSIAN;
+%rename(STC_CHARSET_CYRILLIC)               wxSTC_CHARSET_CYRILLIC;
 %rename(STC_CHARSET_SHIFTJIS)               wxSTC_CHARSET_SHIFTJIS;
 %rename(STC_CHARSET_SYMBOL)                 wxSTC_CHARSET_SYMBOL;
 %rename(STC_CHARSET_TURKISH)                wxSTC_CHARSET_TURKISH;
@@ -81,6 +83,7 @@
 %rename(STC_CHARSET_ARABIC)                 wxSTC_CHARSET_ARABIC;
 %rename(STC_CHARSET_VIETNAMESE)             wxSTC_CHARSET_VIETNAMESE;
 %rename(STC_CHARSET_THAI)                   wxSTC_CHARSET_THAI;
+%rename(STC_CHARSET_8859_15)                wxSTC_CHARSET_8859_15;
 %rename(STC_CASE_MIXED)                     wxSTC_CASE_MIXED;
 %rename(STC_CASE_UPPER)                     wxSTC_CASE_UPPER;
 %rename(STC_CASE_LOWER)                     wxSTC_CASE_LOWER;
 %rename(STC_TIME_FOREVER)                   wxSTC_TIME_FOREVER;
 %rename(STC_WRAP_NONE)                      wxSTC_WRAP_NONE;
 %rename(STC_WRAP_WORD)                      wxSTC_WRAP_WORD;
+%rename(STC_WRAP_CHAR)                      wxSTC_WRAP_CHAR;
 %rename(STC_WRAPVISUALFLAG_NONE)            wxSTC_WRAPVISUALFLAG_NONE;
 %rename(STC_WRAPVISUALFLAG_END)             wxSTC_WRAPVISUALFLAG_END;
 %rename(STC_WRAPVISUALFLAG_START)           wxSTC_WRAPVISUALFLAG_START;
 %rename(STC_PERFORMED_USER)                 wxSTC_PERFORMED_USER;
 %rename(STC_PERFORMED_UNDO)                 wxSTC_PERFORMED_UNDO;
 %rename(STC_PERFORMED_REDO)                 wxSTC_PERFORMED_REDO;
+%rename(STC_MULTISTEPUNDOREDO)              wxSTC_MULTISTEPUNDOREDO;
 %rename(STC_LASTSTEPINUNDOREDO)             wxSTC_LASTSTEPINUNDOREDO;
 %rename(STC_MOD_CHANGEMARKER)               wxSTC_MOD_CHANGEMARKER;
 %rename(STC_MOD_BEFOREINSERT)               wxSTC_MOD_BEFOREINSERT;
 %rename(STC_MOD_BEFOREDELETE)               wxSTC_MOD_BEFOREDELETE;
+%rename(STC_MULTILINEUNDOREDO)              wxSTC_MULTILINEUNDOREDO;
 %rename(STC_MODEVENTMASKALL)                wxSTC_MODEVENTMASKALL;
 %rename(STC_KEY_DOWN)                       wxSTC_KEY_DOWN;
 %rename(STC_KEY_UP)                         wxSTC_KEY_UP;
 %rename(STC_KEY_ADD)                        wxSTC_KEY_ADD;
 %rename(STC_KEY_SUBTRACT)                   wxSTC_KEY_SUBTRACT;
 %rename(STC_KEY_DIVIDE)                     wxSTC_KEY_DIVIDE;
+%rename(STC_SCMOD_NORM)                     wxSTC_SCMOD_NORM;
 %rename(STC_SCMOD_SHIFT)                    wxSTC_SCMOD_SHIFT;
 %rename(STC_SCMOD_CTRL)                     wxSTC_SCMOD_CTRL;
 %rename(STC_SCMOD_ALT)                      wxSTC_SCMOD_ALT;
 %rename(STC_LEX_NNCRONTAB)                  wxSTC_LEX_NNCRONTAB;
 %rename(STC_LEX_BULLANT)                    wxSTC_LEX_BULLANT;
 %rename(STC_LEX_VBSCRIPT)                   wxSTC_LEX_VBSCRIPT;
-%rename(STC_LEX_ASP)                        wxSTC_LEX_ASP;
-%rename(STC_LEX_PHP)                        wxSTC_LEX_PHP;
 %rename(STC_LEX_BAAN)                       wxSTC_LEX_BAAN;
 %rename(STC_LEX_MATLAB)                     wxSTC_LEX_MATLAB;
 %rename(STC_LEX_SCRIPTOL)                   wxSTC_LEX_SCRIPTOL;
 %rename(STC_LEX_BASH)                       wxSTC_LEX_BASH;
 %rename(STC_LEX_ASN1)                       wxSTC_LEX_ASN1;
 %rename(STC_LEX_VHDL)                       wxSTC_LEX_VHDL;
+%rename(STC_LEX_CAML)                       wxSTC_LEX_CAML;
+%rename(STC_LEX_BLITZBASIC)                 wxSTC_LEX_BLITZBASIC;
+%rename(STC_LEX_PUREBASIC)                  wxSTC_LEX_PUREBASIC;
+%rename(STC_LEX_HASKELL)                    wxSTC_LEX_HASKELL;
+%rename(STC_LEX_PHPSCRIPT)                  wxSTC_LEX_PHPSCRIPT;
+%rename(STC_LEX_TADS3)                      wxSTC_LEX_TADS3;
+%rename(STC_LEX_REBOL)                      wxSTC_LEX_REBOL;
+%rename(STC_LEX_SMALLTALK)                  wxSTC_LEX_SMALLTALK;
+%rename(STC_LEX_FLAGSHIP)                   wxSTC_LEX_FLAGSHIP;
+%rename(STC_LEX_CSOUND)                     wxSTC_LEX_CSOUND;
+%rename(STC_LEX_FREEBASIC)                  wxSTC_LEX_FREEBASIC;
 %rename(STC_LEX_AUTOMATIC)                  wxSTC_LEX_AUTOMATIC;
 %rename(STC_P_DEFAULT)                      wxSTC_P_DEFAULT;
 %rename(STC_P_COMMENTLINE)                  wxSTC_P_COMMENTLINE;
 %rename(STC_P_IDENTIFIER)                   wxSTC_P_IDENTIFIER;
 %rename(STC_P_COMMENTBLOCK)                 wxSTC_P_COMMENTBLOCK;
 %rename(STC_P_STRINGEOL)                    wxSTC_P_STRINGEOL;
+%rename(STC_P_WORD2)                        wxSTC_P_WORD2;
+%rename(STC_P_DECORATOR)                    wxSTC_P_DECORATOR;
 %rename(STC_C_DEFAULT)                      wxSTC_C_DEFAULT;
 %rename(STC_C_COMMENT)                      wxSTC_C_COMMENT;
 %rename(STC_C_COMMENTLINE)                  wxSTC_C_COMMENTLINE;
 %rename(STC_PL_ARRAY)                       wxSTC_PL_ARRAY;
 %rename(STC_PL_HASH)                        wxSTC_PL_HASH;
 %rename(STC_PL_SYMBOLTABLE)                 wxSTC_PL_SYMBOLTABLE;
+%rename(STC_PL_VARIABLE_INDEXER)            wxSTC_PL_VARIABLE_INDEXER;
 %rename(STC_PL_REGEX)                       wxSTC_PL_REGEX;
 %rename(STC_PL_REGSUBST)                    wxSTC_PL_REGSUBST;
 %rename(STC_PL_LONGQUOTE)                   wxSTC_PL_LONGQUOTE;
 %rename(STC_PL_STRING_QX)                   wxSTC_PL_STRING_QX;
 %rename(STC_PL_STRING_QR)                   wxSTC_PL_STRING_QR;
 %rename(STC_PL_STRING_QW)                   wxSTC_PL_STRING_QW;
+%rename(STC_PL_POD_VERB)                    wxSTC_PL_POD_VERB;
+%rename(STC_RB_DEFAULT)                     wxSTC_RB_DEFAULT;
+%rename(STC_RB_ERROR)                       wxSTC_RB_ERROR;
+%rename(STC_RB_COMMENTLINE)                 wxSTC_RB_COMMENTLINE;
+%rename(STC_RB_POD)                         wxSTC_RB_POD;
+%rename(STC_RB_NUMBER)                      wxSTC_RB_NUMBER;
+%rename(STC_RB_WORD)                        wxSTC_RB_WORD;
+%rename(STC_RB_STRING)                      wxSTC_RB_STRING;
+%rename(STC_RB_CHARACTER)                   wxSTC_RB_CHARACTER;
+%rename(STC_RB_CLASSNAME)                   wxSTC_RB_CLASSNAME;
+%rename(STC_RB_DEFNAME)                     wxSTC_RB_DEFNAME;
+%rename(STC_RB_OPERATOR)                    wxSTC_RB_OPERATOR;
+%rename(STC_RB_IDENTIFIER)                  wxSTC_RB_IDENTIFIER;
+%rename(STC_RB_REGEX)                       wxSTC_RB_REGEX;
+%rename(STC_RB_GLOBAL)                      wxSTC_RB_GLOBAL;
+%rename(STC_RB_SYMBOL)                      wxSTC_RB_SYMBOL;
+%rename(STC_RB_MODULE_NAME)                 wxSTC_RB_MODULE_NAME;
+%rename(STC_RB_INSTANCE_VAR)                wxSTC_RB_INSTANCE_VAR;
+%rename(STC_RB_CLASS_VAR)                   wxSTC_RB_CLASS_VAR;
+%rename(STC_RB_BACKTICKS)                   wxSTC_RB_BACKTICKS;
+%rename(STC_RB_DATASECTION)                 wxSTC_RB_DATASECTION;
+%rename(STC_RB_HERE_DELIM)                  wxSTC_RB_HERE_DELIM;
+%rename(STC_RB_HERE_Q)                      wxSTC_RB_HERE_Q;
+%rename(STC_RB_HERE_QQ)                     wxSTC_RB_HERE_QQ;
+%rename(STC_RB_HERE_QX)                     wxSTC_RB_HERE_QX;
+%rename(STC_RB_STRING_Q)                    wxSTC_RB_STRING_Q;
+%rename(STC_RB_STRING_QQ)                   wxSTC_RB_STRING_QQ;
+%rename(STC_RB_STRING_QX)                   wxSTC_RB_STRING_QX;
+%rename(STC_RB_STRING_QR)                   wxSTC_RB_STRING_QR;
+%rename(STC_RB_STRING_QW)                   wxSTC_RB_STRING_QW;
+%rename(STC_RB_WORD_DEMOTED)                wxSTC_RB_WORD_DEMOTED;
+%rename(STC_RB_STDIN)                       wxSTC_RB_STDIN;
+%rename(STC_RB_STDOUT)                      wxSTC_RB_STDOUT;
+%rename(STC_RB_STDERR)                      wxSTC_RB_STDERR;
+%rename(STC_RB_UPPER_BOUND)                 wxSTC_RB_UPPER_BOUND;
 %rename(STC_B_DEFAULT)                      wxSTC_B_DEFAULT;
 %rename(STC_B_COMMENT)                      wxSTC_B_COMMENT;
 %rename(STC_B_NUMBER)                       wxSTC_B_NUMBER;
 %rename(STC_B_KEYWORD4)                     wxSTC_B_KEYWORD4;
 %rename(STC_B_CONSTANT)                     wxSTC_B_CONSTANT;
 %rename(STC_B_ASM)                          wxSTC_B_ASM;
+%rename(STC_B_LABEL)                        wxSTC_B_LABEL;
+%rename(STC_B_ERROR)                        wxSTC_B_ERROR;
+%rename(STC_B_HEXNUMBER)                    wxSTC_B_HEXNUMBER;
+%rename(STC_B_BINNUMBER)                    wxSTC_B_BINNUMBER;
 %rename(STC_PROPS_DEFAULT)                  wxSTC_PROPS_DEFAULT;
 %rename(STC_PROPS_COMMENT)                  wxSTC_PROPS_COMMENT;
 %rename(STC_PROPS_SECTION)                  wxSTC_PROPS_SECTION;
 %rename(STC_LISP_COMMENT)                   wxSTC_LISP_COMMENT;
 %rename(STC_LISP_NUMBER)                    wxSTC_LISP_NUMBER;
 %rename(STC_LISP_KEYWORD)                   wxSTC_LISP_KEYWORD;
+%rename(STC_LISP_KEYWORD_KW)                wxSTC_LISP_KEYWORD_KW;
+%rename(STC_LISP_SYMBOL)                    wxSTC_LISP_SYMBOL;
 %rename(STC_LISP_STRING)                    wxSTC_LISP_STRING;
 %rename(STC_LISP_STRINGEOL)                 wxSTC_LISP_STRINGEOL;
 %rename(STC_LISP_IDENTIFIER)                wxSTC_LISP_IDENTIFIER;
 %rename(STC_LISP_OPERATOR)                  wxSTC_LISP_OPERATOR;
+%rename(STC_LISP_SPECIAL)                   wxSTC_LISP_SPECIAL;
+%rename(STC_LISP_MULTI_COMMENT)             wxSTC_LISP_MULTI_COMMENT;
 %rename(STC_EIFFEL_DEFAULT)                 wxSTC_EIFFEL_DEFAULT;
 %rename(STC_EIFFEL_COMMENTLINE)             wxSTC_EIFFEL_COMMENTLINE;
 %rename(STC_EIFFEL_NUMBER)                  wxSTC_EIFFEL_NUMBER;
 %rename(STC_CSS_DOUBLESTRING)               wxSTC_CSS_DOUBLESTRING;
 %rename(STC_CSS_SINGLESTRING)               wxSTC_CSS_SINGLESTRING;
 %rename(STC_CSS_IDENTIFIER2)                wxSTC_CSS_IDENTIFIER2;
+%rename(STC_CSS_ATTRIBUTE)                  wxSTC_CSS_ATTRIBUTE;
 %rename(STC_POV_DEFAULT)                    wxSTC_POV_DEFAULT;
 %rename(STC_POV_COMMENT)                    wxSTC_POV_COMMENT;
 %rename(STC_POV_COMMENTLINE)                wxSTC_POV_COMMENTLINE;
 %rename(STC_NSIS_MACRODEF)                  wxSTC_NSIS_MACRODEF;
 %rename(STC_NSIS_STRINGVAR)                 wxSTC_NSIS_STRINGVAR;
 %rename(STC_NSIS_NUMBER)                    wxSTC_NSIS_NUMBER;
+%rename(STC_NSIS_SECTIONGROUP)              wxSTC_NSIS_SECTIONGROUP;
+%rename(STC_NSIS_PAGEEX)                    wxSTC_NSIS_PAGEEX;
+%rename(STC_NSIS_FUNCTIONDEF)               wxSTC_NSIS_FUNCTIONDEF;
+%rename(STC_NSIS_COMMENTBOX)                wxSTC_NSIS_COMMENTBOX;
 %rename(STC_MMIXAL_LEADWS)                  wxSTC_MMIXAL_LEADWS;
 %rename(STC_MMIXAL_COMMENT)                 wxSTC_MMIXAL_COMMENT;
 %rename(STC_MMIXAL_LABEL)                   wxSTC_MMIXAL_LABEL;
 %rename(STC_CLW_PICTURE_STRING)             wxSTC_CLW_PICTURE_STRING;
 %rename(STC_CLW_KEYWORD)                    wxSTC_CLW_KEYWORD;
 %rename(STC_CLW_COMPILER_DIRECTIVE)         wxSTC_CLW_COMPILER_DIRECTIVE;
+%rename(STC_CLW_RUNTIME_EXPRESSIONS)        wxSTC_CLW_RUNTIME_EXPRESSIONS;
 %rename(STC_CLW_BUILTIN_PROCEDURES_FUNCTION)  wxSTC_CLW_BUILTIN_PROCEDURES_FUNCTION;
 %rename(STC_CLW_STRUCTURE_DATA_TYPE)        wxSTC_CLW_STRUCTURE_DATA_TYPE;
 %rename(STC_CLW_ATTRIBUTE)                  wxSTC_CLW_ATTRIBUTE;
 %rename(STC_CLW_STANDARD_EQUATE)            wxSTC_CLW_STANDARD_EQUATE;
 %rename(STC_CLW_ERROR)                      wxSTC_CLW_ERROR;
+%rename(STC_CLW_DEPRECATED)                 wxSTC_CLW_DEPRECATED;
 %rename(STC_LOT_DEFAULT)                    wxSTC_LOT_DEFAULT;
 %rename(STC_LOT_HEADER)                     wxSTC_LOT_HEADER;
 %rename(STC_LOT_BREAK)                      wxSTC_LOT_BREAK;
 %rename(STC_AU3_SENT)                       wxSTC_AU3_SENT;
 %rename(STC_AU3_PREPROCESSOR)               wxSTC_AU3_PREPROCESSOR;
 %rename(STC_AU3_SPECIAL)                    wxSTC_AU3_SPECIAL;
+%rename(STC_AU3_EXPAND)                     wxSTC_AU3_EXPAND;
+%rename(STC_AU3_COMOBJ)                     wxSTC_AU3_COMOBJ;
 %rename(STC_APDL_DEFAULT)                   wxSTC_APDL_DEFAULT;
 %rename(STC_APDL_COMMENT)                   wxSTC_APDL_COMMENT;
 %rename(STC_APDL_COMMENTBLOCK)              wxSTC_APDL_COMMENTBLOCK;
 %rename(STC_VHDL_STDPACKAGE)                wxSTC_VHDL_STDPACKAGE;
 %rename(STC_VHDL_STDTYPE)                   wxSTC_VHDL_STDTYPE;
 %rename(STC_VHDL_USERWORD)                  wxSTC_VHDL_USERWORD;
+%rename(STC_CAML_DEFAULT)                   wxSTC_CAML_DEFAULT;
+%rename(STC_CAML_IDENTIFIER)                wxSTC_CAML_IDENTIFIER;
+%rename(STC_CAML_TAGNAME)                   wxSTC_CAML_TAGNAME;
+%rename(STC_CAML_KEYWORD)                   wxSTC_CAML_KEYWORD;
+%rename(STC_CAML_KEYWORD2)                  wxSTC_CAML_KEYWORD2;
+%rename(STC_CAML_KEYWORD3)                  wxSTC_CAML_KEYWORD3;
+%rename(STC_CAML_LINENUM)                   wxSTC_CAML_LINENUM;
+%rename(STC_CAML_OPERATOR)                  wxSTC_CAML_OPERATOR;
+%rename(STC_CAML_NUMBER)                    wxSTC_CAML_NUMBER;
+%rename(STC_CAML_CHAR)                      wxSTC_CAML_CHAR;
+%rename(STC_CAML_STRING)                    wxSTC_CAML_STRING;
+%rename(STC_CAML_COMMENT)                   wxSTC_CAML_COMMENT;
+%rename(STC_CAML_COMMENT1)                  wxSTC_CAML_COMMENT1;
+%rename(STC_CAML_COMMENT2)                  wxSTC_CAML_COMMENT2;
+%rename(STC_CAML_COMMENT3)                  wxSTC_CAML_COMMENT3;
+%rename(STC_HA_DEFAULT)                     wxSTC_HA_DEFAULT;
+%rename(STC_HA_IDENTIFIER)                  wxSTC_HA_IDENTIFIER;
+%rename(STC_HA_KEYWORD)                     wxSTC_HA_KEYWORD;
+%rename(STC_HA_NUMBER)                      wxSTC_HA_NUMBER;
+%rename(STC_HA_STRING)                      wxSTC_HA_STRING;
+%rename(STC_HA_CHARACTER)                   wxSTC_HA_CHARACTER;
+%rename(STC_HA_CLASS)                       wxSTC_HA_CLASS;
+%rename(STC_HA_MODULE)                      wxSTC_HA_MODULE;
+%rename(STC_HA_CAPITAL)                     wxSTC_HA_CAPITAL;
+%rename(STC_HA_DATA)                        wxSTC_HA_DATA;
+%rename(STC_HA_IMPORT)                      wxSTC_HA_IMPORT;
+%rename(STC_HA_OPERATOR)                    wxSTC_HA_OPERATOR;
+%rename(STC_HA_INSTANCE)                    wxSTC_HA_INSTANCE;
+%rename(STC_HA_COMMENTLINE)                 wxSTC_HA_COMMENTLINE;
+%rename(STC_HA_COMMENTBLOCK)                wxSTC_HA_COMMENTBLOCK;
+%rename(STC_HA_COMMENTBLOCK2)               wxSTC_HA_COMMENTBLOCK2;
+%rename(STC_HA_COMMENTBLOCK3)               wxSTC_HA_COMMENTBLOCK3;
+%rename(STC_T3_DEFAULT)                     wxSTC_T3_DEFAULT;
+%rename(STC_T3_X_DEFAULT)                   wxSTC_T3_X_DEFAULT;
+%rename(STC_T3_PREPROCESSOR)                wxSTC_T3_PREPROCESSOR;
+%rename(STC_T3_BLOCK_COMMENT)               wxSTC_T3_BLOCK_COMMENT;
+%rename(STC_T3_LINE_COMMENT)                wxSTC_T3_LINE_COMMENT;
+%rename(STC_T3_OPERATOR)                    wxSTC_T3_OPERATOR;
+%rename(STC_T3_KEYWORD)                     wxSTC_T3_KEYWORD;
+%rename(STC_T3_NUMBER)                      wxSTC_T3_NUMBER;
+%rename(STC_T3_IDENTIFIER)                  wxSTC_T3_IDENTIFIER;
+%rename(STC_T3_S_STRING)                    wxSTC_T3_S_STRING;
+%rename(STC_T3_D_STRING)                    wxSTC_T3_D_STRING;
+%rename(STC_T3_X_STRING)                    wxSTC_T3_X_STRING;
+%rename(STC_T3_LIB_DIRECTIVE)               wxSTC_T3_LIB_DIRECTIVE;
+%rename(STC_T3_MSG_PARAM)                   wxSTC_T3_MSG_PARAM;
+%rename(STC_T3_HTML_TAG)                    wxSTC_T3_HTML_TAG;
+%rename(STC_T3_HTML_DEFAULT)                wxSTC_T3_HTML_DEFAULT;
+%rename(STC_T3_HTML_STRING)                 wxSTC_T3_HTML_STRING;
+%rename(STC_T3_USER1)                       wxSTC_T3_USER1;
+%rename(STC_T3_USER2)                       wxSTC_T3_USER2;
+%rename(STC_T3_USER3)                       wxSTC_T3_USER3;
+%rename(STC_REBOL_DEFAULT)                  wxSTC_REBOL_DEFAULT;
+%rename(STC_REBOL_COMMENTLINE)              wxSTC_REBOL_COMMENTLINE;
+%rename(STC_REBOL_COMMENTBLOCK)             wxSTC_REBOL_COMMENTBLOCK;
+%rename(STC_REBOL_PREFACE)                  wxSTC_REBOL_PREFACE;
+%rename(STC_REBOL_OPERATOR)                 wxSTC_REBOL_OPERATOR;
+%rename(STC_REBOL_CHARACTER)                wxSTC_REBOL_CHARACTER;
+%rename(STC_REBOL_QUOTEDSTRING)             wxSTC_REBOL_QUOTEDSTRING;
+%rename(STC_REBOL_BRACEDSTRING)             wxSTC_REBOL_BRACEDSTRING;
+%rename(STC_REBOL_NUMBER)                   wxSTC_REBOL_NUMBER;
+%rename(STC_REBOL_PAIR)                     wxSTC_REBOL_PAIR;
+%rename(STC_REBOL_TUPLE)                    wxSTC_REBOL_TUPLE;
+%rename(STC_REBOL_BINARY)                   wxSTC_REBOL_BINARY;
+%rename(STC_REBOL_MONEY)                    wxSTC_REBOL_MONEY;
+%rename(STC_REBOL_ISSUE)                    wxSTC_REBOL_ISSUE;
+%rename(STC_REBOL_TAG)                      wxSTC_REBOL_TAG;
+%rename(STC_REBOL_FILE)                     wxSTC_REBOL_FILE;
+%rename(STC_REBOL_EMAIL)                    wxSTC_REBOL_EMAIL;
+%rename(STC_REBOL_URL)                      wxSTC_REBOL_URL;
+%rename(STC_REBOL_DATE)                     wxSTC_REBOL_DATE;
+%rename(STC_REBOL_TIME)                     wxSTC_REBOL_TIME;
+%rename(STC_REBOL_IDENTIFIER)               wxSTC_REBOL_IDENTIFIER;
+%rename(STC_REBOL_WORD)                     wxSTC_REBOL_WORD;
+%rename(STC_REBOL_WORD2)                    wxSTC_REBOL_WORD2;
+%rename(STC_REBOL_WORD3)                    wxSTC_REBOL_WORD3;
+%rename(STC_REBOL_WORD4)                    wxSTC_REBOL_WORD4;
+%rename(STC_REBOL_WORD5)                    wxSTC_REBOL_WORD5;
+%rename(STC_REBOL_WORD6)                    wxSTC_REBOL_WORD6;
+%rename(STC_REBOL_WORD7)                    wxSTC_REBOL_WORD7;
+%rename(STC_REBOL_WORD8)                    wxSTC_REBOL_WORD8;
+%rename(STC_SQL_DEFAULT)                    wxSTC_SQL_DEFAULT;
+%rename(STC_SQL_COMMENT)                    wxSTC_SQL_COMMENT;
+%rename(STC_SQL_COMMENTLINE)                wxSTC_SQL_COMMENTLINE;
+%rename(STC_SQL_COMMENTDOC)                 wxSTC_SQL_COMMENTDOC;
+%rename(STC_SQL_NUMBER)                     wxSTC_SQL_NUMBER;
+%rename(STC_SQL_WORD)                       wxSTC_SQL_WORD;
+%rename(STC_SQL_STRING)                     wxSTC_SQL_STRING;
+%rename(STC_SQL_CHARACTER)                  wxSTC_SQL_CHARACTER;
+%rename(STC_SQL_SQLPLUS)                    wxSTC_SQL_SQLPLUS;
+%rename(STC_SQL_SQLPLUS_PROMPT)             wxSTC_SQL_SQLPLUS_PROMPT;
+%rename(STC_SQL_OPERATOR)                   wxSTC_SQL_OPERATOR;
+%rename(STC_SQL_IDENTIFIER)                 wxSTC_SQL_IDENTIFIER;
+%rename(STC_SQL_SQLPLUS_COMMENT)            wxSTC_SQL_SQLPLUS_COMMENT;
+%rename(STC_SQL_COMMENTLINEDOC)             wxSTC_SQL_COMMENTLINEDOC;
+%rename(STC_SQL_WORD2)                      wxSTC_SQL_WORD2;
+%rename(STC_SQL_COMMENTDOCKEYWORD)          wxSTC_SQL_COMMENTDOCKEYWORD;
+%rename(STC_SQL_COMMENTDOCKEYWORDERROR)     wxSTC_SQL_COMMENTDOCKEYWORDERROR;
+%rename(STC_SQL_USER1)                      wxSTC_SQL_USER1;
+%rename(STC_SQL_USER2)                      wxSTC_SQL_USER2;
+%rename(STC_SQL_USER3)                      wxSTC_SQL_USER3;
+%rename(STC_SQL_USER4)                      wxSTC_SQL_USER4;
+%rename(STC_SQL_QUOTEDIDENTIFIER)           wxSTC_SQL_QUOTEDIDENTIFIER;
+%rename(STC_ST_DEFAULT)                     wxSTC_ST_DEFAULT;
+%rename(STC_ST_STRING)                      wxSTC_ST_STRING;
+%rename(STC_ST_NUMBER)                      wxSTC_ST_NUMBER;
+%rename(STC_ST_COMMENT)                     wxSTC_ST_COMMENT;
+%rename(STC_ST_SYMBOL)                      wxSTC_ST_SYMBOL;
+%rename(STC_ST_BINARY)                      wxSTC_ST_BINARY;
+%rename(STC_ST_BOOL)                        wxSTC_ST_BOOL;
+%rename(STC_ST_SELF)                        wxSTC_ST_SELF;
+%rename(STC_ST_SUPER)                       wxSTC_ST_SUPER;
+%rename(STC_ST_NIL)                         wxSTC_ST_NIL;
+%rename(STC_ST_GLOBAL)                      wxSTC_ST_GLOBAL;
+%rename(STC_ST_RETURN)                      wxSTC_ST_RETURN;
+%rename(STC_ST_SPECIAL)                     wxSTC_ST_SPECIAL;
+%rename(STC_ST_KWSEND)                      wxSTC_ST_KWSEND;
+%rename(STC_ST_ASSIGN)                      wxSTC_ST_ASSIGN;
+%rename(STC_ST_CHARACTER)                   wxSTC_ST_CHARACTER;
+%rename(STC_ST_SPEC_SEL)                    wxSTC_ST_SPEC_SEL;
+%rename(STC_FS_DEFAULT)                     wxSTC_FS_DEFAULT;
+%rename(STC_FS_COMMENT)                     wxSTC_FS_COMMENT;
+%rename(STC_FS_COMMENTLINE)                 wxSTC_FS_COMMENTLINE;
+%rename(STC_FS_COMMENTDOC)                  wxSTC_FS_COMMENTDOC;
+%rename(STC_FS_COMMENTLINEDOC)              wxSTC_FS_COMMENTLINEDOC;
+%rename(STC_FS_COMMENTDOCKEYWORD)           wxSTC_FS_COMMENTDOCKEYWORD;
+%rename(STC_FS_COMMENTDOCKEYWORDERROR)      wxSTC_FS_COMMENTDOCKEYWORDERROR;
+%rename(STC_FS_KEYWORD)                     wxSTC_FS_KEYWORD;
+%rename(STC_FS_KEYWORD2)                    wxSTC_FS_KEYWORD2;
+%rename(STC_FS_KEYWORD3)                    wxSTC_FS_KEYWORD3;
+%rename(STC_FS_KEYWORD4)                    wxSTC_FS_KEYWORD4;
+%rename(STC_FS_NUMBER)                      wxSTC_FS_NUMBER;
+%rename(STC_FS_STRING)                      wxSTC_FS_STRING;
+%rename(STC_FS_PREPROCESSOR)                wxSTC_FS_PREPROCESSOR;
+%rename(STC_FS_OPERATOR)                    wxSTC_FS_OPERATOR;
+%rename(STC_FS_IDENTIFIER)                  wxSTC_FS_IDENTIFIER;
+%rename(STC_FS_DATE)                        wxSTC_FS_DATE;
+%rename(STC_FS_STRINGEOL)                   wxSTC_FS_STRINGEOL;
+%rename(STC_FS_CONSTANT)                    wxSTC_FS_CONSTANT;
+%rename(STC_FS_ASM)                         wxSTC_FS_ASM;
+%rename(STC_FS_LABEL)                       wxSTC_FS_LABEL;
+%rename(STC_FS_ERROR)                       wxSTC_FS_ERROR;
+%rename(STC_FS_HEXNUMBER)                   wxSTC_FS_HEXNUMBER;
+%rename(STC_FS_BINNUMBER)                   wxSTC_FS_BINNUMBER;
+%rename(STC_CSOUND_DEFAULT)                 wxSTC_CSOUND_DEFAULT;
+%rename(STC_CSOUND_COMMENT)                 wxSTC_CSOUND_COMMENT;
+%rename(STC_CSOUND_NUMBER)                  wxSTC_CSOUND_NUMBER;
+%rename(STC_CSOUND_OPERATOR)                wxSTC_CSOUND_OPERATOR;
+%rename(STC_CSOUND_INSTR)                   wxSTC_CSOUND_INSTR;
+%rename(STC_CSOUND_IDENTIFIER)              wxSTC_CSOUND_IDENTIFIER;
+%rename(STC_CSOUND_OPCODE)                  wxSTC_CSOUND_OPCODE;
+%rename(STC_CSOUND_HEADERSTMT)              wxSTC_CSOUND_HEADERSTMT;
+%rename(STC_CSOUND_USERKEYWORD)             wxSTC_CSOUND_USERKEYWORD;
+%rename(STC_CSOUND_COMMENTBLOCK)            wxSTC_CSOUND_COMMENTBLOCK;
+%rename(STC_CSOUND_PARAM)                   wxSTC_CSOUND_PARAM;
+%rename(STC_CSOUND_ARATE_VAR)               wxSTC_CSOUND_ARATE_VAR;
+%rename(STC_CSOUND_KRATE_VAR)               wxSTC_CSOUND_KRATE_VAR;
+%rename(STC_CSOUND_IRATE_VAR)               wxSTC_CSOUND_IRATE_VAR;
+%rename(STC_CSOUND_GLOBAL_VAR)              wxSTC_CSOUND_GLOBAL_VAR;
+%rename(STC_CSOUND_STRINGEOL)               wxSTC_CSOUND_STRINGEOL;
 %rename(STC_CMD_REDO)                       wxSTC_CMD_REDO;
 %rename(STC_CMD_SELECTALL)                  wxSTC_CMD_SELECTALL;
 %rename(STC_CMD_UNDO)                       wxSTC_CMD_UNDO;
index 3f11a3fc07250709501e2c3308e4390591c38b2e..986065c26ac3b651e3f62d24506e3ff2945fec36 100644 (file)
@@ -79,6 +79,7 @@ EVT_STC_ZOOM = wx.PyEventBinder( wxEVT_STC_ZOOM, 1 )
 EVT_STC_HOTSPOT_CLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_CLICK, 1 )
 EVT_STC_HOTSPOT_DCLICK = wx.PyEventBinder( wxEVT_STC_HOTSPOT_DCLICK, 1 )
 EVT_STC_CALLTIP_CLICK = wx.PyEventBinder( wxEVT_STC_CALLTIP_CLICK, 1 )
+EVT_STC_AUTOCOMP_SELECTION = wx.PyEventBinder( wxEVT_STC_AUTOCOMP_SELECTION, 1 )
 }
 
 //---------------------------------------------------------------------------